Core/Conditions: Convert npc_spellclick_spells data to condition system. This implements CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT (previous CONDITION_SOURCE_TYPE_UNUSED_18). Wiki needs to be updated accordingly.

This commit is contained in:
Machiavelli
2012-02-20 23:25:59 +01:00
parent 1155161916
commit 16818d7548
7 changed files with 387 additions and 149 deletions
+41 -13
View File
@@ -299,6 +299,7 @@ uint32 Condition::GetMaxAvailableConditionTargets()
case CONDITION_SOURCE_TYPE_SPELL:
case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE:
case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
case CONDITION_SOURCE_TYPE_SMART_EVENT:
@@ -409,17 +410,34 @@ ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType
return spellCond;
}
ConditionList ConditionMgr::GetConditionsForVehicleSpell(uint32 creatureID, uint32 spellID)
ConditionList ConditionMgr::GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId)
{
ConditionList cond;
VehicleSpellConditionContainer::const_iterator itr = VehicleSpellConditionStore.find(creatureID);
if (itr != VehicleSpellConditionStore.end())
CreatureSpellConditionContainer::const_iterator itr = SpellClickEventConditionStore.find(creatureId);
if (itr != SpellClickEventConditionStore.end())
{
ConditionTypeContainer::const_iterator i = (*itr).second.find(spellID);
ConditionTypeContainer::const_iterator i = (*itr).second.find(spellId);
if (i != (*itr).second.end())
{
cond = (*i).second;
sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForVehicleSpell: found conditions for Vehicle entry %u spell %u", creatureID, spellID);
sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForSpellClickEvent: found conditions for Vehicle entry %u spell %u", creatureId, spellId);
}
}
return cond;
}
ConditionList ConditionMgr::GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId)
{
ConditionList cond;
CreatureSpellConditionContainer::const_iterator itr = VehicleSpellConditionStore.find(creatureId);
if (itr != VehicleSpellConditionStore.end())
{
ConditionTypeContainer::const_iterator i = (*itr).second.find(spellId);
if (i != (*itr).second.end())
{
cond = (*i).second;
sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForVehicleSpell: found conditions for Vehicle entry %u spell %u", creatureId, spellId);
}
}
return cond;
@@ -1073,9 +1091,19 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
return false;
}
break;
case CONDITION_SOURCE_TYPE_UNUSED_18:
sLog->outErrorDb("Found SourceTypeOrReferenceId = CONDITION_SOURCE_TYPE_UNUSED_18 in `conditions` table - ignoring");
return false;
case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
{
sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->SourceGroup);
return false;
}
if (!sSpellMgr->GetSpellInfo(cond->SourceEntry))
{
sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry);
return false;
}
break;
case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
case CONDITION_SOURCE_TYPE_SMART_EVENT:
@@ -1110,7 +1138,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
return false;
}
if (cond->ConditionValue2 > 2)
if (cond->ConditionValue2 > EFFECT_2)
{
sLog->outErrorDb("Aura condition has non existing effect index (%u) (must be 0..2), skipped", cond->ConditionValue2);
return false;
@@ -1574,13 +1602,13 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_19 in `conditions` table - ignoring");
return false;
case CONDITION_UNUSED_20:
sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_19 in `conditions` table - ignoring");
sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_20 in `conditions` table - ignoring");
return false;
case CONDITION_UNUSED_21:
sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_19 in `conditions` table - ignoring");
sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_21 in `conditions` table - ignoring");
return false;
case CONDITION_UNUSED_24:
sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_19 in `conditions` table - ignoring");
sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_24 in `conditions` table - ignoring");
return false;
default:
break;
@@ -1612,7 +1640,7 @@ void ConditionMgr::Clean()
ConditionStore.clear();
for (VehicleSpellConditionContainer::iterator itr = VehicleSpellConditionStore.begin(); itr != VehicleSpellConditionStore.end(); ++itr)
for (CreatureSpellConditionContainer::iterator itr = VehicleSpellConditionStore.begin(); itr != VehicleSpellConditionStore.end(); ++itr)
{
for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
{
+8 -5
View File
@@ -92,7 +92,7 @@ enum ConditionSourceType
CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION = 15,
CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE = 16,
CONDITION_SOURCE_TYPE_SPELL = 17,
CONDITION_SOURCE_TYPE_UNUSED_18 = 18,
CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT = 18,
CONDITION_SOURCE_TYPE_QUEST_ACCEPT = 19,
CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK = 20,
CONDITION_SOURCE_TYPE_VEHICLE_SPELL = 21,
@@ -167,7 +167,7 @@ struct Condition
ConditionValue2 = 0;
ConditionValue3 = 0;
ReferenceId = 0;
ErrorTextId = 0;
ErrorTextId = 0;
ScriptId = 0;
NegativeCondition = false;
}
@@ -180,7 +180,7 @@ struct Condition
typedef std::list<Condition*> ConditionList;
typedef std::map<uint32, ConditionList> ConditionTypeContainer;
typedef std::map<ConditionSourceType, ConditionTypeContainer> ConditionContainer;
typedef std::map<uint32, ConditionTypeContainer> VehicleSpellConditionContainer;
typedef std::map<uint32, ConditionTypeContainer> CreatureSpellConditionContainer;
typedef std::map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionTypeContainer> SmartEventConditionContainer;
typedef std::map<uint32, ConditionList> ConditionReferenceContainer;//only used for references
@@ -202,8 +202,9 @@ class ConditionMgr
bool IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions);
bool IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions);
ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry);
ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId);
ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType);
ConditionList GetConditionsForVehicleSpell(uint32 creatureID, uint32 spellID);
ConditionList GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId);
private:
bool isSourceTypeValid(Condition* cond);
@@ -228,6 +229,7 @@ class ConditionMgr
sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU ||
sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION ||
sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT ||
sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL ||
sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
}
@@ -237,7 +239,8 @@ class ConditionMgr
ConditionContainer ConditionStore;
ConditionReferenceContainer ConditionReferenceStore;
VehicleSpellConditionContainer VehicleSpellConditionStore;
CreatureSpellConditionContainer VehicleSpellConditionStore;
CreatureSpellConditionContainer SpellClickEventConditionStore;
SmartEventConditionContainer SmartEventConditionStore;
};
+10 -1
View File
@@ -22365,7 +22365,16 @@ void Player::UpdateForQuestWorldObjects()
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(obj->GetEntry());
for (SpellClickInfoContainer::const_iterator _itr = clickPair.first; _itr != clickPair.second; ++_itr)
if (_itr->second.questStart || _itr->second.questEnd)
{
//! This code doesn't look right, but it was logically converted to condition system to do the exact
//! same thing it did before. It definitely needs to be overlooked for intended functionality.
ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(obj->GetEntry(), _itr->second.spellId);
bool buildUpdateBlock = false;
for (ConditionList::const_iterator jtr = conds.begin(); jtr != conds.end() && !buildUpdateBlock; ++jtr)
if ((*jtr)->ConditionType == CONDITION_QUESTREWARDED || (*jtr)->ConditionType == CONDITION_QUESTTAKEN)
buildUpdateBlock = true;
if (buildUpdateBlock)
{
obj->BuildCreateUpdateBlockForPlayer(&udata, this);
break;
+47 -42
View File
@@ -55,6 +55,7 @@
#include "SpellInfo.h"
#include "MoveSplineInit.h"
#include "MoveSpline.h"
#include "ConditionMgr.h"
#include <math.h>
@@ -16870,57 +16871,61 @@ void Unit::JumpTo(WorldObject* obj, float speedZ)
bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
{
bool success = false;
uint32 spellClickEntry = GetVehicleKit() ? GetVehicleKit()->GetCreatureEntry() : GetEntry();
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(spellClickEntry);
for (SpellClickInfoContainer::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
{
if (itr->second.IsFitToRequirements(clicker, this))
//! First check simple relations from clicker to clickee
if (!itr->second.IsFitToRequirements(clicker, this))
return false;
//! Check database conditions
ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(spellClickEntry, itr->second.spellId);
ConditionSourceInfo info = ConditionSourceInfo(clicker, this);
if (!sConditionMgr->IsObjectMeetToConditions(info, conds))
return false;
Unit* caster = (itr->second.castFlags & NPC_CLICK_CAST_CASTER_CLICKER) ? clicker : this;
Unit* target = (itr->second.castFlags & NPC_CLICK_CAST_TARGET_CLICKER) ? clicker : this;
uint64 origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? GetOwnerGUID() : clicker->GetGUID();
SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(itr->second.spellId);
// if (!spellEntry) should be checked at npc_spellclick load
if (seatId > -1)
{
Unit* caster = (itr->second.castFlags & NPC_CLICK_CAST_CASTER_CLICKER) ? clicker : this;
Unit* target = (itr->second.castFlags & NPC_CLICK_CAST_TARGET_CLICKER) ? clicker : this;
uint64 origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? GetOwnerGUID() : clicker->GetGUID();
SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(itr->second.spellId);
// if (!spellEntry) should be checked at npc_spellclick load
if (seatId > -1)
uint8 i = 0;
bool valid = false;
while (i < MAX_SPELL_EFFECTS && !valid)
{
uint8 i = 0;
bool valid = false;
while (i < MAX_SPELL_EFFECTS && !valid)
if (spellEntry->Effects[i].ApplyAuraName == SPELL_AURA_CONTROL_VEHICLE)
{
if (spellEntry->Effects[i].ApplyAuraName == SPELL_AURA_CONTROL_VEHICLE)
{
valid = true;
break;
}
++i;
}
if (!valid)
{
sLog->outErrorDb("Spell %u specified in npc_spellclick_spells is not a valid vehicle enter aura!", itr->second.spellId);
return false;
}
if (IsInMap(caster))
caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1, target, true, NULL, NULL, origCasterGUID);
else // This can happen during Player::_LoadAuras
{
int32 bp0 = seatId;
Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, &bp0, NULL, origCasterGUID);
valid = true;
break;
}
++i;
}
if (!valid)
{
sLog->outErrorDb("Spell %u specified in npc_spellclick_spells is not a valid vehicle enter aura!", itr->second.spellId);
return false;
}
if (IsInMap(caster))
caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1, target, true, NULL, NULL, origCasterGUID);
else // This can happen during Player::_LoadAuras
{
int32 bp0 = seatId;
Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, &bp0, NULL, origCasterGUID);
}
}
else
{
if (IsInMap(caster))
caster->CastSpell(target, spellEntry, true, NULL, NULL, origCasterGUID);
else
{
if (IsInMap(caster))
caster->CastSpell(target, spellEntry, true, NULL, NULL, origCasterGUID);
else
Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, NULL, NULL, origCasterGUID);
}
success = true;
Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, NULL, NULL, origCasterGUID);
}
}
@@ -16928,7 +16933,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
if (creature && creature->IsAIEnabled)
creature->AI()->DoAction(EVENT_SPELLCLICK);
return success;
return true;
}
void Unit::EnterVehicle(Unit* base, int8 seatId)
+6 -83
View File
@@ -194,30 +194,8 @@ LanguageDesc const* GetLanguageDescByID(uint32 lang)
bool SpellClickInfo::IsFitToRequirements(Unit const* clicker, Unit const* clickee) const
{
Player const* playerClicker = clicker->ToPlayer();
if (playerClicker)
{
if (questStart)
{
// not in expected required quest state
if ((!questStartCanActive || !playerClicker->IsActiveQuest(questStart)) && !playerClicker->GetQuestRewardStatus(questStart))
return false;
}
if (questEnd)
{
// not in expected forbidden quest state
if (playerClicker->GetQuestRewardStatus(questEnd))
return false;
}
}
if (auraRequired)
if (!clicker->HasAura(auraRequired))
return false;
if (auraForbidden)
if (clicker->HasAura(auraForbidden))
return false;
if (!playerClicker)
return true;
Unit const* summoner = NULL;
// Check summoners for party
@@ -226,9 +204,6 @@ bool SpellClickInfo::IsFitToRequirements(Unit const* clicker, Unit const* clicke
if (!summoner)
summoner = clickee;
if (!playerClicker)
return true;
// This only applies to players
switch (userType)
{
@@ -7117,8 +7092,8 @@ void ObjectMgr::LoadNPCSpellClickSpells()
uint32 oldMSTime = getMSTime();
_spellClickInfoStore.clear();
// 0 1 2 3 4 5 6 7 8
QueryResult result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_start, quest_start_active, quest_end, cast_flags, aura_required, aura_forbidden, user_type FROM npc_spellclick_spells");
// 0 1 2 3
QueryResult result = WorldDatabase.Query("SELECT npc_entry, spell_id, cast_flags, user_type FROM npc_spellclick_spells");
if (!result)
{
@@ -7149,66 +7124,14 @@ void ObjectMgr::LoadNPCSpellClickSpells()
continue;
}
uint32 auraRequired = fields[6].GetUInt32();
if (auraRequired)
{
SpellInfo const* aurReqInfo = sSpellMgr->GetSpellInfo(auraRequired);
if (!aurReqInfo)
{
sLog->outErrorDb("Table npc_spellclick_spells references unknown aura required %u. Skipping entry.", auraRequired);
continue;
}
}
uint32 auraForbidden = fields[7].GetUInt32();
if (auraForbidden)
{
SpellInfo const* aurForInfo = sSpellMgr->GetSpellInfo(auraForbidden);
if (!aurForInfo)
{
sLog->outErrorDb("Table npc_spellclick_spells references unknown aura forbidden %u. Skipping entry.", auraForbidden);
continue;
}
}
uint32 quest_start = fields[2].GetUInt32();
// quest might be 0 to enable spellclick independent of any quest
if (quest_start)
{
if (_questTemplates.find(quest_start) == _questTemplates.end())
{
sLog->outErrorDb("Table npc_spellclick_spells references unknown start quest %u. Skipping entry.", quest_start);
continue;
}
}
bool quest_start_active = fields[3].GetBool();
uint32 quest_end = fields[4].GetUInt32();
// quest might be 0 to enable spellclick active infinity after start quest
if (quest_end)
{
if (_questTemplates.find(quest_end) == _questTemplates.end())
{
sLog->outErrorDb("Table npc_spellclick_spells references unknown end quest %u. Skipping entry.", quest_end);
continue;
}
}
uint8 userType = fields[8].GetUInt8();
uint8 userType = fields[3].GetUInt8();
if (userType >= SPELL_CLICK_USER_MAX)
sLog->outErrorDb("Table npc_spellclick_spells references unknown user type %u. Skipping entry.", uint32(userType));
uint8 castFlags = fields[5].GetUInt8();
uint8 castFlags = fields[2].GetUInt8();
SpellClickInfo info;
info.spellId = spellid;
info.questStart = quest_start;
info.questStartCanActive = quest_start_active;
info.questEnd = quest_end;
info.castFlags = castFlags;
info.auraRequired = auraRequired;
info.auraForbidden = auraForbidden;
info.userType = SpellClickUserTypes(userType);
_spellClickInfoStore.insert(SpellClickInfoContainer::value_type(npc_entry, info));
-5
View File
@@ -337,12 +337,7 @@ std::string GetScriptCommandName(ScriptCommands command);
struct SpellClickInfo
{
uint32 spellId;
uint32 questStart; // quest start (quest must be active or rewarded for spell apply)
uint32 questEnd; // quest end (quest must not be rewarded for spell apply)
bool questStartCanActive; // if true then quest start can be active (not only rewarded)
uint8 castFlags;
uint32 auraRequired;
uint32 auraForbidden;
SpellClickUserTypes userType;
// helpers