Core/Conditions: Initial support for UnitCondition.db2

This commit is contained in:
Shauren
2022-01-15 00:52:55 +01:00
parent ccccf8a2b5
commit 72286dc5e4
6 changed files with 413 additions and 11 deletions

View File

@@ -3562,3 +3562,275 @@ bool ConditionMgr::IsPlayerMeetingExpression(Player const* player, WorldStateExp
return finalResult;
}
int32 GetUnitConditionVariable(Unit const* unit, Unit const* otherUnit, UnitConditionVariable variable, int32 value)
{
switch (variable)
{
case UnitConditionVariable::Race:
return unit->GetRace();
case UnitConditionVariable::Class:
return unit->GetClass();
case UnitConditionVariable::Level:
return unit->GetLevel();
case UnitConditionVariable::IsSelf:
return unit == otherUnit;
case UnitConditionVariable::IsMyPet:
return otherUnit && unit->GetCharmerOrOwnerGUID() == otherUnit->GetGUID();
case UnitConditionVariable::IsMaster:
return otherUnit && otherUnit->GetCharmerOrOwnerGUID() == unit->GetGUID();
case UnitConditionVariable::IsTarget:
return otherUnit && otherUnit->GetTarget() == unit->GetGUID();
case UnitConditionVariable::CanAssist:
return otherUnit && unit->IsValidAssistTarget(otherUnit);
case UnitConditionVariable::CanAttack:
return otherUnit && unit->IsValidAttackTarget(otherUnit);
case UnitConditionVariable::HasPet:
return !unit->GetCharmedGUID().IsEmpty() || !unit->GetMinionGUID().IsEmpty();
case UnitConditionVariable::HasWeapon:
if (Player const* player = unit->ToPlayer())
return player->GetWeaponForAttack(BASE_ATTACK) || player->GetWeaponForAttack(OFF_ATTACK);
return unit->GetVirtualItemId(0) || unit->GetVirtualItemId(1);
case UnitConditionVariable::HealthPct:
return unit->GetHealthPct();
case UnitConditionVariable::ManaPct:
return unit->GetPowerPct(POWER_MANA);
case UnitConditionVariable::RagePct:
return unit->GetPowerPct(POWER_RAGE);
case UnitConditionVariable::EnergyPct:
return unit->GetPowerPct(POWER_ENERGY);
case UnitConditionVariable::ComboPoints:
return unit->GetPower(POWER_COMBO_POINTS);
case UnitConditionVariable::HasHelpfulAuraSpell:
return unit->GetAuraApplication(value, [](AuraApplication const* aurApp)
{
return (aurApp->GetFlags() & AFLAG_NEGATIVE) == 0;
}) != nullptr ? value : 0;
case UnitConditionVariable::HasHelpfulAuraDispelType:
return unit->GetAuraApplication([value](AuraApplication const* aurApp)
{
return (aurApp->GetFlags() & AFLAG_NEGATIVE) == 0 && int32(aurApp->GetBase()->GetSpellInfo()->Dispel) == value;
}) != nullptr ? value : 0;
case UnitConditionVariable::HasHelpfulAuraMechanic:
return unit->GetAuraApplication([value](AuraApplication const* aurApp)
{
return (aurApp->GetFlags() & AFLAG_NEGATIVE) == 0 && (aurApp->GetBase()->GetSpellInfo()->GetSpellMechanicMaskByEffectMask(aurApp->GetEffectMask()) & (1 << value)) != 0;
}) != nullptr ? value : 0;
case UnitConditionVariable::HasHarmfulAuraSpell:
return unit->GetAuraApplication(value, [](AuraApplication const* aurApp)
{
return (aurApp->GetFlags() & AFLAG_NEGATIVE) != 0;
}) != nullptr ? value : 0;
case UnitConditionVariable::HasHarmfulAuraDispelType:
return unit->GetAuraApplication([value](AuraApplication const* aurApp)
{
return (aurApp->GetFlags() & AFLAG_NEGATIVE) != 0 && int32(aurApp->GetBase()->GetSpellInfo()->Dispel) == value;
}) != nullptr ? value : 0;
case UnitConditionVariable::HasHarmfulAuraMechanic:
return unit->GetAuraApplication([value](AuraApplication const* aurApp)
{
return (aurApp->GetFlags() & AFLAG_NEGATIVE) != 0 && (aurApp->GetBase()->GetSpellInfo()->GetSpellMechanicMaskByEffectMask(aurApp->GetEffectMask()) & (1 << value)) != 0;
}) != nullptr ? value : 0;
case UnitConditionVariable::HasHarmfulAuraSchool:
return unit->GetAuraApplication([value](AuraApplication const* aurApp)
{
return (aurApp->GetFlags() & AFLAG_NEGATIVE) != 0 && (aurApp->GetBase()->GetSpellInfo()->GetSchoolMask() & (1 << value)) != 0;
}) != nullptr ? value : 0;
case UnitConditionVariable::DamagePhysicalPct:
break;
case UnitConditionVariable::DamageHolyPct:
break;
case UnitConditionVariable::DamageFirePct:
break;
case UnitConditionVariable::DamageNaturePct:
break;
case UnitConditionVariable::DamageFrostPct:
break;
case UnitConditionVariable::DamageShadowPct:
break;
case UnitConditionVariable::DamageArcanePct:
break;
case UnitConditionVariable::InCombat:
break;
case UnitConditionVariable::IsMoving:
break;
case UnitConditionVariable::IsCasting:
break;
case UnitConditionVariable::IsCastingSpell:
break;
case UnitConditionVariable::IsChanneling:
break;
case UnitConditionVariable::IsChannelingSpell:
break;
case UnitConditionVariable::NumberOfMeleeAttackers:
break;
case UnitConditionVariable::IsAttackingMe:
break;
case UnitConditionVariable::Range:
break;
case UnitConditionVariable::InMeleeRange:
break;
case UnitConditionVariable::PursuitTime:
break;
case UnitConditionVariable::HasHarmfulAuraCanceledByDamage:
break;
case UnitConditionVariable::HasHarmfulAuraWithPeriodicDamage:
break;
case UnitConditionVariable::NumberOfEnemies:
break;
case UnitConditionVariable::NumberOfFriends:
break;
case UnitConditionVariable::ThreatPhysicalPct:
break;
case UnitConditionVariable::ThreatHolyPct:
break;
case UnitConditionVariable::ThreatFirePct:
break;
case UnitConditionVariable::ThreatNaturePct:
break;
case UnitConditionVariable::ThreatFrostPct:
break;
case UnitConditionVariable::ThreatShadowPct:
break;
case UnitConditionVariable::ThreatArcanePct:
break;
case UnitConditionVariable::IsInterruptible:
break;
case UnitConditionVariable::NumberOfAttackers:
break;
case UnitConditionVariable::NumberOfRangedAttackers:
break;
case UnitConditionVariable::CreatureType:
break;
case UnitConditionVariable::IsMeleeAttacking:
break;
case UnitConditionVariable::IsRangedAttacking:
break;
case UnitConditionVariable::Health:
break;
case UnitConditionVariable::SpellKnown:
break;
case UnitConditionVariable::HasHarmfulAuraEffect:
break;
case UnitConditionVariable::IsImmuneToAreaOfEffect:
break;
case UnitConditionVariable::IsPlayer:
break;
case UnitConditionVariable::DamageMagicPct:
break;
case UnitConditionVariable::DamageTotalPct:
break;
case UnitConditionVariable::ThreatMagicPct:
break;
case UnitConditionVariable::ThreatTotalPct:
break;
case UnitConditionVariable::HasCritter:
return !unit->GetCritterGUID().IsEmpty();
case UnitConditionVariable::HasTotemInSlot1:
break;
case UnitConditionVariable::HasTotemInSlot2:
break;
case UnitConditionVariable::HasTotemInSlot3:
break;
case UnitConditionVariable::HasTotemInSlot4:
break;
case UnitConditionVariable::HasTotemInSlot5:
break;
case UnitConditionVariable::Creature:
break;
case UnitConditionVariable::StringID:
break;
case UnitConditionVariable::HasAura:
break;
case UnitConditionVariable::IsEnemy:
break;
case UnitConditionVariable::IsSpecMelee:
break;
case UnitConditionVariable::IsSpecTank:
break;
case UnitConditionVariable::IsSpecRanged:
break;
case UnitConditionVariable::IsSpecHealer:
break;
case UnitConditionVariable::IsPlayerControlledNPC:
break;
case UnitConditionVariable::IsDying:
break;
case UnitConditionVariable::PathFailCount:
break;
case UnitConditionVariable::IsMounted:
break;
case UnitConditionVariable::Label:
break;
case UnitConditionVariable::IsMySummon:
break;
case UnitConditionVariable::IsSummoner:
break;
case UnitConditionVariable::IsMyTarget:
break;
case UnitConditionVariable::Sex:
break;
case UnitConditionVariable::LevelWithinContentTuning:
break;
case UnitConditionVariable::IsFlying:
break;
case UnitConditionVariable::IsHovering:
break;
case UnitConditionVariable::HasHelpfulAuraEffect:
break;
case UnitConditionVariable::HasHelpfulAuraSchool:
return unit->GetAuraApplication([value](AuraApplication const* aurApp)
{
return (aurApp->GetFlags() & AFLAG_NEGATIVE) == 0 && (aurApp->GetBase()->GetSpellInfo()->GetSchoolMask() & (1 << value)) != 0;
}) != nullptr ? value : 0;
default:
break;
}
return 0;
}
bool ConditionMgr::IsUnitMeetingCondition(Unit const* unit, Unit const* otherUnit, UnitConditionEntry const* condition)
{
for (size_t i = 0; i < MAX_UNIT_CONDITION_VALUES; ++i)
{
if (!condition->Variable[i])
break;
int32 unitValue = GetUnitConditionVariable(unit, otherUnit, UnitConditionVariable(condition->Variable[i]), condition->Value[i]);
bool meets = false;
switch (UnitConditionOp(condition->Op[i]))
{
case UnitConditionOp::EqualTo:
meets = unitValue == condition->Value[i];
break;
case UnitConditionOp::NotEqualTo:
meets = unitValue != condition->Value[i];
break;
case UnitConditionOp::LessThan:
meets = unitValue < condition->Value[i];
break;
case UnitConditionOp::LessThanOrEqualTo:
meets = unitValue <= condition->Value[i];
break;
case UnitConditionOp::GreaterThan:
meets = unitValue > condition->Value[i];
break;
case UnitConditionOp::GreaterThanOrEqualTo:
meets = unitValue >= condition->Value[i];
break;
default:
break;
}
if (condition->GetFlags().HasFlag(UnitConditionFlags::LogicOr))
{
if (meets)
return true;
}
else if (!meets)
return false;
}
return !condition->GetFlags().HasFlag(UnitConditionFlags::LogicOr);
}

View File

@@ -33,6 +33,7 @@ class WorldObject;
class LootTemplate;
struct Condition;
struct PlayerConditionEntry;
struct UnitConditionEntry;
struct WorldStateExpressionEntry;
enum class PlayerConditionLfgStatus : uint8;
@@ -304,6 +305,7 @@ class TC_GAME_API ConditionMgr
static uint32 GetPlayerConditionLfgValue(Player const* player, PlayerConditionLfgStatus status);
static bool IsPlayerMeetingCondition(Player const* player, PlayerConditionEntry const* condition);
static bool IsPlayerMeetingExpression(Player const* player, WorldStateExpressionEntry const* expression);
static bool IsUnitMeetingCondition(Unit const* unit, Unit const* otherUnit, UnitConditionEntry const* condition);
struct ConditionTypeInfo
{

View File

@@ -3871,13 +3871,17 @@ struct UISplashScreenEntry
int32 RequiredTimeEventPassed; // serverside TimeEvent table, see ModifierTreeType::HasTimeEventPassed
};
#define MAX_UNIT_CONDITION_VALUES 8
struct UnitConditionEntry
{
uint32 ID;
uint8 Flags;
uint8 Variable[8];
int8 Op[8];
int32 Value[8];
uint8 Variable[MAX_UNIT_CONDITION_VALUES];
int8 Op[MAX_UNIT_CONDITION_VALUES];
int32 Value[MAX_UNIT_CONDITION_VALUES];
EnumFlag<UnitConditionFlags> GetFlags() const { return static_cast<UnitConditionFlags>(Flags); }
};
struct UnitPowerBarEntry

View File

@@ -1694,6 +1694,124 @@ enum UiMapType : int8
UI_MAP_TYPE_ORPHAN = 6,
};
enum class UnitConditionFlags : uint8
{
LogicOr = 0x1
};
DEFINE_ENUM_FLAG(UnitConditionFlags);
enum class UnitConditionOp : int8
{
EqualTo = 1,
NotEqualTo = 2,
LessThan = 3,
LessThanOrEqualTo = 4,
GreaterThan = 5,
GreaterThanOrEqualTo = 6
};
enum class UnitConditionVariable : uint8
{
None = 0, // - NONE -
Race = 1, // Race {$Is/Is Not} "{ChrRaces}"
Class = 2, // Class {$Is/Is Not} "{ChrClasses}"
Level = 3, // Level {$Relative Op} "{#Level}"
IsSelf = 4, // Is self? {$Yes/No}{=1}
IsMyPet = 5, // Is my pet? {$Yes/No}{=1}
IsMaster = 6, // Is master? {$Yes/No}{=1}
IsTarget = 7, // Is target? {$Yes/No}{=1}
CanAssist = 8, // Can assist? {$Yes/No}{=1}
CanAttack = 9, // Can attack? {$Yes/No}{=1}
HasPet = 10, // Has pet? {$Yes/No}{=1}
HasWeapon = 11, // Has weapon? {$Yes/No}{=1}
HealthPct = 12, // Health {$Relative Op} {#Health %}%
ManaPct = 13, // Mana {$Relative Op} {#Mana %}%
RagePct = 14, // Rage {$Relative Op} {#Rage %}%
EnergyPct = 15, // Energy {$Relative Op} {#Energy %}%
ComboPoints = 16, // Combo Points {$Relative Op} {#Points}
HasHelpfulAuraSpell = 17, // Has helpful aura spell? {$Yes/No} "{Spell}"
HasHelpfulAuraDispelType = 18, // Has helpful aura dispel type? {$Yes/No} "{SpellDispelType}"
HasHelpfulAuraMechanic = 19, // Has helpful aura mechanic? {$Yes/No} "{SpellMechanic}"
HasHarmfulAuraSpell = 20, // Has harmful aura spell? {$Yes/No} "{Spell}"
HasHarmfulAuraDispelType = 21, // Has harmful aura dispel type? {$Yes/No} "{SpellDispelType}"
HasHarmfulAuraMechanic = 22, // Has harmful aura mechanic? {$Yes/No} "{SpellMechanic}"
HasHarmfulAuraSchool = 23, // Has harmful aura school? {$Yes/No} "{Resistances}"
DamagePhysicalPct = 24, // NYI Damage (Physical) {$Relative Op} {#Physical Damage %}%
DamageHolyPct = 25, // NYI Damage (Holy) {$Relative Op} {#Holy Damage %}%
DamageFirePct = 26, // NYI Damage (Fire) {$Relative Op} {#Fire Damage %}%
DamageNaturePct = 27, // NYI Damage (Nature) {$Relative Op} {#Nature Damage %}%
DamageFrostPct = 28, // NYI Damage (Frost) {$Relative Op} {#Frost Damage %}%
DamageShadowPct = 29, // NYI Damage (Shadow) {$Relative Op} {#Shadow Damage %}%
DamageArcanePct = 30, // NYI Damage (Arcane) {$Relative Op} {#Arcane Damage %}%
InCombat = 31, // NYI In combat? {$Yes/No}{=1}
IsMoving = 32, // NYI Is moving? {$Yes/No}{=1}
IsCasting = 33, // NYI Is casting? {$Yes/No}{=1}
IsCastingSpell = 34, // NYI Is casting spell? {$Yes/No}{=1}
IsChanneling = 35, // NYI Is channeling? {$Yes/No}{=1}
IsChannelingSpell = 36, // NYI Is channeling spell? {$Yes/No}{=1}
NumberOfMeleeAttackers = 37, // NYI Number of melee attackers {$Relative Op} {#Attackers}
IsAttackingMe = 38, // NYI Is attacking me? {$Yes/No}{=1}
Range = 39, // NYI Range {$Relative Op} {#Yards}
InMeleeRange = 40, // NYI In melee range? {$Yes/No}{=1}
PursuitTime = 41, // NYI Pursuit time {$Relative Op} {#Seconds}
HasHarmfulAuraCanceledByDamage = 42, // NYI Has harmful aura canceled by damage? {$Yes/No}{=1}
HasHarmfulAuraWithPeriodicDamage = 43, // NYI Has harmful aura with periodic damage? {$Yes/No}{=1}
NumberOfEnemies = 44, // NYI Number of enemies {$Relative Op} {#Enemies}
NumberOfFriends = 45, // NYI Number of friends {$Relative Op} {#Friends}
ThreatPhysicalPct = 46, // NYI Threat (Physical) {$Relative Op} {#Physical Threat %}%
ThreatHolyPct = 47, // NYI Threat (Holy) {$Relative Op} {#Holy Threat %}%
ThreatFirePct = 48, // NYI Threat (Fire) {$Relative Op} {#Fire Threat %}%
ThreatNaturePct = 49, // NYI Threat (Nature) {$Relative Op} {#Nature Threat %}%
ThreatFrostPct = 50, // NYI Threat (Frost) {$Relative Op} {#Frost Threat %}%
ThreatShadowPct = 51, // NYI Threat (Shadow) {$Relative Op} {#Shadow Threat %}%
ThreatArcanePct = 52, // NYI Threat (Arcane) {$Relative Op} {#Arcane Threat %}%
IsInterruptible = 53, // NYI Is interruptible? {$Yes/No}{=1}
NumberOfAttackers = 54, // NYI Number of attackers {$Relative Op} {#Attackers}
NumberOfRangedAttackers = 55, // NYI Number of ranged attackers {$Relative Op} {#Ranged Attackers}
CreatureType = 56, // NYI Creature type {$Is/Is Not} "{CreatureType}"
IsMeleeAttacking = 57, // NYI Is melee-attacking? {$Yes/No}{=1}
IsRangedAttacking = 58, // NYI Is ranged-attacking? {$Yes/No}{=1}
Health = 59, // NYI Health {$Relative Op} {#HP} HP
SpellKnown = 60, // NYI Spell known? {$Yes/No} "{Spell}"
HasHarmfulAuraEffect = 61, // NYI Has harmful aura effect? {$Yes/No} "{#Spell Aura}"
IsImmuneToAreaOfEffect = 62, // NYI Is immune to area-of-effect? {$Yes/No}{=1}
IsPlayer = 63, // NYI Is player? {$Yes/No}{=1}
DamageMagicPct = 64, // NYI Damage (Magic) {$Relative Op} {#Magic Damage %}%
DamageTotalPct = 65, // NYI Damage (Total) {$Relative Op} {#Damage %}%
ThreatMagicPct = 66, // NYI Threat (Magic) {$Relative Op} {#Magic Threat %}%
ThreatTotalPct = 67, // NYI Threat (Total) {$Relative Op} {#Threat %}%
HasCritter = 68, // NYI Has critter? {$Yes/No}{=1}
HasTotemInSlot1 = 69, // NYI Has totem in slot 1? {$Yes/No}{=1}
HasTotemInSlot2 = 70, // NYI Has totem in slot 2? {$Yes/No}{=1}
HasTotemInSlot3 = 71, // NYI Has totem in slot 3? {$Yes/No}{=1}
HasTotemInSlot4 = 72, // NYI Has totem in slot 4? {$Yes/No}{=1}
HasTotemInSlot5 = 73, // NYI Has totem in slot 5? {$Yes/No}{=1}
Creature = 74, // NYI Creature {$Is/Is Not} "{Creature}"
StringID = 75, // NYI String ID {$Is/Is Not} "{StringID}"
HasAura = 76, // NYI Has aura? {$Yes/No} {Spell}
IsEnemy = 77, // NYI Is enemy? {$Yes/No}{=1}
IsSpecMelee = 78, // NYI Is spec - melee? {$Yes/No}{=1}
IsSpecTank = 79, // NYI Is spec - tank? {$Yes/No}{=1}
IsSpecRanged = 80, // NYI Is spec - ranged? {$Yes/No}{=1}
IsSpecHealer = 81, // NYI Is spec - healer? {$Yes/No}{=1}
IsPlayerControlledNPC = 82, // NYI Is player controlled NPC? {$Yes/No}{=1}
IsDying = 83, // NYI Is dying? {$Yes/No}{=1}
PathFailCount = 84, // NYI Path fail count {$Relative Op} {#Path Fail Count}
IsMounted = 85, // NYI Is mounted? {$Yes/No}{=1}
Label = 86, // NYI Label {$Is/Is Not} "{Label}"
IsMySummon = 87, // NYI
IsSummoner = 88, // NYI
IsMyTarget = 89, // NYI
Sex = 90, // NYI Sex {$Is/Is Not} "{UnitSex}"
LevelWithinContentTuning = 91, // NYI Level is within {$Is/Is Not} {ContentTuning}
IsFlying = 93, // NYI Is flying? {$Yes/No}{=1}
IsHovering = 94, // NYI Is hovering? {$Yes/No}{=1}
HasHelpfulAuraEffect = 95, // NYI Has helpful aura effect? {$Yes/No} "{#Spell Aura}"
HasHelpfulAuraSchool = 96, // Has helpful aura school? {$Yes/No} "{Resistances}"
};
enum VehicleSeatFlags
{
VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_ENTER = 0x00000001,

View File

@@ -4285,21 +4285,27 @@ bool SpellInfo::IsHighRankOf(SpellInfo const* spellInfo) const
return false;
}
uint32 SpellInfo::GetSpellXSpellVisualId(WorldObject const* caster /*= nullptr*/) const
uint32 SpellInfo::GetSpellXSpellVisualId(WorldObject const* caster /*= nullptr*/, WorldObject const* viewer /*= nullptr*/) const
{
for (SpellXSpellVisualEntry const* visual : _visuals)
{
PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(visual->CasterPlayerConditionID);
if (!playerCondition || (caster && caster->GetTypeId() == TYPEID_PLAYER && sConditionMgr->IsPlayerMeetingCondition(caster->ToPlayer(), playerCondition)))
return visual->ID;
if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(visual->CasterPlayerConditionID))
if (!caster || !caster->IsPlayer() || !ConditionMgr::IsPlayerMeetingCondition(caster->ToPlayer(), playerCondition))
continue;
if (UnitConditionEntry const* unitCondition = sUnitConditionStore.LookupEntry(visual->CasterUnitConditionID))
if (!caster || !caster->IsUnit() || !ConditionMgr::IsUnitMeetingCondition(caster->ToUnit(), viewer->ToUnit(), unitCondition))
continue;
return visual->ID;
}
return 0;
}
uint32 SpellInfo::GetSpellVisual(WorldObject const* caster /*= nullptr*/) const
uint32 SpellInfo::GetSpellVisual(WorldObject const* caster /*= nullptr*/, WorldObject const* viewer /*= nullptr*/) const
{
if (SpellXSpellVisualEntry const* visual = sSpellXSpellVisualStore.LookupEntry(GetSpellXSpellVisualId(caster)))
if (SpellXSpellVisualEntry const* visual = sSpellXSpellVisualStore.LookupEntry(GetSpellXSpellVisualId(caster, viewer)))
{
//if (visual->LowViolenceSpellVisualID && forPlayer->GetViolenceLevel() operator 2)
// return visual->LowViolenceSpellVisualID;

View File

@@ -573,8 +573,8 @@ class TC_GAME_API SpellInfo
bool IsDifferentRankOf(SpellInfo const* spellInfo) const;
bool IsHighRankOf(SpellInfo const* spellInfo) const;
uint32 GetSpellXSpellVisualId(WorldObject const* caster = nullptr) const;
uint32 GetSpellVisual(WorldObject const* caster = nullptr) const;
uint32 GetSpellXSpellVisualId(WorldObject const* caster = nullptr, WorldObject const* viewer = nullptr) const;
uint32 GetSpellVisual(WorldObject const* caster = nullptr, WorldObject const* viewer = nullptr) const;
std::vector<SpellEffectInfo> const& GetEffects() const { return _effects; }
SpellEffectInfo const& GetEffect(SpellEffIndex index) const { ASSERT(index < _effects.size()); return _effects[index]; }