AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id) { int32 areaflag = GetAreaFlagByAreaID(area_id); if(areaflag < 0) return NULL; return sAreaStore.LookupEntry(areaflag ); }
/** * this function will be called whenever the user might have done a criteria relevant action */ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, Unit *unit, uint32 time) { sLog.outDetail("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time); AchievementCriteriaEntryList const& achievementCriteriaList = achievementmgr.GetAchievementCriteriaByType(type); for(AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i!=achievementCriteriaList.end(); ++i) { AchievementCriteriaEntry const *achievementCriteria = (*i); // don't update already completed criteria if(IsCompletedCriteria(achievementCriteria)) continue; if(achievementCriteria->groupFlag & ACHIEVEMENT_CRITERIA_GROUP_NOT_IN_GROUP && GetPlayer()->GetGroup()) continue; AchievementEntry const *achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement); if(!achievement) continue; if(achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_HORDE && GetPlayer()->GetTeam() != HORDE || achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_ALLIANCE && GetPlayer()->GetTeam() != ALLIANCE) continue; switch (type) { case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel()); break; case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1); break; case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; if(achievementCriteria->kill_creature.creatureID != miscvalue1) continue; SetCriteriaProgress(achievementCriteria, miscvalue2, true); break; case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: if(uint32 skillvalue = GetPlayer()->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID)) SetCriteriaProgress(achievementCriteria, skillvalue); break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT: { uint32 counter =0; for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++) if(itr->second.m_rewarded) counter++; SetCriteriaProgress(achievementCriteria, counter); break; } case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE: { uint32 counter =0; for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++) { Quest const* quest = objmgr.GetQuestTemplate(itr->first); if(itr->second.m_rewarded && quest->GetZoneOrSort() == achievementCriteria->complete_quests_in_zone.zoneID) counter++; } SetCriteriaProgress(achievementCriteria, counter); break; } case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; SetCriteriaProgress(achievementCriteria, miscvalue1, true); break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; if(GetPlayer()->GetMapId() != achievementCriteria->complete_battleground.mapID) continue; SetCriteriaProgress(achievementCriteria, miscvalue1, true); break; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID)) SetCriteriaProgress(achievementCriteria, 1); break; case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; if(GetPlayer()->GetMapId() != achievementCriteria->death_at_map.mapID) continue; SetCriteriaProgress(achievementCriteria, 1, true); break; case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; if(miscvalue1 != achievementCriteria->killed_by_creature.creatureEntry) continue; SetCriteriaProgress(achievementCriteria, 1, true); break; case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; SetCriteriaProgress(achievementCriteria, 1, true); break; case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: { // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; if(achievement->ID == 1260) { if(Player::GetDrunkenstateByValue(GetPlayer()->GetDrunkValue()) != DRUNKEN_SMASHED) continue; // TODO: hardcoding eventid is bad, it can differ from DB to DB - maye implement something using HolidayNames.dbc? if(!gameeventmgr.IsActiveEvent(26)) continue; } // miscvalue1 is the ingame fallheight*100 as stored in dbc SetCriteriaProgress(achievementCriteria, miscvalue1); break; } case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID)) SetCriteriaProgress(achievementCriteria, 1); break; case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; if(achievementCriteria->use_item.itemID != miscvalue1) continue; SetCriteriaProgress(achievementCriteria, 1, true); break; case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: // speedup for non-login case if(miscvalue1 && achievementCriteria->own_item.itemID!=miscvalue1) continue; SetCriteriaProgress(achievementCriteria, GetPlayer()->GetItemCount(achievementCriteria->own_item.itemID, true)); break; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: // You _have_ to loot that item, just owning it when logging in does _not_ count! if(!miscvalue1) continue; if(miscvalue1 != achievementCriteria->own_item.itemID) continue; SetCriteriaProgress(achievementCriteria, miscvalue2, true); break; case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: if (!miscvalue1 || miscvalue1 != achievementCriteria->be_spell_target.spellID) continue; SetCriteriaProgress(achievementCriteria, 1, true); break; case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) continue; SetCriteriaProgress(achievementCriteria, 1, true); break; case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: { if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) continue; // those requirements couldn't be found in the dbc if (CriteriaCastSpellRequirement const* requirement = AchievementGlobalMgr::GetCriteriaCastSpellRequirement(achievementCriteria)) { if (!unit) continue; if (requirement->creatureEntry && unit->GetEntry() != requirement->creatureEntry) continue; if (requirement->playerRace && (unit->GetTypeId() != TYPEID_PLAYER || unit->getRace()!=requirement->playerRace)) continue; if (requirement->playerClass && (unit->GetTypeId() != TYPEID_PLAYER || unit->getClass()!=requirement->playerClass)) continue; } SetCriteriaProgress(achievementCriteria, 1, true); break; } case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: { uint32 spellCount = 0; for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin(); spellIter != GetPlayer()->GetSpellMap().end(); spellIter++) { for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first); skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first); skillIter++) { if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine) spellCount++; } } SetCriteriaProgress(achievementCriteria, spellCount); break; } case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: { // skip for login case if(!miscvalue1) continue; SetCriteriaProgress(achievementCriteria, 1); break; } case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION: { int32 reputation = GetPlayer()->GetReputation(achievementCriteria->gain_reputation.factionID); if (reputation > 0) SetCriteriaProgress(achievementCriteria, reputation); break; } case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION: { uint32 counter = 0; const FactionStateList factionStateList = GetPlayer()->GetFactionStateList(); for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); iter++) { if(GetPlayer()->ReputationToRank(iter->second.Standing) >= REP_EXALTED) ++counter; } SetCriteriaProgress(achievementCriteria, counter); break; } case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: { WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference); if(!worldOverlayEntry) break; int32 exploreFlag = GetAreaFlagByAreaID(worldOverlayEntry->areatableID); if(exploreFlag < 0) break; uint32 playerIndexOffset = uint32(exploreFlag) / 32; uint32 mask = 1<< (uint32(exploreFlag) % 32); if(GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask) SetCriteriaProgress(achievementCriteria, 1); break; } case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: { // miscvalue1 = itemid // miscvalue2 = diced value if(!miscvalue1) continue; if(miscvalue2 != achievementCriteria->roll_greed_on_loot.rollValue) continue; ItemPrototype const *pProto = objmgr.GetItemPrototype( miscvalue1 ); uint32 requiredItemLevel = 0; if (achievementCriteria->ID == 2412 || achievementCriteria->ID == 2358) requiredItemLevel = 185; if(!pProto || pProto->ItemLevel <requiredItemLevel) continue; SetCriteriaProgress(achievementCriteria, 1, true); break; } } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); } }