diff options
-rw-r--r-- | src/server/game/Conditions/ConditionMgr.cpp | 76 | ||||
-rw-r--r-- | src/server/game/Conditions/ConditionMgr.h | 5 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Trainer.cpp | 9 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Trainer.h | 2 |
4 files changed, 77 insertions, 15 deletions
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 1c5c294d9c1..dcb67d0f631 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -80,7 +80,9 @@ char const* const ConditionMgr::StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX] "Phase", "Graveyard", "AreaTrigger", - "ConversationLine" + "ConversationLine", + "AreaTrigger Client Triggered", + "Trainer Spell" }; ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[CONDITION_MAX] = @@ -951,7 +953,8 @@ bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT || sourceType == CONDITION_SOURCE_TYPE_NPC_VENDOR || sourceType == CONDITION_SOURCE_TYPE_PHASE || - sourceType == CONDITION_SOURCE_TYPE_AREATRIGGER); + sourceType == CONDITION_SOURCE_TYPE_AREATRIGGER || + sourceType == CONDITION_SOURCE_TYPE_TRAINER_SPELL); } bool ConditionMgr::CanHaveSourceIdSet(ConditionSourceType sourceType) @@ -1060,7 +1063,7 @@ bool ConditionMgr::IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 ConditionsByEntryMap::const_iterator i = (*itr).second.find(itemId); if (i != (*itr).second.end()) { - TC_LOG_DEBUG("condition", "GetConditionsForNpcVendorEvent: found conditions for creature entry %u item %u", creatureId, itemId); + TC_LOG_DEBUG("condition", "GetConditionsForNpcVendor: found conditions for creature entry %u item %u", creatureId, itemId); ConditionSourceInfo sourceInfo(player, vendor); return IsObjectMeetToConditions(sourceInfo, i->second); } @@ -1073,6 +1076,21 @@ ConditionContainer const* ConditionMgr::GetConditionsForAreaTrigger(uint32 areaT return Trinity::Containers::MapGetValuePtr(AreaTriggerConditionContainerStore, { areaTriggerId, isServerSide }); } +bool ConditionMgr::IsObjectMeetingTrainerSpellConditions(uint32 trainerId, uint32 spellId, Player* player) const +{ + ConditionEntriesByCreatureIdMap::const_iterator itr = TrainerSpellConditionContainerStore.find(trainerId); + if (itr != TrainerSpellConditionContainerStore.end()) + { + ConditionsByEntryMap::const_iterator i = (*itr).second.find(spellId); + if (i != (*itr).second.end()) + { + TC_LOG_DEBUG("condition", "GetConditionsForTrainerSpell: found conditions for trainer id %u spell %u", trainerId, spellId); + return IsObjectMeetToConditions(player, i->second); + } + } + return true; +} + ConditionMgr* ConditionMgr::instance() { static ConditionMgr instance; @@ -1316,6 +1334,13 @@ void ConditionMgr::LoadConditions(bool isReload) ++count; continue; } + case CONDITION_SOURCE_TYPE_TRAINER_SPELL: + { + TrainerSpellConditionContainerStore[cond->SourceGroup][cond->SourceEntry].push_back(cond); + valid = true; + ++count; + continue; + } default: break; } @@ -1769,7 +1794,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE); if (!spellInfo) { - TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str()); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", cond->ToString().c_str()); return false; } @@ -1836,7 +1861,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE); if (!spellProto) { - TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str()); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1851,26 +1876,26 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const case CONDITION_SOURCE_TYPE_VEHICLE_SPELL: if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString().c_str()); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString().c_str()); return false; } if (!sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE)) { - TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str()); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", cond->ToString().c_str()); return false; } break; case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT: if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString().c_str()); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString().c_str()); return false; } if (!sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE)) { - TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str()); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1878,7 +1903,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const { if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString().c_str()); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString().c_str()); return false; } ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(cond->SourceEntry); @@ -1893,7 +1918,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const { if (!sMapStore.LookupEntry(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in Map.dbc, ignoring.", cond->ToString().c_str()); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in Map.db2, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1902,7 +1927,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const { if (cond->SourceEntry && !sAreaTableStore.LookupEntry(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in AreaTable.dbc, ignoring.", cond->ToString().c_str()); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in AreaTable.db2, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1944,6 +1969,20 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const return false; } break; + case CONDITION_SOURCE_TYPE_TRAINER_SPELL: + { + if (!sObjectMgr->GetTrainer(cond->SourceGroup)) + { + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `trainer`, ignoring.", cond->ToString().c_str()); + return false; + } + if (!sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE)) + { + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", cond->ToString().c_str()); + return false; + } + break; + } default: TC_LOG_ERROR("sql.sql", "%s Invalid ConditionSourceType in `condition` table, ignoring.", cond->ToString().c_str()); return false; @@ -2517,6 +2556,19 @@ void ConditionMgr::Clean() NpcVendorConditionContainerStore.clear(); + for (ConditionEntriesByAreaTriggerIdMap::iterator itr = AreaTriggerConditionContainerStore.begin(); itr != AreaTriggerConditionContainerStore.end(); ++itr) + for (ConditionContainer::const_iterator i = itr->second.begin(); i != itr->second.end(); ++i) + delete *i; + + AreaTriggerConditionContainerStore.clear(); + + for (ConditionEntriesByCreatureIdMap::iterator itr = TrainerSpellConditionContainerStore.begin(); itr != TrainerSpellConditionContainerStore.end(); ++itr) + for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it) + for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i) + delete *i; + + TrainerSpellConditionContainerStore.clear(); + // this is a BIG hack, feel free to fix it if you can figure out the ConditionMgr ;) for (std::vector<Condition*>::const_iterator itr = AllocatedMemoryStore.begin(); itr != AllocatedMemoryStore.end(); ++itr) delete *itr; diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index d4f3bf8a188..1085adef996 100644 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -172,7 +172,8 @@ enum ConditionSourceType CONDITION_SOURCE_TYPE_AREATRIGGER = 28, CONDITION_SOURCE_TYPE_CONVERSATION_LINE = 29, CONDITION_SOURCE_TYPE_AREATRIGGER_CLIENT_TRIGGERED = 30, - CONDITION_SOURCE_TYPE_MAX = 31 // MAX + CONDITION_SOURCE_TYPE_TRAINER_SPELL = 31, + CONDITION_SOURCE_TYPE_MAX = 32 // MAX }; enum RelationType @@ -292,6 +293,7 @@ class TC_GAME_API ConditionMgr bool IsObjectMeetingSmartEventConditions(int64 entryOrGuid, uint32 eventId, uint32 sourceType, Unit* unit, WorldObject* baseObject) const; bool IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 itemId, Player* player, Creature* vendor) const; ConditionContainer const* GetConditionsForAreaTrigger(uint32 areaTriggerId, bool isServerSide) const; + bool IsObjectMeetingTrainerSpellConditions(uint32 trainerId, uint32 spellId, Player* player) const; static uint32 GetPlayerConditionLfgValue(Player const* player, PlayerConditionLfgStatus status); static bool IsPlayerMeetingCondition(Player const* player, PlayerConditionEntry const* condition); @@ -328,6 +330,7 @@ class TC_GAME_API ConditionMgr ConditionEntriesByCreatureIdMap NpcVendorConditionContainerStore; SmartEventConditionContainer SmartEventConditionStore; ConditionEntriesByAreaTriggerIdMap AreaTriggerConditionContainerStore; + ConditionEntriesByCreatureIdMap TrainerSpellConditionContainerStore; }; #define sConditionMgr ConditionMgr::instance() diff --git a/src/server/game/Entities/Creature/Trainer.cpp b/src/server/game/Entities/Creature/Trainer.cpp index 2e72b87f7a4..dcdd28edb19 100644 --- a/src/server/game/Entities/Creature/Trainer.cpp +++ b/src/server/game/Entities/Creature/Trainer.cpp @@ -18,6 +18,7 @@ #include "Trainer.h" #include "BattlePetMgr.h" #include "Creature.h" +#include "Log.h" #include "NPCPackets.h" #include "Player.h" #include "SpellInfo.h" @@ -36,7 +37,7 @@ namespace Trainer _greeting[DEFAULT_LOCALE] = std::move(greeting); } - void Trainer::SendSpells(Creature const* npc, Player const* player, LocaleConstant locale) const + void Trainer::SendSpells(Creature const* npc, Player* player, LocaleConstant locale) const { float reputationDiscount = player->GetReputationPriceDiscount(npc); @@ -51,6 +52,12 @@ namespace Trainer if (!player->IsSpellFitByClassAndRace(trainerSpell.SpellId)) continue; + if (!sConditionMgr->IsObjectMeetingTrainerSpellConditions(_id, trainerSpell.SpellId, player)) + { + TC_LOG_DEBUG("condition", "SendSpells: conditions not met for trainer id %u spell %u player '%s' (%s)", _id, trainerSpell.SpellId, player->GetName().c_str(), player->GetGUID().ToString().c_str()); + continue; + } + trainerList.Spells.emplace_back(); WorldPackets::NPC::TrainerListSpell& trainerListSpell = trainerList.Spells.back(); trainerListSpell.SpellID = trainerSpell.SpellId; diff --git a/src/server/game/Entities/Creature/Trainer.h b/src/server/game/Entities/Creature/Trainer.h index 303abe4fd0e..76ca1d69898 100644 --- a/src/server/game/Entities/Creature/Trainer.h +++ b/src/server/game/Entities/Creature/Trainer.h @@ -67,7 +67,7 @@ namespace Trainer public: Trainer(uint32 id, Type type, std::string greeting, std::vector<Spell> spells); - void SendSpells(Creature const* npc, Player const* player, LocaleConstant locale) const; + void SendSpells(Creature const* npc, Player* player, LocaleConstant locale) const; void TeachSpell(Creature const* npc, Player* player, uint32 spellId) const; private: |