Merge branch 'master' into 310

Conflicts:
	src/game/BattleGroundHandler.cpp
	src/game/Unit.cpp
This commit is contained in:
tomrus88 2009-04-08 15:01:06 +04:00
commit 769a24252b
22 changed files with 795 additions and 774 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_7627_01_mangos_achievement_criteria_data` bit(1) default NULL `required_7633_01_mangos_achievement_criteria_data` 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';
-- --
@ -46,7 +46,7 @@ CREATE TABLE `achievement_criteria_data` (
`type` tinyint(3) unsigned NOT NULL DEFAULT '0', `type` tinyint(3) unsigned NOT NULL DEFAULT '0',
`value1` mediumint(8) unsigned NOT NULL DEFAULT '0', `value1` mediumint(8) unsigned NOT NULL DEFAULT '0',
`value2` mediumint(8) unsigned NOT NULL DEFAULT '0', `value2` mediumint(8) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`criteria_id`) PRIMARY KEY (`criteria_id`,`type`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Achievment system'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Achievment system';
-- --

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_7627_01_mangos_achievement_criteria_data required_7633_01_mangos_achievement_criteria_data bit;
ALTER TABLE `achievement_criteria_data`
DROP PRIMARY KEY,
ADD PRIMARY KEY (`criteria_id`,`type`);

View file

@ -218,6 +218,7 @@ pkgdata_DATA = \
7622_02_mangos_creature_ai_summons.sql \ 7622_02_mangos_creature_ai_summons.sql \
7622_03_mangos_creature_ai_texts.sql \ 7622_03_mangos_creature_ai_texts.sql \
7627_01_mangos_achievement_criteria_data.sql \ 7627_01_mangos_achievement_criteria_data.sql \
7633_01_mangos_achievement_criteria_data.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -416,4 +417,5 @@ EXTRA_DIST = \
7622_02_mangos_creature_ai_summons.sql \ 7622_02_mangos_creature_ai_summons.sql \
7622_03_mangos_creature_ai_texts.sql \ 7622_03_mangos_creature_ai_texts.sql \
7627_01_mangos_achievement_criteria_data.sql \ 7627_01_mangos_achievement_criteria_data.sql \
7633_01_mangos_achievement_criteria_data.sql \
README README

View file

@ -79,17 +79,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
switch(criteria->requiredType) switch(criteria->requiredType)
{ {
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
switch(dataType) case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
{
case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE:
case ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE:
case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE:
case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH:
break;
default:
sLog.outErrorDb( "Table `achievement_criteria_data` for criteria (Entry: %u Type: %u) have wrong data type (%u), ignore.", criteria->ID, criteria->requiredType,dataType);
return false;
}
break; break;
default: default:
sLog.outErrorDb( "Table `achievement_criteria_data` have data for not supported criteria type (Entry: %u Type: %u), ignore.", criteria->ID, criteria->requiredType); sLog.outErrorDb( "Table `achievement_criteria_data` have data for not supported criteria type (Entry: %u Type: %u), ignore.", criteria->ID, criteria->requiredType);
@ -100,7 +90,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
{ {
case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE: case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE:
return true; return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE: case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE:
if(!creature.id || !objmgr.GetCreatureTemplate(creature.id)) if(!creature.id || !objmgr.GetCreatureTemplate(creature.id))
{ {
sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) have not existed creature id in value1 (%u), ignore.", sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) have not existed creature id in value1 (%u), ignore.",
@ -108,7 +98,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
return false; return false;
} }
return true; return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE: case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE:
if(!classRace.class_id && !classRace.race_id) if(!classRace.class_id && !classRace.race_id)
{ {
sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE (%u) must have not 0 in one from value fields, ignore.", sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE (%u) must have not 0 in one from value fields, ignore.",
@ -128,14 +118,48 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
return false; return false;
} }
return true; return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH: case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH:
if(health.percent < 1 || health.percent > 100) if(health.percent < 1 || health.percent > 100)
{ {
sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH (%u) have prong percent value in value1 (%u), ignore.", sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH (%u) have wrong percent value in value1 (%u), ignore.",
criteria->ID, criteria->requiredType,dataType,health.percent); criteria->ID, criteria->requiredType,dataType,health.percent);
return false; return false;
} }
return true; return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD:
return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA:
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA:
{
SpellEntry const* spellEntry = sSpellStore.LookupEntry(aura.spell_id);
if(!spellEntry)
{
sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) have wrong spell id in value1 (%u), ignore.",
criteria->ID, criteria->requiredType,(dataType==ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"),dataType,aura.spell_id);
return false;
}
if(aura.effect_idx >= 3)
{
sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) have wrong spell effect index in value2 (%u), ignore.",
criteria->ID, criteria->requiredType,(dataType==ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"),dataType,aura.effect_idx);
return false;
}
if(!spellEntry->EffectApplyAuraName[aura.effect_idx])
{
sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) have non-aura spell effect (ID: %u Effect: %u), ignore.",
criteria->ID, criteria->requiredType,(dataType==ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"),dataType,aura.spell_id,aura.effect_idx);
return false;
}
return true;
}
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA:
if(!GetAreaEntryByAreaID(area.id))
{
sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA (%u) have wrong area id in value1 (%u), ignore.",
criteria->ID, criteria->requiredType,dataType,area.id);
return false;
}
return true;
default: default:
sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) have data for not supported data type (%u), ignore.", criteria->ID, criteria->requiredType,dataType); sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) have data for not supported data type (%u), ignore.", criteria->ID, criteria->requiredType,dataType);
return false; return false;
@ -143,38 +167,56 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
return false; return false;
} }
bool AchievementCriteriaData::Meets( Unit const* target ) const bool AchievementCriteriaData::Meets(Player const* source, Unit const* target) const
{ {
if (!target)
return false;
switch(dataType) switch(dataType)
{ {
case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE: case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE:
return true; return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE: case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE:
if (target->GetTypeId()!=TYPEID_UNIT) if (!target || target->GetTypeId()!=TYPEID_UNIT)
return false; return false;
if (target->GetEntry() != creature.id) if (target->GetEntry() != creature.id)
return false; return false;
return true; return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE: case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE:
if (target->GetTypeId()!=TYPEID_PLAYER) if (!target || target->GetTypeId()!=TYPEID_PLAYER)
return false; return false;
if(classRace.class_id && classRace.class_id != ((Player*)target)->getClass()) if(classRace.class_id && classRace.class_id != ((Player*)target)->getClass())
return false; return false;
if(classRace.race_id && classRace.race_id != ((Player*)target)->getRace()) if(classRace.race_id && classRace.race_id != ((Player*)target)->getRace())
return false; return false;
return true; return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH: case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH:
if (target->GetTypeId()!=TYPEID_PLAYER) if (!target || target->GetTypeId()!=TYPEID_PLAYER)
return false; return false;
return target->GetHealth()*100 <= health.percent*target->GetMaxHealth(); return target->GetHealth()*100 <= health.percent*target->GetMaxHealth();
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD:
return target && target->GetTypeId() == TYPEID_PLAYER && !target->isAlive() && ((Player*)target)->GetDeathTimer() != 0;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA:
return source->HasAura(aura.spell_id,aura.effect_idx);
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA:
{
uint32 zone_id,area_id;
source->GetZoneAndAreaId(zone_id,area_id);
return area.id==zone_id || area.id==area_id;
}
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA:
return target && target->HasAura(aura.spell_id,aura.effect_idx);
} }
return false; return false;
} }
bool AchievementCriteriaDataSet::Meets(Player const* source, Unit const* target) const
{
for(Storage::const_iterator itr = storage.begin(); itr != storage.end(); ++itr)
if(!itr->Meets(source,target))
return false;
return true;
}
AchievementMgr::AchievementMgr(Player *player) AchievementMgr::AchievementMgr(Player *player)
{ {
m_player = player; m_player = player;
@ -863,22 +905,18 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
{ {
// miscvalue1 = emote // miscvalue1 = emote
// miscvalue2 = achievement->ID for special requirement
if(!miscvalue1) if(!miscvalue1)
continue; continue;
if(miscvalue1 != achievementCriteria->do_emote.emoteID) if(miscvalue1 != achievementCriteria->do_emote.emoteID)
continue; continue;
if(achievementCriteria->do_emote.count) if(achievementCriteria->do_emote.count)
{ {
// harcoded case // those requirements couldn't be found in the dbc
if(achievement->ID==247) AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria);
{ if(!data)
if (!unit || unit->GetTypeId() != TYPEID_PLAYER ||
unit->isAlive() || ((Player*)unit)->GetDeathTimer() == 0)
continue; continue;
}
// expected as scripted case if(!data->Meets(GetPlayer(),unit))
else if(!miscvalue2 || !achievement->ID != miscvalue2)
continue; continue;
} }
@ -949,11 +987,11 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
continue; continue;
// those requirements couldn't be found in the dbc // those requirements couldn't be found in the dbc
AchievementCriteriaData const* data = achievementmgr.GetCriteriaData(achievementCriteria); AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria);
if(!data) if(!data)
continue; continue;
if(!data->Meets(unit)) if(!data->Meets(GetPlayer(),unit))
continue; continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
@ -1478,7 +1516,14 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
if(!data.IsValid(criteria)) if(!data.IsValid(criteria))
continue; continue;
m_criteriaDataMap[criteria_id] = data; // this will allocate empty data set storage
AchievementCriteriaDataSet& dataSet = m_criteriaDataMap[criteria_id];
// add real data only for not NONE data types
if(data.dataType!=ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE)
dataSet.Add(data);
// counting data by and data types
++count; ++count;
} while(result->NextRow()); } while(result->NextRow());
@ -1494,7 +1539,11 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
switch(criteria->requiredType) switch(criteria->requiredType)
{ {
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
if(!GetCriteriaData(criteria)) if(!GetCriteriaDataSet(criteria))
sLog.outErrorDb( "Table `achievement_criteria_data` not have expected data for for criteria (Entry: %u Type: %u).", criteria->ID, criteria->requiredType);
break;
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: // need skip generic cases
if(criteria->do_emote.count && !GetCriteriaDataSet(criteria))
sLog.outErrorDb( "Table `achievement_criteria_data` not have expected data for for criteria (Entry: %u Type: %u).", criteria->ID, criteria->requiredType); sLog.outErrorDb( "Table `achievement_criteria_data` not have expected data for for criteria (Entry: %u Type: %u).", criteria->ID, criteria->requiredType);
break; break;
default: // unexpected case processed in IsValid check default: // unexpected case processed in IsValid check

View file

@ -41,15 +41,20 @@ struct CriteriaProgress
}; };
enum AchievementCriteriaDataType enum AchievementCriteriaDataType
{ // value1 value2 for the Condition enumed { // value1 value2 comment
ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0, // 0 0 ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0, // 0 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE = 1, // creature_id ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1, // creature_id 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE = 2, // class_id race_id ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2, // class_id race_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH = 3, // health_percent ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH= 3, // health_percent 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD = 4, // 0 0 not corpse (not released body)
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5, // spell_id effect_idx
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA = 6, // area id 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7, // spell_id effect_idx
}; };
#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 4 // maximum value in AchievementCriteriaDataType enum #define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 8 // maximum value in AchievementCriteriaDataType enum
class Player;
class Unit; class Unit;
struct AchievementCriteriaData struct AchievementCriteriaData
@ -57,23 +62,35 @@ struct AchievementCriteriaData
AchievementCriteriaDataType dataType; AchievementCriteriaDataType dataType;
union union
{ {
// ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE
struct struct
{ {
uint32 id; uint32 id;
} creature; } creature;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE
struct struct
{ {
uint32 class_id; uint32 class_id;
uint32 race_id; uint32 race_id;
} classRace; } classRace;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH
struct struct
{ {
uint32 percent; uint32 percent;
} health; } health;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA
struct
{
uint32 spell_id;
uint32 effect_idx;
} aura;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA
struct
{
uint32 id;
} area;
// ...
struct struct
{ {
uint32 value1; uint32 value1;
@ -94,11 +111,20 @@ struct AchievementCriteriaData
} }
bool IsValid(AchievementCriteriaEntry const* criteria); bool IsValid(AchievementCriteriaEntry const* criteria);
// Checks correctness of values bool Meets(Player const* source, Unit const* target) const;
bool Meets(Unit const* target) const;// Checks if the target meets the requirement
}; };
typedef std::map<uint32,AchievementCriteriaData> AchievementCriteriaDataMap; struct AchievementCriteriaDataSet
{
typedef std::vector<AchievementCriteriaData> Storage;
void Add(AchievementCriteriaData const& data) { storage.push_back(data); }
bool Meets(Player const* source, Unit const* target) const;
private:
Storage storage;
};
typedef std::map<uint32,AchievementCriteriaDataSet> AchievementCriteriaDataMap;
struct AchievementReward struct AchievementReward
{ {
@ -194,7 +220,7 @@ class AchievementGlobalMgr
return iter!=m_achievementRewardLocales.end() ? &iter->second : NULL; return iter!=m_achievementRewardLocales.end() ? &iter->second : NULL;
} }
AchievementCriteriaData const* GetCriteriaData(AchievementCriteriaEntry const *achievementCriteria) AchievementCriteriaDataSet const* GetCriteriaDataSet(AchievementCriteriaEntry const *achievementCriteria)
{ {
AchievementCriteriaDataMap::const_iterator iter = m_criteriaDataMap.find(achievementCriteria->ID); AchievementCriteriaDataMap::const_iterator iter = m_criteriaDataMap.find(achievementCriteria->ID);
return iter!=m_criteriaDataMap.end() ? &iter->second : NULL; return iter!=m_criteriaDataMap.end() ? &iter->second : NULL;

View file

@ -739,9 +739,6 @@ void BattleGround::EndBattleGround(uint32 winner)
loser_arena_team->NotifyStatsChanged(); loser_arena_team->NotifyStatsChanged();
} }
// inform invited players about the removal
sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
if (winmsg_id) if (winmsg_id)
SendMessageToAll(winmsg_id, CHAT_MSG_BG_SYSTEM_NEUTRAL); SendMessageToAll(winmsg_id, CHAT_MSG_BG_SYSTEM_NEUTRAL);
} }
@ -1603,8 +1600,6 @@ void BattleGround::EndNow()
RemoveFromBGFreeSlotQueue(); RemoveFromBGFreeSlotQueue();
SetStatus(STATUS_WAIT_LEAVE); SetStatus(STATUS_WAIT_LEAVE);
SetEndTime(0); SetEndTime(0);
// inform invited players about the removal
sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
} }
/* /*

View file

@ -430,8 +430,16 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
// not yet invited // not yet invited
// set invitation // set invitation
ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID(); ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); BattleGroundTypeId bgTypeId = bg->GetTypeID();
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, bg->GetArenaType());
BGQueueIdBasedOnLevel queue_id = bg->GetQueueId(); BGQueueIdBasedOnLevel queue_id = bg->GetQueueId();
// set ArenaTeamId for rated matches
if (bg->isArena() && bg->isRated())
bg->SetArenaTeamIdForTeam(ginfo->Team, ginfo->ArenaTeamId);
ginfo->RemoveInviteTime = getMSTime() + INVITE_ACCEPT_WAIT_TIME;
// loop through the players // loop through the players
for(std::map<uint64,PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr) for(std::map<uint64,PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr)
{ {
@ -443,8 +451,19 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
// invite the player // invite the player
PlayerInvitedToBGUpdateAverageWaitTime(ginfo, queue_id); PlayerInvitedToBGUpdateAverageWaitTime(ginfo, queue_id);
ginfo->RemoveInviteTime = getMSTime() + INVITE_ACCEPT_WAIT_TIME; //sBattleGroundMgr.InvitePlayer(plr, bg, ginfo->Team);
sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), bg->GetTypeID(), ginfo->Team);
// set invited player counters
bg->IncreaseInvitedCount(ginfo->Team);
plr->SetInviteForBattleGroundQueueType(bgQueueTypeId, ginfo->IsInvitedToBGInstanceGUID);
// create remind invite events
BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, ginfo->RemoveInviteTime);
plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITATION_REMIND_TIME));
// create automatic remove events
BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, bgQueueTypeId, ginfo->RemoveInviteTime);
plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME));
WorldPacket data; WorldPacket data;
@ -462,63 +481,6 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
return false; return false;
} }
// used to remove the Enter Battle window if the battle has already ended, but someone still has it
// (this can happen in arenas mainly, since the preparation is shorter than the timer for the bgqueueremove event
void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg)
{
BGQueueIdBasedOnLevel queue_id = bg->GetQueueId();
uint32 bgInstanceId = bg->GetInstanceID();
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
GroupsQueueType::iterator itr, next;
for(uint32 i = 0; i < BG_QUEUE_GROUP_TYPES_COUNT; i++)
{
itr = m_QueuedGroups[queue_id][i].begin();
next = itr;
while (next != m_QueuedGroups[queue_id][i].end())
{
// must do this way, because the groupinfo will be deleted when all playerinfos are removed
itr = next;
++next;
GroupQueueInfo * ginfo = (*itr);
// if group was invited to this bg instance, then remove all references
if( ginfo->IsInvitedToBGInstanceGUID == bgInstanceId )
{
// after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop
uint32 to_remove = ginfo->Players.size();
for(uint32 j = 0; j < to_remove; j++)
{
// always remove the first one in the group
std::map<uint64, PlayerQueueInfo * >::iterator itr2 = ginfo->Players.begin();
if( itr2 == ginfo->Players.end() )
{
sLog.outError("Empty Players in ginfo, this should never happen!");
return;
}
// get the player
Player * plr = objmgr.GetPlayer(itr2->first);
if( !plr )
{
sLog.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen.");
continue;
}
// get the queueslot
uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
{
plr->RemoveBattleGroundQueueId(bgQueueTypeId);
// remove player from queue, this might delete the ginfo as well! don't use that pointer after this!
RemovePlayer(itr2->first, true);
WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
plr->GetSession()->SendPacket(&data);
}
}
}
}
}
}
/* /*
This function is inviting players to already running battlegrounds This function is inviting players to already running battlegrounds
Invitation type is based on config file Invitation type is based on config file
@ -1048,28 +1010,27 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{ {
Player* plr = objmgr.GetPlayer( m_PlayerGuid ); Player* plr = objmgr.GetPlayer( m_PlayerGuid );
// player logged off (we should do nothing, he is correctly removed from queue in another procedure) // player logged off (we should do nothing, he is correctly removed from queue in another procedure)
if (!plr) if (!plr)
return true; return true;
// Player can be in another BG queue and must be removed in normal way in any case
BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID, m_BgTypeId); BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID, m_BgTypeId);
//if battleground ended and its instance deleted - do nothing
if (!bg) if (!bg)
return true; return true;
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue if( queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES ) // player is in queue or in battleground
{ {
// check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems // check if player is invited to this bg
BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid);
if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) if( qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID
&& qItr->second.GroupInfo->RemoveInviteTime == m_RemoveTime )
{ {
WorldPacket data; WorldPacket data;
//here must be remaining time //we must send remaining time in queue
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, 0, qItr->second.GroupInfo->ArenaType); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, 0, qItr->second.GroupInfo->ArenaType);
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
} }
@ -1079,10 +1040,18 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
void BGQueueInviteEvent::Abort(uint64 /*e_time*/) void BGQueueInviteEvent::Abort(uint64 /*e_time*/)
{ {
//this should not be called //do nothing
sLog.outError("Battleground invite event ABORTED!");
} }
/*
this event has many possibilities when it is executed:
1. player is in battleground ( he clicked enter on invitation window )
2. player left battleground queue and he isn't there any more
3. player left battleground queue and he joined it again and IsInvitedToBGInstanceGUID = 0
4. player left queue and he joined again and he has been invited to same battleground again -> we should not remove him from queue yet
5. player is invited to bg and he didn't choose what to do and timer expired - only in this condition we should call queue::RemovePlayer
we must remove player in the 5. case even if battleground object doesn't exist!
*/
bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{ {
Player* plr = objmgr.GetPlayer( m_PlayerGuid ); Player* plr = objmgr.GetPlayer( m_PlayerGuid );
@ -1091,30 +1060,32 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
return true; return true;
BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID, m_BgTypeId); BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID, m_BgTypeId);
if (!bg) //battleground can be deleted already when we are removing queue info
return true; //bg pointer can be NULL! so use it carefully!
uint32 queueSlot = plr->GetBattleGroundQueueIndex(m_BgQueueTypeId);
if( queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES ) // player is in queue, or in Battleground
{
// check if player is in queue for this BG and if we are removing his invite event
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = qpMap.find(m_PlayerGuid);
if( qMapItr != qpMap.end() && qMapItr->second.GroupInfo
&& qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID
&& qMapItr->second.GroupInfo->RemoveInviteTime == m_RemoveTime )
{
sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID); sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID);
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); plr->RemoveBattleGroundQueueId(m_BgQueueTypeId);
uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].RemovePlayer(m_PlayerGuid, true);
if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue //update queues if battleground isn't ended
{ if (bg)
// check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].Update(m_BgTypeId, bg->GetQueueId());
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = qpMap.find(m_PlayerGuid);
if (qMapItr != qpMap.end() && qMapItr->second.GroupInfo && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID)
{
plr->RemoveBattleGroundQueueId(bgQueueTypeId);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(), bg->GetQueueId());
WorldPacket data; WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
} }
} }
else
sLog.outDebug("Battleground: Player was already removed from queue");
//event will be deleted //event will be deleted
return true; return true;
@ -1122,8 +1093,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
void BGQueueRemoveEvent::Abort(uint64 /*e_time*/) void BGQueueRemoveEvent::Abort(uint64 /*e_time*/)
{ {
//this should not be called //do nothing
sLog.outError("Battleground remove event ABORTED!");
} }
/*********************************************************/ /*********************************************************/
@ -1232,7 +1202,8 @@ void BattleGroundMgr::Update(uint32 diff)
void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype) void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype)
{ {
// we can be in 3 queues in same time... // we can be in 3 queues in same time...
if(StatusID == 0)
if (StatusID == 0 || !bg)
{ {
data->Initialize(SMSG_BATTLEFIELD_STATUS, 4*3); data->Initialize(SMSG_BATTLEFIELD_STATUS, 4*3);
*data << uint32(QueueSlot); // queue id (0...2) *data << uint32(QueueSlot); // queue id (0...2)
@ -1465,43 +1436,6 @@ void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Pla
*data << uint64(plr->GetGUID()); *data << uint64(plr->GetGUID());
} }
void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, BattleGroundTypeId bgTypeId, uint32 team)
{
// set invited player counters:
BattleGround* bg = GetBattleGround(bgInstanceGUID, bgTypeId);
if(!bg)
return;
bg->IncreaseInvitedCount(team);
plr->SetInviteForBattleGroundQueueType(BGQueueTypeId(bg->GetTypeID(),bg->GetArenaType()), bgInstanceGUID);
// set the arena teams for rated matches
if(bg->isArena() && bg->isRated())
{
switch(bg->GetArenaType())
{
case ARENA_TYPE_2v2:
bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(0));
break;
case ARENA_TYPE_3v3:
bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(1));
break;
case ARENA_TYPE_5v5:
bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(2));
break;
default:
break;
}
}
// create invite events:
//add events to player's counters ---- this is not good way - there should be something like global event processor, where we should add those events
BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID, bgTypeId);
plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITATION_REMIND_TIME));
BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, bgTypeId, team);
plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME));
}
BattleGround * BattleGroundMgr::GetBattleGroundThroughClientInstance(uint32 instanceId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id) BattleGround * BattleGroundMgr::GetBattleGroundThroughClientInstance(uint32 instanceId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id)
{ {
//cause at HandleBattleGroundJoinOpcode the clients sends the instanceid he gets from //cause at HandleBattleGroundJoinOpcode the clients sends the instanceid he gets from

View file

@ -84,7 +84,6 @@ class BattleGroundQueue
uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id); uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id);
void DecreaseGroupLength(uint32 queueId, uint32 AsGroup); void DecreaseGroupLength(uint32 queueId, uint32 AsGroup);
void BGEndedRemoveInvites(BattleGround * bg);
void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue); void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue);
typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap; typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap;
@ -136,8 +135,8 @@ class BattleGroundQueue
class BGQueueInviteEvent : public BasicEvent class BGQueueInviteEvent : public BasicEvent
{ {
public: public:
BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID, BattleGroundTypeId BgTypeId) : BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID, BattleGroundTypeId BgTypeId, uint32 removeTime) :
m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId) m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId), m_RemoveTime(removeTime)
{ {
}; };
virtual ~BGQueueInviteEvent() {}; virtual ~BGQueueInviteEvent() {};
@ -147,17 +146,20 @@ class BGQueueInviteEvent : public BasicEvent
private: private:
uint64 m_PlayerGuid; uint64 m_PlayerGuid;
uint32 m_BgInstanceGUID; uint32 m_BgInstanceGUID;
uint32 m_RemoveTime;
BattleGroundTypeId m_BgTypeId; BattleGroundTypeId m_BgTypeId;
}; };
/* /*
This class is used to remove player from BG queue after 2 minutes from first invitation This class is used to remove player from BG queue after 1 minute 20 seconds from first invitation
We must store removeInvite time in case player left queue and joined and is invited again
We must store bgQueueTypeId, because battleground can be deleted already, when player entered it
*/ */
class BGQueueRemoveEvent : public BasicEvent class BGQueueRemoveEvent : public BasicEvent
{ {
public: public:
BGQueueRemoveEvent(const uint64& pl_guid, uint32 bgInstanceGUID, BattleGroundTypeId BgTypeId, uint32 playersTeam) : BGQueueRemoveEvent(const uint64& pl_guid, uint32 bgInstanceGUID, BattleGroundTypeId BgTypeId, BattleGroundQueueTypeId bgQueueTypeId, uint32 removeTime) :
m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_BgTypeId(BgTypeId), m_PlayersTeam(playersTeam) m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_BgTypeId(BgTypeId), m_BgQueueTypeId(bgQueueTypeId), m_RemoveTime(removeTime)
{ {
}; };
virtual ~BGQueueRemoveEvent() {}; virtual ~BGQueueRemoveEvent() {};
@ -167,8 +169,9 @@ class BGQueueRemoveEvent : public BasicEvent
private: private:
uint64 m_PlayerGuid; uint64 m_PlayerGuid;
uint32 m_BgInstanceGUID; uint32 m_BgInstanceGUID;
uint32 m_PlayersTeam; uint32 m_RemoveTime;
BattleGroundTypeId m_BgTypeId; BattleGroundTypeId m_BgTypeId;
BattleGroundQueueTypeId m_BgQueueTypeId;
}; };
class BattleGroundMgr class BattleGroundMgr
@ -190,10 +193,6 @@ class BattleGroundMgr
void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid);
void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid); void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid);
/* Player invitation */
// called from Queue update, or from Addplayer to queue
void InvitePlayer(Player* plr, uint32 bgInstanceGUID, BattleGroundTypeId bgTypeId, uint32 team);
/* Battlegrounds */ /* Battlegrounds */
BattleGround* GetBattleGroundThroughClientInstance(uint32 instanceId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id); BattleGround* GetBattleGroundThroughClientInstance(uint32 instanceId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id);
BattleGround* GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId); //there must be uint32 because MAX_BATTLEGROUND_TYPE_ID means unknown BattleGround* GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId); //there must be uint32 because MAX_BATTLEGROUND_TYPE_ID means unknown

View file

@ -583,17 +583,15 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map)
if (!Create(guid,entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state) ) if (!Create(guid,entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state) )
return false; return false;
switch(GetGOInfo()->type) if(!GetDespawnPossibility())
{ {
case GAMEOBJECT_TYPE_DOOR:
case GAMEOBJECT_TYPE_BUTTON:
/* this code (in comment) isn't correct because in battlegrounds we need despawnable doors and buttons, pls remove
SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN); SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN);
m_spawnedByDefault = true; m_spawnedByDefault = true;
m_respawnDelayTime = 0; m_respawnDelayTime = 0;
m_respawnTime = 0; m_respawnTime = 0;
break;*/ }
default: else
{
if(data->spawntimesecs >= 0) if(data->spawntimesecs >= 0)
{ {
m_spawnedByDefault = true; m_spawnedByDefault = true;
@ -613,7 +611,6 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map)
m_respawnDelayTime = -data->spawntimesecs; m_respawnDelayTime = -data->spawntimesecs;
m_respawnTime = 0; m_respawnTime = 0;
} }
break;
} }
return true; return true;

View file

@ -479,6 +479,20 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
} }
} }
bool GetDespawnPossibility() const
{
switch(GetGoType())
{
case GAMEOBJECT_TYPE_DOOR: return GetGOInfo()->door.noDamageImmune;
case GAMEOBJECT_TYPE_BUTTON: return GetGOInfo()->button.noDamageImmune;
case GAMEOBJECT_TYPE_QUESTGIVER: return GetGOInfo()->questgiver.noDamageImmune;
case GAMEOBJECT_TYPE_GOOBER: return GetGOInfo()->goober.noDamageImmune;
case GAMEOBJECT_TYPE_FLAGSTAND: return GetGOInfo()->flagstand.noDamageImmune;
case GAMEOBJECT_TYPE_FLAGDROP: return GetGOInfo()->flagdrop.noDamageImmune;
default: return true;
}
}
time_t GetRespawnTime() const { return m_respawnTime; } time_t GetRespawnTime() const { return m_respawnTime; }
time_t GetRespawnTimeEx() const time_t GetRespawnTimeEx() const
{ {

View file

@ -2516,7 +2516,7 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell)
HitChance -= int32(((Player*)pVictim)->GetRatingBonusValue(CR_HIT_TAKEN_SPELL)*100.0f); HitChance -= int32(((Player*)pVictim)->GetRatingBonusValue(CR_HIT_TAKEN_SPELL)*100.0f);
if (HitChance < 100) HitChance = 100; if (HitChance < 100) HitChance = 100;
if (HitChance > 9900) HitChance = 9900; if (HitChance > 10000) HitChance = 10000;
int32 tmp = 10000 - HitChance; int32 tmp = 10000 - HitChance;

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 "7630" #define REVISION_NR "7635"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__