Merge branch 'master' into Playerbot

# Conflicts:
#	src/server/game/Server/WorldSession.cpp
#	src/server/game/Server/WorldSession.h
This commit is contained in:
郑佩茹
2022-12-07 14:46:21 -07:00
196 changed files with 9181 additions and 1080 deletions
+18 -5
View File
@@ -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();
}
+85 -50
View File
@@ -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;
+100 -100
View File
@@ -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", " ");
}
+36 -36
View File
@@ -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()
+5 -8
View File
@@ -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());
+3 -2
View File
@@ -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;
};
+3
View File
@@ -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);
+17 -14
View File
@@ -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;
+7 -4
View File
@@ -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)
+1 -1
View File
@@ -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);
}
+6 -1
View File
@@ -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();
+1 -1
View File
@@ -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();
+49 -2
View File
@@ -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();
}
+28 -18
View File
@@ -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);
+1 -2
View File
@@ -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; }
};
+2 -2
View File
@@ -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();
}
}
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
+77 -13
View File
@@ -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;
+4 -2
View File
@@ -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
};
+11 -21
View File
@@ -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;
+4 -4
View File
@@ -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;
+14 -30
View File
@@ -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");
}
+8 -14
View File
@@ -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);
+3 -21
View File
@@ -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)
{