From 3fbbe7cfbe1bc51db12bdc1ec7b21c16d1716366 Mon Sep 17 00:00:00 2001 From: Treeston Date: Tue, 1 Sep 2020 00:38:46 +0200 Subject: Core/Misc: DBC std::array refactors, and |Hachievement unit tests --- src/server/game/Achievements/AchievementMgr.h | 2 + src/server/game/AuctionHouse/AuctionHouseMgr.cpp | 2 +- src/server/game/Chat/HyperlinkTags.cpp | 11 +- src/server/game/DataStores/DBCStores.cpp | 4 +- src/server/game/DataStores/DBCStores.h | 2 +- src/server/game/Globals/ObjectMgr.cpp | 2 +- src/server/game/Spells/Spell.cpp | 6 +- src/server/game/Spells/SpellInfo.cpp | 76 ++-- src/server/game/Spells/SpellInfo.h | 22 +- src/server/shared/DataStores/DBCStore.h | 2 + src/server/shared/DataStores/DBCStructure.h | 424 +++++++++++------------ tests/DummyData.cpp | 23 +- tests/DummyData.h | 37 ++ tests/game/Hyperlinks.cpp | 20 +- 14 files changed, 351 insertions(+), 282 deletions(-) diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h index dd28bbd18a4..986b16aba6b 100644 --- a/src/server/game/Achievements/AchievementMgr.h +++ b/src/server/game/Achievements/AchievementMgr.h @@ -405,6 +405,8 @@ class TC_GAME_API AchievementGlobalMgr AchievementRewards m_achievementRewards; AchievementRewardLocales m_achievementRewardLocales; + + friend class UnitTestDataLoader; }; #define sAchievementMgr AchievementGlobalMgr::instance() diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index e80557e2383..93fcedf17bb 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -796,7 +796,7 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player // These are found in ItemRandomSuffix.dbc and ItemRandomProperties.dbc // even though the DBC names seem misleading - char* const* suffix = nullptr; + char const* const* suffix = nullptr; if (propRefID < 0) { diff --git a/src/server/game/Chat/HyperlinkTags.cpp b/src/server/game/Chat/HyperlinkTags.cpp index d9e4fb0aedb..d511265c537 100644 --- a/src/server/game/Chat/HyperlinkTags.cpp +++ b/src/server/game/Chat/HyperlinkTags.cpp @@ -58,13 +58,17 @@ class HyperlinkDataTokenizer bool Trinity::Hyperlinks::LinkTags::achievement::StoreTo(AchievementLinkData& val, std::string_view text) { HyperlinkDataTokenizer t(text); + uint32 achievementId; if (!t.TryConsumeTo(achievementId)) return false; val.Achievement = sAchievementMgr->GetAchievement(achievementId); - if (!(val.Achievement && t.TryConsumeTo(val.CharacterId) && t.TryConsumeTo(val.IsFinished) && - t.TryConsumeTo(val.Month) && t.TryConsumeTo(val.Day))) + + if (!(val.Achievement && t.TryConsumeTo(val.CharacterId) && t.TryConsumeTo(val.IsFinished) && t.TryConsumeTo(val.Month) && t.TryConsumeTo(val.Day))) return false; + if ((12 < val.Month) || (31 < val.Day)) + return false; + int8 year; if (!t.TryConsumeTo(year)) return false; @@ -77,8 +81,7 @@ bool Trinity::Hyperlinks::LinkTags::achievement::StoreTo(AchievementLinkData& va else val.Year = 0; - return (t.TryConsumeTo(val.Criteria[0]) && - t.TryConsumeTo(val.Criteria[1]) && t.TryConsumeTo(val.Criteria[2]) && t.TryConsumeTo(val.Criteria[3]) && t.IsEmpty()); + return (t.TryConsumeTo(val.Criteria[0]) && t.TryConsumeTo(val.Criteria[1]) && t.TryConsumeTo(val.Criteria[2]) && t.TryConsumeTo(val.Criteria[3]) && t.IsEmpty()); } bool Trinity::Hyperlinks::LinkTags::enchant::StoreTo(SpellInfo const*& val, std::string_view text) diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index d62d2c2b12f..eb6ca3c3a49 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -676,14 +676,14 @@ SimpleFactionsList const* GetFactionTeamList(uint32 faction) return nullptr; } -char* GetPetName(uint32 petfamily, uint32 dbclang) +char const* GetPetName(uint32 petfamily, uint32 dbclang) { if (!petfamily) return nullptr; CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(petfamily); if (!pet_family) return nullptr; - return pet_family->Name[dbclang]?pet_family->Name[dbclang]:nullptr; + return pet_family->Name[dbclang]; } TalentSpellPos const* GetTalentSpellPos(uint32 spellId) diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index a273460f434..f3974d09307 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -36,7 +36,7 @@ enum LocaleConstant : uint8; typedef std::list SimpleFactionsList; TC_GAME_API SimpleFactionsList const* GetFactionTeamList(uint32 faction); -TC_GAME_API char* GetPetName(uint32 petfamily, uint32 dbclang); +TC_GAME_API char const* GetPetName(uint32 petfamily, uint32 dbclang); TC_GAME_API uint32 GetTalentSpellCost(uint32 spellId); TC_GAME_API TalentSpellPos const* GetTalentSpellPos(uint32 spellId); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index c3d0cb0996f..8498e19dfc5 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -7869,7 +7869,7 @@ std::string ObjectMgr::GeneratePetName(uint32 entry) if (!cinfo) return std::string(); - char* petname = GetPetName(cinfo->family, sWorld->GetDefaultDbcLocale()); + char const* petname = GetPetName(cinfo->family, sWorld->GetDefaultDbcLocale()); if (petname) return std::string(petname); else diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 6e57a17172f..3412310bce6 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -867,13 +867,14 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar case TARGET_SELECT_CATEGORY_NEARBY: case TARGET_SELECT_CATEGORY_CONE: case TARGET_SELECT_CATEGORY_AREA: + { // targets for effect already selected if (effectMask & processedEffectMask) return; + std::array const& effects = GetSpellInfo()->Effects; // choose which targets we can select at once - for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j) + for (uint32 j = effIndex + 1; j < effects.size(); ++j) { - SpellEffectInfo const* effects = GetSpellInfo()->Effects; if (effects[j].IsEffect() && effects[effIndex].TargetA.GetTarget() == effects[j].TargetA.GetTarget() && effects[effIndex].TargetB.GetTarget() == effects[j].TargetB.GetTarget() && @@ -886,6 +887,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar } processedEffectMask |= effectMask; break; + } default: break; } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 60122176508..7bfb4593469 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -211,8 +211,8 @@ uint32 SpellImplicitTargetInfo::GetExplicitTargetMask(bool& srcSet, bool& dstSet return targetMask; } -SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_TARGETS] = -{ +std::array SpellImplicitTargetInfo::_data = +{ { {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 1 TARGET_UNIT_CASTER {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 2 TARGET_UNIT_NEARBY_ENEMY @@ -324,7 +324,7 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_T {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 108 TARGET_GAMEOBJECT_CONE {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 109 {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 110 TARGET_UNIT_CONE_ENTRY_110 -}; +} }; SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex) { @@ -595,8 +595,8 @@ SpellTargetObjectTypes SpellEffectInfo::GetUsedTargetObjectType() const return _data[Effect].UsedTargetObjectType; } -SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] = -{ +std::array SpellEffectInfo::_data = +{ { // implicit target type used target object type {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 0 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 1 SPELL_EFFECT_INSTAKILL @@ -763,7 +763,7 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] = {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 162 SPELL_EFFECT_TALENT_SPEC_SELECT {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 163 SPELL_EFFECT_163 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 164 SPELL_EFFECT_REMOVE_AURA -}; +} }; SpellInfo::SpellInfo(SpellEntry const* spellEntry) { @@ -819,33 +819,19 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry) RangeEntry = spellEntry->RangeIndex ? sSpellRangeStore.LookupEntry(spellEntry->RangeIndex) : nullptr; Speed = spellEntry->Speed; StackAmount = spellEntry->CumulativeAura; - for (uint8 i = 0; i < 2; ++i) - Totem[i] = spellEntry->Totem[i]; - - for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i) - Reagent[i] = spellEntry->Reagent[i]; - - for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i) - ReagentCount[i] = spellEntry->ReagentCount[i]; - + Totem = spellEntry->Totem; + Reagent = spellEntry->Reagent; + ReagentCount = spellEntry->ReagentCount; EquippedItemClass = spellEntry->EquippedItemClass; EquippedItemSubClassMask = spellEntry->EquippedItemSubclass; EquippedItemInventoryTypeMask = spellEntry->EquippedItemInvTypes; - for (uint8 i = 0; i < 2; ++i) - TotemCategory[i] = spellEntry->RequiredTotemCategoryID[i]; - - for (uint8 i = 0; i < 2; ++i) - SpellVisual[i] = spellEntry->SpellVisualID[i]; - + TotemCategory = spellEntry->RequiredTotemCategoryID; + SpellVisual = spellEntry->SpellVisualID; SpellIconID = spellEntry->SpellIconID; ActiveIconID = spellEntry->ActiveIconID; Priority = spellEntry->SpellPriority; - for (uint8 i = 0; i < 16; ++i) - SpellName[i] = spellEntry->Name[i]; - - for (uint8 i = 0; i < 16; ++i) - Rank[i] = spellEntry->NameSubtext[i]; - + SpellName = spellEntry->Name; + Rank = spellEntry->NameSubtext; MaxTargetLevel = spellEntry->MaxTargetLevel; MaxAffectedTargets = spellEntry->MaxTargets; SpellFamilyName = spellEntry->SpellClassSet; @@ -2856,9 +2842,9 @@ void SpellInfo::_LoadImmunityInfo() void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool apply) const { - ImmunityInfo const* immuneInfo = _immunityInfo + effIndex; + ImmunityInfo const& immuneInfo = _immunityInfo[effIndex]; - if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask) + if (uint32 schoolImmunity = immuneInfo.SchoolImmuneMask) { target->ApplySpellImmune(Id, IMMUNITY_SCHOOL, schoolImmunity, apply); @@ -2876,7 +2862,7 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool app } } - if (uint32 mechanicImmunity = immuneInfo->MechanicImmuneMask) + if (uint32 mechanicImmunity = immuneInfo.MechanicImmuneMask) { for (uint32 i = 0; i < MAX_MECHANIC; ++i) if (mechanicImmunity & (1 << i)) @@ -2886,7 +2872,7 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool app target->RemoveAurasWithMechanic(mechanicImmunity, AURA_REMOVE_BY_DEFAULT, Id); } - if (uint32 dispelImmunity = immuneInfo->DispelImmune) + if (uint32 dispelImmunity = immuneInfo.DispelImmune) { target->ApplySpellImmune(Id, IMMUNITY_DISPEL, dispelImmunity, apply); @@ -2903,17 +2889,17 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool app } } - if (uint32 damageImmunity = immuneInfo->DamageSchoolMask) + if (uint32 damageImmunity = immuneInfo.DamageSchoolMask) target->ApplySpellImmune(Id, IMMUNITY_DAMAGE, damageImmunity, apply); - for (AuraType auraType : immuneInfo->AuraTypeImmune) + for (AuraType auraType : immuneInfo.AuraTypeImmune) { target->ApplySpellImmune(Id, IMMUNITY_STATE, auraType, apply); if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)) target->RemoveAurasByType(auraType); } - for (SpellEffects effectType : immuneInfo->SpellEffectImmune) + for (SpellEffects effectType : immuneInfo.SpellEffectImmune) target->ApplySpellImmune(Id, IMMUNITY_EFFECT, effectType, apply); } @@ -2922,22 +2908,20 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf if (!auraSpellInfo) return false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (ImmunityInfo const& immuneInfo : _immunityInfo) { - ImmunityInfo const* immuneInfo = _immunityInfo + i; - if (!auraSpellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE)) { - if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask) + if (uint32 schoolImmunity = immuneInfo.SchoolImmuneMask) if ((auraSpellInfo->SchoolMask & schoolImmunity) != 0) return true; } - if (uint32 mechanicImmunity = immuneInfo->MechanicImmuneMask) + if (uint32 mechanicImmunity = immuneInfo.MechanicImmuneMask) if ((mechanicImmunity & (1 << auraSpellInfo->Mechanic)) != 0) return true; - if (uint32 dispelImmunity = immuneInfo->DispelImmune) + if (uint32 dispelImmunity = immuneInfo.DispelImmune) if (auraSpellInfo->Dispel == dispelImmunity) return true; @@ -2948,8 +2932,8 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf if (!effectName) continue; - auto spellImmuneItr = immuneInfo->SpellEffectImmune.find(static_cast(effectName)); - if (spellImmuneItr == immuneInfo->SpellEffectImmune.cend()) + auto spellImmuneItr = immuneInfo.SpellEffectImmune.find(static_cast(effectName)); + if (spellImmuneItr == immuneInfo.SpellEffectImmune.cend()) { immuneToAllEffects = false; break; @@ -2957,7 +2941,7 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf if (uint32 mechanic = auraSpellInfo->Effects[effIndex].Mechanic) { - if (!(immuneInfo->MechanicImmuneMask & (1 << mechanic))) + if (!(immuneInfo.MechanicImmuneMask & (1 << mechanic))) { immuneToAllEffects = false; break; @@ -2969,13 +2953,13 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf if (uint32 auraName = auraSpellInfo->Effects[effIndex].ApplyAuraName) { bool isImmuneToAuraEffectApply = false; - auto auraImmuneItr = immuneInfo->AuraTypeImmune.find(static_cast(auraName)); - if (auraImmuneItr != immuneInfo->AuraTypeImmune.cend()) + auto auraImmuneItr = immuneInfo.AuraTypeImmune.find(static_cast(auraName)); + if (auraImmuneItr != immuneInfo.AuraTypeImmune.cend()) isImmuneToAuraEffectApply = true; if (!isImmuneToAuraEffectApply && !auraSpellInfo->IsPositiveEffect(effIndex) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE)) { - if (uint32 applyHarmfulAuraImmunityMask = immuneInfo->ApplyHarmfulAuraImmuneMask) + if (uint32 applyHarmfulAuraImmunityMask = immuneInfo.ApplyHarmfulAuraImmuneMask) if ((auraSpellInfo->GetSchoolMask() & applyHarmfulAuraImmunityMask) != 0) isImmuneToAuraEffectApply = true; } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index c48e90cde61..e897b63cfe1 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -232,7 +232,7 @@ private: SpellTargetCheckTypes SelectionCheckType; // defines selection criteria SpellTargetDirectionTypes DirectionType; // direction for cone and dest targets }; - static StaticData _data[TOTAL_SPELL_TARGETS]; + static std::array _data; }; class TC_GAME_API SpellEffectInfo @@ -296,7 +296,7 @@ private: SpellEffectImplicitTargetTypes ImplicitTargetType; // defines what target can be added to effect target list if there's no valid target type provided for effect SpellTargetObjectTypes UsedTargetObjectType; // defines valid target object type for spell effect }; - static StaticData _data[TOTAL_SPELL_EFFECTS]; + static std::array _data; }; struct TC_GAME_API SpellDiminishInfo @@ -376,19 +376,19 @@ class TC_GAME_API SpellInfo SpellRangeEntry const* RangeEntry; float Speed; uint32 StackAmount; - uint32 Totem[2]; - int32 Reagent[MAX_SPELL_REAGENTS]; - uint32 ReagentCount[MAX_SPELL_REAGENTS]; + std::array Totem; + std::array Reagent; + std::array ReagentCount; int32 EquippedItemClass; int32 EquippedItemSubClassMask; int32 EquippedItemInventoryTypeMask; - uint32 TotemCategory[2]; - uint32 SpellVisual[2]; + std::array TotemCategory; + std::array SpellVisual; uint32 SpellIconID; uint32 ActiveIconID; uint32 Priority; - char* SpellName[16]; - char* Rank[16]; + std::array SpellName; + std::array Rank; uint32 MaxTargetLevel; uint32 MaxAffectedTargets; uint32 SpellFamilyName; @@ -397,7 +397,7 @@ class TC_GAME_API SpellInfo uint32 PreventionType; int32 AreaGroupId; uint32 SchoolMask; - SpellEffectInfo Effects[MAX_SPELL_EFFECTS]; + std::array Effects; uint32 ExplicitTargetMask; SpellChainNode const* ChainEntry; @@ -552,7 +552,7 @@ class TC_GAME_API SpellInfo uint32 _allowedMechanicMask; - ImmunityInfo _immunityInfo[MAX_SPELL_EFFECTS]; + std::array _immunityInfo; }; #endif // _SPELLINFO_H diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h index cccc4650b05..87c119e9cd8 100644 --- a/src/server/shared/DataStores/DBCStore.h +++ b/src/server/shared/DataStores/DBCStore.h @@ -98,6 +98,8 @@ class DBCStorage : public DBCStorageBase DBCStorage(DBCStorage const& right) = delete; DBCStorage& operator=(DBCStorage const& right) = delete; + + friend class UnitTestDataLoader; }; #endif diff --git a/src/server/shared/DataStores/DBCStructure.h b/src/server/shared/DataStores/DBCStructure.h index e6deee31630..e3b67d43703 100644 --- a/src/server/shared/DataStores/DBCStructure.h +++ b/src/server/shared/DataStores/DBCStructure.h @@ -34,16 +34,16 @@ struct AchievementEntry int32 Faction; // 1 -1=all, 0=horde, 1=alliance int32 InstanceID; // 2 -1=none //uint32 Supercedes; // 3 its Achievement parent (can`t start while parent uncomplete, use its Criteria if don`t have own, use its progress on begin) - char* Title[16]; // 4-19 + std::array Title; // 4-19 //uint32 Title_lang_mask; // 20 - //char* Description[16]; // 21-36 + //char const* Description[16]; // 21-36 //uint32 Description_lang_mask; // 37 uint32 Category; // 38 uint32 Points; // 39 reward points //uint32 UiOrder; // 40 icon (from SpellIcon.dbc) uint32 Flags; // 41 //uint32 IconID; // 42 - //char* Reward[16]; // 43-58 + //char const* Reward[16]; // 43-58 //uint32 Reward_lang_mask; // 59 uint32 MinimumCriteria; // 60 - need this count of completed criterias (own or referenced achievement criterias) uint32 SharesCriteria; // 61 - referenced achievement (counting of all completed criterias) @@ -164,7 +164,7 @@ struct AchievementCriteriaEntry uint32 Asset; } AdditionalRequirements[MAX_CRITERIA_REQUIREMENTS]; // 5-8 - //char* Description[16]; // 9-24 + //char const* Description[16]; // 9-24 //uint32 Description_lang_mask; // 25 uint32 Flags; // 26 uint32 StartEvent; // 27 AchievementCriteriaTimedTypes @@ -186,7 +186,7 @@ struct AreaTableEntry //uint32 ZoneMusic; // 8 //uint32 IntroSound; // 9 int32 ExplorationLevel; // 10 - char* AreaName[16]; // 11-26 + char const* AreaName[16]; // 11-26 //uint32 AreaName_lang_mask; // 27 uint32 FactionGroupMask; // 28 uint32 LiquidTypeID[4]; // 29-32 liquid override by type @@ -233,9 +233,9 @@ struct AreaPOIEntry uint32 ContinentID; // 15 //uint32 Flags; // 16 uint32 AreaID; // 17 - //char* Name[16]; // 18-33 + //char const* Name[16]; // 18-33 //uint32 Name_lang_mask; // 34 - //char* Description[16]; // 35-50 + //char const* Description[16]; // 35-50 //uint32 Description_lang_mask; // 51 uint32 WorldStateID; // 52 //uint32 WorldMapLink; // 53 @@ -259,7 +259,7 @@ struct AuctionHouseEntry uint32 FactionID; // 1 id of faction.dbc for player factions associated with city uint32 DepositRate; // 2 1/3 from real uint32 ConsignmentRate; // 3 - //char* Name[16]; // 4-19 + //char const* Name[16]; // 4-19 //uint32 Name_lang_mask; // 20 }; @@ -282,7 +282,7 @@ struct BarberShopStyleEntry { uint32 ID; // 0 uint32 Type; // 1 value 0 -> hair, value 2 -> facialhair - //char* DisplayName[16]; // 2-17 + //char const* DisplayName[16]; // 2-17 //uint32 DisplayName_lang_mask; // 18 //uint32 Description[16]; // 19-34, all empty //uint32 Description_lang_mask; // 35 @@ -298,7 +298,7 @@ struct BattlemasterListEntry int32 MapID[8]; // 1-8 uint32 InstanceType; // 9 map type (3 - BG, 4 - arena) //uint32 GroupsAllowed; // 10 - char* Name[16]; // 11-26 + char const* Name[16]; // 11-26 //uint32 Name_lang_mask; // 27 uint32 MaxGroupSize; // 28 used for checking if queue as group uint32 HolidayWorldState; // 29 @@ -335,7 +335,7 @@ struct CharSectionsEntry uint32 RaceID; // 1 uint32 SexID; // 2 uint32 BaseSection; // 3 - //char* TextureName[3]; // 4-6 + //char const* TextureName[3]; // 4-6 uint32 Flags; // 7 uint32 VariationIndex; // 8 uint32 ColorIndex; // 9 @@ -361,9 +361,9 @@ struct CharTitlesEntry { uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId() //uint32 ConditionID; // 1 - char* Name[16]; // 2-17 male + char const* Name[16]; // 2-17 male //uint32 Name_lang_mask; // 18 - char* Name1[16]; // 19-34 female + char const* Name1[16]; // 19-34 female //uint32 Name1_lang_mask; // 35 uint32 MaskID; // 36 used in PLAYER_CHOSEN_TITLE and 1< ShapeshiftMask; // 12-13 + std::array ShapeshiftExclude; // 14-15 + uint32 Targets; // 16 + uint32 TargetCreatureType; // 17 + uint32 RequiresSpellFocus; // 18 + uint32 FacingCasterFlags; // 19 + uint32 CasterAuraState; // 20 + uint32 TargetAuraState; // 21 + uint32 ExcludeCasterAuraState; // 22 + uint32 ExcludeTargetAuraState; // 23 + uint32 CasterAuraSpell; // 24 + uint32 TargetAuraSpell; // 25 + uint32 ExcludeCasterAuraSpell; // 26 + uint32 ExcludeTargetAuraSpell; // 27 + uint32 CastingTimeIndex; // 28 + uint32 RecoveryTime; // 29 + uint32 CategoryRecoveryTime; // 30 + uint32 InterruptFlags; // 31 + uint32 AuraInterruptFlags; // 32 + uint32 ChannelInterruptFlags; // 33 + uint32 ProcTypeMask; // 34 + uint32 ProcChance; // 35 + uint32 ProcCharges; // 36 + uint32 MaxLevel; // 37 + uint32 BaseLevel; // 38 + uint32 SpellLevel; // 39 + uint32 DurationIndex; // 40 + uint32 PowerType; // 41 + uint32 ManaCost; // 42 + uint32 ManaCostPerLevel; // 43 + uint32 ManaPerSecond; // 44 + uint32 ManaPerSecondPerLevel; // 45 + uint32 RangeIndex; // 46 + float Speed; // 47 + //uint32 ModalNextSpell; // 48 + uint32 CumulativeAura; // 49 + std::array Totem; // 50-51 + std::array Reagent; // 52-59 + std::array ReagentCount; // 60-67 + int32 EquippedItemClass; // 68 + int32 EquippedItemSubclass; // 69 + int32 EquippedItemInvTypes; // 70 + std::array Effect; // 71-73 + std::array EffectDieSides; // 74-76 + std::array EffectRealPointsPerLevel; // 77-79 + std::array EffectBasePoints; // 80-82 + std::array EffectMechanic; // 83-85 + std::array EffectImplicitTargetA; // 86-88 + std::array EffectImplicitTargetB; // 89-91 + std::array EffectRadiusIndex; // 92-94 + std::array EffectAura; // 95-97 + std::array EffectAuraPeriod; // 98-100 + std::array EffectAmplitude; // 101-103 + std::array EffectChainTargets; // 104-106 + std::array EffectItemType; // 107-109 + std::array EffectMiscValue; // 110-112 + std::array EffectMiscValueB; // 113-115 + std::array EffectTriggerSpell; // 116-118 + std::array EffectPointsPerCombo; // 119-121 + std::array EffectSpellClassMask; // 122-130 + std::array SpellVisualID; // 131-132 + uint32 SpellIconID; // 133 + uint32 ActiveIconID; // 134 + uint32 SpellPriority; // 135 + std::array Name; // 136-151 + //uint32 Name_lang_mask; // 152 + std::array NameSubtext; // 153-168 + //uint32 NameSubtext_lang_mask; // 169 + //std::array Description; // 170-185 + //uint32 Description_lang_mask; // 186 + //std::array AuraDescription; // 187-202 + //uint32 AuraDescription_lang_mask; // 203 + uint32 ManaCostPct; // 204 + uint32 StartRecoveryCategory; // 205 + uint32 StartRecoveryTime; // 206 + uint32 MaxTargetLevel; // 207 + uint32 SpellClassSet; // 208 + flag96 SpellClassMask; // 209-211 + uint32 MaxTargets; // 212 + uint32 DefenseType; // 213 + uint32 PreventionType; // 214 + //uint32 StanceBarOrder; // 215 + std::array EffectChainAmplitude; // 216-218 + //uint32 MinFactionID; // 219 + //uint32 MinReputation; // 220 + //uint32 RequiredAuraVision; // 221 + std::array RequiredTotemCategoryID; // 222-223 + int32 RequiredAreasID; // 224 + uint32 SchoolMask; // 225 + uint32 RuneCostID; // 226 + //uint32 SpellMissileID; // 227 + //uint32 PowerDisplayID; // 228 + std::array EffectBonusCoefficient; // 229-231 + //uint32 DescriptionVariablesID; // 232 + //uint32 Difficulty; // 233 }; typedef std::set PetFamilySpellsSet; @@ -1529,7 +1529,7 @@ struct SpellDurationEntry struct SpellFocusObjectEntry { uint32 ID; // 0 - //char* Name[16]; // 1-15 + //char const* Name[16]; // 1-15 //uint32 Name_lang_mask; // 16 }; @@ -1541,7 +1541,7 @@ struct SpellItemEnchantmentEntry uint32 EffectPointsMin[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 5-7 //uint32 EffectPointsMax[MAX_ITEM_ENCHANTMENT_EFFECTS] // 8-10 uint32 EffectArg[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 11-13 - char* Name[16]; // 14-29 + char const* Name[16]; // 14-29 //uint32 Name_lang_mask; // 30 uint32 ItemVisual; // 31 uint32 Flags; // 32 @@ -1577,9 +1577,9 @@ struct SpellRangeEntry float RangeMin[2]; // 1-2 [0] Hostile [1] Friendly float RangeMax[2]; // 3-4 [0] Hostile [1] Friendly uint32 Flags; // 5 - //char* DisplayName[16]; // 6-21 + //char const* DisplayName[16]; // 6-21 //uint32 DisplayName_lang_mask; // 22 - //char* DisplayNameShort[16]; // 23-38 + //char const* DisplayNameShort[16]; // 23-38 //uint32 DisplayNameShort_lang_mask; // 39 }; @@ -1599,7 +1599,7 @@ struct SpellShapeshiftFormEntry { uint32 ID; // 0 //uint32 BonusActionBar; // 1 - //char* Name[16]; // 2-17 + //char const* Name[16]; // 2-17 //uint32 Name_lang_mask; // 18 uint32 Flags; // 19 int32 CreatureType; // 20 <= 0 humanoid, other normal creature types @@ -1677,14 +1677,14 @@ struct TalentEntry struct TalentTabEntry { uint32 ID; // 0 - //char* Name[16]; // 1-16 + //char const* Name[16]; // 1-16 //uint32 Name_lang_mask; // 17 //unit32 SpellIconID; // 18 //uint32 RaceMask; // 19 uint32 ClassMask; // 20 uint32 PetTalentMask; // 21 uint32 OrderIndex; // 22 - //char* BackgroundFile; // 23 + //char const* BackgroundFile; // 23 }; struct TaxiNodesEntry @@ -1692,7 +1692,7 @@ struct TaxiNodesEntry uint32 ID; // 0 uint32 ContinentID; // 1 DBCPosition3D Pos; // 2-4 - char* Name[16]; // 5-21 + char const* Name[16]; // 5-21 //uint32 Name_lang_mask; // 22 uint32 MountCreatureID[2]; // 23-24 }; @@ -1727,7 +1727,7 @@ struct TeamContributionPointsEntry struct TotemCategoryEntry { uint32 ID; // 0 - //char* Name[16]; // 1-16 + //char const* Name[16]; // 1-16 //uint32 Name_lang_mask; // 17 uint32 TotemCategoryType; // 18 (one for specialization) uint32 TotemCategoryMask; // 19 (compatibility mask for same type: different for totems, compatible from high to low for rods) @@ -1778,9 +1778,9 @@ struct VehicleEntry float MsslTrgtArcRepeat; // 25 float MsslTrgtArcWidth; // 26 float MsslTrgtImpactRadius[2]; // 27-28 - char* MsslTrgtArcTexture; // 29 - char* MsslTrgtImpactTexture; // 30 - char* MsslTrgtImpactModel[2]; // 31-32 + char const* MsslTrgtArcTexture; // 29 + char const* MsslTrgtImpactTexture; // 30 + char const* MsslTrgtImpactModel[2]; // 31-32 float CameraYawOffset; // 33 uint32 UiLocomotionType; // 34 float MsslTrgtImpactTexRadius; // 35 @@ -1870,7 +1870,7 @@ struct WMOAreaTableEntry //uint32 IntroSound; // 8 uint32 Flags; // 9 used for indoor/outdoor determination uint32 AreaTableID; // 10 link to AreaTableEntry.ID - //char* AreaName[16]; // 11 + //char const* AreaName[16]; // 11 //uint32 AreaName_lang_mask; // 12 }; @@ -1879,7 +1879,7 @@ struct WorldMapAreaEntry //uint32 ID; // 0 uint32 MapID; // 1 uint32 AreaID; // 2 - //char* AreaName // 3 + //char const* AreaName // 3 float LocLeft; // 4 float LocRight; // 5 float LocTop; // 6 @@ -1898,7 +1898,7 @@ struct WorldMapOverlayEntry uint32 AreaID[MAX_WORLD_MAP_OVERLAY_AREA_IDX]; // 2-5 //uint32 MapPointX; // 6 //uint32 MapPointY; // 7 - //char* TextureName // 8 + //char const* TextureName // 8 //uint32 TextureWidth; // 9 //uint32 TextureHeight; // 10 //uint32 OffsetX; // 11 @@ -1914,7 +1914,7 @@ struct WorldSafeLocsEntry uint32 ID; // 0 uint32 Continent; // 1 DBCPosition3D Loc; // 2-4 - //char* AreaName[16] // 5-20 + //char const* AreaName[16] // 5-20 //uint32 AreaName_lang_mask; // 21 }; @@ -1925,17 +1925,17 @@ struct WorldStateUI uint32 MapID; // 1 Can be -1 to show up everywhere. uint32 AreaID; // 2 Can be zero for "everywhere". uint32 PhaseShift; // 3 Phase this WorldState is avaliable in - char* Icon; // 4 The icon that is used in the interface. - char* String; // 5-20 + char const* Icon; // 4 The icon that is used in the interface. + char const* String; // 5-20 uint32 String_lang_mask; // 21 - char* Tooltip; // 22-37 + char const* Tooltip; // 22-37 uint32 Tooltip_lang_mask; // 38 uint32 StateVariable; // 39 uint32 Type; // 40 0 = unknown, 1 = unknown, 2 = not shown in ui, 3 = wintergrasp - char* DynamicIcon; // 41 - char* DynamicTooltip[16]; // 42-57 + char const* DynamicIcon; // 41 + char const* DynamicTooltip[16]; // 42-57 uint32 DynamicTooltip_lang_mask; // 58 - char* ExtendedUI; // 59 + char const* ExtendedUI; // 59 uint32 ExtendedUIStateVariable[3]; // 60-62 }; */ diff --git a/tests/DummyData.cpp b/tests/DummyData.cpp index 916edb0accd..b6b70363bc7 100644 --- a/tests/DummyData.cpp +++ b/tests/DummyData.cpp @@ -1,4 +1,4 @@ -/* +/* * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it @@ -17,6 +17,7 @@ #include "DummyData.h" +#include "AchievementMgr.h" #include "ItemDefines.h" #include "ItemTemplate.h" #include "ObjectMgr.h" @@ -127,3 +128,23 @@ SetItemLocale(6948, LocaleConstant::LOCALE_esMX, "Piedra de hogar"); } + +static UnitTestDataLoader::DBC achievements(sAchievementStore); +/*static*/ void UnitTestDataLoader::LoadAchievementTemplates() +{ + auto loader = achievements.Loader(); + + AchievementEntry& toc5 = loader.Add(); + toc5.ID = 4298; + toc5.Faction = 1; + toc5.InstanceID = 650; + toc5.Title.fill(""); + toc5.Title[LOCALE_enUS] = "Heroic: Trial of the Champion"; + toc5.Title[LOCALE_esES] = "Heroico: Prueba del Campe\xc3\xb3n"; + toc5.Title[LOCALE_esMX] = "Heroico: Prueba del Campe\xc3\xb3n"; + toc5.Category = 14921; + toc5.Points = 10; + toc5.Flags = 0; + toc5.MinimumCriteria = 0; + toc5.SharesCriteria = 0; +} diff --git a/tests/DummyData.h b/tests/DummyData.h index 98812d3b6b8..f1cf76c073a 100644 --- a/tests/DummyData.h +++ b/tests/DummyData.h @@ -20,6 +20,7 @@ #include "Common.h" #include "Define.h" +#include "DBCStore.h" #include @@ -28,6 +29,42 @@ struct ItemTemplate; class UnitTestDataLoader { public: + template + class DBC + { + class LoaderGuard + { + public: + LoaderGuard(DBC& d) : _d(d) {} + ~LoaderGuard() { _d.Dump(); } + + T& Add() { return _d._storage.emplace_back(); } + private: + DBC& _d; + }; + + public: + DBC(DBCStorage& store) : _store(store) {} + LoaderGuard Loader() { return {*this}; } + void Dump() + { + delete[] _store._indexTable.AsT; + for (T const& entry : _storage) + if (entry.*ID >= _store._indexTableSize) + _store._indexTableSize = entry.*ID + 1; + _store._indexTable.AsT = new T*[_store._indexTableSize]; + for (size_t i = 0; i < _store._indexTableSize; ++i) + _store._indexTable.AsT[i] = nullptr; + for (T& entry : _storage) + _store._indexTable.AsT[entry.*ID] = &entry; + } + + private: + std::vector _storage; + DBCStorage& _store; + }; + + static void LoadAchievementTemplates(); static void LoadItemTemplates(); private: diff --git a/tests/game/Hyperlinks.cpp b/tests/game/Hyperlinks.cpp index e7ac5287f74..4648d295328 100644 --- a/tests/game/Hyperlinks.cpp +++ b/tests/game/Hyperlinks.cpp @@ -1,4 +1,4 @@ -/* +/* * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it @@ -72,3 +72,21 @@ TEST_CASE("|Hitem validation", "[Hyperlinks]") REQUIRE(false == CheckAllLinks("This is a |cffffffff|Hitem:6948:-1:0:0:0:0:0:0:-1|h[Hearthstone]|h|r that is quite negative.")); } } + +TEST_CASE("|Hachievement validation", "[Hyperlinks]") +{ + UnitTestDataLoader::LoadAchievementTemplates(); + sWorld->setIntConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY, 1); + + REQUIRE(true == CheckAllLinks("|cffffff00|Hachievement:4298:00000000000000FD:0:0:0:-1:0:0:0:0|h[Heroic: Trial of the Champion]|h|r")); + REQUIRE(false == CheckAllLinks("|cffffff00|Hachievement|h[Heroic: Trial of the Champion]|h|r")); + REQUIRE(false == CheckAllLinks("|cffffff00|Hachievement:1:00000000000000FD:0:0:0:-1:0:0:0:0|h[Heroic: Trial of the Champion]|h|r")); + REQUIRE(false == CheckAllLinks("|cffff0000|Hachievement:4298:00000000000000FD:0:0:0:-1:0:0:0:0|h[Heroic: Trial of the Champion]|h|r")); + REQUIRE(false == CheckAllLinks("|cffffff00|Hachievement:4298:00000000000000XY:0:0:0:-1:0:0:0:0|h[Heroic: Trial of the Champion]|h|r")); + REQUIRE(true == CheckAllLinks("|cffffff00|Hachievement:4298:00000000000000FD:1:12:20:12:0:0:0:0|h[Heroic: Trial of the Champion]|h|r")); + REQUIRE(false == CheckAllLinks("|cffffff00|Hachievement:4298:00000000000000FD:1:12:40:12:0:0:0:0|h[Heroic: Trial of the Champion]|h|r")); + REQUIRE(false == CheckAllLinks("|cffffff00|Hachievement:4298:00000000000000FD:1:14:20:12:0:0:0:0|h[Heroic: Trial of the Champion]|h|r")); + REQUIRE(false == CheckAllLinks("|cffffff00|Hachievement:4298:00000000000000FD:1:0:0:-1:0:0:0:0|h[Heroic: Trial of the Champion]|h|r")); + + REQUIRE(true == CheckAllLinks("|cffffff00|Hachievement:4298:00000000000000FD:1:12:20:12:0:0:0:0|h[Heroico: Prueba del Campe\xc3\xb3n]|h|r")); +} -- cgit v1.2.3