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`;
CREATE TABLE `db_version` (
`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';
--
@ -46,7 +46,7 @@ CREATE TABLE `achievement_criteria_data` (
`type` tinyint(3) unsigned NOT NULL DEFAULT '0',
`value1` 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';
--

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_03_mangos_creature_ai_texts.sql \
7627_01_mangos_achievement_criteria_data.sql \
7633_01_mangos_achievement_criteria_data.sql \
README
## Additional files to include when running 'make dist'
@ -416,4 +417,5 @@ EXTRA_DIST = \
7622_02_mangos_creature_ai_summons.sql \
7622_03_mangos_creature_ai_texts.sql \
7627_01_mangos_achievement_criteria_data.sql \
7633_01_mangos_achievement_criteria_data.sql \
README

View file

@ -79,17 +79,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
switch(criteria->requiredType)
{
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
switch(dataType)
{
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;
}
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
break;
default:
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:
return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE:
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE:
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.",
@ -108,7 +98,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
return false;
}
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)
{
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 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)
{
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);
return false;
}
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:
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;
@ -143,38 +167,56 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
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)
{
case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE:
return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE:
if (target->GetTypeId()!=TYPEID_UNIT)
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE:
if (!target || target->GetTypeId()!=TYPEID_UNIT)
return false;
if (target->GetEntry() != creature.id)
return false;
return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE:
if (target->GetTypeId()!=TYPEID_PLAYER)
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE:
if (!target || target->GetTypeId()!=TYPEID_PLAYER)
return false;
if(classRace.class_id && classRace.class_id != ((Player*)target)->getClass())
return false;
if(classRace.race_id && classRace.race_id != ((Player*)target)->getRace())
return false;
return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH:
if (target->GetTypeId()!=TYPEID_PLAYER)
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH:
if (!target || target->GetTypeId()!=TYPEID_PLAYER)
return false;
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;
}
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)
{
m_player = player;
@ -863,22 +905,18 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
{
// miscvalue1 = emote
// miscvalue2 = achievement->ID for special requirement
if(!miscvalue1)
continue;
if(miscvalue1 != achievementCriteria->do_emote.emoteID)
continue;
if(achievementCriteria->do_emote.count)
{
// harcoded case
if(achievement->ID==247)
{
if (!unit || unit->GetTypeId() != TYPEID_PLAYER ||
unit->isAlive() || ((Player*)unit)->GetDeathTimer() == 0)
// those requirements couldn't be found in the dbc
AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria);
if(!data)
continue;
}
// expected as scripted case
else if(!miscvalue2 || !achievement->ID != miscvalue2)
if(!data->Meets(GetPlayer(),unit))
continue;
}
@ -949,11 +987,11 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
continue;
// those requirements couldn't be found in the dbc
AchievementCriteriaData const* data = achievementmgr.GetCriteriaData(achievementCriteria);
AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria);
if(!data)
continue;
if(!data->Meets(unit))
if(!data->Meets(GetPlayer(),unit))
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
@ -1478,7 +1516,14 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
if(!data.IsValid(criteria))
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;
} while(result->NextRow());
@ -1494,7 +1539,11 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
switch(criteria->requiredType)
{
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);
break;
default: // unexpected case processed in IsValid check

View file

@ -41,15 +41,20 @@ struct CriteriaProgress
};
enum AchievementCriteriaDataType
{ // value1 value2 for the Condition enumed
{ // value1 value2 comment
ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0, // 0 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE = 1, // creature_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE = 2, // class_id race_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH = 3, // health_percent
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1, // creature_id 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2, // class_id race_id
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;
struct AchievementCriteriaData
@ -57,23 +62,35 @@ struct AchievementCriteriaData
AchievementCriteriaDataType dataType;
union
{
// ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE
struct
{
uint32 id;
} creature;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE
struct
{
uint32 class_id;
uint32 race_id;
} classRace;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH
struct
{
uint32 percent;
} 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
{
uint32 value1;
@ -94,11 +111,20 @@ struct AchievementCriteriaData
}
bool IsValid(AchievementCriteriaEntry const* criteria);
// Checks correctness of values
bool Meets(Unit const* target) const;// Checks if the target meets the requirement
bool Meets(Player const* source, Unit const* target) const;
};
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
{
@ -194,7 +220,7 @@ class AchievementGlobalMgr
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);
return iter!=m_criteriaDataMap.end() ? &iter->second : NULL;

View file

@ -739,9 +739,6 @@ void BattleGround::EndBattleGround(uint32 winner)
loser_arena_team->NotifyStatsChanged();
}
// inform invited players about the removal
sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
if (winmsg_id)
SendMessageToAll(winmsg_id, CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
@ -1603,8 +1600,6 @@ void BattleGround::EndNow()
RemoveFromBGFreeSlotQueue();
SetStatus(STATUS_WAIT_LEAVE);
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
// set invitation
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();
// 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
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
PlayerInvitedToBGUpdateAverageWaitTime(ginfo, queue_id);
ginfo->RemoveInviteTime = getMSTime() + INVITE_ACCEPT_WAIT_TIME;
sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), bg->GetTypeID(), ginfo->Team);
//sBattleGroundMgr.InvitePlayer(plr, bg, 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;
@ -462,63 +481,6 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
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
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*/)
{
Player* plr = objmgr.GetPlayer( m_PlayerGuid );
// player logged off (we should do nothing, he is correctly removed from queue in another procedure)
if (!plr)
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);
//if battleground ended and its instance deleted - do nothing
if (!bg)
return true;
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
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_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;
//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);
plr->GetSession()->SendPacket(&data);
}
@ -1079,10 +1040,18 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
void BGQueueInviteEvent::Abort(uint64 /*e_time*/)
{
//this should not be called
sLog.outError("Battleground invite event ABORTED!");
//do nothing
}
/*
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*/)
{
Player* plr = objmgr.GetPlayer( m_PlayerGuid );
@ -1091,30 +1060,32 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
return true;
BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID, m_BgTypeId);
if (!bg)
return true;
//battleground can be deleted already when we are removing queue info
//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);
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
{
// 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
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());
plr->RemoveBattleGroundQueueId(m_BgQueueTypeId);
sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].RemovePlayer(m_PlayerGuid, true);
//update queues if battleground isn't ended
if (bg)
sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].Update(m_BgTypeId, bg->GetQueueId());
WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
plr->GetSession()->SendPacket(&data);
}
}
else
sLog.outDebug("Battleground: Player was already removed from queue");
//event will be deleted
return true;
@ -1122,8 +1093,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
void BGQueueRemoveEvent::Abort(uint64 /*e_time*/)
{
//this should not be called
sLog.outError("Battleground remove event ABORTED!");
//do nothing
}
/*********************************************************/
@ -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)
{
// we can be in 3 queues in same time...
if(StatusID == 0)
if (StatusID == 0 || !bg)
{
data->Initialize(SMSG_BATTLEFIELD_STATUS, 4*3);
*data << uint32(QueueSlot); // queue id (0...2)
@ -1465,43 +1436,6 @@ void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Pla
*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)
{
//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);
void DecreaseGroupLength(uint32 queueId, uint32 AsGroup);
void BGEndedRemoveInvites(BattleGround * bg);
void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue);
typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap;
@ -136,8 +135,8 @@ class BattleGroundQueue
class BGQueueInviteEvent : public BasicEvent
{
public:
BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID, BattleGroundTypeId BgTypeId) :
m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId)
BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID, BattleGroundTypeId BgTypeId, uint32 removeTime) :
m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId), m_RemoveTime(removeTime)
{
};
virtual ~BGQueueInviteEvent() {};
@ -147,17 +146,20 @@ class BGQueueInviteEvent : public BasicEvent
private:
uint64 m_PlayerGuid;
uint32 m_BgInstanceGUID;
uint32 m_RemoveTime;
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
{
public:
BGQueueRemoveEvent(const uint64& pl_guid, uint32 bgInstanceGUID, BattleGroundTypeId BgTypeId, uint32 playersTeam) :
m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_BgTypeId(BgTypeId), m_PlayersTeam(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_BgQueueTypeId(bgQueueTypeId), m_RemoveTime(removeTime)
{
};
virtual ~BGQueueRemoveEvent() {};
@ -167,8 +169,9 @@ class BGQueueRemoveEvent : public BasicEvent
private:
uint64 m_PlayerGuid;
uint32 m_BgInstanceGUID;
uint32 m_PlayersTeam;
uint32 m_RemoveTime;
BattleGroundTypeId m_BgTypeId;
BattleGroundQueueTypeId m_BgQueueTypeId;
};
class BattleGroundMgr
@ -190,10 +193,6 @@ class BattleGroundMgr
void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid);
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 */
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

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) )
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);
m_spawnedByDefault = true;
m_respawnDelayTime = 0;
m_respawnTime = 0;
break;*/
default:
}
else
{
if(data->spawntimesecs >= 0)
{
m_spawnedByDefault = true;
@ -613,7 +611,6 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map)
m_respawnDelayTime = -data->spawntimesecs;
m_respawnTime = 0;
}
break;
}
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 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);
if (HitChance < 100) HitChance = 100;
if (HitChance > 9900) HitChance = 9900;
if (HitChance > 10000) HitChance = 10000;
int32 tmp = 10000 - HitChance;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "7630"
#define REVISION_NR "7635"
#endif // __REVISION_NR_H__