Merge branch 'master' into Playerbot
# Conflicts: # src/server/game/Server/WorldSession.cpp # src/server/game/Server/WorldSession.h
This commit is contained in:
@@ -108,14 +108,14 @@ void UnitAI::DoSpellAttackToRandomTargetIfReady(uint32 spell, uint32 threatTable
|
||||
}
|
||||
}
|
||||
|
||||
Unit* UnitAI::SelectTarget(SelectTargetMethod targetType, uint32 position, float dist, bool playerOnly, int32 aura)
|
||||
Unit* UnitAI::SelectTarget(SelectTargetMethod targetType, uint32 position, float dist, bool playerOnly, bool withTank, int32 aura)
|
||||
{
|
||||
return SelectTarget(targetType, position, DefaultTargetSelector(me, dist, playerOnly, aura));
|
||||
return SelectTarget(targetType, position, DefaultTargetSelector(me, dist, playerOnly, withTank, aura));
|
||||
}
|
||||
|
||||
void UnitAI::SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectTargetMethod targetType, float dist, bool playerOnly, int32 aura)
|
||||
void UnitAI::SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectTargetMethod targetType, uint32 position, float dist, bool playerOnly, bool withTank, int32 aura)
|
||||
{
|
||||
SelectTargetList(targetList, DefaultTargetSelector(me, dist, playerOnly, aura), num, targetType);
|
||||
SelectTargetList(targetList, num, targetType, position, DefaultTargetSelector(me, dist, playerOnly, withTank, aura));
|
||||
}
|
||||
|
||||
float UnitAI::DoGetSpellMaxRange(uint32 spellId, bool positive)
|
||||
@@ -210,7 +210,7 @@ SpellCastResult UnitAI::DoCast(uint32 spellId)
|
||||
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER);
|
||||
float range = spellInfo->GetMaxRange(false);
|
||||
|
||||
DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId);
|
||||
DefaultTargetSelector targetSelector(me, range, playerOnly, true, -(int32)spellId);
|
||||
if (!(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM)
|
||||
&& targetSelector(me->GetVictim()))
|
||||
target = me->GetVictim();
|
||||
@@ -317,6 +317,16 @@ void UnitAI::FillAISpellInfo()
|
||||
}
|
||||
}
|
||||
|
||||
ThreatMgr& UnitAI::GetThreatMgr()
|
||||
{
|
||||
return me->GetThreatMgr();
|
||||
}
|
||||
|
||||
void UnitAI::SortByDistance(std::list<Unit*>& list, bool ascending)
|
||||
{
|
||||
list.sort(Acore::ObjectDistanceOrderPred(me, ascending));
|
||||
}
|
||||
|
||||
//Enable PlayerAI when charmed
|
||||
void PlayerAI::OnCharmed(bool apply)
|
||||
{
|
||||
@@ -397,5 +407,8 @@ bool NonTankTargetSelector::operator()(Unit const* target) const
|
||||
if (_playerOnly && target->GetTypeId() != TYPEID_PLAYER)
|
||||
return false;
|
||||
|
||||
if (Unit* currentVictim = _source->GetThreatMgr().GetCurrentVictim())
|
||||
return target != currentVictim;
|
||||
|
||||
return target != _source->GetVictim();
|
||||
}
|
||||
|
||||
@@ -43,14 +43,16 @@ struct DefaultTargetSelector : public Acore::unary_function<Unit*, bool>
|
||||
{
|
||||
Unit const* me;
|
||||
float m_dist;
|
||||
Unit const* except;
|
||||
bool m_playerOnly;
|
||||
int32 m_aura;
|
||||
|
||||
// unit: the reference unit
|
||||
// dist: if 0: ignored, if > 0: maximum distance to the reference unit, if < 0: minimum distance to the reference unit
|
||||
// playerOnly: self explaining
|
||||
// withMainTank: allow current tank to be selected
|
||||
// aura: if 0: ignored, if > 0: the target shall have the aura, if < 0, the target shall NOT have the aura
|
||||
DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, int32 aura) : me(unit), m_dist(dist), m_playerOnly(playerOnly), m_aura(aura) {}
|
||||
DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, bool withMainTank, int32 aura) : me(unit), m_dist(dist), except(withMainTank ? me->GetThreatMgr().GetCurrentVictim() : nullptr), m_playerOnly(playerOnly), m_aura(aura) {}
|
||||
|
||||
bool operator()(Unit const* target) const
|
||||
{
|
||||
@@ -60,6 +62,9 @@ struct DefaultTargetSelector : public Acore::unary_function<Unit*, bool>
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
if (target == except)
|
||||
return false;
|
||||
|
||||
if (m_playerOnly && (target->GetTypeId() != TYPEID_PLAYER))
|
||||
return false;
|
||||
|
||||
@@ -208,7 +213,7 @@ public:
|
||||
// - Not the current tank (if withTank = false)
|
||||
// - Has aura with ID <aura> (if aura > 0)
|
||||
// - Does not have aura with ID -<aura> (if aura < 0)
|
||||
Unit* SelectTarget(SelectTargetMethod targetType, uint32 position = 0, float dist = 0.0f, bool playerOnly = false, int32 aura = 0);
|
||||
Unit* SelectTarget(SelectTargetMethod targetType, uint32 position = 0, float dist = 0.0f, bool playerOnly = false, bool withTank = true, int32 aura = 0);
|
||||
|
||||
// Select the best target (in <targetType> order) satisfying <predicate> from the threat list.
|
||||
// If <offset> is nonzero, the first <offset> entries in <targetType> order (or SelectTargetMethod::MaxThreat
|
||||
@@ -216,48 +221,30 @@ public:
|
||||
template <class PREDICATE>
|
||||
Unit* SelectTarget(SelectTargetMethod targetType, uint32 position, PREDICATE const& predicate)
|
||||
{
|
||||
ThreatContainer::StorageType const& threatlist = me->GetThreatMgr().GetThreatList();
|
||||
if (position >= threatlist.size())
|
||||
ThreatMgr& mgr = GetThreatMgr();
|
||||
// shortcut: if we ignore the first <offset> elements, and there are at most <offset> elements, then we ignore ALL elements
|
||||
if (mgr.GetThreatListSize() <= position)
|
||||
return nullptr;
|
||||
|
||||
std::list<Unit*> targetList;
|
||||
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
|
||||
if (predicate((*itr)->getTarget()))
|
||||
targetList.push_back((*itr)->getTarget());
|
||||
SelectTargetList(targetList, mgr.GetThreatListSize(), targetType, position, predicate);
|
||||
|
||||
if (position >= targetList.size())
|
||||
// maybe nothing fulfills the predicate
|
||||
if (targetList.empty())
|
||||
return nullptr;
|
||||
|
||||
if (targetType == SelectTargetMethod::MaxDistance || targetType == SelectTargetMethod::MinDistance)
|
||||
targetList.sort(Acore::ObjectDistanceOrderPred(me));
|
||||
|
||||
switch (targetType)
|
||||
{
|
||||
case SelectTargetMethod::MaxDistance:
|
||||
case SelectTargetMethod::MaxThreat:
|
||||
{
|
||||
std::list<Unit*>::iterator itr = targetList.begin();
|
||||
std::advance(itr, position);
|
||||
return *itr;
|
||||
}
|
||||
case SelectTargetMethod::MinDistance:
|
||||
case SelectTargetMethod::MinThreat:
|
||||
{
|
||||
std::list<Unit*>::reverse_iterator ritr = targetList.rbegin();
|
||||
std::advance(ritr, position);
|
||||
return *ritr;
|
||||
}
|
||||
case SelectTargetMethod::Random:
|
||||
{
|
||||
std::list<Unit*>::iterator itr = targetList.begin();
|
||||
std::advance(itr, urand(position, targetList.size() - 1));
|
||||
return *itr;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
case SelectTargetMethod::MaxThreat:
|
||||
case SelectTargetMethod::MinThreat:
|
||||
case SelectTargetMethod::MaxDistance:
|
||||
case SelectTargetMethod::MinDistance:
|
||||
return targetList.front();
|
||||
case SelectTargetMethod::Random:
|
||||
return Acore::Containers::SelectRandomContainerElement(targetList);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Select the best (up to) <num> targets (in <targetType> order) from the threat list that fulfill the following:
|
||||
@@ -270,35 +257,79 @@ public:
|
||||
// - Has aura with ID <aura> (if aura > 0)
|
||||
// - Does not have aura with ID -<aura> (if aura < 0)
|
||||
// The resulting targets are stored in <targetList> (which is cleared first).
|
||||
void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectTargetMethod targetType, float dist = 0.0f, bool playerOnly = false, int32 aura = 0);
|
||||
void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectTargetMethod targetType, uint32 position = 0, float dist = 0.0f, bool playerOnly = false, bool withTank = true, int32 aura = 0);
|
||||
|
||||
// Select the best (up to) <num> targets (in <targetType> order) satisfying <predicate> from the threat list and stores them in <targetList> (which is cleared first).
|
||||
// If <offset> is nonzero, the first <offset> entries in <targetType> order (or SelectTargetMethod::MaxThreat
|
||||
// order, if <targetType> is SelectTargetMethod::Random) are skipped.
|
||||
template <class PREDICATE>
|
||||
void SelectTargetList(std::list<Unit*>& targetList, PREDICATE const& predicate, uint32 maxTargets, SelectTargetMethod targetType)
|
||||
void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectTargetMethod targetType, uint32 position, PREDICATE const& predicate)
|
||||
{
|
||||
ThreatContainer::StorageType const& threatlist = me->GetThreatMgr().GetThreatList();
|
||||
if (threatlist.empty())
|
||||
return;
|
||||
|
||||
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
|
||||
if (predicate((*itr)->getTarget()))
|
||||
targetList.push_back((*itr)->getTarget());
|
||||
|
||||
if (targetList.size() < maxTargets)
|
||||
targetList.clear();
|
||||
ThreatMgr& mgr = GetThreatMgr();
|
||||
// shortcut: we're gonna ignore the first <offset> elements, and there's at most <offset> elements, so we ignore them all - nothing to do here
|
||||
if (mgr.GetThreatListSize() <= position)
|
||||
return;
|
||||
|
||||
if (targetType == SelectTargetMethod::MaxDistance || targetType == SelectTargetMethod::MinDistance)
|
||||
targetList.sort(Acore::ObjectDistanceOrderPred(me));
|
||||
{
|
||||
for (ThreatReference const* ref : mgr.GetUnsortedThreatList())
|
||||
{
|
||||
if (ref->IsOffline())
|
||||
continue;
|
||||
|
||||
if (targetType == SelectTargetMethod::MinDistance || targetType == SelectTargetMethod::MinThreat)
|
||||
targetList.push_back(ref->GetVictim());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* currentVictim = mgr.GetCurrentVictim();
|
||||
if (currentVictim)
|
||||
targetList.push_back(currentVictim);
|
||||
|
||||
for (ThreatReference const* ref : mgr.GetSortedThreatList())
|
||||
{
|
||||
if (ref->IsOffline())
|
||||
continue;
|
||||
|
||||
Unit* thisTarget = ref->GetVictim();
|
||||
if (thisTarget != currentVictim)
|
||||
targetList.push_back(thisTarget);
|
||||
}
|
||||
}
|
||||
|
||||
// shortcut: the list isn't gonna get any larger
|
||||
if (targetList.size() <= position)
|
||||
{
|
||||
targetList.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// right now, list is unsorted for DISTANCE types - re-sort by SelectTargetMethod::MaxDistance
|
||||
if (targetType == SelectTargetMethod::MaxDistance || targetType == SelectTargetMethod::MinDistance)
|
||||
SortByDistance(targetList, targetType == SelectTargetMethod::MinDistance);
|
||||
|
||||
// now the list is MAX sorted, reverse for MIN types
|
||||
if (targetType == SelectTargetMethod::MinThreat)
|
||||
targetList.reverse();
|
||||
|
||||
// ignore the first <offset> elements
|
||||
while (position)
|
||||
{
|
||||
targetList.pop_front();
|
||||
--position;
|
||||
}
|
||||
|
||||
// then finally filter by predicate
|
||||
targetList.remove_if([&predicate](Unit* target) { return !predicate(target); });
|
||||
|
||||
if (targetList.size() <= num)
|
||||
return;
|
||||
|
||||
if (targetType == SelectTargetMethod::Random)
|
||||
Acore::Containers::RandomResize(targetList, maxTargets);
|
||||
Acore::Containers::RandomResize(targetList, num);
|
||||
else
|
||||
targetList.resize(maxTargets);
|
||||
targetList.resize(num);
|
||||
}
|
||||
|
||||
// Called at any Damage to any victim (before damage apply)
|
||||
@@ -348,6 +379,10 @@ public:
|
||||
virtual void sOnGameEvent(bool /*start*/, uint16 /*eventId*/) {}
|
||||
|
||||
virtual std::string GetDebugInfo() const;
|
||||
|
||||
private:
|
||||
ThreatMgr& GetThreatMgr();
|
||||
void SortByDistance(std::list<Unit*>& list, bool ascending = true);
|
||||
};
|
||||
|
||||
class PlayerAI : public UnitAI
|
||||
|
||||
@@ -810,6 +810,7 @@ void SmartAI::KilledUnit(Unit* victim)
|
||||
void SmartAI::JustSummoned(Creature* creature)
|
||||
{
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_SUMMONED_UNIT, creature);
|
||||
GetScript()->AddCreatureSummon(creature->GetGUID());
|
||||
}
|
||||
|
||||
void SmartAI::SummonedCreatureDies(Creature* summon, Unit* /*killer*/)
|
||||
@@ -890,6 +891,7 @@ void SmartAI::DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType /*damag
|
||||
void SmartAI::SummonedCreatureDespawn(Creature* unit)
|
||||
{
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_SUMMON_DESPAWNED, unit);
|
||||
GetScript()->RemoveCreatureSummon(unit->GetGUID());
|
||||
}
|
||||
|
||||
void SmartAI::CorpseRemoved(uint32& respawnDelay)
|
||||
|
||||
@@ -1950,7 +1950,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundTarget && me && IsCreature(me))
|
||||
if (!foundTarget && me && IsCreature(me) && me->IsAlive())
|
||||
{
|
||||
if (e.action.moveRandom.distance)
|
||||
me->GetMotionMaster()->MoveRandom(float(e.action.moveRandom.distance));
|
||||
@@ -3334,6 +3334,24 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_TARGET_SUMMONED_CREATURES:
|
||||
{
|
||||
if (me)
|
||||
{
|
||||
for (ObjectGuid const& guid : _summonList)
|
||||
{
|
||||
if (!e.target.summonedCreatures.entry || guid.GetEntry() == e.target.summonedCreatures.entry)
|
||||
{
|
||||
if (Creature* creature = me->GetMap()->GetCreature(guid))
|
||||
{
|
||||
targets.push_back(creature);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_TARGET_NONE:
|
||||
case SMART_TARGET_POSITION:
|
||||
@@ -4560,3 +4578,13 @@ bool SmartScript::IsInPhase(uint32 p) const
|
||||
|
||||
return ((1 << (mEventPhase - 1)) & p) != 0;
|
||||
}
|
||||
|
||||
void SmartScript::AddCreatureSummon(ObjectGuid const& guid)
|
||||
{
|
||||
_summonList.insert(guid);
|
||||
}
|
||||
|
||||
void SmartScript::RemoveCreatureSummon(ObjectGuid const& guid)
|
||||
{
|
||||
_summonList.erase(guid);
|
||||
}
|
||||
|
||||
@@ -232,6 +232,9 @@ public:
|
||||
bool AllowPhaseReset() const { return _allowPhaseReset; }
|
||||
void SetPhaseReset(bool allow) { _allowPhaseReset = allow; }
|
||||
|
||||
void AddCreatureSummon(ObjectGuid const& guid);
|
||||
void RemoveCreatureSummon(ObjectGuid const& guid);
|
||||
|
||||
private:
|
||||
void IncPhase(uint32 p);
|
||||
void DecPhase(uint32 p);
|
||||
@@ -306,6 +309,8 @@ private:
|
||||
SmartScriptHolder s;
|
||||
return s;
|
||||
}
|
||||
|
||||
GuidUnorderedSet _summonList;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -413,6 +413,14 @@ bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case SMART_TARGET_SUMMONED_CREATURES:
|
||||
{
|
||||
if (e.target.summonedCreatures.entry && !IsCreatureValid(e, e.target.summonedCreatures.entry))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_TARGET_HOSTILE_SECOND_AGGRO:
|
||||
case SMART_TARGET_HOSTILE_LAST_AGGRO:
|
||||
case SMART_TARGET_HOSTILE_RANDOM:
|
||||
|
||||
@@ -1407,8 +1407,9 @@ enum SMARTAI_TARGETS
|
||||
SMART_TARGET_PLAYER_WITH_AURA = 201, // spellId, negation, MaxDist, MinDist, set target.o to a number to random resize the list
|
||||
SMART_TARGET_RANDOM_POINT = 202, // range, amount (for summoning creature), self als middle (0/1) else use xyz
|
||||
SMART_TARGET_ROLE_SELECTION = 203, // Range Max, TargetMask (Tanks (1), Healer (2) Damage (4)), resize list
|
||||
SMART_TARGET_SUMMONED_CREATURES = 204, // Entry
|
||||
|
||||
SMART_TARGET_AC_END = 204 // placeholder
|
||||
SMART_TARGET_AC_END = 205 // placeholder
|
||||
};
|
||||
|
||||
struct SmartTarget
|
||||
@@ -1564,6 +1565,11 @@ struct SmartTarget
|
||||
uint32 distMin;
|
||||
} playerWithAura;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 entry;
|
||||
} summonedCreatures;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 param1;
|
||||
|
||||
@@ -470,8 +470,8 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
|
||||
|
||||
bool AchievementCriteriaDataSet::Meets(Player const* source, Unit const* target, uint32 miscvalue /*= 0*/) const
|
||||
{
|
||||
for (Storage::const_iterator itr = storage.begin(); itr != storage.end(); ++itr)
|
||||
if (!itr->Meets(criteria_id, source, target, miscvalue))
|
||||
for (Storage::const_iterator itr = _storage.begin(); itr != _storage.end(); ++itr)
|
||||
if (!itr->Meets(_criteria_id, source, target, miscvalue))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -479,7 +479,7 @@ bool AchievementCriteriaDataSet::Meets(Player const* source, Unit const* target,
|
||||
|
||||
AchievementMgr::AchievementMgr(Player* player)
|
||||
{
|
||||
m_player = player;
|
||||
_player = player;
|
||||
}
|
||||
|
||||
AchievementMgr::~AchievementMgr()
|
||||
@@ -488,23 +488,23 @@ AchievementMgr::~AchievementMgr()
|
||||
|
||||
void AchievementMgr::Reset()
|
||||
{
|
||||
for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
|
||||
for (CompletedAchievementMap::const_iterator iter = _completedAchievements.begin(); iter != _completedAchievements.end(); ++iter)
|
||||
{
|
||||
WorldPacket data(SMSG_ACHIEVEMENT_DELETED, 4);
|
||||
data << uint32(iter->first);
|
||||
m_player->SendDirectMessage(&data);
|
||||
_player->SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
for (CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter)
|
||||
for (CriteriaProgressMap::const_iterator iter = _criteriaProgress.begin(); iter != _criteriaProgress.end(); ++iter)
|
||||
{
|
||||
WorldPacket data(SMSG_CRITERIA_DELETED, 4);
|
||||
data << uint32(iter->first);
|
||||
m_player->SendDirectMessage(&data);
|
||||
_player->SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
m_completedAchievements.clear();
|
||||
m_criteriaProgress.clear();
|
||||
DeleteFromDB(m_player->GetGUID().GetCounter());
|
||||
_completedAchievements.clear();
|
||||
_criteriaProgress.clear();
|
||||
DeleteFromDB(_player->GetGUID().GetCounter());
|
||||
|
||||
// re-fill data
|
||||
CheckAllAchievementCriteria();
|
||||
@@ -513,7 +513,7 @@ void AchievementMgr::Reset()
|
||||
void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaCondition condition, uint32 value, bool evenIfCriteriaComplete)
|
||||
{
|
||||
// disable for gamemasters with GM-mode enabled
|
||||
if (m_player->IsGameMaster())
|
||||
if (_player->IsGameMaster())
|
||||
return;
|
||||
|
||||
LOG_DEBUG("achievement", "AchievementMgr::ResetAchievementCriteria({}, {}, {})", condition, value, evenIfCriteriaComplete);
|
||||
@@ -554,9 +554,9 @@ void AchievementMgr::DeleteFromDB(ObjectGuid::LowType lowguid)
|
||||
|
||||
void AchievementMgr::SaveToDB(CharacterDatabaseTransaction trans)
|
||||
{
|
||||
if (!m_completedAchievements.empty())
|
||||
if (!_completedAchievements.empty())
|
||||
{
|
||||
for (CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
|
||||
for (CompletedAchievementMap::iterator iter = _completedAchievements.begin(); iter != _completedAchievements.end(); ++iter)
|
||||
{
|
||||
if (!iter->second.changed)
|
||||
continue;
|
||||
@@ -578,9 +578,9 @@ void AchievementMgr::SaveToDB(CharacterDatabaseTransaction trans)
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_criteriaProgress.empty())
|
||||
if (!_criteriaProgress.empty())
|
||||
{
|
||||
for (CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter)
|
||||
for (CriteriaProgressMap::iterator iter = _criteriaProgress.begin(); iter != _criteriaProgress.end(); ++iter)
|
||||
{
|
||||
if (!iter->second.changed)
|
||||
continue;
|
||||
@@ -622,7 +622,7 @@ void AchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQ
|
||||
if (!achievement)
|
||||
continue;
|
||||
|
||||
CompletedAchievementData& ca = m_completedAchievements[achievementid];
|
||||
CompletedAchievementData& ca = _completedAchievements[achievementid];
|
||||
ca.date = time_t(fields[1].Get<uint32>());
|
||||
ca.changed = false;
|
||||
|
||||
@@ -662,7 +662,7 @@ void AchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQ
|
||||
if (criteria->timeLimit && time_t(date + criteria->timeLimit) < GameTime::GetGameTime().count())
|
||||
continue;
|
||||
|
||||
CriteriaProgress& progress = m_criteriaProgress[id];
|
||||
CriteriaProgress& progress = _criteriaProgress[id];
|
||||
progress.counter = counter;
|
||||
progress.date = date;
|
||||
progress.changed = false;
|
||||
@@ -789,7 +789,7 @@ static const uint32 achievIdForDungeon[][4] =
|
||||
void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit* unit /*= nullptr*/)
|
||||
{
|
||||
// disable for gamemasters with GM-mode enabled
|
||||
if (m_player->IsGameMaster())
|
||||
if (_player->IsGameMaster())
|
||||
return;
|
||||
|
||||
if (type >= ACHIEVEMENT_CRITERIA_TYPE_TOTAL)
|
||||
@@ -1596,7 +1596,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
||||
if (!miscValue1)
|
||||
{
|
||||
uint32 points = 0;
|
||||
for (CompletedAchievementMap::iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
|
||||
for (CompletedAchievementMap::iterator itr = _completedAchievements.begin(); itr != _completedAchievements.end(); ++itr)
|
||||
if (AchievementEntry const* pAchievement = sAchievementStore.LookupEntry(itr->first))
|
||||
points += pAchievement->points;
|
||||
SetCriteriaProgress(achievementCriteria, points, PROGRESS_SET);
|
||||
@@ -2027,9 +2027,9 @@ bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
|
||||
|
||||
CriteriaProgress* AchievementMgr::GetCriteriaProgress(AchievementCriteriaEntry const* entry)
|
||||
{
|
||||
CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID);
|
||||
CriteriaProgressMap::iterator iter = _criteriaProgress.find(entry->ID);
|
||||
|
||||
if (iter == m_criteriaProgress.end())
|
||||
if (iter == _criteriaProgress.end())
|
||||
return nullptr;
|
||||
|
||||
return &(iter->second);
|
||||
@@ -2038,8 +2038,8 @@ CriteriaProgress* AchievementMgr::GetCriteriaProgress(AchievementCriteriaEntry c
|
||||
void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype)
|
||||
{
|
||||
// Don't allow to cheat - doing timed achievements without timer active
|
||||
TimedAchievementMap::iterator timedIter = m_timedAchievements.find(entry->ID);
|
||||
if (entry->timeLimit && timedIter == m_timedAchievements.end())
|
||||
TimedAchievementMap::iterator timedIter = _timedAchievements.find(entry->ID);
|
||||
if (entry->timeLimit && timedIter == _timedAchievements.end())
|
||||
return;
|
||||
|
||||
if (!sScriptMgr->OnBeforeCriteriaProgress(GetPlayer(), entry))
|
||||
@@ -2047,7 +2047,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG("achievement", "AchievementMgr::SetCriteriaProgress({}, {}) for {}", entry->ID, changeValue, m_player->GetGUID().ToString());
|
||||
LOG_DEBUG("achievement", "AchievementMgr::SetCriteriaProgress({}, {}) for {}", entry->ID, changeValue, _player->GetGUID().ToString());
|
||||
|
||||
CriteriaProgress* progress = GetCriteriaProgress(entry);
|
||||
if (!progress)
|
||||
@@ -2057,7 +2057,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
|
||||
if (changeValue == 0 && !entry->timeLimit)
|
||||
return;
|
||||
|
||||
progress = &m_criteriaProgress[entry->ID];
|
||||
progress = &_criteriaProgress[entry->ID];
|
||||
progress->counter = changeValue;
|
||||
}
|
||||
else
|
||||
@@ -2103,7 +2103,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
|
||||
|
||||
// Remove the timer, we wont need it anymore
|
||||
if (timedCompleted)
|
||||
m_timedAchievements.erase(timedIter);
|
||||
_timedAchievements.erase(timedIter);
|
||||
}
|
||||
|
||||
SendCriteriaUpdate(entry, progress, timeElapsed, true);
|
||||
@@ -2113,29 +2113,29 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
|
||||
|
||||
void AchievementMgr::RemoveCriteriaProgress(const AchievementCriteriaEntry* entry)
|
||||
{
|
||||
CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID);
|
||||
if (criteriaProgress == m_criteriaProgress.end())
|
||||
CriteriaProgressMap::iterator criteriaProgress = _criteriaProgress.find(entry->ID);
|
||||
if (criteriaProgress == _criteriaProgress.end())
|
||||
return;
|
||||
|
||||
WorldPacket data(SMSG_CRITERIA_DELETED, 4);
|
||||
data << uint32(entry->ID);
|
||||
m_player->SendDirectMessage(&data);
|
||||
_player->SendDirectMessage(&data);
|
||||
|
||||
m_criteriaProgress.erase(criteriaProgress);
|
||||
_criteriaProgress.erase(criteriaProgress);
|
||||
}
|
||||
|
||||
void AchievementMgr::UpdateTimedAchievements(uint32 timeDiff)
|
||||
{
|
||||
if (!m_timedAchievements.empty())
|
||||
if (!_timedAchievements.empty())
|
||||
{
|
||||
for (TimedAchievementMap::iterator itr = m_timedAchievements.begin(); itr != m_timedAchievements.end();)
|
||||
for (TimedAchievementMap::iterator itr = _timedAchievements.begin(); itr != _timedAchievements.end();)
|
||||
{
|
||||
// Time is up, remove timer and reset progress
|
||||
if (itr->second <= timeDiff)
|
||||
{
|
||||
AchievementCriteriaEntry const* entry = sAchievementCriteriaStore.LookupEntry(itr->first);
|
||||
RemoveCriteriaProgress(entry);
|
||||
m_timedAchievements.erase(itr++);
|
||||
_timedAchievements.erase(itr++);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2155,12 +2155,12 @@ void AchievementMgr::StartTimedAchievement(AchievementCriteriaTimedTypes type, u
|
||||
continue;
|
||||
|
||||
AchievementEntry const* achievement = sAchievementStore.LookupEntry((*i)->referredAchievement);
|
||||
if (m_timedAchievements.find((*i)->ID) == m_timedAchievements.end() && !IsCompletedCriteria(*i, achievement))
|
||||
if (_timedAchievements.find((*i)->ID) == _timedAchievements.end() && !IsCompletedCriteria(*i, achievement))
|
||||
{
|
||||
// Start the timer
|
||||
if ((*i)->timeLimit * IN_MILLISECONDS > timeLost)
|
||||
{
|
||||
m_timedAchievements[(*i)->ID] = (*i)->timeLimit * IN_MILLISECONDS - timeLost;
|
||||
_timedAchievements[(*i)->ID] = (*i)->timeLimit * IN_MILLISECONDS - timeLost;
|
||||
|
||||
// and at client too
|
||||
SetCriteriaProgress(*i, 0, PROGRESS_SET);
|
||||
@@ -2177,26 +2177,26 @@ void AchievementMgr::RemoveTimedAchievement(AchievementCriteriaTimedTypes type,
|
||||
if ((*i)->timerStartEvent != entry)
|
||||
continue;
|
||||
|
||||
TimedAchievementMap::iterator timedIter = m_timedAchievements.find((*i)->ID);
|
||||
TimedAchievementMap::iterator timedIter = _timedAchievements.find((*i)->ID);
|
||||
// We don't have timer for this achievement
|
||||
if (timedIter == m_timedAchievements.end())
|
||||
if (timedIter == _timedAchievements.end())
|
||||
continue;
|
||||
|
||||
// remove progress
|
||||
RemoveCriteriaProgress(*i);
|
||||
|
||||
// Remove the timer
|
||||
m_timedAchievements.erase(timedIter);
|
||||
_timedAchievements.erase(timedIter);
|
||||
}
|
||||
}
|
||||
|
||||
void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
||||
{
|
||||
// disable for gamemasters with GM-mode enabled
|
||||
if (m_player->IsGameMaster())
|
||||
if (_player->IsGameMaster())
|
||||
{
|
||||
LOG_INFO("achievement", "Not available in GM mode.");
|
||||
ChatHandler(m_player->GetSession()).PSendSysMessage("Not available in GM mode");
|
||||
ChatHandler(_player->GetSession()).PSendSysMessage("Not available in GM mode");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2211,7 +2211,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
||||
LOG_DEBUG("achievement", "AchievementMgr::CompletedAchievement({})", achievement->ID);
|
||||
|
||||
SendAchievementEarned(achievement);
|
||||
CompletedAchievementData& ca = m_completedAchievements[achievement->ID];
|
||||
CompletedAchievementData& ca = _completedAchievements[achievement->ID];
|
||||
ca.date = GameTime::GetGameTime().count();
|
||||
ca.changed = true;
|
||||
|
||||
@@ -2240,7 +2240,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
||||
}
|
||||
}
|
||||
|
||||
if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL) && AccountMgr::IsPlayerAccount(m_player->GetSession()->GetSecurity()))
|
||||
if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL) && AccountMgr::IsPlayerAccount(_player->GetSession()->GetSecurity()))
|
||||
sAchievementMgr->SetRealmCompleted(achievement);
|
||||
|
||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, achievement->ID);
|
||||
@@ -2304,14 +2304,14 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
||||
|
||||
void AchievementMgr::SendAllAchievementData() const
|
||||
{
|
||||
WorldPacket data(SMSG_ALL_ACHIEVEMENT_DATA, m_completedAchievements.size() * 8 + 4 + m_criteriaProgress.size() * 38 + 4);
|
||||
WorldPacket data(SMSG_ALL_ACHIEVEMENT_DATA, _completedAchievements.size() * 8 + 4 + _criteriaProgress.size() * 38 + 4);
|
||||
BuildAllDataPacket(&data);
|
||||
GetPlayer()->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void AchievementMgr::SendRespondInspectAchievements(Player* player) const
|
||||
{
|
||||
WorldPacket data(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, 9 + m_completedAchievements.size() * 8 + 4 + m_criteriaProgress.size() * 38 + 4);
|
||||
WorldPacket data(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, 9 + _completedAchievements.size() * 8 + 4 + _criteriaProgress.size() * 38 + 4);
|
||||
data << GetPlayer()->GetPackGUID();
|
||||
BuildAllDataPacket(&data);
|
||||
player->GetSession()->SendPacket(&data);
|
||||
@@ -2322,7 +2322,7 @@ void AchievementMgr::SendRespondInspectAchievements(Player* player) const
|
||||
*/
|
||||
void AchievementMgr::BuildAllDataPacket(WorldPacket* data) const
|
||||
{
|
||||
for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
|
||||
for (CompletedAchievementMap::const_iterator iter = _completedAchievements.begin(); iter != _completedAchievements.end(); ++iter)
|
||||
{
|
||||
// Skip hidden achievements
|
||||
AchievementEntry const* achievement = sAchievementStore.LookupEntry(iter->first);
|
||||
@@ -2336,7 +2336,7 @@ void AchievementMgr::BuildAllDataPacket(WorldPacket* data) const
|
||||
*data << int32(-1);
|
||||
time_t now = GameTime::GetGameTime().count();
|
||||
|
||||
for (CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter)
|
||||
for (CriteriaProgressMap::const_iterator iter = _criteriaProgress.begin(); iter != _criteriaProgress.end(); ++iter)
|
||||
{
|
||||
*data << uint32(iter->first);
|
||||
data->appendPackGUID(iter->second.counter);
|
||||
@@ -2352,7 +2352,7 @@ void AchievementMgr::BuildAllDataPacket(WorldPacket* data) const
|
||||
|
||||
bool AchievementMgr::HasAchieved(uint32 achievementId) const
|
||||
{
|
||||
return m_completedAchievements.find(achievementId) != m_completedAchievements.end();
|
||||
return _completedAchievements.find(achievementId) != _completedAchievements.end();
|
||||
}
|
||||
|
||||
bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement)
|
||||
@@ -2402,10 +2402,10 @@ AchievementGlobalMgr* AchievementGlobalMgr::instance()
|
||||
|
||||
bool AchievementGlobalMgr::IsStatisticCriteria(AchievementCriteriaEntry const* achievementCriteria) const
|
||||
{
|
||||
return isStatisticAchievement(sAchievementStore.LookupEntry(achievementCriteria->referredAchievement));
|
||||
return IsStatisticAchievement(sAchievementStore.LookupEntry(achievementCriteria->referredAchievement));
|
||||
}
|
||||
|
||||
bool AchievementGlobalMgr::isStatisticAchievement(AchievementEntry const* achievement) const
|
||||
bool AchievementGlobalMgr::IsStatisticAchievement(AchievementEntry const* achievement) const
|
||||
{
|
||||
if (!achievement)
|
||||
return false;
|
||||
@@ -2430,8 +2430,8 @@ bool AchievementGlobalMgr::isStatisticAchievement(AchievementEntry const* achiev
|
||||
|
||||
bool AchievementGlobalMgr::IsRealmCompleted(AchievementEntry const* achievement) const
|
||||
{
|
||||
auto itr = m_allCompletedAchievements.find(achievement->ID);
|
||||
if (itr == m_allCompletedAchievements.end())
|
||||
auto itr = _allCompletedAchievements.find(achievement->ID);
|
||||
if (itr == _allCompletedAchievements.end())
|
||||
return false;
|
||||
|
||||
if (itr->second == SystemTimePoint::min())
|
||||
@@ -2459,7 +2459,7 @@ void AchievementGlobalMgr::SetRealmCompleted(AchievementEntry const* achievement
|
||||
if (IsRealmCompleted(achievement))
|
||||
return;
|
||||
|
||||
m_allCompletedAchievements[achievement->ID] = GameTime::GetSystemTime();
|
||||
_allCompletedAchievements[achievement->ID] = GameTime::GetSystemTime();
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
@@ -2481,67 +2481,67 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList()
|
||||
if (!criteria)
|
||||
continue;
|
||||
|
||||
m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria);
|
||||
m_AchievementCriteriaListByAchievement[criteria->referredAchievement].push_back(criteria);
|
||||
_achievementCriteriasByType[criteria->requiredType].push_back(criteria);
|
||||
_achievementCriteriaListByAchievement[criteria->referredAchievement].push_back(criteria);
|
||||
|
||||
if (criteria->additionalRequirements[0].additionalRequirement_type != ACHIEVEMENT_CRITERIA_CONDITION_NONE)
|
||||
m_AchievementCriteriasByCondition[criteria->additionalRequirements[0].additionalRequirement_type][criteria->additionalRequirements[0].additionalRequirement_value].push_back(criteria);
|
||||
_achievementCriteriasByCondition[criteria->additionalRequirements[0].additionalRequirement_type][criteria->additionalRequirements[0].additionalRequirement_value].push_back(criteria);
|
||||
if (criteria->additionalRequirements[1].additionalRequirement_type != ACHIEVEMENT_CRITERIA_CONDITION_NONE &&
|
||||
criteria->additionalRequirements[1].additionalRequirement_type != criteria->additionalRequirements[0].additionalRequirement_type)
|
||||
m_AchievementCriteriasByCondition[criteria->additionalRequirements[1].additionalRequirement_type][criteria->additionalRequirements[1].additionalRequirement_value].push_back(criteria);
|
||||
_achievementCriteriasByCondition[criteria->additionalRequirements[1].additionalRequirement_type][criteria->additionalRequirements[1].additionalRequirement_value].push_back(criteria);
|
||||
|
||||
switch (criteria->requiredType)
|
||||
{
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
|
||||
m_SpecialList[criteria->requiredType][criteria->kill_creature.creatureID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->kill_creature.creatureID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
|
||||
m_SpecialList[criteria->requiredType][criteria->win_bg.bgMapID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->win_bg.bgMapID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
|
||||
m_SpecialList[criteria->requiredType][criteria->reach_skill_level.skillID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->reach_skill_level.skillID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
|
||||
m_SpecialList[criteria->requiredType][criteria->complete_achievement.linkedAchievement].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->complete_achievement.linkedAchievement].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
|
||||
m_SpecialList[criteria->requiredType][criteria->complete_quests_in_zone.zoneID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->complete_quests_in_zone.zoneID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
|
||||
m_SpecialList[criteria->requiredType][criteria->complete_battleground.mapID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->complete_battleground.mapID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
|
||||
m_SpecialList[criteria->requiredType][criteria->killed_by_creature.creatureEntry].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->killed_by_creature.creatureEntry].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
|
||||
m_SpecialList[criteria->requiredType][criteria->complete_quest.questID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->complete_quest.questID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
|
||||
m_SpecialList[criteria->requiredType][criteria->be_spell_target.spellID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->be_spell_target.spellID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
|
||||
m_SpecialList[criteria->requiredType][criteria->cast_spell.spellID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->cast_spell.spellID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
|
||||
m_SpecialList[criteria->requiredType][criteria->bg_objective.objectiveId].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->bg_objective.objectiveId].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
|
||||
m_SpecialList[criteria->requiredType][criteria->honorable_kill_at_area.areaID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->honorable_kill_at_area.areaID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
|
||||
m_SpecialList[criteria->requiredType][criteria->learn_spell.spellID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->learn_spell.spellID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
|
||||
m_SpecialList[criteria->requiredType][criteria->own_item.itemID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->own_item.itemID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
|
||||
m_SpecialList[criteria->requiredType][criteria->learn_skill_level.skillID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->learn_skill_level.skillID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
|
||||
m_SpecialList[criteria->requiredType][criteria->use_item.itemID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->use_item.itemID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
|
||||
m_SpecialList[criteria->requiredType][criteria->own_item.itemID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->own_item.itemID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
|
||||
{
|
||||
@@ -2557,53 +2557,53 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList()
|
||||
if (worldOverlayEntry->areatableID[j] == worldOverlayEntry->areatableID[i])
|
||||
valid = false;
|
||||
if (valid)
|
||||
m_SpecialList[criteria->requiredType][worldOverlayEntry->areatableID[j]].push_back(criteria);
|
||||
_specialList[criteria->requiredType][worldOverlayEntry->areatableID[j]].push_back(criteria);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
|
||||
m_SpecialList[criteria->requiredType][criteria->gain_reputation.factionID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->gain_reputation.factionID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
|
||||
m_SpecialList[criteria->requiredType][criteria->equip_epic_item.itemSlot].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->equip_epic_item.itemSlot].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
|
||||
m_SpecialList[criteria->requiredType][criteria->hk_class.classID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->hk_class.classID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
|
||||
m_SpecialList[criteria->requiredType][criteria->hk_race.raceID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->hk_race.raceID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
|
||||
m_SpecialList[criteria->requiredType][criteria->do_emote.emoteID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->do_emote.emoteID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
|
||||
m_SpecialList[criteria->requiredType][criteria->equip_item.itemID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->equip_item.itemID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
|
||||
m_SpecialList[criteria->requiredType][criteria->use_gameobject.goEntry].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->use_gameobject.goEntry].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
|
||||
m_SpecialList[criteria->requiredType][criteria->be_spell_target.spellID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->be_spell_target.spellID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
|
||||
m_SpecialList[criteria->requiredType][criteria->fish_in_gameobject.goEntry].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->fish_in_gameobject.goEntry].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
|
||||
m_SpecialList[criteria->requiredType][criteria->learn_skillline_spell.skillLine].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->learn_skillline_spell.skillLine].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
|
||||
m_SpecialList[criteria->requiredType][criteria->loot_type.lootType].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->loot_type.lootType].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
|
||||
m_SpecialList[criteria->requiredType][criteria->cast_spell.spellID].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->cast_spell.spellID].push_back(criteria);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
|
||||
m_SpecialList[criteria->requiredType][criteria->learn_skill_line.skillLine].push_back(criteria);
|
||||
_specialList[criteria->requiredType][criteria->learn_skill_line.skillLine].push_back(criteria);
|
||||
break;
|
||||
}
|
||||
|
||||
if (criteria->timeLimit)
|
||||
m_AchievementCriteriasByTimedType[criteria->timedType].push_back(criteria);
|
||||
_achievementCriteriasByTimedType[criteria->timedType].push_back(criteria);
|
||||
|
||||
++loaded;
|
||||
}
|
||||
@@ -2631,7 +2631,7 @@ void AchievementGlobalMgr::LoadAchievementReferenceList()
|
||||
if (!achievement || !achievement->refAchievement)
|
||||
continue;
|
||||
|
||||
m_AchievementListByReferencedId[achievement->refAchievement].push_back(achievement);
|
||||
_achievementListByReferencedId[achievement->refAchievement].push_back(achievement);
|
||||
++count;
|
||||
}
|
||||
|
||||
@@ -2643,7 +2643,7 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
m_criteriaDataMap.clear(); // need for reload case
|
||||
_criteriaDataMap.clear(); // need for reload case
|
||||
|
||||
QueryResult result = WorldDatabase.Query("SELECT criteria_id, type, value1, value2, ScriptName FROM achievement_criteria_data");
|
||||
|
||||
@@ -2686,7 +2686,7 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
|
||||
continue;
|
||||
|
||||
// this will allocate empty data set storage
|
||||
AchievementCriteriaDataSet& dataSet = m_criteriaDataMap[criteria_id];
|
||||
AchievementCriteriaDataSet& dataSet = _criteriaDataMap[criteria_id];
|
||||
dataSet.SetCriteriaId(criteria_id);
|
||||
|
||||
// add real data only for not NONE data types
|
||||
@@ -2786,7 +2786,7 @@ void AchievementGlobalMgr::LoadCompletedAchievements()
|
||||
for (uint32 i = 0; i < sAchievementStore.GetNumRows(); ++i)
|
||||
if (AchievementEntry const* achievement = sAchievementStore.LookupEntry(i))
|
||||
if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
|
||||
m_allCompletedAchievements[achievement->ID] = SystemTimePoint::min();
|
||||
_allCompletedAchievements[achievement->ID] = SystemTimePoint::min();
|
||||
|
||||
if (!result)
|
||||
{
|
||||
@@ -2814,10 +2814,10 @@ void AchievementGlobalMgr::LoadCompletedAchievements()
|
||||
continue;
|
||||
}
|
||||
else if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
|
||||
m_allCompletedAchievements[achievementId] = SystemTimePoint::max();
|
||||
_allCompletedAchievements[achievementId] = SystemTimePoint::max();
|
||||
} while (result->NextRow());
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} completed achievements in {} ms", (unsigned long)m_allCompletedAchievements.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", ">> Loaded {} completed achievements in {} ms", (unsigned long)_allCompletedAchievements.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
@@ -2825,7 +2825,7 @@ void AchievementGlobalMgr::LoadRewards()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
m_achievementRewards.clear(); // need for reload case
|
||||
_achievementRewards.clear(); // need for reload case
|
||||
|
||||
// 0 1 2 3 4 5 6 7
|
||||
QueryResult result = WorldDatabase.Query("SELECT ID, TitleA, TitleH, ItemID, Sender, Subject, Body, MailTemplateID FROM achievement_reward");
|
||||
@@ -2934,7 +2934,7 @@ void AchievementGlobalMgr::LoadRewards()
|
||||
}
|
||||
}
|
||||
|
||||
m_achievementRewards[entry] = reward;
|
||||
_achievementRewards[entry] = reward;
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
|
||||
@@ -2946,7 +2946,7 @@ void AchievementGlobalMgr::LoadRewardLocales()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
m_achievementRewardLocales.clear(); // need for reload case
|
||||
_achievementRewardLocales.clear(); // need for reload case
|
||||
|
||||
// 0 1 2 3
|
||||
QueryResult result = WorldDatabase.Query("SELECT ID, Locale, Subject, Text FROM achievement_reward_locale");
|
||||
@@ -2963,7 +2963,7 @@ void AchievementGlobalMgr::LoadRewardLocales()
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 ID = fields[0].Get<uint32>();
|
||||
if (m_achievementRewards.find(ID) == m_achievementRewards.end())
|
||||
if (_achievementRewards.find(ID) == _achievementRewards.end())
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `achievement_reward_locale` (Entry: {}) has locale strings for non-existing achievement reward.", ID);
|
||||
continue;
|
||||
@@ -2973,12 +2973,12 @@ void AchievementGlobalMgr::LoadRewardLocales()
|
||||
if (locale == LOCALE_enUS)
|
||||
continue;
|
||||
|
||||
AchievementRewardLocale& data = m_achievementRewardLocales[ID];
|
||||
AchievementRewardLocale& data = _achievementRewardLocales[ID];
|
||||
ObjectMgr::AddLocaleString(fields[2].Get<std::string>(), locale, data.Subject);
|
||||
ObjectMgr::AddLocaleString(fields[3].Get<std::string>(), locale, data.Text);
|
||||
} while (result->NextRow());
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} Achievement Reward Locale Strings in {} ms", (unsigned long)m_achievementRewardLocales.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", ">> Loaded {} Achievement Reward Locale Strings in {} ms", (unsigned long)_achievementRewardLocales.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
|
||||
@@ -233,12 +233,12 @@ struct AchievementCriteriaDataSet
|
||||
{
|
||||
AchievementCriteriaDataSet() = default;
|
||||
typedef std::vector<AchievementCriteriaData> Storage;
|
||||
void Add(AchievementCriteriaData const& data) { storage.push_back(data); }
|
||||
void Add(AchievementCriteriaData const& data) { _storage.push_back(data); }
|
||||
bool Meets(Player const* source, Unit const* target, uint32 miscvalue = 0) const;
|
||||
void SetCriteriaId(uint32 id) {criteria_id = id;}
|
||||
void SetCriteriaId(uint32 id) {_criteria_id = id;}
|
||||
private:
|
||||
uint32 criteria_id{0};
|
||||
Storage storage;
|
||||
uint32 _criteria_id{0};
|
||||
Storage _storage;
|
||||
};
|
||||
|
||||
typedef std::map<uint32, AchievementCriteriaDataSet> AchievementCriteriaDataMap;
|
||||
@@ -293,7 +293,7 @@ public:
|
||||
void SendAllAchievementData() const;
|
||||
void SendRespondInspectAchievements(Player* player) const;
|
||||
[[nodiscard]] bool HasAchieved(uint32 achievementId) const;
|
||||
[[nodiscard]] Player* GetPlayer() const { return m_player; }
|
||||
[[nodiscard]] Player* GetPlayer() const { return _player; }
|
||||
void UpdateTimedAchievements(uint32 timeDiff);
|
||||
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
|
||||
void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry); // used for quest and scripted timed achievements
|
||||
@@ -311,11 +311,11 @@ private:
|
||||
bool CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement);
|
||||
void BuildAllDataPacket(WorldPacket* data) const;
|
||||
|
||||
Player* m_player;
|
||||
CriteriaProgressMap m_criteriaProgress;
|
||||
CompletedAchievementMap m_completedAchievements;
|
||||
Player* _player;
|
||||
CriteriaProgressMap _criteriaProgress;
|
||||
CompletedAchievementMap _completedAchievements;
|
||||
typedef std::map<uint32, uint32> TimedAchievementMap;
|
||||
TimedAchievementMap m_timedAchievements; // Criteria id/time left in MS
|
||||
TimedAchievementMap _timedAchievements; // Criteria id/time left in MS
|
||||
};
|
||||
|
||||
class AchievementGlobalMgr
|
||||
@@ -327,60 +327,60 @@ public:
|
||||
static AchievementGlobalMgr* instance();
|
||||
|
||||
bool IsStatisticCriteria(AchievementCriteriaEntry const* achievementCriteria) const;
|
||||
bool isStatisticAchievement(AchievementEntry const* achievement) const;
|
||||
bool IsStatisticAchievement(AchievementEntry const* achievement) const;
|
||||
|
||||
[[nodiscard]] AchievementCriteriaEntryList const* GetAchievementCriteriaByType(AchievementCriteriaTypes type) const
|
||||
{
|
||||
return &m_AchievementCriteriasByType[type];
|
||||
return &_achievementCriteriasByType[type];
|
||||
}
|
||||
|
||||
AchievementCriteriaEntryList const* GetSpecialAchievementCriteriaByType(AchievementCriteriaTypes type, uint32 val)
|
||||
{
|
||||
if (m_SpecialList[type].find(val) != m_SpecialList[type].end())
|
||||
return &m_SpecialList[type][val];
|
||||
if (_specialList[type].find(val) != _specialList[type].end())
|
||||
return &_specialList[type][val];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AchievementCriteriaEntryList const* GetAchievementCriteriaByCondition(AchievementCriteriaCondition condition, uint32 val)
|
||||
{
|
||||
if (m_AchievementCriteriasByCondition[condition].find(val) != m_AchievementCriteriasByCondition[condition].end())
|
||||
return &m_AchievementCriteriasByCondition[condition][val];
|
||||
if (_achievementCriteriasByCondition[condition].find(val) != _achievementCriteriasByCondition[condition].end())
|
||||
return &_achievementCriteriasByCondition[condition][val];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] AchievementCriteriaEntryList const& GetTimedAchievementCriteriaByType(AchievementCriteriaTimedTypes type) const
|
||||
{
|
||||
return m_AchievementCriteriasByTimedType[type];
|
||||
return _achievementCriteriasByTimedType[type];
|
||||
}
|
||||
|
||||
[[nodiscard]] AchievementCriteriaEntryList const* GetAchievementCriteriaByAchievement(uint32 id) const
|
||||
{
|
||||
AchievementCriteriaListByAchievement::const_iterator itr = m_AchievementCriteriaListByAchievement.find(id);
|
||||
return itr != m_AchievementCriteriaListByAchievement.end() ? &itr->second : nullptr;
|
||||
AchievementCriteriaListByAchievement::const_iterator itr = _achievementCriteriaListByAchievement.find(id);
|
||||
return itr != _achievementCriteriaListByAchievement.end() ? &itr->second : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] AchievementEntryList const* GetAchievementByReferencedId(uint32 id) const
|
||||
{
|
||||
AchievementListByReferencedId::const_iterator itr = m_AchievementListByReferencedId.find(id);
|
||||
return itr != m_AchievementListByReferencedId.end() ? &itr->second : nullptr;
|
||||
AchievementListByReferencedId::const_iterator itr = _achievementListByReferencedId.find(id);
|
||||
return itr != _achievementListByReferencedId.end() ? &itr->second : nullptr;
|
||||
}
|
||||
|
||||
AchievementReward const* GetAchievementReward(AchievementEntry const* achievement) const
|
||||
{
|
||||
AchievementRewards::const_iterator iter = m_achievementRewards.find(achievement->ID);
|
||||
return iter != m_achievementRewards.end() ? &iter->second : nullptr;
|
||||
AchievementRewards::const_iterator iter = _achievementRewards.find(achievement->ID);
|
||||
return iter != _achievementRewards.end() ? &iter->second : nullptr;
|
||||
}
|
||||
|
||||
AchievementRewardLocale const* GetAchievementRewardLocale(AchievementEntry const* achievement) const
|
||||
{
|
||||
AchievementRewardLocales::const_iterator iter = m_achievementRewardLocales.find(achievement->ID);
|
||||
return iter != m_achievementRewardLocales.end() ? &iter->second : nullptr;
|
||||
AchievementRewardLocales::const_iterator iter = _achievementRewardLocales.find(achievement->ID);
|
||||
return iter != _achievementRewardLocales.end() ? &iter->second : nullptr;
|
||||
}
|
||||
|
||||
AchievementCriteriaDataSet const* GetCriteriaDataSet(AchievementCriteriaEntry const* achievementCriteria) const
|
||||
{
|
||||
AchievementCriteriaDataMap::const_iterator iter = m_criteriaDataMap.find(achievementCriteria->ID);
|
||||
return iter != m_criteriaDataMap.end() ? &iter->second : nullptr;
|
||||
AchievementCriteriaDataMap::const_iterator iter = _criteriaDataMap.find(achievementCriteria->ID);
|
||||
return iter != _criteriaDataMap.end() ? &iter->second : nullptr;
|
||||
}
|
||||
|
||||
bool IsRealmCompleted(AchievementEntry const* achievement) const;
|
||||
@@ -396,25 +396,25 @@ public:
|
||||
[[nodiscard]] AchievementEntry const* GetAchievement(uint32 achievementId) const;
|
||||
|
||||
private:
|
||||
AchievementCriteriaDataMap m_criteriaDataMap;
|
||||
AchievementCriteriaDataMap _criteriaDataMap;
|
||||
|
||||
// store achievement criterias by type to speed up lookup
|
||||
AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
|
||||
AchievementCriteriaEntryList m_AchievementCriteriasByTimedType[ACHIEVEMENT_TIMED_TYPE_MAX];
|
||||
AchievementCriteriaEntryList _achievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
|
||||
AchievementCriteriaEntryList _achievementCriteriasByTimedType[ACHIEVEMENT_TIMED_TYPE_MAX];
|
||||
// store achievement criterias by achievement to speed up lookup
|
||||
AchievementCriteriaListByAchievement m_AchievementCriteriaListByAchievement;
|
||||
AchievementCriteriaListByAchievement _achievementCriteriaListByAchievement;
|
||||
// store achievements by referenced achievement id to speed up lookup
|
||||
AchievementListByReferencedId m_AchievementListByReferencedId;
|
||||
AchievementListByReferencedId _achievementListByReferencedId;
|
||||
|
||||
typedef std::unordered_map<uint32 /*achievementId*/, SystemTimePoint /*completionTime*/> AllCompletedAchievements;
|
||||
AllCompletedAchievements m_allCompletedAchievements;
|
||||
AllCompletedAchievements _allCompletedAchievements;
|
||||
|
||||
AchievementRewards m_achievementRewards;
|
||||
AchievementRewardLocales m_achievementRewardLocales;
|
||||
AchievementRewards _achievementRewards;
|
||||
AchievementRewardLocales _achievementRewardLocales;
|
||||
|
||||
// pussywizard:
|
||||
std::map<uint32, AchievementCriteriaEntryList> m_SpecialList[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
|
||||
std::map<uint32, AchievementCriteriaEntryList> m_AchievementCriteriasByCondition[ACHIEVEMENT_CRITERIA_CONDITION_TOTAL];
|
||||
std::map<uint32, AchievementCriteriaEntryList> _specialList[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
|
||||
std::map<uint32, AchievementCriteriaEntryList> _achievementCriteriasByCondition[ACHIEVEMENT_CRITERIA_CONDITION_TOTAL];
|
||||
};
|
||||
|
||||
#define sAchievementMgr AchievementGlobalMgr::instance()
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
#include "AddonMgr.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "CryptoHash.h"
|
||||
#include "Log.h"
|
||||
#include "Timer.h"
|
||||
#include <list>
|
||||
#include <openssl/md5.h>
|
||||
|
||||
namespace AddonMgr
|
||||
{
|
||||
@@ -66,6 +66,7 @@ namespace AddonMgr
|
||||
|
||||
oldMSTime = getMSTime();
|
||||
result = CharacterDatabase.Query("SELECT id, name, version, UNIX_TIMESTAMP(timestamp) FROM banned_addons");
|
||||
|
||||
if (result)
|
||||
{
|
||||
uint32 count2 = 0;
|
||||
@@ -78,14 +79,10 @@ namespace AddonMgr
|
||||
BannedAddon addon{};
|
||||
addon.Id = fields[0].Get<uint32>() + offset;
|
||||
addon.Timestamp = uint32(fields[3].Get<uint64>());
|
||||
addon.NameMD5 = Acore::Crypto::MD5::GetDigestOf(fields[1].Get<std::string>());
|
||||
addon.VersionMD5 = Acore::Crypto::MD5::GetDigestOf(fields[2].Get<std::string>());
|
||||
|
||||
std::string name = fields[1].Get<std::string>();
|
||||
std::string version = fields[2].Get<std::string>();
|
||||
|
||||
MD5(reinterpret_cast<uint8 const*>(name.c_str()), name.length(), addon.NameMD5);
|
||||
MD5(reinterpret_cast<uint8 const*>(version.c_str()), version.length(), addon.VersionMD5);
|
||||
|
||||
m_bannedAddons.push_back(addon);
|
||||
m_bannedAddons.emplace_back(addon);
|
||||
|
||||
++count2;
|
||||
} while (result->NextRow());
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define _ADDONMGR_H
|
||||
|
||||
#include "Define.h"
|
||||
#include <array>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -49,8 +50,8 @@ struct SavedAddon
|
||||
struct BannedAddon
|
||||
{
|
||||
uint32 Id;
|
||||
uint8 NameMD5[16];
|
||||
uint8 VersionMD5[16];
|
||||
std::array<uint8, 16> NameMD5;
|
||||
std::array<uint8, 16> VersionMD5;
|
||||
uint32 Timestamp;
|
||||
};
|
||||
|
||||
|
||||
@@ -225,6 +225,9 @@ public:
|
||||
[[nodiscard]] bool isThreatListEmpty() const { return iThreatContainer.empty(); }
|
||||
[[nodiscard]] bool areThreatListsEmpty() const { return iThreatContainer.empty() && iThreatOfflineContainer.empty(); }
|
||||
|
||||
Acore::IteratorPair<std::list<ThreatReference*>::const_iterator> GetSortedThreatList() const { auto& list = iThreatContainer.GetThreatList(); return { list.cbegin(), list.cend() }; }
|
||||
Acore::IteratorPair<std::list<ThreatReference*>::const_iterator> GetUnsortedThreatList() const { return GetSortedThreatList(); }
|
||||
|
||||
void processThreatEvent(ThreatRefStatusChangeEvent* threatRefStatusChangeEvent);
|
||||
|
||||
bool isNeedUpdateToClient(uint32 time);
|
||||
|
||||
@@ -768,21 +768,24 @@ uint32 Condition::GetMaxAvailableConditionTargets()
|
||||
// returns number of targets which are available for given source type
|
||||
switch (SourceType)
|
||||
{
|
||||
case CONDITION_SOURCE_TYPE_SMART_EVENT:
|
||||
return 3;
|
||||
case CONDITION_SOURCE_TYPE_SPELL:
|
||||
case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
|
||||
case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE:
|
||||
case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
|
||||
case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
|
||||
case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
|
||||
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
|
||||
case CONDITION_SOURCE_TYPE_NPC_VENDOR:
|
||||
case CONDITION_SOURCE_TYPE_SPELL_PROC:
|
||||
return 2;
|
||||
default:
|
||||
return 1;
|
||||
case CONDITION_SOURCE_TYPE_SMART_EVENT:
|
||||
return 3;
|
||||
case CONDITION_SOURCE_TYPE_SPELL:
|
||||
case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
|
||||
case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE:
|
||||
case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
|
||||
case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
|
||||
case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
|
||||
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
|
||||
case CONDITION_SOURCE_TYPE_NPC_VENDOR:
|
||||
case CONDITION_SOURCE_TYPE_SPELL_PROC:
|
||||
case CONDITION_SOURCE_TYPE_CREATURE_VISIBILITY:
|
||||
return 2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ConditionMgr::ConditionMgr() {}
|
||||
|
||||
@@ -52,6 +52,7 @@ GameObject::GameObject() : WorldObject(false), MovableMapObject(),
|
||||
m_respawnDelayTime = 300;
|
||||
m_despawnDelay = 0;
|
||||
m_despawnRespawnTime = 0s;
|
||||
m_restockTime = 0s;
|
||||
m_lootState = GO_NOT_READY;
|
||||
m_spawnedByDefault = true;
|
||||
m_allowModifyDestructibleBuilding = true;
|
||||
@@ -585,6 +586,16 @@ void GameObject::Update(uint32 diff)
|
||||
spellCaster->CastSpell(spellCaster, spellId, triggered);
|
||||
return;
|
||||
}
|
||||
case GAMEOBJECT_TYPE_CHEST:
|
||||
if (m_restockTime > GameTime::GetGameTime())
|
||||
{
|
||||
return;
|
||||
}
|
||||
// If there is no restock timer, or if the restock timer passed, the chest becomes ready to loot
|
||||
m_restockTime = 0s;
|
||||
m_lootState = GO_READY;
|
||||
AddToObjectUpdateIfNeeded();
|
||||
break;
|
||||
default:
|
||||
m_lootState = GO_READY; // for other GOis same switched without delay to GO_READY
|
||||
break;
|
||||
@@ -768,6 +779,14 @@ void GameObject::Update(uint32 diff)
|
||||
m_groupLootTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
// Non-consumable chest was partially looted and restock time passed, restock all loot now
|
||||
if (GetGOInfo()->chest.consumable == 0 && GameTime::GetGameTime() >= m_restockTime)
|
||||
{
|
||||
m_restockTime = 0s;
|
||||
m_lootState = GO_READY;
|
||||
AddToObjectUpdateIfNeeded();
|
||||
}
|
||||
break;
|
||||
case GAMEOBJECT_TYPE_TRAP:
|
||||
{
|
||||
@@ -826,21 +845,29 @@ void GameObject::Update(uint32 diff)
|
||||
|
||||
loot.clear();
|
||||
|
||||
//! If this is summoned by a spell with ie. SPELL_EFFECT_SUMMON_OBJECT_WILD, with or without owner, we check respawn criteria based on spell
|
||||
//! The GetOwnerGUID() check is mostly for compatibility with hacky scripts - 99% of the time summoning should be done trough spells.
|
||||
if (GetSpellId() || GetOwnerGUID())
|
||||
// Do not delete chests or goobers that are not consumed on loot, while still allowing them to despawn when they expire if summoned
|
||||
bool isSummonedAndExpired = (GetOwner() || GetSpellId()) && m_respawnTime == 0;
|
||||
if ((GetGoType() == GAMEOBJECT_TYPE_CHEST || GetGoType() == GAMEOBJECT_TYPE_GOOBER) && !GetGOInfo()->IsDespawnAtAction() && !isSummonedAndExpired)
|
||||
{
|
||||
//Don't delete spell spawned chests, which are not consumed on loot
|
||||
if (m_respawnTime > 0 && GetGoType() == GAMEOBJECT_TYPE_CHEST && !GetGOInfo()->IsDespawnAtAction())
|
||||
if (GetGoType() == GAMEOBJECT_TYPE_CHEST && GetGOInfo()->chest.chestRestockTime > 0)
|
||||
{
|
||||
UpdateObjectVisibility();
|
||||
SetLootState(GO_READY);
|
||||
// Start restock timer when the chest is fully looted
|
||||
m_restockTime = GameTime::GetGameTime() + Seconds(GetGOInfo()->chest.chestRestockTime);
|
||||
SetLootState(GO_NOT_READY);
|
||||
AddToObjectUpdateIfNeeded();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetRespawnTime(0);
|
||||
Delete();
|
||||
SetLootState(GO_READY);
|
||||
}
|
||||
|
||||
UpdateObjectVisibility();
|
||||
return;
|
||||
}
|
||||
else if (GetOwnerGUID() || GetSpellId())
|
||||
{
|
||||
SetRespawnTime(0);
|
||||
Delete();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2422,6 +2449,13 @@ void GameObject::SetLootState(LootState state, Unit* unit)
|
||||
|
||||
AI()->OnStateChanged(state, unit);
|
||||
sScriptMgr->OnGameObjectLootStateChanged(this, state, unit);
|
||||
|
||||
// Start restock timer if the chest is partially looted or not looted at all
|
||||
if (GetGoType() == GAMEOBJECT_TYPE_CHEST && state == GO_ACTIVATED && GetGOInfo()->chest.chestRestockTime > 0 && m_restockTime == 0s)
|
||||
{
|
||||
m_restockTime = GameTime::GetGameTime() + Seconds(GetGOInfo()->chest.chestRestockTime);
|
||||
}
|
||||
|
||||
// pussywizard: lootState has nothing to do with collision, it depends entirely on GOState. Loot state is for timed close/open door and respawning, which then sets GOState
|
||||
/*if (m_model)
|
||||
{
|
||||
|
||||
@@ -1072,9 +1072,10 @@ protected:
|
||||
uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer
|
||||
uint32 m_despawnDelay;
|
||||
Seconds m_despawnRespawnTime; // override respawn time after delayed despawn
|
||||
Seconds m_restockTime;
|
||||
LootState m_lootState;
|
||||
bool m_spawnedByDefault;
|
||||
uint32 m_cooldownTime; // used as internal reaction delay time store (not state change reaction).
|
||||
uint32 m_cooldownTime; // used as internal reaction delay time store (not state change reaction).
|
||||
// For traps this: spell casting cooldown, for doors/buttons: reset time.
|
||||
std::unordered_map<ObjectGuid, int32> m_SkillupList;
|
||||
|
||||
|
||||
@@ -1737,7 +1737,7 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
|
||||
// Creature scripts
|
||||
if (Creature const* cObj = obj->ToCreature())
|
||||
{
|
||||
if (Player const* player = this->ToPlayer())
|
||||
if (Player const* player = ToPlayer())
|
||||
{
|
||||
if (cObj->IsAIEnabled && !cObj->AI()->CanBeSeen(player))
|
||||
{
|
||||
@@ -1745,8 +1745,7 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
|
||||
}
|
||||
|
||||
ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_VISIBILITY, cObj->GetEntry());
|
||||
|
||||
if (!sConditionMgr->IsObjectMeetToConditions((WorldObject*)this, conditions))
|
||||
if (!sConditionMgr->IsObjectMeetToConditions((WorldObject*)this, (WorldObject*)obj, conditions))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1755,8 +1754,12 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
|
||||
|
||||
// Gameobject scripts
|
||||
if (GameObject const* goObj = obj->ToGameObject())
|
||||
if (this->ToPlayer() && !goObj->AI()->CanBeSeen(this->ToPlayer()))
|
||||
{
|
||||
if (ToPlayer() && !goObj->AI()->CanBeSeen(ToPlayer()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// pussywizard: arena spectator
|
||||
if (obj->GetTypeId() == TYPEID_PLAYER)
|
||||
|
||||
@@ -1316,7 +1316,7 @@ public:
|
||||
void DestroyZoneLimitedItem(bool update, uint32 new_zone);
|
||||
void SplitItem(uint16 src, uint16 dst, uint32 count);
|
||||
void SwapItem(uint16 src, uint16 dst);
|
||||
void AddItemToBuyBackSlot(Item* pItem);
|
||||
void AddItemToBuyBackSlot(Item* pItem, uint32 money);
|
||||
Item* GetItemFromBuyBackSlot(uint32 slot);
|
||||
void RemoveItemFromBuyBackSlot(uint32 slot, bool del);
|
||||
[[nodiscard]] uint32 GetMaxKeyringSize() const { return KEYRING_SLOT_END - KEYRING_SLOT_START; }
|
||||
|
||||
@@ -3961,7 +3961,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
|
||||
AutoUnequipOffhandIfNeed();
|
||||
}
|
||||
|
||||
void Player::AddItemToBuyBackSlot(Item* pItem)
|
||||
void Player::AddItemToBuyBackSlot(Item* pItem, uint32 money)
|
||||
{
|
||||
if (pItem)
|
||||
{
|
||||
@@ -4003,10 +4003,7 @@ void Player::AddItemToBuyBackSlot(Item* pItem)
|
||||
uint32 eslot = slot - BUYBACK_SLOT_START;
|
||||
|
||||
SetGuidValue(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (eslot * 2), pItem->GetGUID());
|
||||
if (ItemTemplate const* proto = pItem->GetTemplate())
|
||||
SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, proto->SellPrice * pItem->GetCount());
|
||||
else
|
||||
SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, 0);
|
||||
SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, money);
|
||||
SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + eslot, (uint32)etime);
|
||||
|
||||
// move to next (for non filled list is move most optimized choice)
|
||||
|
||||
@@ -1763,28 +1763,33 @@ void Player::UpdateForQuestWorldObjects()
|
||||
continue;
|
||||
|
||||
// check if this unit requires quest specific flags
|
||||
if (!obj->HasNpcFlag(UNIT_NPC_FLAG_SPELLCLICK))
|
||||
continue;
|
||||
|
||||
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(obj->GetEntry());
|
||||
for (SpellClickInfoContainer::const_iterator _itr = clickPair.first; _itr != clickPair.second; ++_itr)
|
||||
if (obj->HasNpcFlag(UNIT_NPC_FLAG_SPELLCLICK))
|
||||
{
|
||||
//! This code doesn't look right, but it was logically converted to condition system to do the exact
|
||||
//! same thing it did before. It definitely needs to be overlooked for intended functionality.
|
||||
ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(obj->GetEntry(), _itr->second.spellId);
|
||||
bool buildUpdateBlock = false;
|
||||
for (ConditionList::const_iterator jtr = conds.begin(); jtr != conds.end() && !buildUpdateBlock; ++jtr)
|
||||
if ((*jtr)->ConditionType == CONDITION_QUESTREWARDED || (*jtr)->ConditionType == CONDITION_QUESTTAKEN)
|
||||
buildUpdateBlock = true;
|
||||
|
||||
if (buildUpdateBlock)
|
||||
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(obj->GetEntry());
|
||||
for (SpellClickInfoContainer::const_iterator _itr = clickPair.first; _itr != clickPair.second; ++_itr)
|
||||
{
|
||||
obj->BuildValuesUpdateBlockForPlayer(&udata, this);
|
||||
break;
|
||||
//! This code doesn't look right, but it was logically converted to condition system to do the exact
|
||||
//! same thing it did before. It definitely needs to be overlooked for intended functionality.
|
||||
ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(obj->GetEntry(), _itr->second.spellId);
|
||||
bool buildUpdateBlock = false;
|
||||
for (ConditionList::const_iterator jtr = conds.begin(); jtr != conds.end() && !buildUpdateBlock; ++jtr)
|
||||
if ((*jtr)->ConditionType == CONDITION_QUESTREWARDED || (*jtr)->ConditionType == CONDITION_QUESTTAKEN)
|
||||
buildUpdateBlock = true;
|
||||
|
||||
if (buildUpdateBlock)
|
||||
{
|
||||
obj->BuildValuesUpdateBlockForPlayer(&udata, this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (obj->HasNpcFlag(UNIT_NPC_FLAG_VENDOR_MASK | UNIT_NPC_FLAG_TRAINER))
|
||||
{
|
||||
obj->BuildValuesUpdateBlockForPlayer(&udata, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
udata.BuildPacket(&packet);
|
||||
GetSession()->SendPacket(&packet);
|
||||
}
|
||||
|
||||
@@ -1031,7 +1031,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
||||
if (!attacker || attacker->IsControlledByPlayer() || attacker->IsCreatedByPlayer())
|
||||
{
|
||||
uint32 unDamage = health < damage ? health : damage;
|
||||
bool damagedByPlayer = unDamage && attacker && attacker->m_movedByPlayer != nullptr;
|
||||
bool damagedByPlayer = unDamage && attacker && (attacker->IsPlayer() || attacker->m_movedByPlayer != nullptr);
|
||||
victim->ToCreature()->LowerPlayerDamageReq(unDamage, damagedByPlayer);
|
||||
}
|
||||
}
|
||||
@@ -18215,6 +18215,11 @@ void Unit::SetControlled(bool apply, UnitState state)
|
||||
|
||||
void Unit::SetStunned(bool apply)
|
||||
{
|
||||
if (HasUnitState(UNIT_STATE_IN_FLIGHT))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (apply)
|
||||
{
|
||||
SetTarget();
|
||||
|
||||
@@ -2303,7 +2303,7 @@ public:
|
||||
void SendPetAIReaction(ObjectGuid guid);
|
||||
///----------End of Pet responses methods----------
|
||||
|
||||
void propagateSpeedChange() { GetMotionMaster()->propagateSpeedChange(); }
|
||||
void propagateSpeedChange() { GetMotionMaster()->PropagateSpeedChange(); }
|
||||
|
||||
// reactive attacks
|
||||
void ClearAllReactives();
|
||||
|
||||
@@ -818,6 +818,51 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
|
||||
if (sWorld->getBoolConfig(CONFIG_ITEMDELETE_VENDOR))
|
||||
recoveryItem(pItem);
|
||||
|
||||
uint32 maxDurability = pItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY);
|
||||
if (maxDurability)
|
||||
{
|
||||
uint32 curDurability = pItem->GetUInt32Value(ITEM_FIELD_DURABILITY);
|
||||
uint32 LostDurability = maxDurability - curDurability;
|
||||
|
||||
if (LostDurability > 0)
|
||||
{
|
||||
DurabilityCostsEntry const* dcost = sDurabilityCostsStore.LookupEntry(pProto->ItemLevel);
|
||||
if (!dcost)
|
||||
{
|
||||
_player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
|
||||
LOG_ERROR("network.opcode", "WORLD: HandleSellItemOpcode - Wrong item lvl {} for item {} count = {}", pProto->ItemLevel, pItem->GetEntry(), count);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 dQualitymodEntryId = (pProto->Quality + 1) * 2;
|
||||
DurabilityQualityEntry const* dQualitymodEntry = sDurabilityQualityStore.LookupEntry(dQualitymodEntryId);
|
||||
if (!dQualitymodEntry)
|
||||
{
|
||||
_player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
|
||||
LOG_ERROR("network.opcode", "WORLD: HandleSellItemOpcode - Wrong dQualityModEntry {} for item {} count = {}", dQualitymodEntryId, pItem->GetEntry(), count);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 dmultiplier = dcost->multiplier[ItemSubClassToDurabilityMultiplierId(pProto->Class, pProto->SubClass)];
|
||||
uint32 refund = uint32(std::ceil(LostDurability * dmultiplier * double(dQualitymodEntry->quality_mod)));
|
||||
|
||||
if (!refund)
|
||||
{
|
||||
refund = 1;
|
||||
}
|
||||
|
||||
//starter items can cost more to refund than vendorprice
|
||||
if (refund > money)
|
||||
{
|
||||
money = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
money -= refund;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count < pItem->GetCount()) // need split items
|
||||
{
|
||||
Item* pNewItem = pItem->CloneItem(count, _player);
|
||||
@@ -828,13 +873,15 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
pNewItem->SetUInt32Value(ITEM_FIELD_DURABILITY, pItem->GetUInt32Value(ITEM_FIELD_DURABILITY));
|
||||
|
||||
pItem->SetCount(pItem->GetCount() - count);
|
||||
_player->ItemRemovedQuestCheck(pItem->GetEntry(), count);
|
||||
if (_player->IsInWorld())
|
||||
pItem->SendUpdateToPlayer(_player);
|
||||
pItem->SetState(ITEM_CHANGED, _player);
|
||||
|
||||
_player->AddItemToBuyBackSlot(pNewItem);
|
||||
_player->AddItemToBuyBackSlot(pNewItem, money);
|
||||
if (_player->IsInWorld())
|
||||
pNewItem->SendUpdateToPlayer(_player);
|
||||
}
|
||||
@@ -843,7 +890,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
|
||||
_player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount());
|
||||
_player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
|
||||
pItem->RemoveFromUpdateQueueOf(_player);
|
||||
_player->AddItemToBuyBackSlot(pItem);
|
||||
_player->AddItemToBuyBackSlot(pItem, money);
|
||||
_player->UpdateTitansGrip();
|
||||
}
|
||||
|
||||
|
||||
@@ -405,7 +405,7 @@ LootItem::LootItem(LootStoreItem const& li)
|
||||
}
|
||||
|
||||
// Basic checks for player/item compatibility - if false no chance to see the item in the loot
|
||||
bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter /*= false*/, bool allowQuestLoot /*= true*/, ObjectGuid source) const
|
||||
bool LootItem::AllowedForPlayer(Player const* player, ObjectGuid source) const
|
||||
{
|
||||
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid);
|
||||
if (!pProto)
|
||||
@@ -419,7 +419,7 @@ bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter
|
||||
if (!sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(player), conditions))
|
||||
{
|
||||
// Master Looter can see conditioned recipes
|
||||
if (!isGivenByMasterLooter && isMasterLooter)
|
||||
if (isMasterLooter && follow_loot_rules && !is_underthreshold)
|
||||
{
|
||||
if ((pProto->Flags & ITEM_FLAG_HIDE_UNUSABLE_RECIPE) || (pProto->Class == ITEM_CLASS_RECIPE && pProto->Bonding == BIND_WHEN_PICKED_UP && pProto->Spells[1].SpellId != 0))
|
||||
{
|
||||
@@ -442,7 +442,7 @@ bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter
|
||||
}
|
||||
|
||||
// Master looter can see all items even if the character can't loot them
|
||||
if (!isGivenByMasterLooter && isMasterLooter && allowQuestLoot)
|
||||
if (isMasterLooter && follow_loot_rules && !is_underthreshold)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -661,26 +661,35 @@ QuestItemList* Loot::FillQuestLoot(Player* player)
|
||||
|
||||
QuestItemList* ql = new QuestItemList();
|
||||
|
||||
Player* lootOwner = (roundRobinPlayer) ? ObjectAccessor::FindPlayer(roundRobinPlayer) : player;
|
||||
|
||||
for (uint8 i = 0; i < quest_items.size(); ++i)
|
||||
{
|
||||
LootItem& item = quest_items[i];
|
||||
|
||||
if (!item.is_looted && (item.AllowedForPlayer(player, false, false) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT ))))
|
||||
// Quest item is not free for all and is already assigned to another player
|
||||
// or player doesn't need it
|
||||
if (item.is_blocked || !item.AllowedForPlayer(player, sourceWorldObjectGUID))
|
||||
{
|
||||
ql->push_back(QuestItem(i));
|
||||
|
||||
// quest items get blocked when they first appear in a
|
||||
// player's quest vector
|
||||
//
|
||||
// increase once if one looter only, looter-times if free for all
|
||||
if (item.freeforall || !item.is_blocked)
|
||||
++unlootedCount;
|
||||
if (!player->GetGroup() || (player->GetGroup()->GetLootMethod() != GROUP_LOOT && player->GetGroup()->GetLootMethod() != ROUND_ROBIN))
|
||||
item.is_blocked = true;
|
||||
|
||||
if (items.size() + ql->size() == MAX_NR_LOOT_ITEMS)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Player is not the loot owner, and loot owner still needs this quest item
|
||||
if (!item.freeforall && lootOwner != player && item.AllowedForPlayer(lootOwner, sourceWorldObjectGUID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ql->push_back(QuestItem(i));
|
||||
++unlootedCount;
|
||||
|
||||
if (!item.freeforall)
|
||||
{
|
||||
item.is_blocked = true;
|
||||
}
|
||||
|
||||
if (items.size() + ql->size() == MAX_NR_LOOT_ITEMS)
|
||||
break;
|
||||
}
|
||||
if (ql->empty())
|
||||
{
|
||||
@@ -699,7 +708,8 @@ QuestItemList* Loot::FillNonQuestNonFFAConditionalLoot(Player* player)
|
||||
for (uint8 i = 0; i < items.size(); ++i)
|
||||
{
|
||||
LootItem& item = items[i];
|
||||
if (!item.is_looted && !item.freeforall && (item.AllowedForPlayer(player, sourceWorldObjectGUID) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT ))))
|
||||
|
||||
if (!item.is_looted && !item.freeforall && item.AllowedForPlayer(player, sourceWorldObjectGUID))
|
||||
{
|
||||
item.AddAllowedLooter(player);
|
||||
|
||||
|
||||
@@ -177,8 +177,7 @@ struct LootItem
|
||||
LootItem() = default;
|
||||
|
||||
// Basic checks for player/item compatibility - if false no chance to see the item in the loot
|
||||
bool AllowedForPlayer(Player const* player, bool isGivenByMasterLooter = false, bool allowQuestLoot = true, ObjectGuid source = ObjectGuid::Empty) const;
|
||||
bool AllowedForPlayer(Player const* player, ObjectGuid source) { return AllowedForPlayer(player, false, true, source); };
|
||||
bool AllowedForPlayer(Player const* player, ObjectGuid source) const;
|
||||
void AddAllowedLooter(Player const* player);
|
||||
[[nodiscard]] const AllowedLooterSet& GetAllowedLooters() const { return allowedGUIDs; }
|
||||
};
|
||||
|
||||
@@ -791,7 +791,7 @@ void MotionMaster::MoveRotate(uint32 time, RotateDirection direction)
|
||||
Mutate(new RotateMovementGenerator(time, direction), MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
|
||||
void MotionMaster::propagateSpeedChange()
|
||||
void MotionMaster::PropagateSpeedChange()
|
||||
{
|
||||
/*Impl::container_type::iterator it = Impl::c.begin();
|
||||
for (; it != end(); ++it)
|
||||
@@ -801,7 +801,7 @@ void MotionMaster::propagateSpeedChange()
|
||||
for (int i = 0; i <= _top; ++i)
|
||||
{
|
||||
if (Impl[i])
|
||||
Impl[i]->unitSpeedChanged();
|
||||
Impl[i]->UnitSpeedChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ public:
|
||||
[[nodiscard]] MovementGeneratorType GetMotionSlotType(int slot) const;
|
||||
[[nodiscard]] uint32 GetCurrentSplineId() const; // Xinef: Escort system
|
||||
|
||||
void propagateSpeedChange();
|
||||
void PropagateSpeedChange();
|
||||
void ReinitializeMovement();
|
||||
|
||||
bool GetDestination(float& x, float& y, float& z);
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
virtual uint32 GetSplineId() const { return 0; } // Xinef: Escort system
|
||||
|
||||
virtual void unitSpeedChanged() { }
|
||||
virtual void UnitSpeedChanged() { }
|
||||
|
||||
// timer in ms
|
||||
virtual void Pause(uint32 /* timer = 0*/) {}
|
||||
|
||||
@@ -54,9 +54,9 @@ void ConfusedMovementGenerator<T>::DoInitialize(T* unit)
|
||||
float new_z = unit->GetMapHeight(wanderX, wanderY, z);
|
||||
if (new_z <= INVALID_HEIGHT || std::fabs(z - new_z) > 3.0f) // pussywizard
|
||||
{
|
||||
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx - 1][0] : x;
|
||||
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx - 1][1] : y;
|
||||
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx - 1][2] : z;
|
||||
_waypoints[idx][0] = idx > 0 ? _waypoints[idx - 1][0] : x;
|
||||
_waypoints[idx][1] = idx > 0 ? _waypoints[idx - 1][1] : y;
|
||||
_waypoints[idx][2] = idx > 0 ? _waypoints[idx - 1][2] : z;
|
||||
continue;
|
||||
}
|
||||
else if (unit->IsWithinLOS(wanderX, wanderY, z))
|
||||
@@ -66,32 +66,32 @@ void ConfusedMovementGenerator<T>::DoInitialize(T* unit)
|
||||
if ((is_water && !is_water_ok) || (!is_water && !is_land_ok))
|
||||
{
|
||||
//! Cannot use coordinates outside our InhabitType. Use the current or previous position.
|
||||
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx - 1][0] : x;
|
||||
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx - 1][1] : y;
|
||||
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx - 1][2] : z;
|
||||
_waypoints[idx][0] = idx > 0 ? _waypoints[idx - 1][0] : x;
|
||||
_waypoints[idx][1] = idx > 0 ? _waypoints[idx - 1][1] : y;
|
||||
_waypoints[idx][2] = idx > 0 ? _waypoints[idx - 1][2] : z;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//! Trying to access path outside line of sight. Skip this by using the current or previous position.
|
||||
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx - 1][0] : x;
|
||||
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx - 1][1] : y;
|
||||
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx - 1][2] : z;
|
||||
_waypoints[idx][0] = idx > 0 ? _waypoints[idx - 1][0] : x;
|
||||
_waypoints[idx][1] = idx > 0 ? _waypoints[idx - 1][1] : y;
|
||||
_waypoints[idx][2] = idx > 0 ? _waypoints[idx - 1][2] : z;
|
||||
continue;
|
||||
}
|
||||
|
||||
//unit->UpdateAllowedPositionZ(wanderX, wanderY, z);
|
||||
|
||||
//! Positions are fine - apply them to this waypoint
|
||||
i_waypoints[idx][0] = wanderX;
|
||||
i_waypoints[idx][1] = wanderY;
|
||||
i_waypoints[idx][2] = new_z;
|
||||
_waypoints[idx][0] = wanderX;
|
||||
_waypoints[idx][1] = wanderY;
|
||||
_waypoints[idx][2] = new_z;
|
||||
}
|
||||
|
||||
// Xinef: Call movement immediately to broadcast movement packet
|
||||
// Xinef: Initial timer is set to 1 so update with 1
|
||||
i_nextMove = urand(1, MAX_CONF_WAYPOINTS);
|
||||
_nextMove = urand(1, MAX_CONF_WAYPOINTS);
|
||||
DoUpdate(unit, 1);
|
||||
|
||||
unit->SetUnitFlag(UNIT_FLAG_CONFUSED);
|
||||
@@ -127,30 +127,30 @@ bool ConfusedMovementGenerator<T>::DoUpdate(T* unit, uint32 diff)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i_nextMoveTime.Passed())
|
||||
if (_nextMoveTime.Passed())
|
||||
{
|
||||
// currently moving, update location
|
||||
unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE);
|
||||
|
||||
if (unit->movespline->Finalized())
|
||||
{
|
||||
i_nextMove = urand(1, MAX_CONF_WAYPOINTS);
|
||||
i_nextMoveTime.Reset(urand(600, 1200)); // Guessed
|
||||
_nextMove = urand(1, MAX_CONF_WAYPOINTS);
|
||||
_nextMoveTime.Reset(urand(600, 1200)); // Guessed
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// waiting for next move
|
||||
i_nextMoveTime.Update(diff);
|
||||
if (i_nextMoveTime.Passed())
|
||||
_nextMoveTime.Update(diff);
|
||||
if (_nextMoveTime.Passed())
|
||||
{
|
||||
// start moving
|
||||
unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE);
|
||||
|
||||
ASSERT(i_nextMove <= MAX_CONF_WAYPOINTS);
|
||||
float x = i_waypoints[i_nextMove][0];
|
||||
float y = i_waypoints[i_nextMove][1];
|
||||
float z = i_waypoints[i_nextMove][2];
|
||||
ASSERT(_nextMove <= MAX_CONF_WAYPOINTS);
|
||||
float x = _waypoints[_nextMove][0];
|
||||
float y = _waypoints[_nextMove][1];
|
||||
float z = _waypoints[_nextMove][2];
|
||||
Movement::MoveSplineInit init(unit);
|
||||
init.MoveTo(x, y, z, true);
|
||||
init.Launch();
|
||||
|
||||
@@ -27,7 +27,7 @@ template<class T>
|
||||
class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
explicit ConfusedMovementGenerator() : i_nextMoveTime(1) {}
|
||||
explicit ConfusedMovementGenerator() : _nextMoveTime(1) {}
|
||||
|
||||
void DoInitialize(T*);
|
||||
void DoFinalize(T*);
|
||||
@@ -37,8 +37,8 @@ public:
|
||||
MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; }
|
||||
private:
|
||||
void _InitSpecific(T*, bool&, bool&);
|
||||
TimeTracker i_nextMoveTime;
|
||||
float i_waypoints[MAX_CONF_WAYPOINTS + 1][3];
|
||||
uint32 i_nextMove;
|
||||
TimeTracker _nextMoveTime;
|
||||
float _waypoints[MAX_CONF_WAYPOINTS + 1][3];
|
||||
uint32 _nextMove;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "MoveSpline.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "Player.h"
|
||||
#include "Unit.h"
|
||||
#include "World.h"
|
||||
|
||||
template<class T>
|
||||
@@ -31,13 +32,13 @@ void EscortMovementGenerator<T>::DoInitialize(T* unit)
|
||||
unit->StopMoving();
|
||||
|
||||
unit->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
|
||||
i_recalculateSpeed = false;
|
||||
_recalculateSpeed = false;
|
||||
Movement::MoveSplineInit init(unit);
|
||||
|
||||
if (m_precomputedPath.size() == 2) // xinef: simple case, just call move to
|
||||
init.MoveTo(m_precomputedPath[1].x, m_precomputedPath[1].y, m_precomputedPath[1].z, true);
|
||||
else if (m_precomputedPath.size())
|
||||
init.MovebyPath(m_precomputedPath);
|
||||
if (_precomputedPath.size() == 2) // xinef: simple case, just call move to
|
||||
init.MoveTo(_precomputedPath[1].x, _precomputedPath[1].y, _precomputedPath[1].z, true);
|
||||
else if (_precomputedPath.size())
|
||||
init.MovebyPath(_precomputedPath);
|
||||
|
||||
init.Launch();
|
||||
|
||||
@@ -60,26 +61,26 @@ bool EscortMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/)
|
||||
|
||||
bool arrived = unit->movespline->Finalized();
|
||||
|
||||
if (i_recalculateSpeed && !arrived)
|
||||
if (_recalculateSpeed && !arrived)
|
||||
{
|
||||
i_recalculateSpeed = false;
|
||||
_recalculateSpeed = false;
|
||||
Movement::MoveSplineInit init(unit);
|
||||
|
||||
// xinef: speed changed during path execution, calculate remaining path and launch it once more
|
||||
if (m_precomputedPath.size())
|
||||
if (_precomputedPath.size())
|
||||
{
|
||||
uint32 offset = std::min(uint32(unit->movespline->_currentSplineIdx()), uint32(m_precomputedPath.size()));
|
||||
Movement::PointsArray::iterator offsetItr = m_precomputedPath.begin();
|
||||
uint32 offset = std::min(uint32(unit->movespline->_currentSplineIdx()), uint32(_precomputedPath.size()));
|
||||
Movement::PointsArray::iterator offsetItr = _precomputedPath.begin();
|
||||
std::advance(offsetItr, offset);
|
||||
m_precomputedPath.erase(m_precomputedPath.begin(), offsetItr);
|
||||
_precomputedPath.erase(_precomputedPath.begin(), offsetItr);
|
||||
|
||||
// restore 0 element (current position)
|
||||
m_precomputedPath.insert(m_precomputedPath.begin(), G3D::Vector3(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ()));
|
||||
_precomputedPath.insert(_precomputedPath.begin(), G3D::Vector3(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ()));
|
||||
|
||||
if (m_precomputedPath.size() > 2)
|
||||
init.MovebyPath(m_precomputedPath);
|
||||
else if (m_precomputedPath.size() == 2)
|
||||
init.MoveTo(m_precomputedPath[1].x, m_precomputedPath[1].y, m_precomputedPath[1].z, true);
|
||||
if (_precomputedPath.size() > 2)
|
||||
init.MovebyPath(_precomputedPath);
|
||||
else if (_precomputedPath.size() == 2)
|
||||
init.MoveTo(_precomputedPath[1].x, _precomputedPath[1].y, _precomputedPath[1].z, true);
|
||||
}
|
||||
|
||||
init.Launch();
|
||||
|
||||
@@ -24,10 +24,10 @@ template<class T>
|
||||
class EscortMovementGenerator : public MovementGeneratorMedium< T, EscortMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
EscortMovementGenerator(Movement::PointsArray* _path = nullptr) : i_recalculateSpeed(false)
|
||||
EscortMovementGenerator(Movement::PointsArray* _path = nullptr) : _recalculateSpeed(false)
|
||||
{
|
||||
if (_path)
|
||||
m_precomputedPath = *_path;
|
||||
_precomputedPath = *_path;
|
||||
}
|
||||
|
||||
void DoInitialize(T*);
|
||||
@@ -35,15 +35,15 @@ public:
|
||||
void DoReset(T*);
|
||||
bool DoUpdate(T*, uint32);
|
||||
|
||||
void unitSpeedChanged() { i_recalculateSpeed = true; }
|
||||
void unitSpeedChanged() { _recalculateSpeed = true; }
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() { return ESCORT_MOTION_TYPE; }
|
||||
|
||||
uint32 GetSplineId() const { return _splineId; }
|
||||
|
||||
private:
|
||||
bool i_recalculateSpeed;
|
||||
Movement::PointsArray m_precomputedPath;
|
||||
bool _recalculateSpeed;
|
||||
Movement::PointsArray _precomputedPath;
|
||||
|
||||
uint32 _splineId;
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ void HomeMovementGenerator<Creature>::DoInitialize(Creature* owner)
|
||||
void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner)
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_EVADE);
|
||||
if (arrived)
|
||||
if (_arrived)
|
||||
{
|
||||
// Xinef: npc run by default
|
||||
//owner->SetWalk(true);
|
||||
@@ -68,15 +68,15 @@ void HomeMovementGenerator<Creature>::_setTargetLocation(Creature* owner)
|
||||
init.SetWalk(false);
|
||||
init.Launch();
|
||||
|
||||
arrived = false;
|
||||
_arrived = false;
|
||||
|
||||
owner->ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~(UNIT_STATE_POSSESSED | UNIT_STATE_EVADE | UNIT_STATE_IGNORE_PATHFINDING | UNIT_STATE_NO_ENVIRONMENT_UPD)));
|
||||
}
|
||||
|
||||
bool HomeMovementGenerator<Creature>::DoUpdate(Creature* owner, const uint32 /*time_diff*/)
|
||||
{
|
||||
arrived = owner->movespline->Finalized();
|
||||
if (arrived)
|
||||
_arrived = owner->movespline->Finalized();
|
||||
if (_arrived)
|
||||
return false;
|
||||
|
||||
if (i_recalculateTravel)
|
||||
|
||||
@@ -29,7 +29,7 @@ template <>
|
||||
class HomeMovementGenerator<Creature> : public MovementGeneratorMedium< Creature, HomeMovementGenerator<Creature> >
|
||||
{
|
||||
public:
|
||||
HomeMovementGenerator() : arrived(false), i_recalculateTravel(false) {}
|
||||
HomeMovementGenerator() : _arrived(false), i_recalculateTravel(false) {}
|
||||
~HomeMovementGenerator() {}
|
||||
|
||||
void DoInitialize(Creature*);
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
|
||||
private:
|
||||
void _setTargetLocation(Creature*);
|
||||
bool arrived : 1;
|
||||
bool _arrived : 1;
|
||||
bool i_recalculateTravel : 1;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -99,10 +99,10 @@ void DistractMovementGenerator::Finalize(Unit* owner)
|
||||
|
||||
bool DistractMovementGenerator::Update(Unit* owner, uint32 time_diff)
|
||||
{
|
||||
if (owner->IsInCombat() || time_diff > m_timer)
|
||||
if (owner->IsInCombat() || time_diff > _timer)
|
||||
return false;
|
||||
|
||||
m_timer -= time_diff;
|
||||
_timer -= time_diff;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ private:
|
||||
class DistractMovementGenerator : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
explicit DistractMovementGenerator(uint32 timer) : m_timer(timer) {}
|
||||
explicit DistractMovementGenerator(uint32 timer) : _timer(timer) {}
|
||||
|
||||
void Initialize(Unit*) override;
|
||||
void Finalize(Unit*) override;
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
MovementGeneratorType GetMovementGeneratorType() override { return DISTRACT_MOTION_TYPE; }
|
||||
|
||||
private:
|
||||
uint32 m_timer;
|
||||
uint32 _timer;
|
||||
};
|
||||
|
||||
class AssistanceDistractMovementGenerator : public DistractMovementGenerator
|
||||
|
||||
@@ -33,7 +33,7 @@ void PointMovementGenerator<T>::DoInitialize(T* unit)
|
||||
{
|
||||
// the next line is to ensure that a new spline is created in DoUpdate() once the unit is no longer rooted/stunned
|
||||
// todo: rename this flag to something more appropriate since it is set to true even without speed change now.
|
||||
i_recalculateSpeed = true;
|
||||
_recalculateSpeed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,48 +46,48 @@ void PointMovementGenerator<T>::DoInitialize(T* unit)
|
||||
unit->AddUnitState(UNIT_STATE_CHARGING);
|
||||
}
|
||||
|
||||
i_recalculateSpeed = false;
|
||||
_recalculateSpeed = false;
|
||||
Movement::MoveSplineInit init(unit);
|
||||
if (m_precomputedPath.size() > 2) // pussywizard: for charge
|
||||
init.MovebyPath(m_precomputedPath);
|
||||
if (_precomputedPath.size() > 2) // pussywizard: for charge
|
||||
init.MovebyPath(_precomputedPath);
|
||||
else if (_generatePath)
|
||||
{
|
||||
PathGenerator path(unit);
|
||||
bool result = path.CalculatePath(i_x, i_y, i_z, _forceDestination);
|
||||
bool result = path.CalculatePath(_x, _y, _z, _forceDestination);
|
||||
if (result && !(path.GetPathType() & PATHFIND_NOPATH) && path.GetPath().size() > 2)
|
||||
{
|
||||
m_precomputedPath = path.GetPath();
|
||||
init.MovebyPath(m_precomputedPath);
|
||||
_precomputedPath = path.GetPath();
|
||||
init.MovebyPath(_precomputedPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Xinef: fix strange client visual bug, moving on z coordinate only switches orientation by 180 degrees (visual only)
|
||||
if (G3D::fuzzyEq(unit->GetPositionX(), i_x) && G3D::fuzzyEq(unit->GetPositionY(), i_y))
|
||||
if (G3D::fuzzyEq(unit->GetPositionX(), _x) && G3D::fuzzyEq(unit->GetPositionY(), _y))
|
||||
{
|
||||
i_x += 0.2f * cos(unit->GetOrientation());
|
||||
i_y += 0.2f * std::sin(unit->GetOrientation());
|
||||
_x += 0.2f * cos(unit->GetOrientation());
|
||||
_y += 0.2f * std::sin(unit->GetOrientation());
|
||||
}
|
||||
|
||||
init.MoveTo(i_x, i_y, i_z, true);
|
||||
init.MoveTo(_x, _y, _z, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Xinef: fix strange client visual bug, moving on z coordinate only switches orientation by 180 degrees (visual only)
|
||||
if (G3D::fuzzyEq(unit->GetPositionX(), i_x) && G3D::fuzzyEq(unit->GetPositionY(), i_y))
|
||||
if (G3D::fuzzyEq(unit->GetPositionX(), _x) && G3D::fuzzyEq(unit->GetPositionY(), _y))
|
||||
{
|
||||
i_x += 0.2f * cos(unit->GetOrientation());
|
||||
i_y += 0.2f * std::sin(unit->GetOrientation());
|
||||
_x += 0.2f * cos(unit->GetOrientation());
|
||||
_y += 0.2f * std::sin(unit->GetOrientation());
|
||||
}
|
||||
|
||||
init.MoveTo(i_x, i_y, i_z, true);
|
||||
init.MoveTo(_x, _y, _z, true);
|
||||
}
|
||||
if (speed > 0.0f)
|
||||
init.SetVelocity(speed);
|
||||
|
||||
if (i_orientation > 0.0f)
|
||||
if (_orientation > 0.0f)
|
||||
{
|
||||
init.SetFacing(i_orientation);
|
||||
init.SetFacing(_orientation);
|
||||
}
|
||||
|
||||
init.Launch();
|
||||
@@ -117,35 +117,35 @@ bool PointMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/)
|
||||
|
||||
unit->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
if (id != EVENT_CHARGE_PREPATH && i_recalculateSpeed && !unit->movespline->Finalized())
|
||||
if (id != EVENT_CHARGE_PREPATH && _recalculateSpeed && !unit->movespline->Finalized())
|
||||
{
|
||||
i_recalculateSpeed = false;
|
||||
_recalculateSpeed = false;
|
||||
Movement::MoveSplineInit init(unit);
|
||||
|
||||
// xinef: speed changed during path execution, calculate remaining path and launch it once more
|
||||
if (m_precomputedPath.size())
|
||||
if (_precomputedPath.size())
|
||||
{
|
||||
uint32 offset = std::min(uint32(unit->movespline->_currentSplineIdx()), uint32(m_precomputedPath.size()));
|
||||
Movement::PointsArray::iterator offsetItr = m_precomputedPath.begin();
|
||||
uint32 offset = std::min(uint32(unit->movespline->_currentSplineIdx()), uint32(_precomputedPath.size()));
|
||||
Movement::PointsArray::iterator offsetItr = _precomputedPath.begin();
|
||||
std::advance(offsetItr, offset);
|
||||
m_precomputedPath.erase(m_precomputedPath.begin(), offsetItr);
|
||||
_precomputedPath.erase(_precomputedPath.begin(), offsetItr);
|
||||
|
||||
// restore 0 element (current position)
|
||||
m_precomputedPath.insert(m_precomputedPath.begin(), G3D::Vector3(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ()));
|
||||
_precomputedPath.insert(_precomputedPath.begin(), G3D::Vector3(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ()));
|
||||
|
||||
if (m_precomputedPath.size() > 2)
|
||||
init.MovebyPath(m_precomputedPath);
|
||||
else if (m_precomputedPath.size() == 2)
|
||||
init.MoveTo(m_precomputedPath[1].x, m_precomputedPath[1].y, m_precomputedPath[1].z, true);
|
||||
if (_precomputedPath.size() > 2)
|
||||
init.MovebyPath(_precomputedPath);
|
||||
else if (_precomputedPath.size() == 2)
|
||||
init.MoveTo(_precomputedPath[1].x, _precomputedPath[1].y, _precomputedPath[1].z, true);
|
||||
}
|
||||
else
|
||||
init.MoveTo(i_x, i_y, i_z, true);
|
||||
init.MoveTo(_x, _y, _z, true);
|
||||
if (speed > 0.0f) // Default value for point motion type is 0.0, if 0.0 spline will use GetSpeed on unit
|
||||
init.SetVelocity(speed);
|
||||
|
||||
if (i_orientation > 0.0f)
|
||||
if (_orientation > 0.0f)
|
||||
{
|
||||
init.SetFacing(i_orientation);
|
||||
init.SetFacing(_orientation);
|
||||
}
|
||||
|
||||
init.Launch();
|
||||
@@ -247,5 +247,5 @@ void EffectMovementGenerator::Finalize(Unit* unit)
|
||||
//}
|
||||
|
||||
if (unit->ToCreature()->AI())
|
||||
unit->ToCreature()->AI()->MovementInform(EFFECT_MOTION_TYPE, m_Id);
|
||||
unit->ToCreature()->AI()->MovementInform(EFFECT_MOTION_TYPE, _Id);
|
||||
}
|
||||
|
||||
@@ -27,11 +27,11 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG
|
||||
public:
|
||||
PointMovementGenerator(uint32 _id, float _x, float _y, float _z, float _speed = 0.0f, float orientation = 0.0f, const Movement::PointsArray* _path = nullptr,
|
||||
bool generatePath = false, bool forceDestination = false, ObjectGuid chargeTargetGUID = ObjectGuid::Empty)
|
||||
: id(_id), i_x(_x), i_y(_y), i_z(_z), speed(_speed), i_orientation(orientation), _generatePath(generatePath), _forceDestination(forceDestination),
|
||||
: id(_id), _x(_x), _y(_y), _z(_z), speed(_speed), _orientation(orientation), _generatePath(generatePath), _forceDestination(forceDestination),
|
||||
_chargeTargetGUID(chargeTargetGUID)
|
||||
{
|
||||
if (_path)
|
||||
m_precomputedPath = *_path;
|
||||
_precomputedPath = *_path;
|
||||
}
|
||||
|
||||
void DoInitialize(T*);
|
||||
@@ -41,18 +41,18 @@ public:
|
||||
|
||||
void MovementInform(T*);
|
||||
|
||||
void unitSpeedChanged() { i_recalculateSpeed = true; }
|
||||
void unitSpeedChanged() { _recalculateSpeed = true; }
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() { return POINT_MOTION_TYPE; }
|
||||
|
||||
bool GetDestination(float& x, float& y, float& z) const { x = i_x; y = i_y; z = i_z; return true; }
|
||||
bool GetDestination(float& x, float& y, float& z) const { x = _x; y = _y; z = _z; return true; }
|
||||
private:
|
||||
uint32 id;
|
||||
float i_x, i_y, i_z;
|
||||
float _x, _y, _z;
|
||||
float speed;
|
||||
float i_orientation;
|
||||
bool i_recalculateSpeed;
|
||||
Movement::PointsArray m_precomputedPath;
|
||||
float _orientation;
|
||||
bool _recalculateSpeed;
|
||||
Movement::PointsArray _precomputedPath;
|
||||
bool _generatePath;
|
||||
bool _forceDestination;
|
||||
ObjectGuid _chargeTargetGUID;
|
||||
@@ -72,14 +72,14 @@ public:
|
||||
class EffectMovementGenerator : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
explicit EffectMovementGenerator(uint32 Id) : m_Id(Id) {}
|
||||
explicit EffectMovementGenerator(uint32 Id) : _Id(Id) {}
|
||||
void Initialize(Unit*) override {}
|
||||
void Finalize(Unit*) override;
|
||||
void Reset(Unit*) override {}
|
||||
bool Update(Unit*, uint32) override;
|
||||
MovementGeneratorType GetMovementGeneratorType() override { return EFFECT_MOTION_TYPE; }
|
||||
private:
|
||||
uint32 m_Id;
|
||||
uint32 _Id;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,7 +36,7 @@ RandomMovementGenerator<Creature>::~RandomMovementGenerator()
|
||||
}
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
|
||||
void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* creature)
|
||||
{
|
||||
if (creature->_moveState != MAP_OBJECT_CELL_MOVE_NONE)
|
||||
return;
|
||||
@@ -292,7 +292,7 @@ bool RandomMovementGenerator<Creature>::DoUpdate(Creature* creature, const uint3
|
||||
{
|
||||
_nextMoveTime.Update(diff);
|
||||
if (_nextMoveTime.Passed())
|
||||
_setRandomLocation(creature);
|
||||
SetRandomLocation(creature);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
}
|
||||
~RandomMovementGenerator();
|
||||
|
||||
void _setRandomLocation(T*);
|
||||
void SetRandomLocation(T*);
|
||||
void DoInitialize(T*);
|
||||
void DoFinalize(T*);
|
||||
void DoReset(T*);
|
||||
|
||||
@@ -75,22 +75,22 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature* creature)
|
||||
creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
m_isArrivalDone = true;
|
||||
|
||||
if (i_path->at(i_currentNode)->event_id && urand(0, 99) < i_path->at(i_currentNode)->event_chance)
|
||||
if (i_path->at(_currentNode)->event_id && urand(0, 99) < i_path->at(_currentNode)->event_chance)
|
||||
{
|
||||
LOG_DEBUG("maps.script", "Creature movement start script {} at point {} for {}.",
|
||||
i_path->at(i_currentNode)->event_id, i_currentNode, creature->GetGUID().ToString());
|
||||
i_path->at(_currentNode)->event_id, _currentNode, creature->GetGUID().ToString());
|
||||
creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
creature->GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, creature, nullptr);
|
||||
creature->GetMap()->ScriptsStart(sWaypointScripts, i_path->at(_currentNode)->event_id, creature, nullptr);
|
||||
}
|
||||
|
||||
// Inform script
|
||||
MovementInform(creature);
|
||||
creature->UpdateWaypointID(i_currentNode);
|
||||
creature->UpdateWaypointID(_currentNode);
|
||||
|
||||
if (i_path->at(i_currentNode)->delay)
|
||||
if (i_path->at(_currentNode)->delay)
|
||||
{
|
||||
creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
Stop(i_path->at(i_currentNode)->delay);
|
||||
Stop(i_path->at(_currentNode)->delay);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,11 +111,11 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
|
||||
if (m_isArrivalDone)
|
||||
{
|
||||
// Xinef: not true... update this at every waypoint!
|
||||
//if ((i_currentNode == i_path->size() - 1) && !repeating) // If that's our last waypoint
|
||||
//if ((_currentNode == i_path->size() - 1) && !repeating) // If that's our last waypoint
|
||||
{
|
||||
float x = i_path->at(i_currentNode)->x;
|
||||
float y = i_path->at(i_currentNode)->y;
|
||||
float z = i_path->at(i_currentNode)->z;
|
||||
float x = i_path->at(_currentNode)->x;
|
||||
float y = i_path->at(_currentNode)->y;
|
||||
float z = i_path->at(_currentNode)->z;
|
||||
float o = creature->GetOrientation();
|
||||
|
||||
if (!transportPath)
|
||||
@@ -136,14 +136,14 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
|
||||
}
|
||||
|
||||
// Xinef: moved the upper IF here
|
||||
if ((i_currentNode == i_path->size() - 1) && !repeating) // If that's our last waypoint
|
||||
if ((_currentNode == i_path->size() - 1) && !repeating) // If that's our last waypoint
|
||||
{
|
||||
creature->AI()->PathEndReached(path_id);
|
||||
creature->GetMotionMaster()->Initialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
i_currentNode = (i_currentNode + 1) % i_path->size();
|
||||
_currentNode = (_currentNode + 1) % i_path->size();
|
||||
}
|
||||
|
||||
// xinef: do not initialize motion if we got stunned in movementinform
|
||||
@@ -152,7 +152,7 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
|
||||
return true;
|
||||
}
|
||||
|
||||
WaypointData const* node = i_path->at(i_currentNode);
|
||||
WaypointData const* node = i_path->at(_currentNode);
|
||||
|
||||
m_isArrivalDone = false;
|
||||
|
||||
@@ -238,7 +238,7 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
|
||||
bool finished = creature->movespline->Finalized();
|
||||
// xinef: code to detect pre-empetively if we should start movement to next waypoint
|
||||
// xinef: do not start pre-empetive movement if current node has delay or we are ending waypoint movement
|
||||
//if (!finished && !i_path->at(i_currentNode)->delay && ((i_currentNode != i_path->size() - 1) || repeating))
|
||||
//if (!finished && !i_path->at(_currentNode)->delay && ((_currentNode != i_path->size() - 1) || repeating))
|
||||
// finished = (creature->movespline->_Spline().length(creature->movespline->_currentSplineIdx() + 1) - creature->movespline->timePassed()) < 200;
|
||||
|
||||
if (finished)
|
||||
@@ -254,13 +254,13 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
|
||||
void WaypointMovementGenerator<Creature>::MovementInform(Creature* creature)
|
||||
{
|
||||
if (creature->AI())
|
||||
creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
|
||||
creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, _currentNode);
|
||||
|
||||
if (Unit* owner = creature->GetCharmerOrOwner())
|
||||
{
|
||||
if (UnitAI* AI = owner->GetAI())
|
||||
{
|
||||
AI->SummonMovementInform(creature, WAYPOINT_MOTION_TYPE, i_currentNode);
|
||||
AI->SummonMovementInform(creature, WAYPOINT_MOTION_TYPE, _currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,13 +269,13 @@ void WaypointMovementGenerator<Creature>::MovementInform(Creature* creature)
|
||||
|
||||
uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const
|
||||
{
|
||||
if (i_currentNode >= i_path.size())
|
||||
if (_currentNode >= i_path.size())
|
||||
{
|
||||
return i_path.size();
|
||||
}
|
||||
|
||||
uint32 curMapId = i_path[i_currentNode]->mapid;
|
||||
for (uint32 i = i_currentNode; i < i_path.size(); ++i)
|
||||
uint32 curMapId = i_path[_currentNode]->mapid;
|
||||
for (uint32 i = _currentNode; i < i_path.size(); ++i)
|
||||
{
|
||||
if (i_path[i]->mapid != curMapId)
|
||||
{
|
||||
@@ -401,15 +401,15 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
|
||||
{
|
||||
// skipping the first spline path point because it's our starting point and not a taxi path point
|
||||
uint32 pointId = player->movespline->currentPathIdx() <= 0 ? 0 : player->movespline->currentPathIdx() - 1;
|
||||
if (pointId > i_currentNode && i_currentNode < i_path.size() - 1)
|
||||
if (pointId > _currentNode && _currentNode < i_path.size() - 1)
|
||||
{
|
||||
bool departureEvent = true;
|
||||
do
|
||||
{
|
||||
ASSERT(i_currentNode < i_path.size(), "Point Id: {}\n{}", pointId, player->GetGUID().ToString().c_str());
|
||||
ASSERT(_currentNode < i_path.size(), "Point Id: {}\n{}", pointId, player->GetGUID().ToString().c_str());
|
||||
|
||||
DoEventIfAny(player, i_path[i_currentNode], departureEvent);
|
||||
while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= i_currentNode)
|
||||
DoEventIfAny(player, i_path[_currentNode], departureEvent);
|
||||
while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= _currentNode)
|
||||
{
|
||||
_pointsForPathSwitch.pop_front();
|
||||
player->m_taxi.NextTaxiDestination();
|
||||
@@ -420,37 +420,37 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
|
||||
}
|
||||
}
|
||||
|
||||
if (pointId == i_currentNode)
|
||||
if (pointId == _currentNode)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (i_currentNode == _preloadTargetNode)
|
||||
if (_currentNode == _preloadTargetNode)
|
||||
{
|
||||
PreloadEndGrid();
|
||||
}
|
||||
|
||||
i_currentNode += departureEvent ? 1 : 0;
|
||||
_currentNode += departureEvent ? 1 : 0;
|
||||
departureEvent = !departureEvent;
|
||||
} while (i_currentNode < i_path.size() - 1);
|
||||
} while (_currentNode < i_path.size() - 1);
|
||||
}
|
||||
|
||||
return i_currentNode < (i_path.size() - 1);
|
||||
return _currentNode < (i_path.size() - 1);
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
|
||||
{
|
||||
if (i_path.empty() || i_currentNode >= i_path.size())
|
||||
if (i_path.empty() || _currentNode >= i_path.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 map0 = i_path[i_currentNode]->mapid;
|
||||
for (size_t i = i_currentNode + 1; i < i_path.size(); ++i)
|
||||
uint32 map0 = i_path[_currentNode]->mapid;
|
||||
for (size_t i = _currentNode + 1; i < i_path.size(); ++i)
|
||||
{
|
||||
if (i_path[i]->mapid != map0)
|
||||
{
|
||||
i_currentNode = i;
|
||||
_currentNode = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -467,7 +467,7 @@ void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry
|
||||
|
||||
bool FlightPathMovementGenerator::GetResetPos(Player*, float& x, float& y, float& z)
|
||||
{
|
||||
TaxiPathNodeEntry const* node = i_path[i_currentNode];
|
||||
TaxiPathNodeEntry const* node = i_path[_currentNode];
|
||||
x = node->x;
|
||||
y = node->y;
|
||||
z = node->z;
|
||||
|
||||
@@ -35,15 +35,15 @@ template<class T, class P>
|
||||
class PathMovementBase
|
||||
{
|
||||
public:
|
||||
PathMovementBase() : i_path(), i_currentNode(0) {}
|
||||
PathMovementBase(P path) : i_path(path), i_currentNode(0) {}
|
||||
PathMovementBase() : i_path(), _currentNode(0) {}
|
||||
PathMovementBase(P path) : i_path(path), _currentNode(0) {}
|
||||
virtual ~PathMovementBase() {};
|
||||
|
||||
uint32 GetCurrentNode() const { return i_currentNode; }
|
||||
uint32 GetCurrentNode() const { return _currentNode; }
|
||||
|
||||
protected:
|
||||
P i_path;
|
||||
uint32 i_currentNode;
|
||||
uint32 _currentNode;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
@@ -104,7 +104,7 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig
|
||||
public:
|
||||
explicit FlightPathMovementGenerator(uint32 startNode = 0)
|
||||
{
|
||||
i_currentNode = startNode;
|
||||
_currentNode = startNode;
|
||||
_endGridX = 0.0f;
|
||||
_endGridY = 0.0f;
|
||||
_endMapId = 0;
|
||||
@@ -119,9 +119,9 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig
|
||||
|
||||
TaxiPathNodeList const& GetPath() { return i_path; }
|
||||
uint32 GetPathAtMapEnd() const;
|
||||
bool HasArrived() const { return (i_currentNode >= i_path.size()); }
|
||||
bool HasArrived() const { return (_currentNode >= i_path.size()); }
|
||||
void SetCurrentNodeAfterTeleport();
|
||||
void SkipCurrentNode() { ++i_currentNode; }
|
||||
void SkipCurrentNode() { ++_currentNode; }
|
||||
void DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure);
|
||||
|
||||
bool GetResetPos(Player*, float& x, float& y, float& z);
|
||||
|
||||
@@ -863,13 +863,6 @@ void WorldSession::SendAuthWaitQueue(uint32 position)
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::LoadGlobalAccountData()
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_DATA);
|
||||
stmt->SetData(0, GetAccountId());
|
||||
LoadAccountData(CharacterDatabase.Query(stmt), GLOBAL_CACHE_MASK);
|
||||
}
|
||||
|
||||
void WorldSession::LoadAccountData(PreparedQueryResult result, uint32 mask)
|
||||
{
|
||||
for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i)
|
||||
@@ -942,15 +935,17 @@ void WorldSession::SendAccountDataTimes(uint32 mask)
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::LoadTutorialsData()
|
||||
void WorldSession::LoadTutorialsData(PreparedQueryResult result)
|
||||
{
|
||||
memset(m_Tutorials, 0, sizeof(uint32) * MAX_ACCOUNT_TUTORIAL_VALUES);
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_TUTORIALS);
|
||||
stmt->SetData(0, GetAccountId());
|
||||
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
|
||||
if (result)
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i)
|
||||
{
|
||||
m_Tutorials[i] = (*result)[i].Get<uint32>();
|
||||
}
|
||||
}
|
||||
|
||||
m_TutorialsChanged = false;
|
||||
}
|
||||
@@ -1275,8 +1270,8 @@ void WorldSession::SendAddonsInfo()
|
||||
for (AddonMgr::BannedAddonList::const_iterator itr = bannedAddons->begin(); itr != bannedAddons->end(); ++itr)
|
||||
{
|
||||
data << uint32(itr->Id);
|
||||
data.append(itr->NameMD5, sizeof(itr->NameMD5));
|
||||
data.append(itr->VersionMD5, sizeof(itr->VersionMD5));
|
||||
data.append(itr->NameMD5);
|
||||
data.append(itr->VersionMD5);
|
||||
data << uint32(itr->Timestamp);
|
||||
data << uint32(1); // IsBanned
|
||||
}
|
||||
@@ -1649,6 +1644,75 @@ void WorldSession::SendTimeSync()
|
||||
_timeSyncNextCounter++;
|
||||
}
|
||||
|
||||
class AccountInfoQueryHolderPerRealm : public CharacterDatabaseQueryHolder
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
GLOBAL_ACCOUNT_DATA = 0,
|
||||
TUTORIALS,
|
||||
|
||||
MAX_QUERIES
|
||||
};
|
||||
|
||||
AccountInfoQueryHolderPerRealm() { SetSize(MAX_QUERIES); }
|
||||
|
||||
bool Initialize(uint32 accountId)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_DATA);
|
||||
stmt->SetData(0, accountId);
|
||||
ok = SetPreparedQuery(GLOBAL_ACCOUNT_DATA, stmt) && ok;
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_TUTORIALS);
|
||||
stmt->SetData(0, accountId);
|
||||
ok = SetPreparedQuery(TUTORIALS, stmt) && ok;
|
||||
|
||||
return ok;
|
||||
}
|
||||
};
|
||||
|
||||
void WorldSession::InitializeSession()
|
||||
{
|
||||
uint32 cacheVersion = sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION);
|
||||
sScriptMgr->OnBeforeFinalizePlayerWorldSession(cacheVersion);
|
||||
|
||||
std::shared_ptr<AccountInfoQueryHolderPerRealm> realmHolder = std::make_shared<AccountInfoQueryHolderPerRealm>();
|
||||
if (!realmHolder->Initialize(GetAccountId()))
|
||||
{
|
||||
SendAuthResponse(AUTH_SYSTEM_ERROR, false);
|
||||
return;
|
||||
}
|
||||
|
||||
AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(realmHolder)).AfterComplete([this, cacheVersion](SQLQueryHolderBase const& holder)
|
||||
{
|
||||
InitializeSessionCallback(static_cast<AccountInfoQueryHolderPerRealm const&>(holder), cacheVersion);
|
||||
});
|
||||
}
|
||||
|
||||
void WorldSession::InitializeSessionCallback(CharacterDatabaseQueryHolder const& realmHolder, uint32 clientCacheVersion)
|
||||
{
|
||||
LoadAccountData(realmHolder.GetPreparedResult(AccountInfoQueryHolderPerRealm::GLOBAL_ACCOUNT_DATA), GLOBAL_CACHE_MASK);
|
||||
LoadTutorialsData(realmHolder.GetPreparedResult(AccountInfoQueryHolderPerRealm::TUTORIALS));
|
||||
|
||||
if (!m_inQueue)
|
||||
{
|
||||
SendAuthResponse(AUTH_OK, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendAuthWaitQueue(0);
|
||||
}
|
||||
|
||||
SetInQueue(false);
|
||||
ResetTimeOutTime(false);
|
||||
|
||||
SendAddonsInfo();
|
||||
SendClientCacheVersion(clientCacheVersion);
|
||||
SendTutorialsData();
|
||||
}
|
||||
|
||||
LockedQueue<WorldPacket*>& WorldSession::GetPacketQueue()
|
||||
{
|
||||
return _recvQueue;
|
||||
|
||||
@@ -467,10 +467,9 @@ public:
|
||||
AccountData* GetAccountData(AccountDataType type) { return &m_accountData[type]; }
|
||||
void SetAccountData(AccountDataType type, time_t tm, std::string const& data);
|
||||
void SendAccountDataTimes(uint32 mask);
|
||||
void LoadGlobalAccountData();
|
||||
void LoadAccountData(PreparedQueryResult result, uint32 mask);
|
||||
|
||||
void LoadTutorialsData();
|
||||
void LoadTutorialsData(PreparedQueryResult result);
|
||||
void SendTutorialsData();
|
||||
void SaveTutorialsData(CharacterDatabaseTransaction trans);
|
||||
uint32 GetTutorialInt(uint8 index) const { return m_Tutorials[index]; }
|
||||
@@ -1100,6 +1099,9 @@ public: // opcodes handlers
|
||||
TransactionCallback& AddTransactionCallback(TransactionCallback&& callback);
|
||||
SQLQueryHolderCallback& AddQueryHolderCallback(SQLQueryHolderCallback&& callback);
|
||||
|
||||
void InitializeSession();
|
||||
void InitializeSessionCallback(CharacterDatabaseQueryHolder const& realmHolder, uint32 clientCacheVersion);
|
||||
|
||||
LockedQueue<WorldPacket*>& GetPacketQueue();
|
||||
|
||||
[[nodiscard]] bool IsBot() const
|
||||
|
||||
@@ -4430,9 +4430,22 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
// Digestive Acid (Temporary)
|
||||
ApplySpellFix({ 26476 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->Attributes |= SPELL_ATTR0_NO_IMMUNITIES;
|
||||
spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT;
|
||||
spellInfo->AttributesEx3 |= SPELL_ATTR3_ALWAYS_HIT;
|
||||
spellInfo->Attributes |= SPELL_ATTR0_NO_IMMUNITIES;
|
||||
spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT;
|
||||
spellInfo->AttributesEx3 |= SPELL_ATTR3_ALWAYS_HIT;
|
||||
});
|
||||
|
||||
// Drums of War/Battle/Speed/Restoration
|
||||
ApplySpellFix({ 35475, 35476, 35477, 35478 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->ExcludeTargetAuraSpell = 51120;
|
||||
});
|
||||
|
||||
// Slap!
|
||||
ApplySpellFix({ 6754 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->AttributesEx |= SPELL_ATTR1_NO_THREAT;
|
||||
spellInfo->AttributesEx3 |= SPELL_ATTR3_SUPRESS_TARGET_PROCS;
|
||||
});
|
||||
|
||||
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
#ifndef _WARDEN_MODULE_MAC_H
|
||||
#define _WARDEN_MODULE_MAC_H
|
||||
|
||||
uint8 Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data[9318] =
|
||||
#include <array>
|
||||
|
||||
std::array<uint8, 9318> Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data =
|
||||
{
|
||||
0x07, 0x0C, 0x44, 0xCD, 0xC9, 0xFB, 0x99, 0xBC, 0x7C, 0x77, 0xDC, 0xE8, 0x8D, 0x07, 0xBE, 0x55,
|
||||
0x37, 0x5C, 0x84, 0x10, 0x23, 0xE1, 0x36, 0x5B, 0xF1, 0xBC, 0x60, 0xF3, 0x68, 0xBA, 0x60, 0x69,
|
||||
@@ -605,7 +607,7 @@ uint8 Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data[9318] =
|
||||
0x43, 0x82, 0xAA, 0x0C, 0xEE, 0x1B
|
||||
};
|
||||
|
||||
uint8 Module_0DBBF209A27B1E279A9FEC5C168A15F7_Key[16] =
|
||||
std::array<uint8, 16> Module_0DBBF209A27B1E279A9FEC5C168A15F7_Key =
|
||||
{
|
||||
0x5B, 0x27, 0x27, 0x01, 0x24, 0x56, 0xB4, 0xD4, 0x2D, 0xD0, 0x96, 0x77, 0x49, 0x51, 0xDC, 0x0A
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "AccountMgr.h"
|
||||
#include "BanMgr.h"
|
||||
#include "ByteBuffer.h"
|
||||
#include "Common.h"
|
||||
#include "CryptoHash.h"
|
||||
#include "Log.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Player.h"
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include <openssl/sha.h>
|
||||
|
||||
Warden::Warden() : _session(nullptr), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0),
|
||||
_dataSent(false), _module(nullptr), _initialized(false)
|
||||
@@ -77,11 +76,11 @@ void Warden::RequestModule()
|
||||
LOG_DEBUG("warden", "Request module");
|
||||
|
||||
// Create packet structure
|
||||
WardenModuleUse request;
|
||||
WardenModuleUse request{};
|
||||
request.Command = WARDEN_SMSG_MODULE_USE;
|
||||
|
||||
memcpy(request.ModuleId, _module->Id, 16);
|
||||
memcpy(request.ModuleKey, _module->Key, 16);
|
||||
memcpy(request.ModuleId, _module->Id.data(), 16);
|
||||
memcpy(request.ModuleKey, _module->Key.data(), 16);
|
||||
request.Size = _module->CompressedSize;
|
||||
|
||||
EndianConvert(request.Size);
|
||||
@@ -155,30 +154,21 @@ bool Warden::IsValidCheckSum(uint32 checksum, const uint8* data, const uint16 le
|
||||
}
|
||||
}
|
||||
|
||||
struct keyData
|
||||
union keyData
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 bytes[20];
|
||||
} bytes;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 ints[5];
|
||||
} ints;
|
||||
};
|
||||
std::array<uint8, 20> bytes;
|
||||
std::array<uint32, 5> ints;
|
||||
};
|
||||
|
||||
uint32 Warden::BuildChecksum(const uint8* data, uint32 length)
|
||||
{
|
||||
keyData hash;
|
||||
SHA1(data, length, hash.bytes.bytes);
|
||||
keyData hash{};
|
||||
hash.bytes = Acore::Crypto::SHA1::GetDigestOf(data, size_t(length));
|
||||
uint32 checkSum = 0;
|
||||
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
{
|
||||
checkSum = checkSum ^ hash.ints.ints[i];
|
||||
checkSum = checkSum ^ hash.ints[i];
|
||||
}
|
||||
|
||||
return checkSum;
|
||||
|
||||
@@ -91,10 +91,10 @@ struct WardenHashRequest
|
||||
|
||||
struct ClientWardenModule
|
||||
{
|
||||
uint8 Id[16];
|
||||
uint8 Key[16];
|
||||
uint32 CompressedSize;
|
||||
uint8* CompressedData;
|
||||
std::array<uint8, 16> Id{};
|
||||
std::array<uint8, 16> Key{};
|
||||
uint32 CompressedSize{};
|
||||
uint8* CompressedData{};
|
||||
};
|
||||
|
||||
class WorldSession;
|
||||
|
||||
@@ -25,15 +25,12 @@
|
||||
#include "WardenModuleMac.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include <openssl/md5.h>
|
||||
|
||||
WardenMac::WardenMac() : Warden()
|
||||
{
|
||||
}
|
||||
|
||||
WardenMac::~WardenMac()
|
||||
{
|
||||
}
|
||||
WardenMac::~WardenMac() = default;
|
||||
|
||||
void WardenMac::Init(WorldSession* pClient, SessionKey const& K)
|
||||
{
|
||||
@@ -64,29 +61,21 @@ void WardenMac::Init(WorldSession* pClient, SessionKey const& K)
|
||||
|
||||
_module = GetModuleForClient();
|
||||
|
||||
LOG_DEBUG("warden", "Module Key: {}", Acore::Impl::ByteArrayToHexStr(_module->Key, 16));
|
||||
LOG_DEBUG("warden", "Module ID: {}", Acore::Impl::ByteArrayToHexStr(_module->Id, 16));
|
||||
LOG_DEBUG("warden", "Module Key: {}", ByteArrayToHexStr(_module->Key));
|
||||
LOG_DEBUG("warden", "Module ID: {}", ByteArrayToHexStr(_module->Id));
|
||||
RequestModule();
|
||||
}
|
||||
|
||||
ClientWardenModule* WardenMac::GetModuleForClient()
|
||||
{
|
||||
ClientWardenModule* mod = new ClientWardenModule;
|
||||
|
||||
uint32 len = sizeof(Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data);
|
||||
auto mod = new ClientWardenModule;
|
||||
|
||||
// data assign
|
||||
mod->CompressedSize = len;
|
||||
mod->CompressedData = new uint8[len];
|
||||
memcpy(mod->CompressedData, Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data, len);
|
||||
memcpy(mod->Key, Module_0DBBF209A27B1E279A9FEC5C168A15F7_Key, 16);
|
||||
mod->CompressedSize = Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data.size();
|
||||
mod->CompressedData = Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data.data();
|
||||
|
||||
// md5 hash
|
||||
MD5_CTX ctx;
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, mod->CompressedData, len);
|
||||
MD5_Final((uint8*)&mod->Id, &ctx);
|
||||
|
||||
mod->Id = Acore::Crypto::MD5::GetDigestOf(mod->CompressedData, mod->CompressedSize);
|
||||
return mod;
|
||||
}
|
||||
|
||||
@@ -100,7 +89,7 @@ void WardenMac::RequestHash()
|
||||
LOG_DEBUG("warden", "Request hash");
|
||||
|
||||
// Create packet structure
|
||||
WardenHashRequest Request;
|
||||
WardenHashRequest Request{};
|
||||
Request.Command = WARDEN_SMSG_HASH_REQUEST;
|
||||
memcpy(Request.Seed, _seed, 16);
|
||||
|
||||
@@ -242,7 +231,7 @@ void WardenMac::HandleData(ByteBuffer& buff)
|
||||
sha1.UpdateData((uint8*)&magic, 4);
|
||||
sha1.Finalize();
|
||||
|
||||
std::array<uint8, Acore::Crypto::SHA1::DIGEST_LENGTH> sha1Hash;
|
||||
Acore::Crypto::SHA1::Digest sha1Hash{};
|
||||
buff.read(sha1Hash.data(), sha1Hash.size());
|
||||
|
||||
if (sha1Hash != sha1.GetDigest())
|
||||
@@ -251,20 +240,15 @@ void WardenMac::HandleData(ByteBuffer& buff)
|
||||
//found = true;
|
||||
}
|
||||
|
||||
MD5_CTX ctx;
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, str.c_str(), str.size());
|
||||
uint8 ourMD5Hash[16];
|
||||
MD5_Final(ourMD5Hash, &ctx);
|
||||
auto ourMD5Hash = Acore::Crypto::MD5::GetDigestOf(str);
|
||||
Acore::Crypto::MD5::Digest theirsMD5Hash{};
|
||||
buff.read(theirsMD5Hash);
|
||||
|
||||
uint8 theirsMD5Hash[16];
|
||||
buff.read(theirsMD5Hash, 16);
|
||||
|
||||
if (memcmp(ourMD5Hash, theirsMD5Hash, 16))
|
||||
if (ourMD5Hash != theirsMD5Hash)
|
||||
{
|
||||
LOG_DEBUG("warden", "Handle data failed: MD5 hash is wrong!");
|
||||
//found = true;
|
||||
}
|
||||
|
||||
_session->KickPlayer("WardenMac");
|
||||
_session->KickPlayer("WardenMac::HandleData");
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include <openssl/md5.h>
|
||||
|
||||
// GUILD is the shortest string that has no client validation (RAID only sends if in a raid group)
|
||||
static constexpr char _luaEvalPrefix[] = "local S,T,R=SendAddonMessage,function()";
|
||||
@@ -97,9 +96,7 @@ static WorldIntConfigs GetMaxWardenChecksForType(uint8 type)
|
||||
|
||||
WardenWin::WardenWin() : Warden(), _serverTicks(0) { }
|
||||
|
||||
WardenWin::~WardenWin()
|
||||
{
|
||||
}
|
||||
WardenWin::~WardenWin() = default;
|
||||
|
||||
void WardenWin::Init(WorldSession* session, SessionKey const& k)
|
||||
{
|
||||
@@ -121,14 +118,14 @@ void WardenWin::Init(WorldSession* session, SessionKey const& k)
|
||||
|
||||
_module = GetModuleForClient();
|
||||
|
||||
LOG_DEBUG("warden", "Module Key: {}", Acore::Impl::ByteArrayToHexStr(_module->Key, 16));
|
||||
LOG_DEBUG("warden", "Module ID: {}", Acore::Impl::ByteArrayToHexStr(_module->Id, 16));
|
||||
LOG_DEBUG("warden", "Module Key: {}", ByteArrayToHexStr(_module->Key));
|
||||
LOG_DEBUG("warden", "Module ID: {}", ByteArrayToHexStr(_module->Id));
|
||||
RequestModule();
|
||||
}
|
||||
|
||||
ClientWardenModule* WardenWin::GetModuleForClient()
|
||||
{
|
||||
ClientWardenModule* mod = new ClientWardenModule;
|
||||
auto mod = new ClientWardenModule;
|
||||
|
||||
uint32 length = sizeof(Module.Module);
|
||||
|
||||
@@ -136,13 +133,10 @@ ClientWardenModule* WardenWin::GetModuleForClient()
|
||||
mod->CompressedSize = length;
|
||||
mod->CompressedData = new uint8[length];
|
||||
memcpy(mod->CompressedData, Module.Module, length);
|
||||
memcpy(mod->Key, Module.ModuleKey, 16);
|
||||
memcpy(mod->Key.data(), Module.ModuleKey, 16);
|
||||
|
||||
// md5 hash
|
||||
MD5_CTX ctx;
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, mod->CompressedData, length);
|
||||
MD5_Final((uint8*)&mod->Id, &ctx);
|
||||
mod->Id = Acore::Crypto::MD5::GetDigestOf(mod->CompressedData, mod->CompressedSize);
|
||||
|
||||
return mod;
|
||||
}
|
||||
@@ -152,7 +146,7 @@ void WardenWin::InitializeModule()
|
||||
LOG_DEBUG("warden", "Initialize module");
|
||||
|
||||
// Create packet structure
|
||||
WardenInitModuleRequest Request;
|
||||
WardenInitModuleRequest Request{};
|
||||
Request.Command1 = WARDEN_SMSG_MODULE_INITIALIZE;
|
||||
Request.Size1 = 20;
|
||||
Request.Unk1 = 1;
|
||||
@@ -209,7 +203,7 @@ void WardenWin::RequestHash()
|
||||
LOG_DEBUG("warden", "Request hash");
|
||||
|
||||
// Create packet structure
|
||||
WardenHashRequest Request;
|
||||
WardenHashRequest Request{};
|
||||
Request.Command = WARDEN_SMSG_HASH_REQUEST;
|
||||
memcpy(Request.Seed, _seed, 16);
|
||||
|
||||
|
||||
@@ -314,14 +314,12 @@ void World::AddSession_(WorldSession* s)
|
||||
|
||||
if (pLimit > 0 && Sessions >= pLimit && AccountMgr::IsPlayerAccount(s->GetSecurity()) && !s->CanSkipQueue() && !HasRecentlyDisconnected(s))
|
||||
{
|
||||
AddQueuedPlayer (s);
|
||||
AddQueuedPlayer(s);
|
||||
UpdateMaxSessionCounters();
|
||||
return;
|
||||
}
|
||||
|
||||
s->SendAuthResponse(AUTH_OK, true);
|
||||
|
||||
FinalizePlayerWorldSession(s);
|
||||
s->InitializeSession();
|
||||
|
||||
UpdateMaxSessionCounters();
|
||||
}
|
||||
@@ -401,13 +399,7 @@ bool World::RemoveQueuedPlayer(WorldSession* sess)
|
||||
if ((!GetPlayerAmountLimit() || sessions < GetPlayerAmountLimit()) && !m_QueuedPlayer.empty())
|
||||
{
|
||||
WorldSession* pop_sess = m_QueuedPlayer.front();
|
||||
pop_sess->SetInQueue(false);
|
||||
pop_sess->ResetTimeOutTime(false);
|
||||
pop_sess->SendAuthWaitQueue(0);
|
||||
pop_sess->SendAccountDataTimes(GLOBAL_CACHE_MASK);
|
||||
|
||||
FinalizePlayerWorldSession(pop_sess);
|
||||
|
||||
pop_sess->InitializeSession();
|
||||
m_QueuedPlayer.pop_front();
|
||||
|
||||
// update iter to point first queued socket or end() if queue is empty now
|
||||
@@ -3402,16 +3394,6 @@ uint32 World::GetNextWhoListUpdateDelaySecs()
|
||||
return uint32(std::ceil(t / 1000.0f));
|
||||
}
|
||||
|
||||
void World::FinalizePlayerWorldSession(WorldSession* session)
|
||||
{
|
||||
uint32 cacheVersion = sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION);
|
||||
sScriptMgr->OnBeforeFinalizePlayerWorldSession(cacheVersion);
|
||||
|
||||
session->SendAddonsInfo();
|
||||
session->SendClientCacheVersion(cacheVersion);
|
||||
session->SendTutorialsData();
|
||||
}
|
||||
|
||||
CliCommandHolder::CliCommandHolder(void* callbackArg, char const* command, Print zprint, CommandFinished commandFinished)
|
||||
: m_callbackArg(callbackArg), m_command(strdup(command)), m_print(zprint), m_commandFinished(commandFinished)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user