[7141] Implement heroic raid instance mode support.

* Heroic mode player amount for instances in DB. Can be used for any instances but added for heroic raid instance.
* Output transfer error at max playrs limit.
* FIXME notes ;) for raid required implementing store 2 reset time and do global reset for 2 modes. But currently raid have inmmap entry data
same reset time for both cases.
* Update instances list where mounts allowed.
* Simplify and fix code for SMSG_RAID_INSTANCE_INFO.

Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
Energy 2009-01-22 02:52:21 +03:00 committed by VladimirMangos
parent 2a891a8c92
commit f26d6151c8
11 changed files with 87 additions and 52 deletions

View file

@ -22,7 +22,7 @@
DROP TABLE IF EXISTS `db_version`; DROP TABLE IF EXISTS `db_version`;
CREATE TABLE `db_version` ( CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`required_7133_02_mangos_spell_loot_template` bit(1) default NULL `required_7141_01_mangos_instance_template` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --
@ -1445,6 +1445,7 @@ CREATE TABLE `instance_template` (
`levelMin` tinyint(3) unsigned NOT NULL default '0', `levelMin` tinyint(3) unsigned NOT NULL default '0',
`levelMax` tinyint(3) unsigned NOT NULL default '0', `levelMax` tinyint(3) unsigned NOT NULL default '0',
`maxPlayers` tinyint(3) unsigned NOT NULL default '0', `maxPlayers` tinyint(3) unsigned NOT NULL default '0',
`maxPlayersHeroic` tinyint(3) unsigned NOT NULL default '0',
`reset_delay` int(10) unsigned NOT NULL default '0', `reset_delay` int(10) unsigned NOT NULL default '0',
`startLocX` float default NULL, `startLocX` float default NULL,
`startLocY` float default NULL, `startLocY` float default NULL,
@ -1461,32 +1462,35 @@ CREATE TABLE `instance_template` (
LOCK TABLES `instance_template` WRITE; LOCK TABLES `instance_template` WRITE;
/*!40000 ALTER TABLE `instance_template` DISABLE KEYS */; /*!40000 ALTER TABLE `instance_template` DISABLE KEYS */;
INSERT INTO `instance_template` VALUES INSERT INTO `instance_template` VALUES
(33,0,22,30,10,7200,NULL,NULL,NULL,NULL,''), (33,0,22,30,10,10,7200,NULL,NULL,NULL,NULL,''),
(34,0,24,32,10,7200,NULL,NULL,NULL,NULL,''), (34,0,24,32,10,10,7200,NULL,NULL,NULL,NULL,''),
(36,0,15,20,10,7200,NULL,NULL,NULL,NULL,''), (36,0,15,20,10,10,7200,NULL,NULL,NULL,NULL,''),
(43,0,15,21,10,7200,NULL,NULL,NULL,NULL,''), (43,0,15,21,10,10,7200,NULL,NULL,NULL,NULL,''),
(47,0,29,38,10,7200,NULL,NULL,NULL,NULL,''), (47,0,29,38,10,10,7200,NULL,NULL,NULL,NULL,''),
(48,0,24,32,10,7200,NULL,NULL,NULL,NULL,''), (48,0,24,32,10,10,7200,NULL,NULL,NULL,NULL,''),
(70,0,35,47,10,7200,NULL,NULL,NULL,NULL,''), (70,0,35,47,10,10,7200,NULL,NULL,NULL,NULL,''),
(90,0,29,38,10,7200,NULL,NULL,NULL,NULL,''), (90,0,29,38,10,10,7200,NULL,NULL,NULL,NULL,''),
(109,0,45,55,10,7200,NULL,NULL,NULL,NULL,''), (109,0,45,55,10,10,7200,NULL,NULL,NULL,NULL,''),
(129,0,37,46,10,7200,NULL,NULL,NULL,NULL,''), (129,0,37,46,10,10,7200,NULL,NULL,NULL,NULL,''),
(189,0,34,45,10,7200,NULL,NULL,NULL,NULL,''), (189,0,34,45,10,10,7200,NULL,NULL,NULL,NULL,''),
(209,0,44,54,10,7200,NULL,NULL,NULL,NULL,''), (209,0,44,54,10,10,7200,NULL,NULL,NULL,NULL,''),
(229,0,58,0,10,120000,78.5083,-225.044,49.839,5.1,''), (229,0,58,0,10,10,120000,78.5083,-225.044,49.839,5.1,''),
(230,0,52,0,5,7200,NULL,NULL,NULL,NULL,''), (230,0,52,0,5,5,7200,NULL,NULL,NULL,NULL,''),
(249,0,60,0,40,432000,NULL,NULL,NULL,NULL,''), (249,0,60,0,40,40,432000,NULL,NULL,NULL,NULL,''),
(289,0,57,0,5,7200,NULL,NULL,NULL,NULL,''), (289,0,57,0,5,5,7200,NULL,NULL,NULL,NULL,''),
(309,0,60,0,20,259200,NULL,NULL,NULL,NULL,''), (309,0,60,0,20,20,259200,NULL,NULL,NULL,NULL,''),
(329,0,58,60,5,7200,NULL,NULL,NULL,NULL,''), (329,0,58,60,5,5,7200,NULL,NULL,NULL,NULL,''),
(349,0,46,55,10,7200,NULL,NULL,NULL,NULL,''), (349,0,46,55,10,10,7200,NULL,NULL,NULL,NULL,''),
(389,0,13,18,10,7200,NULL,NULL,NULL,NULL,''), (389,0,13,18,10,10,7200,NULL,NULL,NULL,NULL,''),
(409,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), (409,0,60,0,40,40,604800,NULL,NULL,NULL,NULL,''),
(429,0,55,60,5,7200,NULL,NULL,NULL,NULL,''), (429,0,55,60,5,5,7200,NULL,NULL,NULL,NULL,''),
(469,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), (469,0,60,0,40,40,604800,NULL,NULL,NULL,NULL,''),
(509,0,60,0,20,259200,NULL,NULL,NULL,NULL,''), (509,0,60,0,20,20,259200,NULL,NULL,NULL,NULL,''),
(531,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), (531,0,60,0,40,40,604800,NULL,NULL,NULL,NULL,''),
(533,0,60,0,40,604800,NULL,NULL,NULL,NULL,''); (533,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(615,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(616,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(624,0,80,0,10,25,0,NULL,NULL,NULL,NULL,'');
/*!40000 ALTER TABLE `instance_template` ENABLE KEYS */; /*!40000 ALTER TABLE `instance_template` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;

View file

@ -0,0 +1,12 @@
ALTER TABLE db_version CHANGE COLUMN required_7133_02_mangos_spell_loot_template required_7141_01_mangos_instance_template bit;
ALTER TABLE instance_template ADD maxPlayersHeroic tinyint(3) unsigned NOT NULL default '0' AFTER maxPlayers;
UPDATE instance_template SET maxPlayersHeroic = maxPlayers;
DELETE FROM instance_template WHERE map IN (533,615,616,624);
INSERT INTO instance_template VALUES
(533,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(615,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(616,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(624,0,80,0,10,25,0,NULL,NULL,NULL,NULL,'');

View file

@ -145,6 +145,7 @@ pkgdata_DATA = \
7118_01_mangos_skill_discovery_template.sql \ 7118_01_mangos_skill_discovery_template.sql \
7133_01_mangos_skill_discovery_template.sql \ 7133_01_mangos_skill_discovery_template.sql \
7133_02_mangos_spell_loot_template.sql \ 7133_02_mangos_spell_loot_template.sql \
7141_01_mangos_instance_template.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -270,4 +271,5 @@ EXTRA_DIST = \
7118_01_mangos_skill_discovery_template.sql \ 7118_01_mangos_skill_discovery_template.sql \
7133_01_mangos_skill_discovery_template.sql \ 7133_01_mangos_skill_discovery_template.sql \
7133_02_mangos_spell_loot_template.sql \ 7133_02_mangos_spell_loot_template.sql \
7141_01_mangos_instance_template.sql \
README README

View file

@ -449,7 +449,7 @@ void InstanceSaveManager::LoadResetTimes()
// add the global reset times to the priority queue // add the global reset times to the priority queue
for(uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++) for(uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++)
{ {
InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(i); InstanceTemplate const* temp = objmgr.GetInstanceTemplate(i);
if(!temp) continue; if(!temp) continue;
// only raid/heroic maps have a global reset time // only raid/heroic maps have a global reset time
const MapEntry* entry = sMapStore.LookupEntry(temp->map); const MapEntry* entry = sMapStore.LookupEntry(temp->map);
@ -578,7 +578,7 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
{ {
// global reset for all instances of the given map // global reset for all instances of the given map
// note: this isn't fast but it's meant to be executed very rarely // note: this isn't fast but it's meant to be executed very rarely
Map *map = (MapInstanced*)MapManager::Instance().GetBaseMap(mapid); Map const *map = MapManager::Instance().GetBaseMap(mapid);
if(!map->Instanceable()) if(!map->Instanceable())
return; return;
uint64 now = (uint64)time(NULL); uint64 now = (uint64)time(NULL);
@ -586,7 +586,7 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
if(!warn) if(!warn)
{ {
// this is called one minute before the reset time // this is called one minute before the reset time
InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(mapid); InstanceTemplate const* temp = objmgr.GetInstanceTemplate(mapid);
if(!temp || !temp->reset_delay) if(!temp || !temp->reset_delay)
{ {
sLog.outError("InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d", mapid); sLog.outError("InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d", mapid);

View file

@ -1528,10 +1528,10 @@ bool InstanceMap::CanEnter(Player *player)
} }
// cannot enter if the instance is full (player cap), GMs don't count // cannot enter if the instance is full (player cap), GMs don't count
InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId()); uint32 maxPlayers = GetMaxPlayers();
if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= iTemplate->maxPlayers) if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= maxPlayers)
{ {
sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), iTemplate->maxPlayers, player->GetName()); sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName());
player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
return false; return false;
} }
@ -1824,6 +1824,14 @@ void InstanceMap::SetResetSchedule(bool on)
} }
} }
uint32 InstanceMap::GetMaxPlayers() const
{
InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId());
if(!iTemplate)
return 0;
return IsHeroic() ? iTemplate->maxPlayersHeroic : iTemplate->maxPlayers;
}
/* ******* Battleground Instance Maps ******* */ /* ******* Battleground Instance Maps ******* */
BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId) BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId)

View file

@ -98,7 +98,8 @@ struct InstanceTemplate
uint32 levelMin; uint32 levelMin;
uint32 levelMax; uint32 levelMax;
uint32 maxPlayers; uint32 maxPlayers;
uint32 reset_delay; uint32 maxPlayersHeroic;
uint32 reset_delay; // FIX ME: now exist normal/heroic raids with possible different time of reset.
float startLocX; float startLocX;
float startLocY; float startLocY;
float startLocZ; float startLocZ;
@ -364,6 +365,7 @@ class MANGOS_DLL_SPEC InstanceMap : public Map
bool CanEnter(Player* player); bool CanEnter(Player* player);
void SendResetWarnings(uint32 timeLeft) const; void SendResetWarnings(uint32 timeLeft) const;
void SetResetSchedule(bool on); void SetResetSchedule(bool on);
uint32 GetMaxPlayers() const;
private: private:
bool m_resetAfterUnload; bool m_resetAfterUnload;
bool m_unloadWhenEmpty; bool m_unloadWhenEmpty;

View file

@ -4336,14 +4336,20 @@ void ObjectMgr::LoadInstanceTemplate()
else if(!entry->HasResetTime()) else if(!entry->HasResetTime())
continue; continue;
//FIXME: now exist heroic instance, normal/heroic raid instances
// entry->resetTimeHeroic store reset time for both heroic mode instance (raid and non-raid)
// entry->resetTimeRaid store reset time for normal raid only
// for current state entry->resetTimeRaid == entry->resetTimeHeroic in case raid instances with heroic mode.
// but at some point wee need implement reset time dependen from raid insatance mode
if(temp->reset_delay == 0) if(temp->reset_delay == 0)
{ {
// use defaults from the DBC // use defaults from the DBC
if(entry->SupportsHeroicMode()) if(entry->resetTimeHeroic) // for both raid and non raids, read above
{ {
temp->reset_delay = entry->resetTimeHeroic / DAY; temp->reset_delay = entry->resetTimeHeroic / DAY;
} }
else if (entry->resetTimeRaid && entry->map_type == MAP_RAID) else if (entry->resetTimeRaid && entry->map_type == MAP_RAID)
// for normal raid only
{ {
temp->reset_delay = entry->resetTimeRaid / DAY; temp->reset_delay = entry->resetTimeRaid / DAY;
} }

View file

@ -15288,29 +15288,29 @@ InstancePlayerBind* Player::BindToInstance(InstanceSave *save, bool permanent, b
void Player::SendRaidInfo() void Player::SendRaidInfo()
{ {
uint32 counter = 0;
WorldPacket data(SMSG_RAID_INSTANCE_INFO, 4); WorldPacket data(SMSG_RAID_INSTANCE_INFO, 4);
uint32 counter = 0, i; size_t p_counter = data.wpos();
for(i = 0; i < TOTAL_DIFFICULTIES; i++) data << uint32(counter); // placeholder
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
if(itr->second.perm) counter++;
data << counter; for(int i = 0; i < TOTAL_DIFFICULTIES; ++i)
for(i = 0; i < TOTAL_DIFFICULTIES; i++)
{ {
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr) for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
{ {
if(itr->second.perm) if(itr->second.perm)
{ {
InstanceSave *save = itr->second.save; InstanceSave *save = itr->second.save;
data << (save->GetMapId()); data << uint32(save->GetMapId());
data << (uint32)(save->GetResetTime() - time(NULL)); data << uint32(save->GetResetTime() - time(NULL));
data << save->GetInstanceId(); data << uint32(save->GetInstanceId());
data << uint32(counter); data << uint32(save->GetDifficulty());
counter--; ++counter;
} }
} }
} }
data.put<uint32>(p_counter,counter);
GetSession()->SendPacket(&data); GetSession()->SendPacket(&data);
} }

View file

@ -941,14 +941,15 @@ struct MapEntry
bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; } bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; }
bool IsBattleArena() const { return map_type == MAP_ARENA; } bool IsBattleArena() const { return map_type == MAP_ARENA; }
bool IsBattleGroundOrArena() const { return map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; } bool IsBattleGroundOrArena() const { return map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; }
bool SupportsHeroicMode() const { return resetTimeHeroic && !resetTimeRaid; } bool SupportsHeroicMode() const { return resetTimeHeroic != 0; }
bool HasResetTime() const { return resetTimeHeroic || resetTimeRaid; } bool HasResetTime() const { return resetTimeHeroic || resetTimeRaid; }
bool IsMountAllowed() const bool IsMountAllowed() const
{ {
return !IsDungeon() || return !IsDungeon() ||
MapID==568 || MapID==309 || MapID==209 || MapID==534 || MapID==209 || MapID==269 || MapID==309 || // TanarisInstance, CavernsOfTime, Zul'gurub
MapID==560 || MapID==509 || MapID==269; MapID==509 || MapID==534 || MapID==560 || // AhnQiraj, HyjalPast, HillsbradPast
MapID==568 || MapID==615 || MapID==616; // ZulAman, Obsidian Sanctrum, Eye Of Eternity
} }
bool IsContinent() const bool IsContinent() const

View file

@ -37,8 +37,8 @@ const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiii"; const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiii";
const char PageTextfmt[]="isi"; const char PageTextfmt[]="isi";
const char SpellThreatfmt[]="ii"; const char SpellThreatfmt[]="ii";
const char InstanceTemplatesrcfmt[]="iiiiiiffffs"; const char InstanceTemplatesrcfmt[]="iiiiiiiffffs";
const char InstanceTemplatedstfmt[]="iiiiiiffffi"; const char InstanceTemplatedstfmt[]="iiiiiiiffffi";
SQLStorage sCreatureStorage(CreatureInfosrcfmt, CreatureInfodstfmt, "entry","creature_template"); SQLStorage sCreatureStorage(CreatureInfosrcfmt, CreatureInfodstfmt, "entry","creature_template");
SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon"); SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon");

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "7140" #define REVISION_NR "7141"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__