mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 04:37:00 +00:00
[10932] Imporvments gameevent creature morphing.
* Table `game_event_model_equip` renamed to `game_event_creature_data`
* Table allow now store same creatures for different events, BUT
expected that related events no active in same time.
* Added possibility switch entry at gameevent time.
This let have diff factions/loot and etc for creatures.
* Added possibility cast spells at gameevent start/end.
Exist some spells that expected casted to creature at gameevent start
for model replace, and for animation in other cases.
Note: `game_event_creature_data`.`modelid` field posisble will removed soon in fowor related spell use.
Ofc, when spells will implemented in core.
This commit is contained in:
parent
e52ebaf7a9
commit
d38df50a7e
11 changed files with 145 additions and 55 deletions
|
|
@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
|
|||
`version` varchar(120) default NULL,
|
||||
`creature_ai_version` varchar(120) default NULL,
|
||||
`cache_id` int(10) default '0',
|
||||
`required_10906_02_mangos_spell_bonus_data` bit(1) default NULL
|
||||
`required_10932_01_mangos_game_event_creature_data` bit(1) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
|
||||
|
||||
--
|
||||
|
|
@ -1649,6 +1649,31 @@ LOCK TABLES `game_event_creature` WRITE;
|
|||
/*!40000 ALTER TABLE `game_event_creature` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `game_event_creature_data`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `game_event_creature_data`;
|
||||
CREATE TABLE `game_event_creature_data` (
|
||||
`guid` int(10) unsigned NOT NULL default '0',
|
||||
`entry_id` mediumint(8) unsigned NOT NULL default '0',
|
||||
`modelid` mediumint(8) unsigned NOT NULL default '0',
|
||||
`equipment_id` mediumint(8) unsigned NOT NULL default '0',
|
||||
`spell_start` mediumint(8) unsigned NOT NULL default '0',
|
||||
`spell_end` mediumint(8) unsigned NOT NULL default '0',
|
||||
`event` smallint(5) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (`guid`,`event`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Dumping data for table `game_event_creature_data`
|
||||
--
|
||||
|
||||
LOCK TABLES `game_event_model_equip` WRITE;
|
||||
/*!40000 ALTER TABLE `game_event_creature_data` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `game_event_creature_data` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `game_event_gameobject`
|
||||
--
|
||||
|
|
@ -1669,28 +1694,6 @@ LOCK TABLES `game_event_gameobject` WRITE;
|
|||
/*!40000 ALTER TABLE `game_event_gameobject` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `game_event_model_equip`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `game_event_model_equip`;
|
||||
CREATE TABLE `game_event_model_equip` (
|
||||
`guid` int(10) unsigned NOT NULL default '0',
|
||||
`modelid` mediumint(8) unsigned NOT NULL default '0',
|
||||
`equipment_id` mediumint(8) unsigned NOT NULL default '0',
|
||||
`event` smallint(5) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (`guid`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Dumping data for table `game_event_model_equip`
|
||||
--
|
||||
|
||||
LOCK TABLES `game_event_model_equip` WRITE;
|
||||
/*!40000 ALTER TABLE `game_event_model_equip` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `game_event_model_equip` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `game_event_quest`
|
||||
--
|
||||
|
|
|
|||
14
sql/updates/10932_01_mangos_game_event_creature_data.sql
Normal file
14
sql/updates/10932_01_mangos_game_event_creature_data.sql
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_10906_02_mangos_spell_bonus_data required_10932_01_mangos_game_event_creature_data bit;
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS game_event_creature_data;
|
||||
RENAME TABLE game_event_model_equip TO game_event_creature_data;
|
||||
|
||||
ALTER TABLE game_event_creature_data
|
||||
ADD COLUMN entry_id mediumint(8) unsigned NOT NULL default '0' AFTER guid,
|
||||
ADD COLUMN spell_start mediumint(8) unsigned NOT NULL default '0' AFTER equipment_id,
|
||||
ADD COLUMN spell_end mediumint(8) unsigned NOT NULL default '0' AFTER spell_start;
|
||||
|
||||
ALTER TABLE game_event_creature_data
|
||||
DROP PRIMARY KEY,
|
||||
ADD PRIMARY KEY (`guid`,`event`);
|
||||
|
|
@ -138,6 +138,7 @@ pkgdata_DATA = \
|
|||
10883_01_mangos_spell_proc_event.sql \
|
||||
10906_01_mangos_spell_proc_event.sql \
|
||||
10906_02_mangos_spell_bonus_data.sql \
|
||||
10932_01_mangos_game_event_creature_data.sql \
|
||||
README
|
||||
|
||||
## Additional files to include when running 'make dist'
|
||||
|
|
@ -256,4 +257,5 @@ EXTRA_DIST = \
|
|||
10883_01_mangos_spell_proc_event.sql \
|
||||
10906_01_mangos_spell_proc_event.sql \
|
||||
10906_02_mangos_spell_bonus_data.sql \
|
||||
10932_01_mangos_game_event_creature_data.sql \
|
||||
README
|
||||
|
|
|
|||
|
|
@ -200,6 +200,10 @@ void Creature::RemoveCorpse()
|
|||
*/
|
||||
bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameEventCreatureData const* eventData /*=NULL*/ )
|
||||
{
|
||||
// use game event entry if any instead default suggested
|
||||
if (eventData && eventData->entry_id)
|
||||
Entry = eventData->entry_id;
|
||||
|
||||
CreatureInfo const *normalInfo = ObjectMgr::GetCreatureTemplate(Entry);
|
||||
if(!normalInfo)
|
||||
{
|
||||
|
|
@ -357,6 +361,10 @@ bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData *data /*=
|
|||
for(int i = 0; i < CREATURE_MAX_SPELLS; ++i)
|
||||
m_spells[i] = GetCreatureInfo()->spells[i];
|
||||
|
||||
// if eventData set then event active and need apply spell_start
|
||||
if (eventData)
|
||||
ApplyGameEventSpells(eventData, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -447,7 +455,11 @@ void Creature::Update(uint32 update_diff, uint32 diff)
|
|||
lootForSkin = false;
|
||||
|
||||
if(m_originalEntry != GetEntry())
|
||||
UpdateEntry(m_originalEntry);
|
||||
{
|
||||
// need preserver gameevent state
|
||||
GameEventCreatureData const* eventData = sGameEventMgr.GetCreatureUpdateDataForActiveEvent(GetDBTableGUIDLow());
|
||||
UpdateEntry(m_originalEntry, TEAM_NONE, NULL, eventData);
|
||||
}
|
||||
|
||||
CreatureInfo const *cinfo = GetCreatureInfo();
|
||||
|
||||
|
|
@ -1351,7 +1363,7 @@ void Creature::DeleteFromDB()
|
|||
WorldDatabase.PExecuteLog("DELETE FROM creature_addon WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecuteLog("DELETE FROM game_event_creature WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecuteLog("DELETE FROM game_event_model_equip WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecuteLog("DELETE FROM game_event_creature_data WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecuteLog("DELETE FROM creature_battleground WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.CommitTransaction();
|
||||
}
|
||||
|
|
@ -2344,3 +2356,17 @@ void Creature::RelocationNotify()
|
|||
float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO);
|
||||
Cell::VisitAllObjects(this, relocationNotifier, radius);
|
||||
}
|
||||
|
||||
void Creature::ApplyGameEventSpells(GameEventCreatureData const* eventData, bool activated)
|
||||
{
|
||||
uint32 cast_spell = activated ? eventData->spell_id_start : eventData->spell_id_end;
|
||||
uint32 remove_spell = activated ? eventData->spell_id_end : eventData->spell_id_start;
|
||||
|
||||
if (remove_spell)
|
||||
if (SpellEntry const* spellEntry = sSpellStore.LookupEntry(remove_spell))
|
||||
if (IsSpellAppliesAura(spellEntry))
|
||||
RemoveAurasDueToSpell(remove_spell);
|
||||
|
||||
if (cast_spell)
|
||||
CastSpell(this, cast_spell, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -502,6 +502,8 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
|||
bool HasSpell(uint32 spellID) const;
|
||||
|
||||
bool UpdateEntry(uint32 entry, Team team = ALLIANCE, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL, bool preserveHPAndPower = true);
|
||||
|
||||
void ApplyGameEventSpells(GameEventCreatureData const* eventData, bool activated);
|
||||
bool UpdateStats(Stats stat);
|
||||
bool UpdateAllStats();
|
||||
void UpdateResistances(uint32 school);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "Log.h"
|
||||
#include "MapManager.h"
|
||||
#include "BattleGroundMgr.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1(GameEventMgr);
|
||||
|
|
@ -345,10 +346,12 @@ void GameEventMgr::LoadFromDB()
|
|||
|
||||
mGameEventCreatureData.resize(mGameEvent.size());
|
||||
// 0 1 2
|
||||
result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.event, game_event_model_equip.modelid,"
|
||||
// 3
|
||||
"game_event_model_equip.equipment_id "
|
||||
"FROM creature JOIN game_event_model_equip ON creature.guid=game_event_model_equip.guid");
|
||||
result = WorldDatabase.Query("SELECT creature.guid, game_event_creature_data.event, game_event_creature_data.modelid,"
|
||||
// 3 4
|
||||
"game_event_creature_data.equipment_id, game_event_creature_data.entry_id, "
|
||||
// 5 6
|
||||
"game_event_creature_data.spell_start, game_event_creature_data.spell_end "
|
||||
"FROM creature JOIN game_event_creature_data ON creature.guid=game_event_creature_data.guid");
|
||||
|
||||
count = 0;
|
||||
if( !result )
|
||||
|
|
@ -357,7 +360,7 @@ void GameEventMgr::LoadFromDB()
|
|||
bar.step();
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString(">> Loaded %u model/equipment changes in game events", count );
|
||||
sLog.outString(">> Loaded %u creature reactions at game events", count );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -371,35 +374,59 @@ void GameEventMgr::LoadFromDB()
|
|||
uint32 guid = fields[0].GetUInt32();
|
||||
uint16 event_id = fields[1].GetUInt16();
|
||||
|
||||
if(event_id==0)
|
||||
{
|
||||
sLog.outErrorDb("`game_event_creature_data` game event id (%i) is reserved and can't be used.",event_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(event_id >= mGameEventCreatureData.size())
|
||||
{
|
||||
sLog.outErrorDb("`game_event_model_equip` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
|
||||
sLog.outErrorDb("`game_event_creature_data` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
++count;
|
||||
GameEventCreatureDataList& equiplist = mGameEventCreatureData[event_id];
|
||||
GameEventCreatureData newModelEquipSet;
|
||||
newModelEquipSet.modelid = fields[2].GetUInt32();
|
||||
newModelEquipSet.equipment_id = fields[3].GetUInt32();
|
||||
GameEventCreatureData newData;
|
||||
newData.modelid = fields[2].GetUInt32();
|
||||
newData.equipment_id = fields[3].GetUInt32();
|
||||
newData.entry_id = fields[4].GetUInt32();
|
||||
newData.spell_id_start = fields[5].GetUInt32();
|
||||
newData.spell_id_end = fields[6].GetUInt32();
|
||||
|
||||
if(newModelEquipSet.equipment_id > 0)
|
||||
if (newData.equipment_id && !sObjectMgr.GetEquipmentInfo(newData.equipment_id))
|
||||
{
|
||||
if(!sObjectMgr.GetEquipmentInfo(newModelEquipSet.equipment_id))
|
||||
{
|
||||
sLog.outErrorDb("Table `game_event_model_equip` have creature (Guid: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", guid, newModelEquipSet.equipment_id);
|
||||
continue;
|
||||
}
|
||||
sLog.outErrorDb("Table `game_event_creature_data` have creature (Guid: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", guid, newData.equipment_id);
|
||||
newData.equipment_id = 0;
|
||||
}
|
||||
|
||||
equiplist.push_back(GameEventCreatureDataPair(guid, newModelEquipSet));
|
||||
mGameEventCreatureDataPerGuid[guid] = event_id;
|
||||
if (newData.entry_id && !sObjectMgr.GetCreatureTemplate(newData.entry_id))
|
||||
{
|
||||
sLog.outErrorDb("Table `game_event_creature_data` have creature (Guid: %u) with event time entry %u not found in table `creature_template`, set to no 0.", guid, newData.entry_id);
|
||||
newData.entry_id = 0;
|
||||
}
|
||||
|
||||
if (newData.spell_id_start && !sSpellStore.LookupEntry(newData.spell_id_start))
|
||||
{
|
||||
sLog.outErrorDb("Table `game_event_creature_data` have creature (Guid: %u) with nonexistent spell_start %u, set to no start spell.", guid, newData.spell_id_start);
|
||||
newData.spell_id_start = 0;
|
||||
}
|
||||
|
||||
if (newData.spell_id_end && !sSpellStore.LookupEntry(newData.spell_id_end))
|
||||
{
|
||||
sLog.outErrorDb("Table `game_event_creature_data` have creature (Guid: %u) with nonexistent spell_end %u, set to no end spell.", guid, newData.spell_id_end);
|
||||
newData.spell_id_end = 0;
|
||||
}
|
||||
|
||||
equiplist.push_back(GameEventCreatureDataPair(guid, newData));
|
||||
mGameEventCreatureDataPerGuid.insert(GameEventCreatureDataPerGuidMap::value_type(guid, event_id));
|
||||
|
||||
} while( result->NextRow() );
|
||||
delete result;
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString( ">> Loaded %u model/equipment changes in game events", count );
|
||||
sLog.outString(">> Loaded %u creature reactions at game events", count );
|
||||
}
|
||||
|
||||
mGameEventQuests.resize(mGameEvent.size());
|
||||
|
|
@ -726,15 +753,22 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
GameEventCreatureData const* GameEventMgr::GetCreatureUpdateDataForActiveEvent(uint32 lowguid) const
|
||||
{
|
||||
// only for active event
|
||||
GameEventCreatureDataPerGuidMap::const_iterator itr = mGameEventCreatureDataPerGuid.find(lowguid);
|
||||
if (itr == mGameEventCreatureDataPerGuid.end() || !IsActiveEvent(itr->second))
|
||||
return NULL;
|
||||
// only for active event, creature can be listed for many so search all
|
||||
uint32 event_id = 0;
|
||||
GameEventCreatureDataPerGuidBounds bounds = mGameEventCreatureDataPerGuid.equal_range(lowguid);
|
||||
for(GameEventCreatureDataPerGuidMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
|
||||
{
|
||||
if (IsActiveEvent(itr->second))
|
||||
{
|
||||
event_id = itr->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 event_id = itr->second;
|
||||
if (!event_id)
|
||||
return NULL;
|
||||
|
||||
for(GameEventCreatureDataList::const_iterator itr = mGameEventCreatureData[event_id].begin();itr != mGameEventCreatureData[event_id].end();++itr)
|
||||
if (itr->first == lowguid)
|
||||
|
|
@ -754,7 +788,13 @@ void GameEventMgr::UpdateCreatureData(int16 event_id, bool activate)
|
|||
|
||||
// Update if spawned
|
||||
if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, itr->first)))
|
||||
{
|
||||
pCreature->UpdateEntry(data->id, TEAM_NONE, data, activate ? &itr->second : NULL);
|
||||
|
||||
// spells not casted for event remove case (sent NULL into update), do it
|
||||
if (!activate)
|
||||
pCreature->ApplyGameEventSpells(&itr->second, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,8 +44,11 @@ struct GameEventData
|
|||
|
||||
struct GameEventCreatureData
|
||||
{
|
||||
uint32 entry_id;
|
||||
uint32 modelid;
|
||||
uint32 equipment_id;
|
||||
uint32 spell_id_start;
|
||||
uint32 spell_id_end;
|
||||
};
|
||||
|
||||
typedef std::pair<uint32, GameEventCreatureData> GameEventCreatureDataPair;
|
||||
|
|
@ -79,7 +82,6 @@ class GameEventMgr
|
|||
void GameEventSpawn(int16 event_id);
|
||||
void GameEventUnspawn(int16 event_id);
|
||||
void UpdateCreatureData(int16 event_id, bool activate);
|
||||
|
||||
void UpdateEventQuests(uint16 event_id, bool Activate);
|
||||
void UpdateWorldStates(uint16 event_id, bool Activate);
|
||||
protected:
|
||||
|
|
@ -89,7 +91,8 @@ class GameEventMgr
|
|||
typedef std::vector<IdList> GameEventIdMap;
|
||||
typedef std::list<GameEventCreatureDataPair> GameEventCreatureDataList;
|
||||
typedef std::vector<GameEventCreatureDataList> GameEventCreatureDataMap;
|
||||
typedef UNORDERED_MAP<uint32, uint32> GameEventCreatureDataPerGuidMap;
|
||||
typedef std::multimap<uint32, uint32> GameEventCreatureDataPerGuidMap;
|
||||
typedef std::pair<GameEventCreatureDataPerGuidMap::const_iterator,GameEventCreatureDataPerGuidMap::const_iterator> GameEventCreatureDataPerGuidBounds;
|
||||
|
||||
typedef std::list<uint32> QuestList;
|
||||
typedef std::vector<QuestList> GameEventQuestMap;
|
||||
|
|
|
|||
|
|
@ -3833,7 +3833,7 @@ bool ChatHandler::HandleAuraCommand(char* args)
|
|||
if (!spellInfo)
|
||||
return false;
|
||||
|
||||
if (!IsSpellAppliesAura(spellInfo, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) &&
|
||||
if (!IsSpellAppliesAura(spellInfo) &&
|
||||
!IsSpellHaveEffect(spellInfo, SPELL_EFFECT_PERSISTENT_AREA_AURA))
|
||||
{
|
||||
PSendSysMessage(LANG_SPELL_NO_HAVE_AURAS, spellID);
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect)
|
|||
return false;
|
||||
}
|
||||
|
||||
inline bool IsSpellAppliesAura(SpellEntry const *spellInfo, uint32 effectMask)
|
||||
inline bool IsSpellAppliesAura(SpellEntry const *spellInfo, uint32 effectMask = ((1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)))
|
||||
{
|
||||
for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "10931"
|
||||
#define REVISION_NR "10932"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef __REVISION_SQL_H__
|
||||
#define __REVISION_SQL_H__
|
||||
#define REVISION_DB_CHARACTERS "required_10862_01_characters_mail"
|
||||
#define REVISION_DB_MANGOS "required_10906_02_mangos_spell_bonus_data"
|
||||
#define REVISION_DB_MANGOS "required_10932_01_mangos_game_event_creature_data"
|
||||
#define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version"
|
||||
#endif // __REVISION_SQL_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue