mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-26 07:06:23 +00:00
fix(Core/CreatureText): race conditions in CreatureTextMgr repeat group (#23153)
Co-authored-by: Shauren <shauren.trinity@gmail.com> Co-authored-by: Giacomo Pozzoni <giacomopoz@gmail.com>
This commit is contained in:
@@ -83,7 +83,7 @@ void CreatureTextMgr::LoadCreatureTexts()
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
mTextMap.clear(); // for reload case
|
||||
mTextRepeatMap.clear(); //reset all currently used temp texts
|
||||
//all currently used temp texts are NOT reset
|
||||
|
||||
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_TEXT);
|
||||
PreparedQueryResult result = WorldDatabase.Query(stmt);
|
||||
@@ -218,7 +218,7 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
|
||||
}
|
||||
|
||||
CreatureTextGroup const& textGroupContainer = itr->second; //has all texts in the group
|
||||
CreatureTextRepeatIds repeatGroup = GetRepeatGroup(source, textGroup);//has all textIDs from the group that were already said
|
||||
CreatureTextRepeatIds repeatGroup = source->GetTextRepeatGroup(textGroup);//has all textIDs from the group that were already said
|
||||
CreatureTextGroup tempGroup;//will use this to talk after sorting repeatGroup
|
||||
|
||||
for (CreatureTextGroup::const_iterator giter = textGroupContainer.begin(); giter != textGroupContainer.end(); ++giter)
|
||||
@@ -227,52 +227,14 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
|
||||
|
||||
if (tempGroup.empty())
|
||||
{
|
||||
CreatureTextRepeatMap::iterator mapItr = mTextRepeatMap.find(source->GetGUID());
|
||||
if (mapItr != mTextRepeatMap.end())
|
||||
{
|
||||
CreatureTextRepeatGroup::iterator groupItr = mapItr->second.find(textGroup);
|
||||
groupItr->second.clear();
|
||||
}
|
||||
|
||||
source->ClearTextRepeatGroup(textGroup);
|
||||
tempGroup = textGroupContainer;
|
||||
}
|
||||
|
||||
uint8 count = 0;
|
||||
float lastChance = -1;
|
||||
bool isEqualChanced = true;
|
||||
|
||||
float totalChance = 0;
|
||||
|
||||
for (CreatureTextGroup::const_iterator iter = tempGroup.begin(); iter != tempGroup.end(); ++iter)
|
||||
auto iter = Acore::Containers::SelectRandomWeightedContainerElement(tempGroup, [](CreatureTextEntry const& t) -> double
|
||||
{
|
||||
if (lastChance >= 0 && lastChance != iter->probability)
|
||||
isEqualChanced = false;
|
||||
|
||||
lastChance = iter->probability;
|
||||
totalChance += iter->probability;
|
||||
++count;
|
||||
}
|
||||
|
||||
int32 offset = -1;
|
||||
if (!isEqualChanced)
|
||||
{
|
||||
for (CreatureTextGroup::const_iterator iter = tempGroup.begin(); iter != tempGroup.end(); ++iter)
|
||||
{
|
||||
uint32 chance = uint32(iter->probability);
|
||||
uint32 r = urand(0, 100);
|
||||
++offset;
|
||||
if (r <= chance)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 pos = 0;
|
||||
if (isEqualChanced || offset < 0)
|
||||
pos = urand(0, count - 1);
|
||||
else if (offset >= 0)
|
||||
pos = offset;
|
||||
|
||||
CreatureTextGroup::const_iterator iter = tempGroup.begin() + pos;
|
||||
return t.probability;
|
||||
});
|
||||
|
||||
ChatMsg finalType = (msgType == CHAT_MSG_ADDON) ? iter->type : msgType;
|
||||
Language finalLang = (language == LANG_ADDON) ? iter->lang : language;
|
||||
@@ -301,9 +263,8 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
|
||||
CreatureTextBuilder builder(finalSource, finalSource->getGender(), finalType, iter->group, iter->id, finalLang, target);
|
||||
SendChatPacket(finalSource, builder, finalType, target, range, teamId, gmOnly);
|
||||
}
|
||||
if (isEqualChanced || (!isEqualChanced && totalChance == 100.0f))
|
||||
SetRepeatId(source, textGroup, iter->id);
|
||||
|
||||
source->SetTextRepeatId(textGroup, iter->id);
|
||||
return iter->duration;
|
||||
}
|
||||
|
||||
@@ -410,34 +371,6 @@ void CreatureTextMgr::SendEmote(Unit* source, uint32 emote)
|
||||
source->HandleEmoteCommand(emote);
|
||||
}
|
||||
|
||||
void CreatureTextMgr::SetRepeatId(Creature* source, uint8 textGroup, uint8 id)
|
||||
{
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
CreatureTextRepeatIds& repeats = mTextRepeatMap[source->GetGUID()][textGroup];
|
||||
if (std::find(repeats.begin(), repeats.end(), id) == repeats.end())
|
||||
repeats.push_back(id);
|
||||
else
|
||||
LOG_ERROR("sql.sql", "CreatureTextMgr: TextGroup {} for Creature {} ({}), id {} already added",
|
||||
uint32(textGroup), source->GetName(), source->GetGUID().ToString(), uint32(id));
|
||||
}
|
||||
|
||||
CreatureTextRepeatIds CreatureTextMgr::GetRepeatGroup(Creature* source, uint8 textGroup)
|
||||
{
|
||||
ASSERT(source);//should never happen
|
||||
CreatureTextRepeatIds ids;
|
||||
|
||||
CreatureTextRepeatMap::const_iterator mapItr = mTextRepeatMap.find(source->GetGUID());
|
||||
if (mapItr != mTextRepeatMap.end())
|
||||
{
|
||||
CreatureTextRepeatGroup::const_iterator groupItr = (*mapItr).second.find(textGroup);
|
||||
if (groupItr != mapItr->second.end())
|
||||
ids = groupItr->second;
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
bool CreatureTextMgr::TextExist(uint32 sourceEntry, uint8 textGroup)
|
||||
{
|
||||
if (!sourceEntry)
|
||||
|
||||
@@ -77,11 +77,6 @@ typedef std::unordered_map<uint32, CreatureTextHolder> CreatureTextMap; // a
|
||||
|
||||
typedef std::map<CreatureTextId, CreatureTextLocale> LocaleCreatureTextMap;
|
||||
|
||||
//used for handling non-repeatable random texts
|
||||
typedef std::vector<uint8> CreatureTextRepeatIds;
|
||||
typedef std::unordered_map<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup;
|
||||
typedef std::unordered_map<ObjectGuid, CreatureTextRepeatGroup> CreatureTextRepeatMap;//guid based
|
||||
|
||||
class CreatureTextMgr
|
||||
{
|
||||
CreatureTextMgr() { }
|
||||
@@ -105,14 +100,10 @@ public:
|
||||
template<class Builder> void SendChatPacket(WorldObject* source, Builder const& builder, ChatMsg msgType, WorldObject const* target = nullptr, CreatureTextRange range = TEXT_RANGE_NORMAL, TeamId teamId = TEAM_NEUTRAL, bool gmOnly = false) const;
|
||||
|
||||
private:
|
||||
CreatureTextRepeatIds GetRepeatGroup(Creature* source, uint8 textGroup);
|
||||
void SetRepeatId(Creature* source, uint8 textGroup, uint8 id);
|
||||
|
||||
void SendNonChatPacket(WorldObject* source, WorldPacket const* data, ChatMsg msgType, WorldObject const* target, CreatureTextRange range, TeamId teamId, bool gmOnly) const;
|
||||
float GetRangeForChatType(ChatMsg msgType) const;
|
||||
|
||||
CreatureTextMap mTextMap;
|
||||
CreatureTextRepeatMap mTextRepeatMap;
|
||||
LocaleCreatureTextMap mLocaleTextMap;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user