[7391] Prevent achievement counter overflow, implement ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE generic support.
Before overflow has been possible at 4294967295 lols for example.
ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE in many cases require check special conditions and targets.
For this allow call it from scripts:
* Add Player::UpdateAchievementCriteria functiona ccessable from scripts
* In emote case it allowed call in form player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote_id, achievement_id, target_unit_ptr);
Author: VladimirMangos
--HG--
branch : trunk
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
DELETE FROM mangos_string WHERE entry = 726;
|
||||
ALTER TABLE db_version CHANGE COLUMN required_7382_01_mangos_creature_template required_7388_01_mangos_mangos_string bit;
|
||||
|
||||
DELETE FROM mangos_string WHERE entry IN (750,751);
|
||||
INSERT INTO mangos_string VALUES (750,'Not enough players. This game will close in %u mins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
INSERT INTO mangos_string VALUES (751,'Not enough players. This game will close in %u seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
|
||||
@@ -730,6 +730,31 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
||||
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
|
||||
{
|
||||
// miscvalue1 = emote
|
||||
// miscvalue2 = achievement->ID for special requirement
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
if(miscvalue1 != achievementCriteria->do_emote.emoteID)
|
||||
continue;
|
||||
if(achievementCriteria->do_emote.count)
|
||||
{
|
||||
// harcoded case
|
||||
if(achievement->ID==247)
|
||||
{
|
||||
if (!unit || unit->GetTypeId() != TYPEID_PLAYER ||
|
||||
unit->isAlive() || ((Player*)unit)->GetDeathTimer() == 0)
|
||||
continue;
|
||||
}
|
||||
// expected as scripted case
|
||||
else if(!miscvalue2 || !achievement->ID != miscvalue2)
|
||||
continue;
|
||||
}
|
||||
|
||||
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
|
||||
{
|
||||
uint32 spellCount = 0;
|
||||
@@ -798,7 +823,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
|
||||
@@ -927,6 +951,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
|
||||
return progress->counter >= achievementCriteria->roll_greed_on_loot.count;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
|
||||
return progress->counter >= achievementCriteria->do_emote.count;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
|
||||
return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
|
||||
@@ -1024,8 +1050,12 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
|
||||
newValue = changeValue;
|
||||
break;
|
||||
case PROGRESS_ACCUMULATE:
|
||||
newValue = progress->counter + changeValue;
|
||||
{
|
||||
// avoid overflow
|
||||
uint32 max_value = std::numeric_limits<uint32>::max();
|
||||
newValue = max_value - progress->counter > changeValue ? progress->counter + changeValue : max_value;
|
||||
break;
|
||||
}
|
||||
case PROGRESS_HIGHEST:
|
||||
newValue = progress->counter < changeValue ? changeValue : progress->counter;
|
||||
break;
|
||||
|
||||
+34
-36
@@ -524,44 +524,42 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
|
||||
}
|
||||
|
||||
EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote);
|
||||
if (em)
|
||||
if (!em)
|
||||
return;
|
||||
|
||||
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);
|
||||
|
||||
uint32 emote_anim = em->textid;
|
||||
|
||||
WorldPacket data;
|
||||
|
||||
switch(emote_anim)
|
||||
{
|
||||
uint32 emote_anim = em->textid;
|
||||
|
||||
WorldPacket data;
|
||||
|
||||
switch(emote_anim)
|
||||
{
|
||||
case EMOTE_STATE_SLEEP:
|
||||
case EMOTE_STATE_SIT:
|
||||
case EMOTE_STATE_KNEEL:
|
||||
case EMOTE_ONESHOT_NONE:
|
||||
break;
|
||||
default:
|
||||
GetPlayer()->HandleEmoteCommand(emote_anim);
|
||||
break;
|
||||
}
|
||||
|
||||
data.Initialize(SMSG_TEXT_EMOTE, (20+namlen));
|
||||
data << GetPlayer()->GetGUID();
|
||||
data << (uint32)text_emote;
|
||||
data << emoteNum;
|
||||
data << (uint32)namlen;
|
||||
if( namlen > 1 )
|
||||
{
|
||||
data.append(nam, namlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
data << (uint8)0x00;
|
||||
}
|
||||
|
||||
GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true);
|
||||
|
||||
//Send scripted event call
|
||||
if (pCreature && Script)
|
||||
Script->ReceiveEmote(GetPlayer(),pCreature,text_emote);
|
||||
case EMOTE_STATE_SLEEP:
|
||||
case EMOTE_STATE_SIT:
|
||||
case EMOTE_STATE_KNEEL:
|
||||
case EMOTE_ONESHOT_NONE:
|
||||
break;
|
||||
default:
|
||||
GetPlayer()->HandleEmoteCommand(emote_anim);
|
||||
break;
|
||||
}
|
||||
|
||||
data.Initialize(SMSG_TEXT_EMOTE, (20+namlen));
|
||||
data << GetPlayer()->GetGUID();
|
||||
data << (uint32)text_emote;
|
||||
data << emoteNum;
|
||||
data << (uint32)namlen;
|
||||
if( namlen > 1 )
|
||||
data.append(nam, namlen);
|
||||
else
|
||||
data << (uint8)0x00;
|
||||
|
||||
GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true);
|
||||
|
||||
//Send scripted event call
|
||||
if (pCreature && Script)
|
||||
Script->ReceiveEmote(GetPlayer(),pCreature,text_emote);
|
||||
}
|
||||
|
||||
void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data )
|
||||
|
||||
@@ -20645,3 +20645,8 @@ void Player::HandleFall(MovementInfo const& movementInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::UpdateAchievementCriteria( AchievementCriteriaTypes type, uint32 miscvalue1/*=0*/, uint32 miscvalue2/*=0*/, Unit *unit/*=NULL*/, uint32 time/*=0*/ )
|
||||
{
|
||||
GetAchievementMgr().UpdateAchievementCriteria(type, miscvalue1,miscvalue2,unit,time);
|
||||
}
|
||||
@@ -2181,6 +2181,7 @@ class TRINITY_DLL_SPEC Player : public Unit
|
||||
void AddRunePower(uint8 index);
|
||||
void InitRunes();
|
||||
AchievementMgr& GetAchievementMgr() { return m_achievementMgr; }
|
||||
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0);
|
||||
bool HasTitle(uint32 bitIndex);
|
||||
bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); }
|
||||
void SetTitle(CharTitlesEntry const* title);
|
||||
|
||||
@@ -359,7 +359,8 @@ struct AchievementCriteriaEntry
|
||||
// TODO: where is the information about the target stored?
|
||||
struct
|
||||
{
|
||||
uint32 emoteID; // 3
|
||||
uint32 emoteID; // 3 enum TextEmotes
|
||||
uint32 count; // 4 count of emotes, always required special target or requirements
|
||||
} do_emote;
|
||||
// ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13
|
||||
// ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "7389"
|
||||
#define REVISION_NR "7391"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
||||
Reference in New Issue
Block a user