aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Utilities/Util.h2
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp60
-rw-r--r--src/server/game/Conditions/ConditionMgr.h3
-rw-r--r--src/server/game/DataStores/DB2HotfixGenerator.h8
-rw-r--r--src/server/game/Entities/Player/Player.cpp6
-rw-r--r--src/server/game/Spells/SpellMgr.cpp30
6 files changed, 62 insertions, 47 deletions
diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h
index 4907b4edbae..9ee4d1d62c0 100644
--- a/src/common/Utilities/Util.h
+++ b/src/common/Utilities/Util.h
@@ -530,7 +530,7 @@ constexpr typename std::underlying_type<E>::type AsUnderlyingType(E enumValue)
}
template<typename Ret, typename T1, typename... T>
-Ret* Coalesce(T1* first, T*... rest)
+constexpr Ret* Coalesce(T1* first, T*... rest)
{
if constexpr (sizeof...(T) > 0)
return (first ? static_cast<Ret*>(first) : Coalesce<Ret>(rest...));
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index efe0d2ec725..a5943a1a38d 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -93,7 +93,8 @@ char const* const ConditionMgr::StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX_D
"Trainer Spell",
"Object Visibility (by ID)",
"Spawn Group",
- "Player Condition"
+ "Player Condition",
+ "Skill Line Ability"
};
ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[CONDITION_MAX] =
@@ -159,27 +160,20 @@ ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[COND
{ "String ID", false, false, false, true }
};
-ConditionSourceInfo::ConditionSourceInfo(WorldObject const* target0, WorldObject const* target1, WorldObject const* target2)
+ConditionSourceInfo::ConditionSourceInfo(WorldObject const* target0, WorldObject const* target1, WorldObject const* target2) :
+ mConditionTargets({ target0, target1, target2 }),
+ mConditionMap(nullptr),
+ mLastFailedCondition(nullptr)
{
- mConditionTargets[0] = target0;
- mConditionTargets[1] = target1;
- mConditionTargets[2] = target2;
- if (target0)
- mConditionMap = target0->GetMap();
- else if (target1)
- mConditionMap = target1->GetMap();
- else if (target2)
- mConditionMap = target2->GetMap();
- else
- mConditionMap = nullptr;
- mLastFailedCondition = nullptr;
+ if (WorldObject const* target = Coalesce<WorldObject const>(target0, target1, target2))
+ mConditionMap = target->GetMap();
}
-ConditionSourceInfo::ConditionSourceInfo(Map const* map)
+ConditionSourceInfo::ConditionSourceInfo(Map const* map) :
+ mConditionTargets(),
+ mConditionMap(map),
+ mLastFailedCondition(nullptr)
{
- std::fill(std::begin(mConditionTargets), std::end(mConditionTargets), nullptr);
- mConditionMap = map;
- mLastFailedCondition = nullptr;
}
std::size_t ConditionId::GetHash() const
@@ -946,7 +940,7 @@ std::string Condition::ToString(bool ext /*= false*/) const
}
ss << "]";
- return ss.str();
+ return std::move(ss).str();
}
ConditionMgr::ConditionMgr() { }
@@ -2067,6 +2061,22 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
}
break;
}
+ case CONDITION_SOURCE_TYPE_SKILL_LINE_ABILITY:
+ {
+ SkillLineAbilityEntry const* skillLineAbility = sSkillLineAbilityStore.LookupEntry(cond->SourceEntry);
+ if (!skillLineAbility)
+ {
+ TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in SkillLineAbility.db2, ignoring.", cond->ToString());
+ return false;
+ }
+ if (skillLineAbility->GetAcquireMethod() != SkillLineAbilityAcquireMethod::LearnedOrAutomaticCharLevel)
+ {
+ TC_LOG_ERROR("sql.sql", "{} in SkillLineAbility.db2 does not have AcquireMethod = {} (LearnedOrAutomaticCharLevel), ignoring.",
+ cond->ToString(), SkillLineAbilityAcquireMethod::LearnedOrAutomaticCharLevel);
+ return false;
+ }
+ break;
+ }
case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
case CONDITION_SOURCE_TYPE_SMART_EVENT:
@@ -3228,7 +3238,7 @@ static int32(* const WorldStateExpressionFunctions[WSE_FUNCTION_MAX])(Map const*
// WSE_FUNCTION_CLOCK_HOUR
[](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
{
- uint32 currentHour = GameTime::GetDateAndTime()->tm_hour + 1;
+ int32 currentHour = GameTime::GetDateAndTime()->tm_hour + 1;
return currentHour <= 12 ? (currentHour ? currentHour : 12) : currentHour - 12;
},
@@ -3456,7 +3466,7 @@ int32 EvalSingleValue(ByteBuffer& buffer, Map const* map)
}
case WorldStateExpressionValueType::WorldState:
{
- uint32 worldStateId = buffer.read<uint32>();
+ int32 worldStateId = buffer.read<int32>();
value = sWorldStateMgr->GetValue(worldStateId, map);
break;
}
@@ -3661,7 +3671,7 @@ int32 GetUnitConditionVariable(Unit const* unit, Unit const* otherUnit, UnitCond
case UnitConditionVariable::IsChannelingSpell: // this is supposed to return spell id by client code but data always has 0 or 1
return unit->GetChannelSpellId() != 0;
case UnitConditionVariable::NumberOfMeleeAttackers:
- return std::count_if(unit->getAttackers().begin(), unit->getAttackers().end(), [unit](Unit* attacker)
+ return std::ranges::count_if(unit->getAttackers(), [unit](Unit const* attacker)
{
float distance = std::max(unit->GetCombatReach() + attacker->GetCombatReach() + 1.3333334f, 5.0f);
if (unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) || attacker->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
@@ -3710,7 +3720,7 @@ int32 GetUnitConditionVariable(Unit const* unit, Unit const* otherUnit, UnitCond
case UnitConditionVariable::NumberOfAttackers:
return unit->getAttackers().size();
case UnitConditionVariable::NumberOfRangedAttackers:
- return std::count_if(unit->getAttackers().begin(), unit->getAttackers().end(), [unit](Unit* attacker)
+ return std::ranges::count_if(unit->getAttackers(), [unit](Unit const* attacker)
{
float distance = std::max(unit->GetCombatReach() + attacker->GetCombatReach() + 1.3333334f, 5.0f);
if (unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) || attacker->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
@@ -3810,10 +3820,10 @@ int32 GetUnitConditionVariable(Unit const* unit, Unit const* otherUnit, UnitCond
case UnitConditionVariable::IsHovering:
return unit->IsHovering();
case UnitConditionVariable::HasHelpfulAuraEffect:
- return value >= 0 && value < int32(TOTAL_AURAS) && std::find_if(unit->GetAuraEffectsByType(AuraType(value)).begin(), unit->GetAuraEffectsByType(AuraType(value)).end(), [unit](AuraEffect const* aurEff)
+ return value >= 0 && value < int32(TOTAL_AURAS) && std::ranges::any_of(unit->GetAuraEffectsByType(AuraType(value)), [unit](AuraEffect const* aurEff)
{
return (aurEff->GetBase()->GetApplicationOfTarget(unit->GetGUID())->GetFlags() & AFLAG_NEGATIVE) == 0;
- }) != unit->GetAuraEffectsByType(AuraType(value)).end();
+ });
case UnitConditionVariable::HasHelpfulAuraSchool:
return unit->GetAuraApplication([value](AuraApplication const* aurApp)
{
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index eba98022709..0a618a6ec95 100644
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -186,6 +186,7 @@ enum ConditionSourceType
CONDITION_SOURCE_TYPE_OBJECT_ID_VISIBILITY = 32,
CONDITION_SOURCE_TYPE_SPAWN_GROUP = 33,
CONDITION_SOURCE_TYPE_PLAYER_CONDITION = 34,
+ CONDITION_SOURCE_TYPE_SKILL_LINE_ABILITY = 35,
CONDITION_SOURCE_TYPE_MAX_DB_ALLOWED,
CONDITION_SOURCE_TYPE_REFERENCE_CONDITION = CONDITION_SOURCE_TYPE_MAX_DB_ALLOWED, // internal, not set in db
@@ -218,7 +219,7 @@ enum MaxConditionTargets
struct TC_GAME_API ConditionSourceInfo
{
- WorldObject const* mConditionTargets[MAX_CONDITION_TARGETS]; // an array of targets available for conditions
+ std::array<WorldObject const*, MAX_CONDITION_TARGETS> mConditionTargets; // an array of targets available for conditions
Map const* mConditionMap;
Condition const* mLastFailedCondition;
ConditionSourceInfo(WorldObject const* target0, WorldObject const* target1 = nullptr, WorldObject const* target2 = nullptr);
diff --git a/src/server/game/DataStores/DB2HotfixGenerator.h b/src/server/game/DataStores/DB2HotfixGenerator.h
index 6287160dbe3..79c926a5731 100644
--- a/src/server/game/DataStores/DB2HotfixGenerator.h
+++ b/src/server/game/DataStores/DB2HotfixGenerator.h
@@ -15,10 +15,11 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef DB2HotfixGenerator_h__
-#define DB2HotfixGenerator_h__
+#ifndef TRINITYCORE_DB2_HOTFIX_GENERATOR_H
+#define TRINITYCORE_DB2_HOTFIX_GENERATOR_H
#include "DB2Store.h"
+#include <initializer_list>
#include <span>
class TC_GAME_API DB2HotfixGeneratorBase
@@ -35,6 +36,7 @@ public:
explicit DB2HotfixGenerator(DB2Storage<T>& storage) : _storage(storage), _count(0) { }
void ApplyHotfix(uint32 id, void(*fixer)(T*), bool notifyClient = false) { ApplyHotfix({ &id, 1 }, fixer, notifyClient); }
+ void ApplyHotfix(std::initializer_list<uint32> ids, void(*fixer)(T*), bool notifyClient = false) { ApplyHotfix({ ids.begin(), ids.end() }, fixer, notifyClient); }
uint32 GetAppliedHotfixesCount() const { return _count; }
@@ -62,4 +64,4 @@ private:
uint32 _count;
};
-#endif // DB2HotfixGenerator_h__
+#endif // TRINITYCORE_DB2_HOTFIX_GENERATOR_H
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 4aaed6dc52b..6cdce3088cd 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -23756,8 +23756,10 @@ void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue, Races r
case SkillLineAbilityAcquireMethod::AutomaticCharLevel:
break;
case SkillLineAbilityAcquireMethod::LearnedOrAutomaticCharLevel:
- if (!ability->GetFlags().HasFlag(SkillLineAbilityFlags::CanFallbackToLearnedOnSkillLearn) ||
- !spellInfo->MeetsFutureSpellPlayerCondition(this))
+ // Treat as AutomaticCharLevel when conditions are met, otherwise treat it as Learned (trainer or quest)
+ if (spellInfo->ShowFutureSpellPlayerConditionID && !ConditionMgr::IsPlayerMeetingCondition(this, spellInfo->ShowFutureSpellPlayerConditionID))
+ continue;
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_SKILL_LINE_ABILITY, ability->ID, this))
continue;
break;
default:
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 6cf7597e024..3d71f8c9d9d 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -20,6 +20,7 @@
#include "BattlefieldMgr.h"
#include "BattlegroundMgr.h"
#include "Chat.h"
+#include "DB2HotfixGenerator.h"
#include "DB2Stores.h"
#include "DatabaseEnv.h"
#include "LanguageMgr.h"
@@ -2074,19 +2075,11 @@ void SpellMgr::LoadSkillLineAbilityMap()
mSkillLineAbilityMap.clear();
- uint32 count = 0;
-
- for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); ++i)
- {
- SkillLineAbilityEntry const* SkillInfo = sSkillLineAbilityStore.LookupEntry(i);
- if (!SkillInfo)
- continue;
-
- mSkillLineAbilityMap.insert(SkillLineAbilityMap::value_type(SkillInfo->Spell, SkillInfo));
- ++count;
- }
+ for (SkillLineAbilityEntry const* skillLineAbility : sSkillLineAbilityStore)
+ mSkillLineAbilityMap.emplace(skillLineAbility->Spell, skillLineAbility);
- TC_LOG_INFO("server.loading", ">> Loaded {} SkillLineAbility MultiMap Data in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded {} SkillLineAbility MultiMap Data in {} ms",
+ mSkillLineAbilityMap.size(), GetMSTimeDiffToNow(oldMSTime));
}
void SpellMgr::LoadSpellPetAuras()
@@ -4827,12 +4820,19 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->MaxAffectedTargets = 1;
}
- if (SummonPropertiesEntry* properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(121)))
+ DB2HotfixGenerator summonProperties(sSummonPropertiesStore);
+ summonProperties.ApplyHotfix(121, [](SummonPropertiesEntry* properties)
+ {
properties->Title = AsUnderlyingType(SummonTitle::Totem);
- if (SummonPropertiesEntry* properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(647))) // 52893
+ });
+ summonProperties.ApplyHotfix(647, [](SummonPropertiesEntry* properties) // 52893
+ {
properties->Title = AsUnderlyingType(SummonTitle::Totem);
- if (SummonPropertiesEntry* properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(628))) // Hungry Plaguehound
+ });
+ summonProperties.ApplyHotfix(628, [](SummonPropertiesEntry* properties) // Hungry Plaguehound
+ {
properties->Control = SUMMON_CATEGORY_PET;
+ });
TC_LOG_INFO("server.loading", ">> Loaded SpellInfo corrections in {} ms", GetMSTimeDiffToNow(oldMSTime));
}