mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 04:37:00 +00:00
[8016] Work at npc click table data use.
* New fields in `npc_spellclick_spells` for allow set npc spell click mode from quest to infinity or to another quest, or from reward quest. * Not expect (and forbid set UNIT_NPC_FLAG_SPELLCLICK in DB and set it at `npc_spellclick_spells` loading. * Apply some speedups for creature checks affected by spel click state
This commit is contained in:
parent
08fe4933c5
commit
5254a498df
9 changed files with 106 additions and 30 deletions
|
|
@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`;
|
|||
CREATE TABLE `db_version` (
|
||||
`version` varchar(120) default NULL,
|
||||
`creature_ai_version` varchar(120) default NULL,
|
||||
`required_7988_09_mangos_spell_proc_event` bit(1) default NULL
|
||||
`required_8016_01_mangos_npc_spellclick_spells` bit(1) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
|
||||
|
||||
--
|
||||
|
|
@ -3191,10 +3191,12 @@ UNLOCK TABLES;
|
|||
|
||||
DROP TABLE IF EXISTS `npc_spellclick_spells`;
|
||||
CREATE TABLE `npc_spellclick_spells` (
|
||||
`npc_entry` INT UNSIGNED NOT NULL COMMENT 'reference to creature_template',
|
||||
`spell_id` INT UNSIGNED NOT NULL COMMENT 'spell which should be casted ',
|
||||
`quest_id` INT UNSIGNED NOT NULL COMMENT 'reference to quest_template',
|
||||
`cast_flags` TINYINT UNSIGNED NOT NULL COMMENT 'first bit defines caster: 1=player, 0=creature; second bit defines target, same mapping as caster bit'
|
||||
`npc_entry` int unsigned NOT NULL COMMENT 'reference to creature_template',
|
||||
`spell_id` int unsigned NOT NULL COMMENT 'spell which should be casted ',
|
||||
`quest_start` mediumint(8) unsigned NOT NULL COMMENT 'reference to quest_template',
|
||||
`quest_start_active` tinyint(1) unsigned NOT NULL default '0',
|
||||
`quest_end` mediumint(8) unsigned NOT NULL default '0',
|
||||
`cast_flags` tinyint unsigned NOT NULL COMMENT 'first bit defines caster: 1=player, 0=creature; second bit defines target, same mapping as caster bit'
|
||||
) ENGINE = MYISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
|
|
|
|||
11
sql/updates/8016_01_mangos_npc_spellclick_spells.sql
Normal file
11
sql/updates/8016_01_mangos_npc_spellclick_spells.sql
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_7988_09_mangos_spell_proc_event required_8016_01_mangos_npc_spellclick_spells bit;
|
||||
|
||||
ALTER TABLE npc_spellclick_spells
|
||||
CHANGE COLUMN quest_id quest_start mediumint(8) unsigned NOT NULL COMMENT 'reference to quest_template',
|
||||
ADD COLUMN quest_start_active tinyint(1) unsigned NOT NULL default '0' AFTER quest_start,
|
||||
ADD COLUMN quest_end mediumint(8) unsigned NOT NULL default '0' AFTER quest_start_active;
|
||||
|
||||
/* compatibility with old data */
|
||||
UPDATE npc_spellclick_spells
|
||||
SET quest_end = quest_start, quest_start_active = 1
|
||||
WHERE quest_start <> 0;
|
||||
|
|
@ -221,6 +221,7 @@ pkgdata_DATA = \
|
|||
7988_07_characters_characters.sql \
|
||||
7988_08_mangos_spell_bonus_data.sql \
|
||||
7988_09_mangos_spell_proc_event.sql \
|
||||
8016_01_mangos_npc_spellclick_spells.sql \
|
||||
README
|
||||
|
||||
## Additional files to include when running 'make dist'
|
||||
|
|
@ -422,4 +423,5 @@ EXTRA_DIST = \
|
|||
7988_07_characters_characters.sql \
|
||||
7988_08_mangos_spell_bonus_data.sql \
|
||||
7988_09_mangos_spell_proc_event.sql \
|
||||
8016_01_mangos_npc_spellclick_spells.sql \
|
||||
README
|
||||
|
|
|
|||
|
|
@ -106,6 +106,25 @@ LanguageDesc const* GetLanguageDescByID(uint32 lang)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool SpellClickInfo::IsFitToRequirements(Player const* player) const
|
||||
{
|
||||
if(questStart)
|
||||
{
|
||||
// not in expected required quest state
|
||||
if(!player || (!questStartCanActive || !player->IsActiveQuest(questStart)) && !player->GetQuestRewardStatus(questStart))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(questEnd)
|
||||
{
|
||||
// not in expected forbidden quest state
|
||||
if(!player || player->GetQuestRewardStatus(questEnd))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ObjectMgr::ObjectMgr()
|
||||
{
|
||||
m_hiCharGuid = 1;
|
||||
|
|
@ -636,6 +655,12 @@ void ObjectMgr::LoadCreatureTemplates()
|
|||
if(cInfo->rangeattacktime == 0)
|
||||
const_cast<CreatureInfo*>(cInfo)->rangeattacktime = BASE_ATTACK_TIME;
|
||||
|
||||
if(cInfo->npcflag & UNIT_NPC_FLAG_SPELLCLICK)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has dynamic flag UNIT_NPC_FLAG_SPELLCLICK (%u) set, it expect to be set by code base at `npc_spellclick_spells` content.",cInfo->Entry,UNIT_NPC_FLAG_SPELLCLICK);
|
||||
const_cast<CreatureInfo*>(cInfo)->npcflag &= ~UNIT_NPC_FLAG_SPELLCLICK;
|
||||
}
|
||||
|
||||
if((cInfo->npcflag & UNIT_NPC_FLAG_TRAINER) && cInfo->trainer_type >= MAX_TRAINER_TYPE)
|
||||
sLog.outErrorDb("Creature (Entry: %u) has wrong trainer type %u",cInfo->Entry,cInfo->trainer_type);
|
||||
|
||||
|
|
@ -6147,8 +6172,8 @@ void ObjectMgr::LoadNPCSpellClickSpells()
|
|||
uint32 count = 0;
|
||||
|
||||
mSpellClickInfoMap.clear();
|
||||
|
||||
QueryResult *result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_id, cast_flags FROM npc_spellclick_spells");
|
||||
// 0 1 2 3 4 5
|
||||
QueryResult *result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_start, quest_start_active, quest_end, cast_flags FROM npc_spellclick_spells");
|
||||
|
||||
if(!result)
|
||||
{
|
||||
|
|
@ -6184,25 +6209,45 @@ void ObjectMgr::LoadNPCSpellClickSpells()
|
|||
continue;
|
||||
}
|
||||
|
||||
uint32 quest = fields[2].GetUInt32();
|
||||
uint32 quest_start = fields[2].GetUInt32();
|
||||
|
||||
// quest might be 0 to enable spellclick independent of any quest
|
||||
if (quest)
|
||||
if (quest_start)
|
||||
{
|
||||
if(mQuestTemplates.find(quest) == mQuestTemplates.end())
|
||||
if(mQuestTemplates.find(quest_start) == mQuestTemplates.end())
|
||||
{
|
||||
sLog.outErrorDb("Table npc_spellclick_spells references unknown quest %u. Skipping entry.", spellid);
|
||||
sLog.outErrorDb("Table npc_spellclick_spells references unknown start quest %u. Skipping entry.", quest_start);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint8 castFlags = fields[3].GetUInt8();
|
||||
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(mQuestTemplates.find(quest_end) == mQuestTemplates.end())
|
||||
{
|
||||
sLog.outErrorDb("Table npc_spellclick_spells references unknown end quest %u. Skipping entry.", quest_end);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint8 castFlags = fields[5].GetUInt8();
|
||||
SpellClickInfo info;
|
||||
info.spellId = spellid;
|
||||
info.questId = quest;
|
||||
info.questStart = quest_start;
|
||||
info.questStartCanActive = quest_start_active;
|
||||
info.questEnd = quest_end;
|
||||
info.castFlags = castFlags;
|
||||
mSpellClickInfoMap.insert(SpellClickInfoMap::value_type(npc_entry, info));
|
||||
|
||||
// mark creature template as spell clickable
|
||||
const_cast<CreatureInfo*>(cInfo)->npcflag |= UNIT_NPC_FLAG_SPELLCLICK;
|
||||
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
|
||||
|
|
|
|||
|
|
@ -98,11 +98,17 @@ extern ScriptMapMap sEventScripts;
|
|||
struct SpellClickInfo
|
||||
{
|
||||
uint32 spellId;
|
||||
uint32 questId;
|
||||
uint32 questStart; // quest start (quest must be active or rewarded for spell apply)
|
||||
uint32 questEnd; // quest end (quest don't must be rewarded for spell apply)
|
||||
bool questStartCanActive; // if true then quest start can be active (not only rewarded)
|
||||
uint8 castFlags;
|
||||
|
||||
// helpers
|
||||
bool IsFitToRequirements(Player const* player) const;
|
||||
};
|
||||
|
||||
typedef std::multimap<uint32, SpellClickInfo> SpellClickInfoMap;
|
||||
typedef std::pair<SpellClickInfoMap::const_iterator,SpellClickInfoMap::const_iterator> SpellClickInfoMapBounds;
|
||||
|
||||
struct AreaTrigger
|
||||
{
|
||||
|
|
@ -531,7 +537,6 @@ class ObjectMgr
|
|||
void LoadReputationOnKill();
|
||||
void LoadPointsOfInterest();
|
||||
|
||||
SpellClickInfoMap mSpellClickInfoMap;
|
||||
void LoadNPCSpellClickSpells();
|
||||
|
||||
void LoadWeatherZoneChances();
|
||||
|
|
@ -756,6 +761,11 @@ class ObjectMgr
|
|||
|
||||
int GetOrNewIndexForLocale(LocaleConstant loc);
|
||||
|
||||
SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const
|
||||
{
|
||||
return SpellClickInfoMapBounds(mSpellClickInfoMap.lower_bound(creature_id),mSpellClickInfoMap.upper_bound(creature_id));
|
||||
}
|
||||
|
||||
ItemRequiredTargetMapBounds GetItemRequiredTargetMapBounds(uint32 uiItemEntry) const
|
||||
{
|
||||
return ItemRequiredTargetMapBounds(m_ItemRequiredTarget.lower_bound(uiItemEntry),m_ItemRequiredTarget.upper_bound(uiItemEntry));
|
||||
|
|
@ -819,6 +829,8 @@ class ObjectMgr
|
|||
|
||||
ScriptNameMap m_scriptNames;
|
||||
|
||||
SpellClickInfoMap mSpellClickInfoMap;
|
||||
|
||||
ItemRequiredTargetMap m_ItemRequiredTarget;
|
||||
|
||||
typedef std::vector<LocaleConstant> LocalForIndex;
|
||||
|
|
|
|||
|
|
@ -18477,18 +18477,20 @@ void Player::UpdateForQuestWorldObjects()
|
|||
Creature *obj = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, *itr);
|
||||
if(!obj)
|
||||
continue;
|
||||
// check if this unit requires quest specific flags
|
||||
|
||||
SpellClickInfoMap const& map = objmgr.mSpellClickInfoMap;
|
||||
for(SpellClickInfoMap::const_iterator itr = map.lower_bound(obj->GetEntry()); itr != map.upper_bound(obj->GetEntry()); ++itr)
|
||||
// check if this unit requires quest specific flags
|
||||
if(!obj->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_SPELLCLICK))
|
||||
continue;
|
||||
|
||||
SpellClickInfoMapBounds clickPair = objmgr.GetSpellClickInfoMapBounds(obj->GetEntry());
|
||||
for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
|
||||
{
|
||||
if(itr->second.questId != 0)
|
||||
if(itr->second.questStart || itr->second.questEnd)
|
||||
{
|
||||
obj->BuildCreateUpdateBlockForPlayer(&udata,this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
udata.BuildPacket(&packet);
|
||||
|
|
@ -20004,12 +20006,14 @@ void Player::ResummonPetTemporaryUnSummonedIfAny()
|
|||
|
||||
bool Player::canSeeSpellClickOn(Creature const *c) const
|
||||
{
|
||||
SpellClickInfoMap const& map = objmgr.mSpellClickInfoMap;
|
||||
for(SpellClickInfoMap::const_iterator itr = map.lower_bound(c->GetEntry()); itr != map.upper_bound(c->GetEntry()); ++itr)
|
||||
{
|
||||
if(itr->second.questId == 0 || GetQuestStatus(itr->second.questId) == QUEST_STATUS_INCOMPLETE)
|
||||
if(!c->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_SPELLCLICK))
|
||||
return false;
|
||||
|
||||
SpellClickInfoMapBounds clickPair = objmgr.GetSpellClickInfoMapBounds(c->GetEntry());
|
||||
for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
|
||||
if(itr->second.IsFitToRequirements(this))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -523,10 +523,10 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data )
|
|||
if(!unit)
|
||||
return;
|
||||
|
||||
SpellClickInfoMap const& map = objmgr.mSpellClickInfoMap;
|
||||
for(SpellClickInfoMap::const_iterator itr = map.lower_bound(unit->GetEntry()); itr != map.upper_bound(unit->GetEntry()); ++itr)
|
||||
SpellClickInfoMapBounds clickPair = objmgr.GetSpellClickInfoMapBounds(unit->GetEntry());
|
||||
for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
|
||||
{
|
||||
if(itr->second.questId == 0 || _player->GetQuestStatus(itr->second.questId) == QUEST_STATUS_INCOMPLETE)
|
||||
if(itr->second.IsFitToRequirements(_player))
|
||||
{
|
||||
Unit *caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit;
|
||||
Unit *target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit;
|
||||
|
|
|
|||
|
|
@ -562,7 +562,7 @@ enum NPCFlags
|
|||
UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, // 100%
|
||||
UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100%
|
||||
UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode
|
||||
UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click)
|
||||
UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click), dynamic, set at loading and don't must be set in DB
|
||||
UNIT_NPC_FLAG_GUARD = 0x10000000, // custom flag for guards
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "8015"
|
||||
#define REVISION_NR "8016"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue