From 17100c67a8a12e75d44e651b4818c62c6c675c75 Mon Sep 17 00:00:00 2001 From: Triply Date: Fri, 6 Mar 2009 13:24:55 +0100 Subject: [PATCH 01/60] [7388] Fixed battleground premature warning message. SQL files are attached, you must execute them! Fix for message's color will be soon. Signed-off-by: Triply --- sql/mangos.sql | 3 ++- sql/updates/7388_01_mangos_mangos_string.sql | 3 +++ sql/updates/Makefile.am | 1 + src/game/BattleGround.cpp | 28 +++++++++++++++++--- src/game/BattleGround.h | 1 + src/game/Language.h | 9 +++++-- src/shared/revision_nr.h | 2 +- 7 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 sql/updates/7388_01_mangos_mangos_string.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index a75345530..6502804bf 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -2812,7 +2812,6 @@ INSERT INTO `mangos_string` VALUES (723,'Your group does not have enough players to join this match.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (724,'The Gold Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (725,'The Green Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(726,'There aren\'t enough players in this battleground. It will end soon unless some more players join to balance the fight.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (727,'Your group has an offline member. Please remove him before joining.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (728,'Your group has players from the opposing faction. You can\'t join the battleground as a group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (729,'Your group has players from different battleground brakets. You can\'t join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), @@ -2833,6 +2832,8 @@ INSERT INTO `mangos_string` VALUES (744,'Modifying played count, arena points etc. for loaded arena teams, sending updated stats to online players...',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (745,'Modification done.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (746,'Done flushing Arena points.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(750,'Not enough players. This game will close in %u mins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(751,'Not enough players. This game will close in %u seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (801,'You do not have enough gold',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (802,'You do not have enough free slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (803,'Your partner does not have enough free bag slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), diff --git a/sql/updates/7388_01_mangos_mangos_string.sql b/sql/updates/7388_01_mangos_mangos_string.sql new file mode 100644 index 000000000..07f60a7fe --- /dev/null +++ b/sql/updates/7388_01_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +DELETE FROM mangos_string WHERE entry = 726; +INSERT INTO mangos_string VALUES (750,'Not enough players. This game will close in %u mins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +INSERT INTO mangos_string VALUES (751,'Not enough players. This game will close in %u seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 138a68cf7..708e98b8d 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -362,4 +362,5 @@ EXTRA_DIST = \ 7369_01_mangos_quest_template.sql \ 7376_01_mangos_spell_area.sql \ 7382_01_mangos_creature_template.sql \ + 7388_01_mangos_mangos_string.sql \ README diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 3cb669f59..6dbeea95e 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -226,7 +226,6 @@ void BattleGround::Update(uint32 diff) { m_PrematureCountDown = true; m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime(); - SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING); } else if(m_PrematureCountDownTimer < diff) { @@ -238,8 +237,17 @@ void BattleGround::Update(uint32 diff) { uint32 newtime = m_PrematureCountDownTimer - diff; // announce every minute - if(m_PrematureCountDownTimer != sBattleGroundMgr.GetPrematureFinishTime() && newtime / 60000 != m_PrematureCountDownTimer / 60000) - SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING); + if( newtime > (MINUTE * IN_MILISECONDS) ) + { + if( newtime / (MINUTE * IN_MILISECONDS) != m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS) ) + PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING, (uint32)(m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS))); + } + else + { + //announce every 15 seconds + if( newtime / (15 * IN_MILISECONDS) != m_PrematureCountDownTimer / (15 * IN_MILISECONDS) ) + PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS, (uint32)(m_PrematureCountDownTimer / IN_MILISECONDS)); + } m_PrematureCountDownTimer = newtime; } } @@ -1024,7 +1032,7 @@ void BattleGround::RemoveFromBGFreeSlotQueue() // returns the number how many players can join battleground to MaxPlayersPerTeam uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const { - //if BG is starting ... invite anyone + //return free slot count to MaxPlayerPerTeam if (GetStatus() == STATUS_WAIT_JOIN || GetStatus() == STATUS_IN_PROGRESS) return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; @@ -1372,6 +1380,18 @@ void BattleGround::SendMessageToAll(int32 entry) SendPacketToAll(&data); } +//copied from void ChatHandler::PSendSysMessage(int32 entry, ...) +void BattleGround::PSendMessageToAll(int32 entry, ...) +{ + const char *format = GetMangosString(entry); + va_list ap; + char str [2048]; + va_start(ap, entry); + vsnprintf(str,2048,format, ap ); + va_end(ap); + SendMessageToAll(str); +} + void BattleGround::EndNow() { RemoveFromBGFreeSlotQueue(); diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 5dd56aa11..779a99221 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -389,6 +389,7 @@ class BattleGround void SendMessageToAll(char const* text); void SendMessageToAll(int32 entry); + void PSendMessageToAll(int32 entry, ... ); /* Raid Group */ Group *GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; } diff --git a/src/game/Language.h b/src/game/Language.h index c0e3bbd32..7a2f5fe85 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -658,7 +658,7 @@ enum MangosStrings LANG_ARENA_NOT_ENOUGH_PLAYERS = 723, // "Your group does not have enough players to join this match." LANG_ARENA_GOLD_WINS = 724, // "The Gold Team wins!" LANG_ARENA_GREEN_WINS = 725, // "The Green Team wins!" - LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 726, // The battleground will end soon, because there aren't enough players. Get more ppl or win already! +// = 726, not used LANG_BG_GROUP_OFFLINE_MEMBER = 727, // "Your group has an offline member. Please remove him before joining." LANG_BG_GROUP_MIXED_FACTION = 728, // "Your group has players from the opposing faction. You can't join the battleground as a group." LANG_BG_GROUP_MIXED_LEVELS = 729, // "Your group has players from different battleground brakets. You can't join as group." @@ -680,7 +680,12 @@ enum MangosStrings LANG_DIST_ARENA_POINTS_TEAM_START = 744, LANG_DIST_ARENA_POINTS_TEAM_END = 745, LANG_DIST_ARENA_POINTS_END = 746, - // Room for batleground/arena strings 747-799 not used +// = 747, not used +// = 748, not used +// = 749, not used + LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins." + LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds." + // Room for batleground/arena strings 752-799 not used // in game strings // = 800, not used diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 160925670..a7b58d43c 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7387" + #define REVISION_NR "7388" #endif // __REVISION_NR_H__ From bda5dffcdbba0e862de607736fb14e1fddfa8269 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 6 Mar 2009 18:08:50 +0300 Subject: [PATCH 02/60] [7389] Fixed sql update order protection data after recent commit. --- sql/mangos.sql | 2 +- sql/updates/Makefile.am | 1 + src/shared/revision_nr.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/mangos.sql b/sql/mangos.sql index 6502804bf..cd306f1f6 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7382_01_mangos_creature_template` bit(1) default NULL + `required_7388_01_mangos_mangos_string` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 708e98b8d..804fb97bd 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -191,6 +191,7 @@ pkgdata_DATA = \ 7369_01_mangos_quest_template.sql \ 7376_01_mangos_spell_area.sql \ 7382_01_mangos_creature_template.sql \ + 7388_01_mangos_mangos_string.sql \ README ## Additional files to include when running 'make dist' diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a7b58d43c..ee9321bda 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7388" + #define REVISION_NR "7389" #endif // __REVISION_NR_H__ From 83affb51fd5107e516f6d41a15852daea451d6de Mon Sep 17 00:00:00 2001 From: NoFantasy Date: Fri, 6 Mar 2009 18:18:19 +0300 Subject: [PATCH 03/60] [7390] Implement heroic instance quest requirement in `areatrigger_teleport`. Also more fixes for prev. sql update. Signed-off-by: VladimirMangos --- sql/mangos.sql | 3 +- sql/updates/7388_01_mangos_mangos_string.sql | 4 +- .../7390_01_mangos_areatrigger_teleport.sql | 4 ++ sql/updates/Makefile.am | 2 + src/game/MiscHandler.cpp | 12 +++++- src/game/ObjectMgr.cpp | 38 ++++++++++++------- src/game/ObjectMgr.h | 1 + src/shared/revision_nr.h | 2 +- 8 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 sql/updates/7390_01_mangos_areatrigger_teleport.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index cd306f1f6..c9d23fbec 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7388_01_mangos_mangos_string` bit(1) default NULL + `required_7390_01_mangos_areatrigger_teleport` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -135,6 +135,7 @@ CREATE TABLE `areatrigger_teleport` ( `heroic_key` mediumint(8) unsigned NOT NULL default '0', `heroic_key2` mediumint(8) unsigned NOT NULL default '0', `required_quest_done` int(11) unsigned NOT NULL default '0', + `required_quest_done_heroic` int(11) unsigned NOT NULL default '0', `required_failed_text` text, `target_map` smallint(5) unsigned NOT NULL default '0', `target_position_x` float NOT NULL default '0', diff --git a/sql/updates/7388_01_mangos_mangos_string.sql b/sql/updates/7388_01_mangos_mangos_string.sql index 07f60a7fe..5a876e713 100644 --- a/sql/updates/7388_01_mangos_mangos_string.sql +++ b/sql/updates/7388_01_mangos_mangos_string.sql @@ -1,3 +1,5 @@ -DELETE FROM mangos_string WHERE entry = 726; +ALTER TABLE db_version CHANGE COLUMN required_7382_01_mangos_creature_template required_7388_01_mangos_mangos_string bit; + +DELETE FROM mangos_string WHERE entry IN (750,751); INSERT INTO mangos_string VALUES (750,'Not enough players. This game will close in %u mins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); INSERT INTO mangos_string VALUES (751,'Not enough players. This game will close in %u seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/7390_01_mangos_areatrigger_teleport.sql b/sql/updates/7390_01_mangos_areatrigger_teleport.sql new file mode 100644 index 000000000..784272a57 --- /dev/null +++ b/sql/updates/7390_01_mangos_areatrigger_teleport.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_7388_01_mangos_mangos_string required_7390_01_mangos_areatrigger_teleport bit; + +ALTER TABLE areatrigger_teleport + ADD COLUMN required_quest_done_heroic int(11) unsigned NOT NULL default '0' AFTER required_quest_done; \ No newline at end of file diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 804fb97bd..4d541d014 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -192,6 +192,7 @@ pkgdata_DATA = \ 7376_01_mangos_spell_area.sql \ 7382_01_mangos_creature_template.sql \ 7388_01_mangos_mangos_string.sql \ + 7390_01_mangos_areatrigger_teleport.sql \ README ## Additional files to include when running 'make dist' @@ -364,4 +365,5 @@ EXTRA_DIST = \ 7376_01_mangos_spell_area.sql \ 7382_01_mangos_creature_template.sql \ 7388_01_mangos_mangos_string.sql \ + 7390_01_mangos_areatrigger_teleport.sql \ README diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 5258f4778..d52d80c10 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -859,8 +859,16 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) } uint32 missingQuest = 0; - if(at->requiredQuest && !GetPlayer()->GetQuestRewardStatus(at->requiredQuest)) - missingQuest = at->requiredQuest; + if(GetPlayer()->GetDifficulty() == DIFFICULTY_HEROIC) + { + if (at->requiredQuestHeroic && !GetPlayer()->GetQuestRewardStatus(at->requiredQuestHeroic)) + missingQuest = at->requiredQuestHeroic; + } + else + { + if(at->requiredQuest && !GetPlayer()->GetQuestRewardStatus(at->requiredQuest)) + missingQuest = at->requiredQuest; + } if(missingLevel || missingItem || missingKey || missingQuest) { diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index df7e6ab5b..948f7d06a 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -4849,8 +4849,8 @@ void ObjectMgr::LoadAreaTriggerTeleports() uint32 count = 0; - // 0 1 2 3 4 5 6 7 8 9 10 11 12 - QueryResult *result = WorldDatabase.Query("SELECT id, required_level, required_item, required_item2, heroic_key, heroic_key2, required_quest_done, required_failed_text, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport"); + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + QueryResult *result = WorldDatabase.Query("SELECT id, required_level, required_item, required_item2, heroic_key, heroic_key2, required_quest_done, required_quest_done_heroic, required_failed_text, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport"); if( !result ) { @@ -4877,18 +4877,19 @@ void ObjectMgr::LoadAreaTriggerTeleports() AreaTrigger at; - at.requiredLevel = fields[1].GetUInt8(); - at.requiredItem = fields[2].GetUInt32(); - at.requiredItem2 = fields[3].GetUInt32(); - at.heroicKey = fields[4].GetUInt32(); - at.heroicKey2 = fields[5].GetUInt32(); - at.requiredQuest = fields[6].GetUInt32(); - at.requiredFailedText = fields[7].GetCppString(); - at.target_mapId = fields[8].GetUInt32(); - at.target_X = fields[9].GetFloat(); - at.target_Y = fields[10].GetFloat(); - at.target_Z = fields[11].GetFloat(); - at.target_Orientation = fields[12].GetFloat(); + at.requiredLevel = fields[1].GetUInt8(); + at.requiredItem = fields[2].GetUInt32(); + at.requiredItem2 = fields[3].GetUInt32(); + at.heroicKey = fields[4].GetUInt32(); + at.heroicKey2 = fields[5].GetUInt32(); + at.requiredQuest = fields[6].GetUInt32(); + at.requiredQuestHeroic = fields[7].GetUInt32(); + at.requiredFailedText = fields[8].GetCppString(); + at.target_mapId = fields[9].GetUInt32(); + at.target_X = fields[10].GetFloat(); + at.target_Y = fields[11].GetFloat(); + at.target_Z = fields[12].GetFloat(); + at.target_Orientation = fields[13].GetFloat(); AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); if(!atEntry) @@ -4945,6 +4946,15 @@ void ObjectMgr::LoadAreaTriggerTeleports() } } + if(at.requiredQuestHeroic) + { + if(!mQuestTemplates[at.requiredQuestHeroic]) + { + sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",at.requiredQuestHeroic,Trigger_ID); + at.requiredQuestHeroic = 0; + } + } + MapEntry const* mapEntry = sMapStore.LookupEntry(at.target_mapId); if(!mapEntry) { diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 011edb85d..89047f60f 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -103,6 +103,7 @@ struct AreaTrigger uint32 heroicKey; uint32 heroicKey2; uint32 requiredQuest; + uint32 requiredQuestHeroic; std::string requiredFailedText; uint32 target_mapId; float target_X; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ee9321bda..8fc9ed7d7 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7389" + #define REVISION_NR "7390" #endif // __REVISION_NR_H__ From 5a8f379a70dc69a868a3557e2daec3b1189675ab Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 6 Mar 2009 22:21:35 +0300 Subject: [PATCH 04/60] [7391] Prevent achievement counter overflow, implement ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE generic support. Before overflow has been possible at 4294967295 lols for example. ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE in many cases require check special conditions and targets. For this allow call it from scripts: * Add Player::UpdateAchievementCriteria functiona ccessable from scripts * In emote case it allowed call in form player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote_id, achievement_id, target_unit_ptr); --- src/game/AchievementMgr.cpp | 34 ++++++++++++++- src/game/ChatHandler.cpp | 70 +++++++++++++++--------------- src/game/Player.cpp | 5 +++ src/game/Player.h | 1 + src/shared/Database/DBCStructure.h | 3 +- src/shared/revision_nr.h | 2 +- 6 files changed, 75 insertions(+), 40 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index b06a2f1c7..0f61962ce 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -730,6 +730,31 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; } + 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) + continue; + } + // expected as scripted case + else if(!miscvalue2 || !achievement->ID != miscvalue2) + continue; + } + + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; + } case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: { uint32 spellCount = 0; @@ -798,7 +823,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS: case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE: - case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE: case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM: @@ -927,6 +951,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: return progress->counter >= achievementCriteria->roll_greed_on_loot.count; + case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: + return progress->counter >= achievementCriteria->do_emote.count; case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD: return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: @@ -1024,8 +1050,12 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, newValue = changeValue; break; case PROGRESS_ACCUMULATE: - newValue = progress->counter + changeValue; + { + // avoid overflow + uint32 max_value = std::numeric_limits::max(); + newValue = max_value - progress->counter > changeValue ? progress->counter + changeValue : max_value; break; + } case PROGRESS_HIGHEST: newValue = progress->counter < changeValue ? changeValue : progress->counter; break; diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp index ea5061001..0edfd30c8 100644 --- a/src/game/ChatHandler.cpp +++ b/src/game/ChatHandler.cpp @@ -522,44 +522,42 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data ) } EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote); - if (em) + if (!em) + return; + + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); + + uint32 emote_anim = em->textid; + + WorldPacket data; + + switch(emote_anim) { - uint32 emote_anim = em->textid; - - WorldPacket data; - - switch(emote_anim) - { - case EMOTE_STATE_SLEEP: - case EMOTE_STATE_SIT: - case EMOTE_STATE_KNEEL: - case EMOTE_ONESHOT_NONE: - break; - default: - GetPlayer()->HandleEmoteCommand(emote_anim); - break; - } - - data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); - data << GetPlayer()->GetGUID(); - data << (uint32)text_emote; - data << emoteNum; - data << (uint32)namlen; - if( namlen > 1 ) - { - data.append(nam, namlen); - } - else - { - data << (uint8)0x00; - } - - GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true); - - //Send scripted event call - if (pCreature && Script) - Script->ReceiveEmote(GetPlayer(),pCreature,text_emote); + case EMOTE_STATE_SLEEP: + case EMOTE_STATE_SIT: + case EMOTE_STATE_KNEEL: + case EMOTE_ONESHOT_NONE: + break; + default: + GetPlayer()->HandleEmoteCommand(emote_anim); + break; } + + data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); + data << GetPlayer()->GetGUID(); + data << (uint32)text_emote; + data << emoteNum; + data << (uint32)namlen; + if( namlen > 1 ) + data.append(nam, namlen); + else + data << (uint8)0x00; + + GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true); + + //Send scripted event call + if (pCreature && Script) + Script->ReceiveEmote(GetPlayer(),pCreature,text_emote); } void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data ) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e42f8d1e8..ead51d937 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -19869,3 +19869,8 @@ void Player::HandleFall(MovementInfo const& movementInfo) } } } + +void Player::UpdateAchievementCriteria( AchievementCriteriaTypes type, uint32 miscvalue1/*=0*/, uint32 miscvalue2/*=0*/, Unit *unit/*=NULL*/, uint32 time/*=0*/ ) +{ + GetAchievementMgr().UpdateAchievementCriteria(type, miscvalue1,miscvalue2,unit,time); +} \ No newline at end of file diff --git a/src/game/Player.h b/src/game/Player.h index f616108cd..69ac16476 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2149,6 +2149,7 @@ class MANGOS_DLL_SPEC Player : public Unit void AddRunePower(uint8 index); void InitRunes(); AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } + void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0); bool HasTitle(uint32 bitIndex); bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); } void SetTitle(CharTitlesEntry const* title); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 60d354863..bcb1d22b6 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -356,7 +356,8 @@ struct AchievementCriteriaEntry // TODO: where is the information about the target stored? struct { - uint32 emoteID; // 3 + uint32 emoteID; // 3 enum TextEmotes + uint32 count; // 4 count of emotes, always required special target or requirements } do_emote; // ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13 // ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 8fc9ed7d7..5b2bf5927 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7390" + #define REVISION_NR "7391" #endif // __REVISION_NR_H__ From 4523a47155f1c828c4a0cf1a1418d3eeb96963c7 Mon Sep 17 00:00:00 2001 From: ApoC Date: Fri, 6 Mar 2009 23:38:55 +0100 Subject: [PATCH 05/60] [7392] Fixed SQL query for storing pending arena points for offline players for PGSQL. Signed-off-by: ApoC --- src/game/BattleGroundMgr.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 7e7291181..a0583688a 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -1752,7 +1752,7 @@ void BattleGroundMgr::DistributeArenaPoints() for (std::map::iterator plr_itr = PlayerPoints.begin(); plr_itr != PlayerPoints.end(); ++plr_itr) { //update to database - CharacterDatabase.PExecute("UPDATE characters SET arena_pending_points = '%u' WHERE `guid` = '%u'", plr_itr->second, plr_itr->first); + CharacterDatabase.PExecute("UPDATE characters SET arena_pending_points = '%u' WHERE guid = '%u'", plr_itr->second, plr_itr->first); //add points if player is online Player* pl = objmgr.GetPlayer(plr_itr->first); if (pl) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 5b2bf5927..ad8269a8f 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7391" + #define REVISION_NR "7392" #endif // __REVISION_NR_H__ From be74937146c4e7a9a9964d878e8f9e92473e268c Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 7 Mar 2009 01:34:46 +0300 Subject: [PATCH 06/60] [7393] Implement access to client side holiday ids. * src/game/GameEvent.* renamed to src/game/GameEventMgr.* for consistence * `game_event` now have new `holiday` field for store client side holiday id associated with game event * Added new enum HolidayIds with existed at this moment holiday ids. * New function "bool IsHolidayActive(HolidayIds id)" added accessabel from scripts for active holidays check. --- sql/mangos.sql | 3 +- sql/updates/7393_01_mangos_game_event.sql | 4 ++ sql/updates/Makefile.am | 2 + src/game/AchievementMgr.cpp | 4 +- src/game/{GameEvent.cpp => GameEventMgr.cpp} | 71 +++++++++++++------- src/game/{GameEvent.h => GameEventMgr.h} | 23 ++++--- src/game/Level2.cpp | 28 ++++---- src/game/Makefile.am | 4 +- src/game/ObjectMgr.cpp | 4 +- src/game/SharedDefines.h | 25 +++++++ src/game/World.cpp | 2 +- src/shared/Database/DBCStores.cpp | 4 +- src/shared/Database/DBCStores.h | 1 + src/shared/Database/DBCStructure.h | 34 ++++++++++ src/shared/Database/DBCfmt.cpp | 1 + src/shared/revision_nr.h | 2 +- win/VC71/game.vcproj | 4 +- win/VC80/game.vcproj | 4 +- win/VC90/game.vcproj | 4 +- 19 files changed, 162 insertions(+), 62 deletions(-) create mode 100644 sql/updates/7393_01_mangos_game_event.sql rename src/game/{GameEvent.cpp => GameEventMgr.cpp} (89%) rename src/game/{GameEvent.h => GameEventMgr.h} (90%) diff --git a/sql/mangos.sql b/sql/mangos.sql index c9d23fbec..93e2382f2 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7390_01_mangos_areatrigger_teleport` bit(1) default NULL + `required_7393_01_mangos_game_event` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -1072,6 +1072,7 @@ CREATE TABLE `game_event` ( `end_time` timestamp NOT NULL default '0000-00-00 00:00:00' COMMENT 'Absolute end date, the event will never start afler', `occurence` bigint(20) unsigned NOT NULL default '86400' COMMENT 'Delay in hours between occurences of the event', `length` bigint(20) unsigned NOT NULL default '43200' COMMENT 'Length in hours of the event', + `holiday` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Client side holiday id', `description` varchar(255) default NULL COMMENT 'Description of the event displayed in console', PRIMARY KEY (`entry`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/7393_01_mangos_game_event.sql b/sql/updates/7393_01_mangos_game_event.sql new file mode 100644 index 000000000..24e576462 --- /dev/null +++ b/sql/updates/7393_01_mangos_game_event.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_7390_01_mangos_areatrigger_teleport required_7393_01_mangos_game_event bit; + +ALTER TABLE game_event + ADD COLUMN holiday mediumint(8) unsigned NOT NULL default '0' COMMENT 'Client side holiday id' AFTER length; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 4d541d014..d7399a86f 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -193,6 +193,7 @@ pkgdata_DATA = \ 7382_01_mangos_creature_template.sql \ 7388_01_mangos_mangos_string.sql \ 7390_01_mangos_areatrigger_teleport.sql \ + 7393_01_mangos_game_event.sql \ README ## Additional files to include when running 'make dist' @@ -366,4 +367,5 @@ EXTRA_DIST = \ 7382_01_mangos_creature_template.sql \ 7388_01_mangos_mangos_string.sql \ 7390_01_mangos_areatrigger_teleport.sql \ + 7393_01_mangos_game_event.sql \ README diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 0f61962ce..df209edf9 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -21,10 +21,10 @@ #include "Player.h" #include "WorldPacket.h" #include "Database/DBCEnums.h" +#include "GameEventMgr.h" #include "ObjectMgr.h" #include "Guild.h" #include "Database/DatabaseEnv.h" -#include "GameEvent.h" #include "World.h" #include "SpellMgr.h" #include "ArenaTeam.h" @@ -607,7 +607,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if(Player::GetDrunkenstateByValue(GetPlayer()->GetDrunkValue()) != DRUNKEN_SMASHED) continue; // TODO: hardcoding eventid is bad, it can differ from DB to DB - maye implement something using HolidayNames.dbc? - if(!gameeventmgr.IsActiveEvent(26)) + if(!IsHolidayActive(HOLIDAY_BREWFEST)) continue; } // miscvalue1 is the ingame fallheight*100 as stored in dbc diff --git a/src/game/GameEvent.cpp b/src/game/GameEventMgr.cpp similarity index 89% rename from src/game/GameEvent.cpp rename to src/game/GameEventMgr.cpp index 2504f454f..e2b7386a8 100644 --- a/src/game/GameEvent.cpp +++ b/src/game/GameEventMgr.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "GameEvent.h" +#include "GameEventMgr.h" #include "World.h" #include "ObjectMgr.h" #include "PoolHandler.h" @@ -26,9 +26,9 @@ #include "MapManager.h" #include "Policies/SingletonImp.h" -INSTANTIATE_SINGLETON_1(GameEvent); +INSTANTIATE_SINGLETON_1(GameEventMgr); -bool GameEvent::CheckOneGameEvent(uint16 entry) const +bool GameEventMgr::CheckOneGameEvent(uint16 entry) const { // Get the event information time_t currenttime = time(NULL); @@ -39,7 +39,7 @@ bool GameEvent::CheckOneGameEvent(uint16 entry) const return false; } -uint32 GameEvent::NextCheck(uint16 entry) const +uint32 GameEventMgr::NextCheck(uint16 entry) const { time_t currenttime = time(NULL); @@ -65,7 +65,7 @@ uint32 GameEvent::NextCheck(uint16 entry) const return delay; } -void GameEvent::StartEvent( uint16 event_id, bool overwrite ) +void GameEventMgr::StartEvent( uint16 event_id, bool overwrite ) { AddActiveEvent(event_id); ApplyNewEvent(event_id); @@ -77,7 +77,7 @@ void GameEvent::StartEvent( uint16 event_id, bool overwrite ) } } -void GameEvent::StopEvent( uint16 event_id, bool overwrite ) +void GameEventMgr::StopEvent( uint16 event_id, bool overwrite ) { RemoveActiveEvent(event_id); UnApplyEvent(event_id); @@ -89,7 +89,7 @@ void GameEvent::StopEvent( uint16 event_id, bool overwrite ) } } -void GameEvent::LoadFromDB() +void GameEventMgr::LoadFromDB() { { QueryResult *result = WorldDatabase.Query("SELECT MAX(entry) FROM game_event"); @@ -108,7 +108,7 @@ void GameEvent::LoadFromDB() mGameEvent.resize(max_event_id+1); } - QueryResult *result = WorldDatabase.Query("SELECT entry,UNIX_TIMESTAMP(start_time),UNIX_TIMESTAMP(end_time),occurence,length,description FROM game_event"); + QueryResult *result = WorldDatabase.Query("SELECT entry,UNIX_TIMESTAMP(start_time),UNIX_TIMESTAMP(end_time),occurence,length,holiday,description FROM game_event"); if( !result ) { mGameEvent.clear(); @@ -142,6 +142,8 @@ void GameEvent::LoadFromDB() pGameEvent.end = time_t(endtime); pGameEvent.occurence = fields[3].GetUInt32(); pGameEvent.length = fields[4].GetUInt32(); + pGameEvent.holiday_id = fields[5].GetUInt32(); + if(pGameEvent.length==0) // length>0 is validity check { @@ -149,7 +151,16 @@ void GameEvent::LoadFromDB() continue; } - pGameEvent.description = fields[5].GetCppString(); + if(pGameEvent.holiday_id) + { + if(!sHolidaysStore.LookupEntry(pGameEvent.holiday_id)) + { + sLog.outErrorDb("`game_event` game event id (%i) have not existed holiday id %u.",event_id,pGameEvent.holiday_id); + pGameEvent.holiday_id = 0; + } + } + + pGameEvent.description = fields[6].GetCppString(); } while( result->NextRow() ); delete result; @@ -405,7 +416,7 @@ void GameEvent::LoadFromDB() } } -uint32 GameEvent::Initialize() // return the next event delay in ms +uint32 GameEventMgr::Initialize() // return the next event delay in ms { m_ActiveEvents.clear(); uint32 delay = Update(); @@ -414,7 +425,7 @@ uint32 GameEvent::Initialize() // return the next e return delay; } -uint32 GameEvent::Update() // return the next event delay in ms +uint32 GameEventMgr::Update() // return the next event delay in ms { uint32 nextEventDelay = max_ge_check_delay; // 1 day uint32 calcDelay; @@ -450,7 +461,7 @@ uint32 GameEvent::Update() // return the next e return (nextEventDelay + 1) * IN_MILISECONDS; // Add 1 second to be sure event has started/stopped at next call } -void GameEvent::UnApplyEvent(uint16 event_id) +void GameEventMgr::UnApplyEvent(uint16 event_id) { sLog.outString("GameEvent %u \"%s\" removed.", event_id, mGameEvent[event_id].description.c_str()); // un-spawn positive event tagged objects @@ -464,7 +475,7 @@ void GameEvent::UnApplyEvent(uint16 event_id) UpdateEventQuests(event_id, false); } -void GameEvent::ApplyNewEvent(uint16 event_id) +void GameEventMgr::ApplyNewEvent(uint16 event_id) { switch(sWorld.getConfig(CONFIG_EVENT_ANNOUNCE)) { @@ -487,13 +498,13 @@ void GameEvent::ApplyNewEvent(uint16 event_id) UpdateEventQuests(event_id, true); } -void GameEvent::GameEventSpawn(int16 event_id) +void GameEventMgr::GameEventSpawn(int16 event_id) { int32 internal_event_id = mGameEvent.size() + event_id - 1; if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size()) { - sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size()); + sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size()); return; } @@ -526,7 +537,7 @@ void GameEvent::GameEventSpawn(int16 event_id) if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size()) { - sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size()); + sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size()); return; } @@ -560,7 +571,7 @@ void GameEvent::GameEventSpawn(int16 event_id) if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size()) { - sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size()); + sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size()); return; } @@ -570,13 +581,13 @@ void GameEvent::GameEventSpawn(int16 event_id) } } -void GameEvent::GameEventUnspawn(int16 event_id) +void GameEventMgr::GameEventUnspawn(int16 event_id) { int32 internal_event_id = mGameEvent.size() + event_id - 1; if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size()) { - sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size()); + sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size()); return; } @@ -597,7 +608,7 @@ void GameEvent::GameEventUnspawn(int16 event_id) if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size()) { - sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size()); + sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size()); return; } @@ -614,7 +625,7 @@ void GameEvent::GameEventUnspawn(int16 event_id) } if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size()) { - sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size()); + sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size()); return; } @@ -624,7 +635,7 @@ void GameEvent::GameEventUnspawn(int16 event_id) } } -void GameEvent::ChangeEquipOrModel(int16 event_id, bool activate) +void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate) { for(ModelEquipList::iterator itr = mGameEventModelEquip[event_id].begin();itr != mGameEventModelEquip[event_id].end();++itr) { @@ -703,7 +714,7 @@ void GameEvent::ChangeEquipOrModel(int16 event_id, bool activate) } } -void GameEvent::UpdateEventQuests(uint16 event_id, bool Activate) +void GameEventMgr::UpdateEventQuests(uint16 event_id, bool Activate) { QuestRelList::iterator itr; for (itr = mGameEventQuests[event_id].begin();itr != mGameEventQuests[event_id].end();++itr) @@ -729,7 +740,19 @@ void GameEvent::UpdateEventQuests(uint16 event_id, bool Activate) } } -GameEvent::GameEvent() +GameEventMgr::GameEventMgr() { isSystemInit = false; } + +MANGOS_DLL_SPEC bool IsHolidayActive( HolidayIds id ) +{ + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEventMgr::ActiveEvents const& ae = gameeventmgr.GetActiveEventList(); + + for(GameEventMgr::ActiveEvents::const_iterator itr = ae.begin(); itr != ae.end(); ++itr) + if(events[id].holiday_id==id) + return true; + + return false; +} \ No newline at end of file diff --git a/src/game/GameEvent.h b/src/game/GameEventMgr.h similarity index 90% rename from src/game/GameEvent.h rename to src/game/GameEventMgr.h index e1752a952..2710c987c 100644 --- a/src/game/GameEvent.h +++ b/src/game/GameEventMgr.h @@ -16,15 +16,18 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef MANGOS_GAMEEVENT_H -#define MANGOS_GAMEEVENT_H +#ifndef MANGOS_GAMEEVENT_MGR_H +#define MANGOS_GAMEEVENT_MGR_H +#include "Common.h" +#include "SharedDefines.h" #include "Platform/Define.h" -#include "Creature.h" -#include "GameObject.h" #define max_ge_check_delay 86400 // 1 day in seconds +class Creature; +class GameObject; + struct GameEventData { GameEventData() : start(1),end(0),occurence(0),length(0) {} @@ -32,6 +35,7 @@ struct GameEventData time_t end; uint32 occurence; uint32 length; + uint32 holiday_id; std::string description; bool isValid() const { return length > 0; } @@ -45,11 +49,11 @@ struct ModelEquip uint32 equipement_id_prev; }; -class GameEvent +class GameEventMgr { public: - GameEvent(); - ~GameEvent() {}; + GameEventMgr(); + ~GameEventMgr() {}; typedef std::set ActiveEvents; typedef std::vector GameEventDataMap; ActiveEvents const& GetActiveEventList() const { return m_ActiveEvents; } @@ -92,5 +96,8 @@ class GameEvent bool isSystemInit; }; -#define gameeventmgr MaNGOS::Singleton::Instance() +#define gameeventmgr MaNGOS::Singleton::Instance() + +MANGOS_DLL_SPEC bool IsHolidayActive(HolidayIds id); + #endif diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 3e623a5ac..be925db6b 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -31,7 +31,7 @@ #include "MapManager.h" #include "Language.h" #include "World.h" -#include "GameEvent.h" +#include "GameEventMgr.h" #include "SpellMgr.h" #include "PoolHandler.h" #include "AccountMgr.h" @@ -162,7 +162,7 @@ bool ChatHandler::HandleTargetObjectCommand(const char* args) { Player* pl = m_session->GetPlayer(); QueryResult *result; - GameEvent::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList(); + GameEventMgr::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList(); if(*args) { int32 id = atoi((char*)args); @@ -185,7 +185,7 @@ bool ChatHandler::HandleTargetObjectCommand(const char* args) eventFilter << " AND (event IS NULL "; bool initString = true; - for (GameEvent::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr) + for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr) { if (initString) { @@ -3617,8 +3617,8 @@ bool ChatHandler::HandleLookupEventCommand(const char* args) uint32 counter = 0; - GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap(); - GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); for(uint32 id = 0; id < events.size(); ++id ) { @@ -3651,12 +3651,12 @@ bool ChatHandler::HandleEventActiveListCommand(const char* /*args*/) { uint32 counter = 0; - GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap(); - GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); char const* active = GetMangosString(LANG_ACTIVE); - for(GameEvent::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr ) + for(GameEventMgr::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr ) { uint32 event_id = *itr; GameEventData const& eventData = events[event_id]; @@ -3687,7 +3687,7 @@ bool ChatHandler::HandleEventInfoCommand(const char* args) uint32 event_id = atoi(cId); - GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); if(event_id >=events.size()) { @@ -3704,7 +3704,7 @@ bool ChatHandler::HandleEventInfoCommand(const char* args) return false; } - GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); bool active = activeEvents.find(event_id) != activeEvents.end(); char const* activeStr = active ? GetMangosString(LANG_ACTIVE) : ""; @@ -3736,7 +3736,7 @@ bool ChatHandler::HandleEventStartCommand(const char* args) int32 event_id = atoi(cId); - GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); if(event_id < 1 || event_id >=events.size()) { @@ -3753,7 +3753,7 @@ bool ChatHandler::HandleEventStartCommand(const char* args) return false; } - GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); if(activeEvents.find(event_id) != activeEvents.end()) { PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id); @@ -3777,7 +3777,7 @@ bool ChatHandler::HandleEventStopCommand(const char* args) int32 event_id = atoi(cId); - GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); if(event_id < 1 || event_id >=events.size()) { @@ -3794,7 +3794,7 @@ bool ChatHandler::HandleEventStopCommand(const char* args) return false; } - GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); if(activeEvents.find(event_id) == activeEvents.end()) { diff --git a/src/game/Makefile.am b/src/game/Makefile.am index 2b10e7b6e..f769811b9 100644 --- a/src/game/Makefile.am +++ b/src/game/Makefile.am @@ -109,8 +109,8 @@ libmangosgame_a_SOURCES = \ FleeingMovementGenerator.cpp \ FleeingMovementGenerator.h \ Formulas.h \ - GameEvent.cpp \ - GameEvent.h \ + GameEventMgr.cpp \ + GameEventMgr.h \ GameObject.cpp \ GameObject.h \ GlobalEvents.cpp \ diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 948f7d06a..282da0002 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -35,7 +35,7 @@ #include "Transports.h" #include "ProgressBar.h" #include "Language.h" -#include "GameEvent.h" +#include "GameEventMgr.h" #include "Spell.h" #include "Chat.h" #include "AccountMgr.h" @@ -6684,7 +6684,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val } case CONDITION_ACTIVE_EVENT: { - GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); if(value1 >=events.size() || !events[value1].isValid()) { sLog.outErrorDb("Active event condition requires existed event id (%u), skipped", value1); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 496eefa4d..7a27b0f03 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -1591,6 +1591,31 @@ enum CreatureEliteType CREATURE_UNKNOWN = 5 // found in 2.2.3 for 2 mobs }; +// values based at Holidays.dbc +enum HolidayIds +{ + HOLIDAY_FIREWORKS_SPECTACULAR = 62, + HOLIDAY_FEAST_OF_WINTER_VEIL = 141, + HOLIDAY_NOBLEGARDEN = 181, + HOLIDAY_CHILDRENS_WEEK = 201, + HOLIDAY_CALL_TO_ARMS_AV = 283, + HOLIDAY_CALL_TO_ARMS_WG = 284, + HOLIDAY_CALL_TO_ARMS_AB = 285, + HOLIDAY_FISHING_EXTRAVAGANZA = 301, + HOLIDAY_HARVEST_FESTIVAL = 321, + HOLIDAY_HALLOWS_END = 324, + HOLIDAY_LUNAR_FESTIVAL = 327, + HOLIDAY_LOVE_IS_IN_THE_AIR = 335, + HOLIDAY_FIRE_FESTIVAL = 341, + HOLIDAY_CALL_TO_ARMS_ES = 353, + HOLIDAY_BREWFEST = 372, + HOLIDAY_DARKMOON_FAIRE_ELWYNN = 374, + HOLIDAY_DARKMOON_FAIRE_THUNDER = 375, + HOLIDAY_DARKMOON_FAIRE_SHATTRATH = 376, + HOLIDAY_CALL_TO_ARMS_SA = 400, + HOLIDAY_WOTLK_LAUNCH = 406 +}; + // values based at QuestInfo.dbc enum QuestTypes { diff --git a/src/game/World.cpp b/src/game/World.cpp index 0f3f1086f..269c38118 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -52,7 +52,7 @@ #include "WaypointMovementGenerator.h" #include "VMapFactory.h" #include "GlobalEvents.h" -#include "GameEvent.h" +#include "GameEventMgr.h" #include "PoolHandler.h" #include "Database/DatabaseImpl.h" #include "GridNotifiersImpl.h" diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp index f2be6e577..671efa5ea 100644 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -75,6 +75,7 @@ DBCStorage sGtOCTRegenHPStore(GtOCTRegenHPfmt); //DBCStorage sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently DBCStorage sGtRegenHPPerSptStore(GtRegenHPPerSptfmt); DBCStorage sGtRegenMPPerSptStore(GtRegenMPPerSptfmt); +DBCStorage sHolidaysStore(Holidaysfmt); DBCStorage sItemStore(Itemfmt); //DBCStorage sItemCondExtCostsStore(ItemCondExtCostsEntryfmt); //DBCStorage sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently @@ -193,7 +194,7 @@ void LoadDBCStores(const std::string& dataPath) { std::string dbcPath = dataPath+"dbc/"; - const uint32 DBCFilesCount = 72; + const uint32 DBCFilesCount = 73; barGoLink bar( DBCFilesCount ); @@ -266,6 +267,7 @@ void LoadDBCStores(const std::string& dataPath) //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenMPStore, dbcPath,"gtOCTRegenMP.dbc"); -- not used currently LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenHPPerSptStore, dbcPath,"gtRegenHPPerSpt.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenMPPerSptStore, dbcPath,"gtRegenMPPerSpt.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sHolidaysStore, dbcPath,"Holidays.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemStore, dbcPath,"Item.dbc"); //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemDisplayInfoStore, dbcPath,"ItemDisplayInfo.dbc"); -- not used currently //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemCondExtCostsStore, dbcPath,"ItemCondExtCosts.dbc"); diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h index dd25b2ed6..5a37201db 100644 --- a/src/shared/Database/DBCStores.h +++ b/src/shared/Database/DBCStores.h @@ -167,6 +167,7 @@ extern DBCStorage sGtOCTRegenHPStore; //extern DBCStorage sGtOCTRegenMPStore; -- not used currently extern DBCStorage sGtRegenHPPerSptStore; extern DBCStorage sGtRegenMPPerSptStore; +extern DBCStorage sHolidaysStore; extern DBCStorage sItemStore; //extern DBCStorage sItemDisplayInfoStore; -- not used currently extern DBCStorage sItemExtendedCostStore; diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index bcb1d22b6..9f8154554 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -854,6 +854,40 @@ struct GtRegenMPPerSptEntry float ratio; }; +/* no used +struct HolidayDescriptionsEntry +{ + uint32 ID; // 0, this is NOT holiday id + //char* name[16] // 1-16 m_name_lang + // 17 name flags +}; +*/ + +/* no used +struct HolidayNamesEntry +{ + uint32 ID; // 0, this is NOT holiday id + //char* name[16] // 1-16 m_name_lang + // 17 name flags +}; +*/ + +struct HolidaysEntry +{ + uint32 ID; // 0, holiday id + //uint32 unk1; // 1 + //uint32 unk2; // 2 + //uint32 unk3[8] // 3-10, empty fields + //uint32 unk11[13] // 11-23, some unknown data (bit strings?) + //uint32 unk11[13] // 24-36, some empty fields (continue prev?) + //uint32 unk11[12] // 37-48, counters? + //uint32 holidayNameId; // 49, id for HolidayNames.dbc + //uint32 holidayDescriptionId; // 50, id for HolidayDescriptions.dbc + //uint32 unk51; // 51 + //uint32 unk52; // 52 + //uint32 unk53; // 53 +}; + struct ItemEntry { uint32 ID; // 0 diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 310d4241c..30c720870 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -53,6 +53,7 @@ const char GtOCTRegenHPfmt[]="f"; //const char GtOCTRegenMPfmt[]="f"; const char GtRegenHPPerSptfmt[]="f"; const char GtRegenMPPerSptfmt[]="f"; +const char Holidaysfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char Itemfmt[]="nixiiiii"; //const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx"; //const char ItemCondExtCostsEntryfmt[]="xiii"; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ad8269a8f..2f255c5e6 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7392" + #define REVISION_NR "7393" #endif // __REVISION_NR_H__ diff --git a/win/VC71/game.vcproj b/win/VC71/game.vcproj index 0643908d5..da274a1f5 100644 --- a/win/VC71/game.vcproj +++ b/win/VC71/game.vcproj @@ -276,10 +276,10 @@ RelativePath="..\..\src\game\DuelHandler.cpp"> + RelativePath="..\..\src\game\GameEventMgr.cpp"> + RelativePath="..\..\src\game\GameEventMgr.h"> diff --git a/win/VC80/game.vcproj b/win/VC80/game.vcproj index 0ac846d64..7e4cc1413 100644 --- a/win/VC80/game.vcproj +++ b/win/VC80/game.vcproj @@ -539,11 +539,11 @@ > Date: Sat, 7 Mar 2009 03:27:43 +0300 Subject: [PATCH 07/60] [7394] Check loot_template.maxcount for max allowed value (255) and make better report for this case. Also optimize strcture LootStoreItem that let use 4 byte for loot template element in memory instead 5 bytes. But limit group id to 127 max value. Check this at loading. --- src/game/AchievementMgr.cpp | 1 - src/game/LootMgr.cpp | 15 ++++++++++++++- src/game/LootMgr.h | 8 ++++---- src/shared/revision_nr.h | 2 +- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index df209edf9..6048c8ea7 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -606,7 +606,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui { if(Player::GetDrunkenstateByValue(GetPlayer()->GetDrunkValue()) != DRUNKEN_SMASHED) continue; - // TODO: hardcoding eventid is bad, it can differ from DB to DB - maye implement something using HolidayNames.dbc? if(!IsHolidayActive(HOLIDAY_BREWFEST)) continue; } diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index 3097cff41..9571bc358 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -114,11 +114,18 @@ void LootStore::LoadLootTable() float chanceOrQuestChance = fields[2].GetFloat(); uint8 group = fields[3].GetUInt8(); int32 mincountOrRef = fields[4].GetInt32(); - uint8 maxcount = fields[5].GetUInt8(); + uint32 maxcount = fields[5].GetUInt32(); ConditionType condition = (ConditionType)fields[6].GetUInt8(); uint32 cond_value1 = fields[7].GetUInt32(); uint32 cond_value2 = fields[8].GetUInt32(); + if(maxcount > std::numeric_limits::max()) + { + sLog.outErrorDb("Table '%s' entry %d item %d: maxcount value (%u) to large. must be less %u - skipped", GetName(), entry, maxcount,std::numeric_limits::max()); + continue; // error already printed to log/console. + } + + if(!PlayerCondition::IsValid(condition,cond_value1, cond_value2)) { sLog.outErrorDb("... in table '%s' entry %u item %u", GetName(), entry, item); @@ -248,6 +255,12 @@ bool LootStoreItem::Roll(bool rate) const // Checks correctness of values bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const { + if(group >= 1 << 7) // it stored in 7 bit field + { + sLog.outErrorDb("Table '%s' entry %d item %d: group (%u) must be less %u - skipped", store.GetName(), entry, itemid, group, 1 << 7); + return false; + } + if (mincountOrRef == 0) { sLog.outErrorDb("Table '%s' entry %d item %d: wrong mincountOrRef (%d) - skipped", store.GetName(), entry, itemid, mincountOrRef); diff --git a/src/game/LootMgr.h b/src/game/LootMgr.h index 0c34d7904..b16757d49 100644 --- a/src/game/LootMgr.h +++ b/src/game/LootMgr.h @@ -63,17 +63,17 @@ struct LootStoreItem uint32 itemid; // id of the item float chance; // always positive, chance to drop for both quest and non-quest items, chance to be used for refs int32 mincountOrRef; // mincount for drop items (positive) or minus referenced TemplateleId (negative) - uint8 group :8; + uint8 group :7; + bool needs_quest :1; // quest drop (negative ChanceOrQuestChance in DB) uint8 maxcount :8; // max drop count for the item (mincountOrRef positive) or Ref multiplicator (mincountOrRef negative) uint16 conditionId :16; // additional loot condition Id - bool needs_quest :1; // quest drop (negative ChanceOrQuestChance in DB) // Constructor, converting ChanceOrQuestChance -> (chance, needs_quest) // displayid is filled in IsValid() which must be called after LootStoreItem(uint32 _itemid, float _chanceOrQuestChance, int8 _group, uint8 _conditionId, int32 _mincountOrRef, uint8 _maxcount) : itemid(_itemid), chance(fabs(_chanceOrQuestChance)), mincountOrRef(_mincountOrRef), - group(_group), maxcount(_maxcount), conditionId(_conditionId), - needs_quest(_chanceOrQuestChance < 0) {} + group(_group), needs_quest(_chanceOrQuestChance < 0), maxcount(_maxcount), conditionId(_conditionId) + {} bool Roll(bool rate) const; // Checks if the entry takes it's chance (at loot generation) bool IsValid(LootStore const& store, uint32 entry) const; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 2f255c5e6..d75e85c3f 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7393" + #define REVISION_NR "7394" #endif // __REVISION_NR_H__ From 2159dee3796861ba4783c24f2a965db22a3486e2 Mon Sep 17 00:00:00 2001 From: multiplexer Date: Sat, 7 Mar 2009 02:33:33 +0100 Subject: [PATCH 08/60] [7395] Default MaxPlayerLevel should be 80 --- src/game/World.cpp | 4 ++-- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/World.cpp b/src/game/World.cpp index 269c38118..2b11c417c 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -663,12 +663,12 @@ void World::LoadConfigSettings(bool reload) if(reload) { - uint32 val = sConfig.GetIntDefault("MaxPlayerLevel", 60); + uint32 val = sConfig.GetIntDefault("MaxPlayerLevel", 80); if(val!=m_configs[CONFIG_MAX_PLAYER_LEVEL]) sLog.outError("MaxPlayerLevel option can't be changed at mangosd.conf reload, using current value (%u).",m_configs[CONFIG_MAX_PLAYER_LEVEL]); } else - m_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfig.GetIntDefault("MaxPlayerLevel", 60); + m_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfig.GetIntDefault("MaxPlayerLevel", 80); if(m_configs[CONFIG_MAX_PLAYER_LEVEL] > MAX_LEVEL) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index d75e85c3f..c16cc5a29 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7394" + #define REVISION_NR "7395" #endif // __REVISION_NR_H__ From 1727657ab517f4d751d74abc0b7fe045fc7d269f Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 7 Mar 2009 07:48:14 +0300 Subject: [PATCH 09/60] [7396] Fixed crash at group disband after some player invite decline and offline. Correctly cleanup invites list at decline. --- src/game/GroupHandler.cpp | 20 +++++--------------- src/game/Player.cpp | 2 +- src/shared/revision_nr.h | 2 +- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index 9ec47103e..16da66253 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -215,26 +215,16 @@ void WorldSession::HandleGroupDeclineOpcode( WorldPacket & /*recv_data*/ ) Group *group = GetPlayer()->GetGroupInvite(); if (!group) return; + // remember leader if online Player *leader = objmgr.GetPlayer(group->GetLeaderGUID()); - /** error handling **/ + // uninvite, group can be deleted + GetPlayer()->UninviteFromGroup(); + if(!leader || !leader->GetSession()) return; - /********************/ - - // everything's fine, do it - if(!group->IsCreated()) - { - // note: this means that if you invite more than one person - // and one of them declines before the first one accepts - // all invites will be cleared - // fixme: is that ok ? - group->RemoveAllInvites(); - delete group; - } - - GetPlayer()->SetGroupInvite(NULL); + // report WorldPacket data( SMSG_GROUP_DECLINE, 10 ); // guess size data << GetPlayer()->GetName(); leader->GetSession()->SendPacket( &data ); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index ead51d937..217a153da 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2074,7 +2074,7 @@ void Player::UninviteFromGroup() group->RemoveInvite(this); - if(group->GetMembersCount() <= 1) // group has just 1 member => disband + if(group->GetMembersCount() <= 1) // group has just 1 member => disband { if(group->IsCreated()) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c16cc5a29..4de2813dd 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7395" + #define REVISION_NR "7396" #endif // __REVISION_NR_H__ From 13ca8d70640cf9f43a08310aa0c6d5c6f9918b11 Mon Sep 17 00:00:00 2001 From: GriffonHeart Date: Sat, 7 Mar 2009 09:12:47 +0300 Subject: [PATCH 10/60] [7397] Implement above ground zone 4395 detection. By hack code until proper multilevel zone data store not implemented. Signed-off-by: VladimirMangos --- src/game/Map.cpp | 5 +++++ src/shared/revision_nr.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/game/Map.cpp b/src/game/Map.cpp index cafb3464c..0796e3a4f 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1240,6 +1240,11 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const case 856: // The Noxious Glade (Eastern Plaguelands) case 2456: // Death's Breach (Eastern Plaguelands) if(z > 350.0f) areaflag = 1950; break; + // Dalaran + case 1593: + case 2484: + case 2492: + if( (x < 6116 && x > 5568) && (y < 982 && y > 282) && z > 563.0f) areaflag = 2153; break; } return areaflag; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 4de2813dd..3323da171 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7396" + #define REVISION_NR "7397" #endif // __REVISION_NR_H__ From 67f307d5f79e24bbd40f5e19944d81bb682cd9cf Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 7 Mar 2009 10:50:23 +0300 Subject: [PATCH 11/60] [7398] Now really really fix error message :/ --- src/game/LootMgr.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index 9571bc358..a190a058a 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -121,7 +121,7 @@ void LootStore::LoadLootTable() if(maxcount > std::numeric_limits::max()) { - sLog.outErrorDb("Table '%s' entry %d item %d: maxcount value (%u) to large. must be less %u - skipped", GetName(), entry, maxcount,std::numeric_limits::max()); + sLog.outErrorDb("Table '%s' entry %d item %d: maxcount value (%u) to large. must be less %u - skipped", GetName(), entry, item, maxcount,std::numeric_limits::max()); continue; // error already printed to log/console. } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3323da171..ffd0c7e3d 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7397" + #define REVISION_NR "7398" #endif // __REVISION_NR_H__ From 1ee232048420776f0986f7787d6f9ea129ffb05c Mon Sep 17 00:00:00 2001 From: Triply Date: Sat, 7 Mar 2009 11:03:56 +0100 Subject: [PATCH 12/60] [7399] Rewrited BattleGround starting code - moved it to battleground class. Fixed message color for premature finish warnings. Fixed .debug bg command won't allow 1v0 arenas now, only battlegrounds 1v0. Added battleground announcer message removed in [7384]. Patch is tested, everything worked for me. You must execute attached sql file! Signed-off-by: Triply --- sql/mangos.sql | 3 + sql/updates/7399_01_mangos_mangos_string.sql | 3 + src/game/BattleGround.cpp | 120 +++++++++++++++++-- src/game/BattleGround.h | 45 +++++-- src/game/BattleGroundAA.cpp | 18 +++ src/game/BattleGroundAA.h | 3 + src/game/BattleGroundAB.cpp | 119 +++++++----------- src/game/BattleGroundAB.h | 2 + src/game/BattleGroundAV.cpp | 13 ++ src/game/BattleGroundAV.h | 2 + src/game/BattleGroundBE.cpp | 89 +++++--------- src/game/BattleGroundBE.h | 2 + src/game/BattleGroundDS.cpp | 18 +++ src/game/BattleGroundDS.h | 3 + src/game/BattleGroundEY.cpp | 96 +++++---------- src/game/BattleGroundEY.h | 2 + src/game/BattleGroundMgr.cpp | 2 +- src/game/BattleGroundNA.cpp | 83 ++++--------- src/game/BattleGroundNA.h | 2 + src/game/BattleGroundRL.cpp | 84 ++++--------- src/game/BattleGroundRL.h | 2 + src/game/BattleGroundRV.cpp | 18 +++ src/game/BattleGroundRV.h | 3 + src/game/BattleGroundSA.cpp | 17 ++- src/game/BattleGroundSA.h | 2 + src/game/BattleGroundWS.cpp | 108 ++++++----------- src/game/BattleGroundWS.h | 2 + src/game/Language.h | 31 +++-- src/shared/revision_nr.h | 2 +- 29 files changed, 469 insertions(+), 425 deletions(-) create mode 100644 sql/updates/7399_01_mangos_mangos_string.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 93e2382f2..197a9e408 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -2836,6 +2836,9 @@ INSERT INTO `mangos_string` VALUES (746,'Done flushing Arena points.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (750,'Not enough players. This game will close in %u mins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (751,'Not enough players. This game will close in %u seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(753,'The battle for Warsong Gulch begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(754,'The battle for Arathi Basin begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(755,'The battle for Eye of the Storm begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (801,'You do not have enough gold',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (802,'You do not have enough free slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (803,'Your partner does not have enough free bag slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), diff --git a/sql/updates/7399_01_mangos_mangos_string.sql b/sql/updates/7399_01_mangos_mangos_string.sql new file mode 100644 index 000000000..d05a8e853 --- /dev/null +++ b/sql/updates/7399_01_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +INSERT INTO mangos_string VALUES (753,'The battle for Warsong Gulch begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +INSERT INTO mangos_string VALUES (754,'The battle for Arathi Basin begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +INSERT INTO mangos_string VALUES (755,'The battle for Eye of the Storm begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 6dbeea95e..f19e013c4 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -88,6 +88,16 @@ BattleGround::BattleGround() m_PrematureCountDown = false; m_PrematureCountDown = 0; + + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_2M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set to some default existing values + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; } BattleGround::~BattleGround() @@ -169,6 +179,11 @@ void BattleGround::Update(uint32 diff) } } + //TODO: move this system to spell system and ressurect players correclt there! + /*********************************************************/ + /*** BATTLEGROUND RESSURECTION SYSTEM ***/ + /*********************************************************/ + //this should be handled by spell system: m_LastResurrectTime += diff; if (m_LastResurrectTime >= RESURRECTION_INTERVAL) @@ -219,6 +234,10 @@ void BattleGround::Update(uint32 diff) m_ResurrectQueue.clear(); } + /*********************************************************/ + /*** BATTLEGROUND BALLANCE SYSTEM ***/ + /*********************************************************/ + // if less then minimum players are in on one side, then start premature finish timer if(GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam())) { @@ -240,13 +259,13 @@ void BattleGround::Update(uint32 diff) if( newtime > (MINUTE * IN_MILISECONDS) ) { if( newtime / (MINUTE * IN_MILISECONDS) != m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS) ) - PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING, (uint32)(m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS))); + PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING, CHAT_MSG_SYSTEM, (uint32)(m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS))); } else { //announce every 15 seconds if( newtime / (15 * IN_MILISECONDS) != m_PrematureCountDownTimer / (15 * IN_MILISECONDS) ) - PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS, (uint32)(m_PrematureCountDownTimer / IN_MILISECONDS)); + PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS, CHAT_MSG_SYSTEM, (uint32)(m_PrematureCountDownTimer / IN_MILISECONDS)); } m_PrematureCountDownTimer = newtime; } @@ -254,6 +273,88 @@ void BattleGround::Update(uint32 diff) else if (m_PrematureCountDown) m_PrematureCountDown = false; + /*********************************************************/ + /*** BATTLEGROUND STARTING SYSTEM ***/ + /*********************************************************/ + + if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) + { + ModifyStartDelayTime(diff); + + if (!(m_Events & BG_STARTING_EVENT_1)) + { + m_Events |= BG_STARTING_EVENT_1; + + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } + + StartingEventCloseDoors(); + SetStartDelayTime(m_StartDelayTimes[BG_STARTING_EVENT_FIRST]); + //first start warning - 2 or 1 minute + SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL); + } + // After 1 minute or 30 seconds, warning is signalled + else if (GetStartDelayTime() <= m_StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2)) + { + m_Events |= BG_STARTING_EVENT_2; + SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL); + } + // After 30 or 15 seconds, warning is signalled + else if (GetStartDelayTime() <= m_StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3)) + { + m_Events |= BG_STARTING_EVENT_3; + SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_THIRD], CHAT_MSG_BG_SYSTEM_NEUTRAL); + } + // delay expired (atfer 2 or 1 minute) + else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4)) + { + m_Events |= BG_STARTING_EVENT_4; + + StartingEventOpenDoors(); + + SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_FOURTH], CHAT_MSG_BG_SYSTEM_NEUTRAL); + SetStatus(STATUS_IN_PROGRESS); + SetStartDelayTime(m_StartDelayTimes[BG_STARTING_EVENT_FOURTH]); + + //remove preparation + if( isArena() ) + { + //TODO : add arena sound (PlaySoundToAll(SOUND_ARENA_START); + + for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + if(Player *plr = objmgr.GetPlayer(itr->first)) + plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); + + if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); + } + else + { + + PlaySoundToAll(SOUND_BG_START); + + for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + if(Player* plr = objmgr.GetPlayer(itr->first)) + plr->RemoveAurasDueToSpell(SPELL_PREPARATION); + //Announce BG starting: + if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) + { + sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel()); + } + } + } + } + + /*********************************************************/ + /*** BATTLEGROUND ENDING SYSTEM ***/ + /*********************************************************/ + if(GetStatus() == STATUS_WAIT_LEAVE) { // remove all players from battleground after 2 minutes @@ -267,6 +368,7 @@ void BattleGround::Update(uint32 diff) // do not change any battleground's private variables } } + } void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O) @@ -1365,31 +1467,31 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float return true; } -void BattleGround::SendMessageToAll(char const* text) +void BattleGround::SendMessageToAll(char const* text, uint8 type) { WorldPacket data; - ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, text, NULL); + ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, text, NULL); SendPacketToAll(&data); } -void BattleGround::SendMessageToAll(int32 entry) +void BattleGround::SendMessageToAll(int32 entry, uint8 type) { char const* text = GetMangosString(entry); WorldPacket data; - ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, text, NULL); + ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, text, NULL); SendPacketToAll(&data); } //copied from void ChatHandler::PSendSysMessage(int32 entry, ...) -void BattleGround::PSendMessageToAll(int32 entry, ...) +void BattleGround::PSendMessageToAll(int32 entry, uint8 type, ...) { const char *format = GetMangosString(entry); va_list ap; char str [2048]; - va_start(ap, entry); + va_start(ap, type); vsnprintf(str,2048,format, ap ); va_end(ap); - SendMessageToAll(str); + SendMessageToAll(str, type); } void BattleGround::EndNow() diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 779a99221..08a703c42 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -90,16 +90,21 @@ enum BattleGroundTimeIntervals INVITE_ACCEPT_WAIT_TIME = 80000, // ms TIME_TO_AUTOREMOVE = 120000, // ms MAX_OFFLINE_TIME = 300000, // ms - START_DELAY0 = 120000, // ms - START_DELAY1 = 60000, // ms - START_DELAY2 = 30000, // ms - START_DELAY3 = 15000, // ms used only in arena RESPAWN_ONE_DAY = 86400, // secs RESPAWN_IMMEDIATELY = 0, // secs BUFF_RESPAWN_TIME = 180, // secs BG_HONOR_SCORE_TICKS = 330 // points }; +enum BattleGroundStartTimeIntervals +{ + BG_START_DELAY_2M = 120000, // ms (2 minutes) + BG_START_DELAY_1M = 60000, // ms (1 minute) + BG_START_DELAY_30S = 30000, // ms (30 seconds) + BG_START_DELAY_15S = 15000, // ms (15 seconds) Used only in arena + BG_START_DELAY_NONE = 0, // ms +}; + enum BattleGroundBuffObjects { BG_OBJECTID_SPEEDBUFF_ENTRY = 179871, @@ -214,6 +219,24 @@ enum BattleGroundTeamId }; #define BG_TEAMS_COUNT 2 +enum BattleGroundStartingEvents +{ + BG_STARTING_EVENT_NONE = 0x00, + BG_STARTING_EVENT_1 = 0x01, + BG_STARTING_EVENT_2 = 0x02, + BG_STARTING_EVENT_3 = 0x04, + BG_STARTING_EVENT_4 = 0x08 +}; + +enum BattleGroundStartingEventsIds +{ + BG_STARTING_EVENT_FIRST = 0, + BG_STARTING_EVENT_SECOND = 1, + BG_STARTING_EVENT_THIRD = 2, + BG_STARTING_EVENT_FOURTH = 3 +}; +#define BG_STARTING_EVENT_COUNT 4 + enum BattleGroundJoinError { BG_JOIN_ERR_OK = 0, @@ -266,6 +289,8 @@ class BattleGround return true; } virtual void Reset(); // resets all common properties for battlegrounds, must be implemented and called in BG subclass + virtual void StartingEventCloseDoors() {} + virtual void StartingEventOpenDoors() {} /* Battleground */ // Get methods: @@ -387,9 +412,9 @@ class BattleGround void EndBattleGround(uint32 winner); void BlockMovement(Player *plr); - void SendMessageToAll(char const* text); - void SendMessageToAll(int32 entry); - void PSendMessageToAll(int32 entry, ... ); + void SendMessageToAll(char const* text, uint8 type); + void SendMessageToAll(int32 entry, uint8 type); + void PSendMessageToAll(int32 entry, uint8 type, ... ); /* Raid Group */ Group *GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; } @@ -421,7 +446,6 @@ class BattleGround virtual void HandleKillPlayer(Player *player, Player *killer); /* Battleground events */ - /* these functions will return true event is possible, but false if player is bugger */ virtual void EventPlayerDroppedFlag(Player* /*player*/) {} virtual void EventPlayerClickedOnFlag(Player* /*player*/, GameObject* /*target_obj*/) {} virtual void EventPlayerCapturedFlag(Player* /*player*/) {} @@ -480,9 +504,12 @@ class BattleGround std::map > m_ReviveQueue; /* - this is important variable used for invitation messages + these are important variables used for starting messages */ uint8 m_Events; + BattleGroundStartTimeIntervals m_StartDelayTimes[BG_STARTING_EVENT_COUNT]; + //this must be filled in constructors! + uint32 m_StartMessageIds[BG_STARTING_EVENT_COUNT]; bool m_BuffChange; diff --git a/src/game/BattleGroundAA.cpp b/src/game/BattleGroundAA.cpp index fcf9bd4ce..b67eb73d6 100644 --- a/src/game/BattleGroundAA.cpp +++ b/src/game/BattleGroundAA.cpp @@ -19,10 +19,20 @@ #include "Player.h" #include "BattleGround.h" #include "BattleGroundAA.h" +#include "Language.h" BattleGroundAA::BattleGroundAA() { + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattleGroundAA::~BattleGroundAA() @@ -35,6 +45,14 @@ void BattleGroundAA::Update(uint32 diff) BattleGround::Update(diff); } +void BattleGroundAA::StartingEventCloseDoors() +{ +} + +void BattleGroundAA::StartingEventOpenDoors() +{ +} + void BattleGroundAA::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); diff --git a/src/game/BattleGroundAA.h b/src/game/BattleGroundAA.h index b144acae3..56a18dfc2 100644 --- a/src/game/BattleGroundAA.h +++ b/src/game/BattleGroundAA.h @@ -39,6 +39,9 @@ class BattleGroundAA : public BattleGround /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + void RemovePlayer(Player *plr, uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); bool SetupBattleGround(); diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index 282e25298..e45909788 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -33,6 +33,11 @@ BattleGroundAB::BattleGroundAB() m_BuffChange = true; m_BgObjects.resize(BG_AB_OBJECT_MAX); m_BgCreatures.resize(BG_AB_ALL_NODES_COUNT); + + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AB_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AB_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AB_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AB_HAS_BEGUN; } BattleGroundAB::~BattleGroundAB() @@ -43,81 +48,7 @@ void BattleGroundAB::Update(uint32 diff) { BattleGround::Update(diff); - if( GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize() ) - { - ModifyStartDelayTime(diff); - - if( !(m_Events & 0x01) ) - { - m_Events |= 0x01; - - // setup here, only when at least one player has ported to the map - if(!SetupBattleGround()) - { - EndNow(); - return; - } - - sLog.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ..."); - - // despawn banners, auras and buffs - for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj) - SpawnBGObject(obj, RESPAWN_ONE_DAY); - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i) - SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY); - - // Starting doors - SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY); - DoorClose(BG_AB_OBJECT_GATE_A); - DoorClose(BG_AB_OBJECT_GATE_H); - - // Starting base spirit guides - _NodeOccupied(BG_AB_SPIRIT_ALIANCE,ALLIANCE); - _NodeOccupied(BG_AB_SPIRIT_HORDE,HORDE); - - SetStartDelayTime(START_DELAY0); - } - // After 1 minute, warning is signalled - else if( GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04) ) - { - m_Events |= 0x04; - SendMessageToAll(GetMangosString(LANG_BG_AB_ONEMINTOSTART)); - } - // After 1,5 minute, warning is signalled - else if( GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08) ) - { - m_Events |= 0x08; - SendMessageToAll(GetMangosString(LANG_BG_AB_HALFMINTOSTART)); - } - // After 2 minutes, gates OPEN ! x) - else if( GetStartDelayTime() < 0 && !(m_Events & 0x10) ) - { - m_Events |= 0x10; - SendMessageToAll(GetMangosString(LANG_BG_AB_STARTED)); - - // spawn neutral banners - for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i) - SpawnBGObject(banner, RESPAWN_IMMEDIATELY); - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - { - //randomly select buff to spawn - uint8 buff = urand(0, 2); - SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY); - } - DoorOpen(BG_AB_OBJECT_GATE_A); - DoorOpen(BG_AB_OBJECT_GATE_H); - - PlaySoundToAll(SOUND_BG_START); - SetStatus(STATUS_IN_PROGRESS); - - for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) - if(Player* plr = objmgr.GetPlayer(itr->first)) - plr->RemoveAurasDueToSpell(SPELL_PREPARATION); - } - - } - else if( GetStatus() == STATUS_IN_PROGRESS ) + if( GetStatus() == STATUS_IN_PROGRESS ) { int team_points[2] = { 0, 0 }; @@ -195,9 +126,9 @@ void BattleGroundAB::Update(uint32 diff) if( !m_IsInformedNearVictory && m_TeamScores[team] > 1800 ) { if( team == BG_TEAM_ALLIANCE ) - SendMessageToAll(GetMangosString(LANG_BG_AB_A_NEAR_VICTORY)); + SendMessageToAll(GetMangosString(LANG_BG_AB_A_NEAR_VICTORY), CHAT_MSG_BG_SYSTEM_NEUTRAL); else - SendMessageToAll(GetMangosString(LANG_BG_AB_H_NEAR_VICTORY)); + SendMessageToAll(GetMangosString(LANG_BG_AB_H_NEAR_VICTORY), CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(SOUND_NEAR_VICTORY); m_IsInformedNearVictory = true; } @@ -219,6 +150,40 @@ void BattleGroundAB::Update(uint32 diff) } } +void BattleGroundAB::StartingEventCloseDoors() +{ + // despawn banners, auras and buffs + for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj) + SpawnBGObject(obj, RESPAWN_ONE_DAY); + for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i) + SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY); + + // Starting doors + DoorClose(BG_AB_OBJECT_GATE_A); + DoorClose(BG_AB_OBJECT_GATE_H); + SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY); + + // Starting base spirit guides + _NodeOccupied(BG_AB_SPIRIT_ALIANCE,ALLIANCE); + _NodeOccupied(BG_AB_SPIRIT_HORDE,HORDE); +} + +void BattleGroundAB::StartingEventOpenDoors() +{ + // spawn neutral banners + for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i) + SpawnBGObject(banner, RESPAWN_IMMEDIATELY); + for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + { + //randomly select buff to spawn + uint8 buff = urand(0, 2); + SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY); + } + DoorOpen(BG_AB_OBJECT_GATE_A); + DoorOpen(BG_AB_OBJECT_GATE_H); +} + void BattleGroundAB::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h index 3b38b3a96..a54f7233d 100644 --- a/src/game/BattleGroundAB.h +++ b/src/game/BattleGroundAB.h @@ -238,6 +238,8 @@ class BattleGroundAB : public BattleGround void Update(uint32 diff); void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); void RemovePlayer(Player *plr,uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); virtual bool SetupBattleGround(); diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp index c444bcbb2..e10020afc 100644 --- a/src/game/BattleGroundAV.cpp +++ b/src/game/BattleGroundAV.cpp @@ -27,6 +27,11 @@ BattleGroundAV::BattleGroundAV() { + //TODO FIX ME! + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN; } BattleGroundAV::~BattleGroundAV() @@ -39,6 +44,14 @@ void BattleGroundAV::Update(uint32 diff) BattleGround::Update(diff); } +void BattleGroundAV::StartingEventCloseDoors() +{ +} + +void BattleGroundAV::StartingEventOpenDoors() +{ +} + void BattleGroundAV::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); diff --git a/src/game/BattleGroundAV.h b/src/game/BattleGroundAV.h index c2e12a872..edacf1cfe 100644 --- a/src/game/BattleGroundAV.h +++ b/src/game/BattleGroundAV.h @@ -46,6 +46,8 @@ class BattleGroundAV : public BattleGround /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); void RemovePlayer(Player *plr,uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index 412479093..ea21320af 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -29,6 +29,16 @@ BattleGroundBE::BattleGroundBE() { m_BgObjects.resize(BG_BE_OBJECT_MAX); + + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattleGroundBE::~BattleGroundBE() @@ -40,73 +50,30 @@ void BattleGroundBE::Update(uint32 diff) { BattleGround::Update(diff); - // after bg start we get there - if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) - { - ModifyStartDelayTime(diff); - - if (!(m_Events & 0x01)) - { - m_Events |= 0x01; - // setup here, only when at least one player has ported to the map - if(!SetupBattleGround()) - { - EndNow(); - return; - } - for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - - for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++) - SpawnBGObject(i, RESPAWN_ONE_DAY); - - SetStartDelayTime(START_DELAY1); - SendMessageToAll(LANG_ARENA_ONE_MINUTE); - } - // After 30 seconds, warning is signalled - else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04)) - { - m_Events |= 0x04; - SendMessageToAll(LANG_ARENA_THIRTY_SECONDS); - } - // After 15 seconds, warning is signalled - else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08)) - { - m_Events |= 0x08; - SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS); - } - // delay expired (1 minute) - else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10)) - { - m_Events |= 0x10; - - for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; i++) - DoorOpen(i); - - for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++) - SpawnBGObject(i, 60); - - SendMessageToAll(LANG_ARENA_BEGUN); - SetStatus(STATUS_IN_PROGRESS); - SetStartDelayTime(0); - - for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) - if(Player *plr = objmgr.GetPlayer(itr->first)) - plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); - - if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) - EndBattleGround(HORDE); - else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) - EndBattleGround(ALLIANCE); - } - } - /*if(GetStatus() == STATUS_IN_PROGRESS) { // update something }*/ } +void BattleGroundBE::StartingEventCloseDoors() +{ + for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + + for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++) + SpawnBGObject(i, RESPAWN_ONE_DAY); +} + +void BattleGroundBE::StartingEventOpenDoors() +{ + for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; i++) + DoorOpen(i); + + for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++) + SpawnBGObject(i, 60); +} + void BattleGroundBE::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); diff --git a/src/game/BattleGroundBE.h b/src/game/BattleGroundBE.h index 3d15d612d..0fea026e5 100644 --- a/src/game/BattleGroundBE.h +++ b/src/game/BattleGroundBE.h @@ -59,6 +59,8 @@ class BattleGroundBE : public BattleGround /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); void RemovePlayer(Player *plr, uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); diff --git a/src/game/BattleGroundDS.cpp b/src/game/BattleGroundDS.cpp index 825a52967..78360b9b1 100644 --- a/src/game/BattleGroundDS.cpp +++ b/src/game/BattleGroundDS.cpp @@ -19,10 +19,20 @@ #include "Player.h" #include "BattleGround.h" #include "BattleGroundDS.h" +#include "Language.h" BattleGroundDS::BattleGroundDS() { + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattleGroundDS::~BattleGroundDS() @@ -35,6 +45,14 @@ void BattleGroundDS::Update(uint32 diff) BattleGround::Update(diff); } +void BattleGroundDS::StartingEventCloseDoors() +{ +} + +void BattleGroundDS::StartingEventOpenDoors() +{ +} + void BattleGroundDS::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); diff --git a/src/game/BattleGroundDS.h b/src/game/BattleGroundDS.h index 7f9de8ca7..44a6cfbd3 100644 --- a/src/game/BattleGroundDS.h +++ b/src/game/BattleGroundDS.h @@ -39,6 +39,9 @@ class BattleGroundDS : public BattleGround /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + void RemovePlayer(Player *plr, uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); bool SetupBattleGround(); diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index acdd4ca51..9d425fbc1 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -37,6 +37,11 @@ BattleGroundEY::BattleGroundEY() m_Points_Trigger[BLOOD_ELF] = TR_BLOOD_ELF_BUFF; m_Points_Trigger[DRAENEI_RUINS] = TR_DRAENEI_RUINS_BUFF; m_Points_Trigger[MAGE_TOWER] = TR_MAGE_TOWER_BUFF; + + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN; } BattleGroundEY::~BattleGroundEY() @@ -46,71 +51,8 @@ BattleGroundEY::~BattleGroundEY() void BattleGroundEY::Update(uint32 diff) { BattleGround::Update(diff); - // after bg start we get there (once) - if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) - { - ModifyStartDelayTime(diff); - if(!(m_Events & 0x01)) - { - m_Events |= 0x01; - - // setup here, only when at least one player has ported to the map - if(!SetupBattleGround()) - { - EndNow(); - return; - } - - SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY); - -// SpawnBGCreature(EY_SPIRIT_MAIN_ALLIANCE, RESPAWN_IMMEDIATELY); -// SpawnBGCreature(EY_SPIRIT_MAIN_HORDE, RESPAWN_IMMEDIATELY); - for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i) - SpawnBGObject(i, RESPAWN_ONE_DAY); - - SetStartDelayTime(START_DELAY0); - } - // After 1 minute, warning is signalled - else if(GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04)) - { - m_Events |= 0x04; - SendMessageToAll(GetMangosString(LANG_BG_EY_ONE_MINUTE)); - } - // After 1,5 minute, warning is signalled - else if(GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08)) - { - m_Events |= 0x08; - SendMessageToAll(GetMangosString(LANG_BG_EY_HALF_MINUTE)); - } - // After 2 minutes, gates OPEN ! x) - else if(GetStartDelayTime() < 0 && !(m_Events & 0x10)) - { - m_Events |= 0x10; - SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY); - SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY); - - for(uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - for(uint32 i = 0; i < EY_POINTS_MAX; ++i) - { - //randomly spawn buff - uint8 buff = urand(0, 2); - SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + buff + i * 3, RESPAWN_IMMEDIATELY); - } - - SendMessageToAll(GetMangosString(LANG_BG_EY_BEGIN)); - - PlaySoundToAll(SOUND_BG_START); - SetStatus(STATUS_IN_PROGRESS); - - for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) - if(Player *plr = objmgr.GetPlayer(itr->first)) - plr->RemoveAurasDueToSpell(SPELL_PREPARATION); - } - } - else if(GetStatus() == STATUS_IN_PROGRESS) + if( GetStatus() == STATUS_IN_PROGRESS ) { m_PointAddingTimer -= diff; if(m_PointAddingTimer <= 0) @@ -152,6 +94,30 @@ void BattleGroundEY::Update(uint32 diff) } } +void BattleGroundEY::StartingEventCloseDoors() +{ + SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY); + + for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i) + SpawnBGObject(i, RESPAWN_ONE_DAY); +} + +void BattleGroundEY::StartingEventOpenDoors() +{ + SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY); + SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY); + + for(uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + for(uint32 i = 0; i < EY_POINTS_MAX; ++i) + { + //randomly spawn buff + uint8 buff = urand(0, 2); + SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + buff + i * 3, RESPAWN_IMMEDIATELY); + } +} + void BattleGroundEY::AddPoints(uint32 Team, uint32 Points) { uint8 team_index = GetTeamIndexByTeamId(Team); @@ -554,7 +520,7 @@ void BattleGroundEY::RespawnFlag(bool send_message) if(send_message) { - SendMessageToAll(GetMangosString(LANG_BG_EY_RESETED_FLAG)); + SendMessageToAll(GetMangosString(LANG_BG_EY_RESETED_FLAG), CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(BG_EY_SOUND_FLAG_RESET); // flags respawned sound... } diff --git a/src/game/BattleGroundEY.h b/src/game/BattleGroundEY.h index 0da776457..ed3958401 100644 --- a/src/game/BattleGroundEY.h +++ b/src/game/BattleGroundEY.h @@ -302,6 +302,8 @@ class BattleGroundEY : public BattleGround /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); /* BG Flags */ uint64 GetFlagPickerGUID() const { return m_FlagKeeper; } diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index a0583688a..a07ba6c62 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -622,7 +622,7 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBas return false; } //allow 1v0 if debug bg - if( sBattleGroundMgr.isTesting() && (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()) ) + if( sBattleGroundMgr.isTesting() && bg_template->isBattleGround() && (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()) ) return true; //return true if there are enough players in selection pools - enable to work .debug bg command correctly return m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= minPlayers; diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp index 01d766adf..8a4ba7f07 100644 --- a/src/game/BattleGroundNA.cpp +++ b/src/game/BattleGroundNA.cpp @@ -29,6 +29,16 @@ BattleGroundNA::BattleGroundNA() { m_BgObjects.resize(BG_NA_OBJECT_MAX); + + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattleGroundNA::~BattleGroundNA() @@ -40,70 +50,27 @@ void BattleGroundNA::Update(uint32 diff) { BattleGround::Update(diff); - // after bg start we get there - if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) - { - ModifyStartDelayTime(diff); - - if (!(m_Events & 0x01)) - { - m_Events |= 0x01; - // setup here, only when at least one player has ported to the map - if(!SetupBattleGround()) - { - EndNow(); - return; - } - for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - - SetStartDelayTime(START_DELAY1); - SendMessageToAll(LANG_ARENA_ONE_MINUTE); - } - // After 30 seconds, warning is signalled - else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04)) - { - m_Events |= 0x04; - SendMessageToAll(LANG_ARENA_THIRTY_SECONDS); - } - // After 15 seconds, warning is signalled - else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08)) - { - m_Events |= 0x08; - SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS); - } - // delay expired (1 minute) - else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10)) - { - m_Events |= 0x10; - - for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++) - DoorOpen(i); - - for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; i++) - SpawnBGObject(i, 60); - - SendMessageToAll(LANG_ARENA_BEGUN); - SetStatus(STATUS_IN_PROGRESS); - SetStartDelayTime(0); - - for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) - if(Player *plr = objmgr.GetPlayer(itr->first)) - plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); - - if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) - EndBattleGround(HORDE); - else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) - EndBattleGround(ALLIANCE); - } - } - /*if(GetStatus() == STATUS_IN_PROGRESS) { // update something }*/ } +void BattleGroundNA::StartingEventCloseDoors() +{ + for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); +} + +void BattleGroundNA::StartingEventOpenDoors() +{ + for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++) + DoorOpen(i); + + for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; i++) + SpawnBGObject(i, 60); +} + void BattleGroundNA::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); diff --git a/src/game/BattleGroundNA.h b/src/game/BattleGroundNA.h index ab70dea55..1d35b839e 100644 --- a/src/game/BattleGroundNA.h +++ b/src/game/BattleGroundNA.h @@ -60,6 +60,8 @@ class BattleGroundNA : public BattleGround /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); void RemovePlayer(Player *plr, uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index b1dbaec55..6794b8263 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -29,6 +29,16 @@ BattleGroundRL::BattleGroundRL() { m_BgObjects.resize(BG_RL_OBJECT_MAX); + + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattleGroundRL::~BattleGroundRL() @@ -40,71 +50,27 @@ void BattleGroundRL::Update(uint32 diff) { BattleGround::Update(diff); - if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) - { - ModifyStartDelayTime(diff); - - if (!(m_Events & 0x01)) - { - m_Events |= 0x01; - - // setup here, only when at least one player has ported to the map - if(!SetupBattleGround()) - { - EndNow(); - return; - } - - for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - - SetStartDelayTime(START_DELAY1); - SendMessageToAll(LANG_ARENA_ONE_MINUTE); - } - // After 30 seconds, warning is signalled - else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04)) - { - m_Events |= 0x04; - SendMessageToAll(LANG_ARENA_THIRTY_SECONDS); - } - // After 15 seconds, warning is signalled - else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08)) - { - m_Events |= 0x08; - SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS); - } - // delay expired (1 minute) - else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10)) - { - m_Events |= 0x10; - - for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) - DoorOpen(i); - - for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; i++) - SpawnBGObject(i, 60); - - SendMessageToAll(LANG_ARENA_BEGUN); - SetStatus(STATUS_IN_PROGRESS); - SetStartDelayTime(0); - - for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) - if(Player *plr = objmgr.GetPlayer(itr->first)) - plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); - - if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) - EndBattleGround(HORDE); - else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) - EndBattleGround(ALLIANCE); - } - } - /*if(GetStatus() == STATUS_IN_PROGRESS) { // update something }*/ } +void BattleGroundRL::StartingEventCloseDoors() +{ + for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); +} + +void BattleGroundRL::StartingEventOpenDoors() +{ + for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) + DoorOpen(i); + + for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; i++) + SpawnBGObject(i, 60); +} + void BattleGroundRL::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); diff --git a/src/game/BattleGroundRL.h b/src/game/BattleGroundRL.h index 87ac54a98..dd0dfd2af 100644 --- a/src/game/BattleGroundRL.h +++ b/src/game/BattleGroundRL.h @@ -58,6 +58,8 @@ class BattleGroundRL : public BattleGround virtual void AddPlayer(Player *plr); virtual void Reset(); virtual void FillInitialWorldStates(WorldPacket &d); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); void RemovePlayer(Player *plr, uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); diff --git a/src/game/BattleGroundRV.cpp b/src/game/BattleGroundRV.cpp index a66f0ce30..8c252c35c 100644 --- a/src/game/BattleGroundRV.cpp +++ b/src/game/BattleGroundRV.cpp @@ -19,10 +19,20 @@ #include "Player.h" #include "BattleGround.h" #include "BattleGroundRV.h" +#include "Language.h" BattleGroundRV::BattleGroundRV() { + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattleGroundRV::~BattleGroundRV() @@ -35,6 +45,14 @@ void BattleGroundRV::Update(uint32 diff) BattleGround::Update(diff); } +void BattleGroundRV::StartingEventCloseDoors() +{ +} + +void BattleGroundRV::StartingEventOpenDoors() +{ +} + void BattleGroundRV::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); diff --git a/src/game/BattleGroundRV.h b/src/game/BattleGroundRV.h index 2d2ad12c9..e3e94baf1 100644 --- a/src/game/BattleGroundRV.h +++ b/src/game/BattleGroundRV.h @@ -39,6 +39,9 @@ class BattleGroundRV : public BattleGround /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + void RemovePlayer(Player *plr, uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); bool SetupBattleGround(); diff --git a/src/game/BattleGroundSA.cpp b/src/game/BattleGroundSA.cpp index d5585fd93..68ef2af19 100644 --- a/src/game/BattleGroundSA.cpp +++ b/src/game/BattleGroundSA.cpp @@ -16,13 +16,18 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "Player.h" #include "BattleGround.h" #include "BattleGroundSA.h" -#include "Player.h" +#include "Language.h" BattleGroundSA::BattleGroundSA() { - + //TODO FIX ME! + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; } BattleGroundSA::~BattleGroundSA() @@ -35,6 +40,14 @@ void BattleGroundSA::Update(uint32 diff) BattleGround::Update(diff); } +void BattleGroundSA::StartingEventCloseDoors() +{ +} + +void BattleGroundSA::StartingEventOpenDoors() +{ +} + void BattleGroundSA::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); diff --git a/src/game/BattleGroundSA.h b/src/game/BattleGroundSA.h index 331a41455..3ba23d026 100644 --- a/src/game/BattleGroundSA.h +++ b/src/game/BattleGroundSA.h @@ -39,6 +39,8 @@ class BattleGroundSA : public BattleGround /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); void RemovePlayer(Player *plr,uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index 0c85dff86..e28be3f34 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -32,6 +32,11 @@ BattleGroundWS::BattleGroundWS() { m_BgObjects.resize(BG_WS_OBJECT_MAX); m_BgCreatures.resize(BG_CREATURES_MAX_WS); + + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; } BattleGroundWS::~BattleGroundWS() @@ -42,75 +47,7 @@ void BattleGroundWS::Update(uint32 diff) { BattleGround::Update(diff); - // after bg start we get there (once) - if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) - { - ModifyStartDelayTime(diff); - - if(!(m_Events & 0x01)) - { - m_Events |= 0x01; - - // setup here, only when at least one player has ported to the map - if(!SetupBattleGround()) - { - EndNow(); - return; - } - -// for(uint32 i = WS_SPIRIT_MAIN_ALLIANCE; i <= WS_SPIRIT_MAIN_HORDE; i++) -// SpawnBGCreature(i, RESPAWN_IMMEDIATELY); - - for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++) - { - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - DoorClose(i); - } - for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++) - SpawnBGObject(i, RESPAWN_ONE_DAY); - - SetStartDelayTime(START_DELAY0); - } - // After 1 minute, warning is signalled - else if(GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04)) - { - m_Events |= 0x04; - SendMessageToAll(GetMangosString(LANG_BG_WS_ONE_MINUTE)); - } - // After 1,5 minute, warning is signalled - else if(GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08)) - { - m_Events |= 0x08; - SendMessageToAll(GetMangosString(LANG_BG_WS_HALF_MINUTE)); - } - // After 2 minutes, gates OPEN ! x) - else if(GetStartDelayTime() < 0 && !(m_Events & 0x10)) - { - m_Events |= 0x10; - for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_4; i++) - DoorOpen(i); - for(uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_2; i++) - DoorOpen(i); - - SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY); - SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY); - SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY); - SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY); - - for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - - SendMessageToAll(GetMangosString(LANG_BG_WS_BEGIN)); - - PlaySoundToAll(SOUND_BG_START); - SetStatus(STATUS_IN_PROGRESS); - - for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) - if(Player* plr = objmgr.GetPlayer(itr->first)) - plr->RemoveAurasDueToSpell(SPELL_PREPARATION); - } - } - else if(GetStatus() == STATUS_IN_PROGRESS) + if(GetStatus() == STATUS_IN_PROGRESS) { if(m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN) { @@ -155,6 +92,33 @@ void BattleGroundWS::Update(uint32 diff) } } +void BattleGroundWS::StartingEventCloseDoors() +{ + for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++) + { + DoorClose(i); + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + } + for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++) + SpawnBGObject(i, RESPAWN_ONE_DAY); +} + +void BattleGroundWS::StartingEventOpenDoors() +{ + for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_4; i++) + DoorOpen(i); + for(uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_2; i++) + DoorOpen(i); + + SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY); + SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY); + SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY); + SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY); + + for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); +} + void BattleGroundWS::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); @@ -182,7 +146,7 @@ void BattleGroundWS::RespawnFlag(uint32 Team, bool captured) //when map_update will be allowed for battlegrounds this code will be useless SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(GetMangosString(LANG_BG_WS_F_PLACED)); + SendMessageToAll(GetMangosString(LANG_BG_WS_F_PLACED), CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); // flag respawned sound... } } @@ -196,12 +160,12 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team) if(team == ALLIANCE) { SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(GetMangosString(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED)); + SendMessageToAll(GetMangosString(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED), CHAT_MSG_BG_SYSTEM_NEUTRAL); } else { SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(GetMangosString(LANG_BG_WS_HORDE_FLAG_RESPAWNED)); + SendMessageToAll(GetMangosString(LANG_BG_WS_HORDE_FLAG_RESPAWNED), CHAT_MSG_BG_SYSTEM_NEUTRAL); } PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h index f36834f65..6a8f5eceb 100644 --- a/src/game/BattleGroundWS.h +++ b/src/game/BattleGroundWS.h @@ -138,6 +138,8 @@ class BattleGroundWS : public BattleGround /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); /* BG Flags */ uint64 GetAllianceFlagPickerGUID() const { return m_FlagKeepers[BG_TEAM_ALLIANCE]; } diff --git a/src/game/Language.h b/src/game/Language.h index 7a2f5fe85..a2d5500f8 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -569,9 +569,11 @@ enum MangosStrings // Battleground LANG_BG_A_WINS = 600, LANG_BG_H_WINS = 601, - LANG_BG_WS_ONE_MINUTE = 602, - LANG_BG_WS_HALF_MINUTE = 603, - LANG_BG_WS_BEGIN = 604, + + LANG_BG_WS_START_TWO_MINUTES = 753, + LANG_BG_WS_START_ONE_MINUTE = 602, + LANG_BG_WS_START_HALF_MINUTE = 603, + LANG_BG_WS_HAS_BEGUN = 604, LANG_BG_WS_CAPTURED_HF = 605, LANG_BG_WS_CAPTURED_AF = 606, @@ -585,9 +587,10 @@ enum MangosStrings LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED = 614, LANG_BG_WS_HORDE_FLAG_RESPAWNED = 615, - LANG_BG_EY_ONE_MINUTE = 636, - LANG_BG_EY_HALF_MINUTE = 637, - LANG_BG_EY_BEGIN = 638, + LANG_BG_EY_START_TWO_MINUTES = 755, + LANG_BG_EY_START_ONE_MINUTE = 636, + LANG_BG_EY_START_HALF_MINUTE = 637, + LANG_BG_EY_HAS_BEGUN = 638, LANG_BG_AB_ALLY = 650, LANG_BG_AB_HORDE = 651, @@ -600,9 +603,11 @@ enum MangosStrings LANG_BG_AB_NODE_DEFENDED = 658, LANG_BG_AB_NODE_ASSAULTED = 659, LANG_BG_AB_NODE_CLAIMED = 660, - LANG_BG_AB_ONEMINTOSTART = 661, - LANG_BG_AB_HALFMINTOSTART = 662, - LANG_BG_AB_STARTED = 663, + + LANG_BG_AB_START_TWO_MINUTES = 754, + LANG_BG_AB_START_ONE_MINUTE = 661, + LANG_BG_AB_START_HALF_MINUTE = 662, + LANG_BG_AB_HAS_BEGUN = 663, LANG_BG_AB_A_NEAR_VICTORY = 664, LANG_BG_AB_H_NEAR_VICTORY = 665, LANG_BG_MARK_BY_MAIL = 666, @@ -633,7 +638,7 @@ enum MangosStrings LANG_ARENA_ONE_MINUTE = 701, LANG_ARENA_THIRTY_SECONDS = 702, LANG_ARENA_FIFTEEN_SECONDS = 703, - LANG_ARENA_BEGUN = 704, + LANG_ARENA_HAS_BEGUN = 704, LANG_WAIT_BEFORE_SPEAKING = 705, LANG_NOT_EQUIPPED_ITEM = 706, @@ -685,7 +690,11 @@ enum MangosStrings // = 749, not used LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins." LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds." - // Room for batleground/arena strings 752-799 not used +// = 752, not used +// LANG_BG_WS_START_TWO_MINUTES = 753, +// LANG_BG_AB_START_TWO_MINUTES = 754, +// LANG_BG_EY_START_TWO_MINUTES = 755, + // Room for batleground/arena strings 756-799 not used // in game strings // = 800, not used diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ffd0c7e3d..df4b10044 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7398" + #define REVISION_NR "7399" #endif // __REVISION_NR_H__ From f64341068b282aecf75eb564ad08d0ae7a588e9d Mon Sep 17 00:00:00 2001 From: Triply Date: Sat, 7 Mar 2009 11:30:33 +0100 Subject: [PATCH 13/60] [7400] fixed sql change from my previous commit. Signed-off-by: Triply --- sql/mangos.sql | 2 +- sql/updates/Makefile.am | 1 + src/shared/revision_nr.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/mangos.sql b/sql/mangos.sql index 197a9e408..3de564fca 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7393_01_mangos_game_event` bit(1) default NULL + `required_7399_01_mangos_mangos_string` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index d7399a86f..9857066c0 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -368,4 +368,5 @@ EXTRA_DIST = \ 7388_01_mangos_mangos_string.sql \ 7390_01_mangos_areatrigger_teleport.sql \ 7393_01_mangos_game_event.sql \ + 7399_01_mangos_mangos_string.sql \ README diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index df4b10044..eb04afb51 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7399" + #define REVISION_NR "7400" #endif // __REVISION_NR_H__ From 898fef99d222a3e86daa4f12dd1021f4fdccdac1 Mon Sep 17 00:00:00 2001 From: Triply Date: Sat, 7 Mar 2009 17:51:21 +0100 Subject: [PATCH 14/60] [7401] Fixed bgqueue invitation to already started battlegrounds - not tested. Finally fixed sql update in [7399]. Thx to Lake292. Signed-off-by: Triply --- sql/updates/7399_01_mangos_mangos_string.sql | 3 +++ sql/updates/Makefile.am | 1 + src/game/BattleGroundMgr.cpp | 14 ++++++++------ src/shared/revision_nr.h | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/sql/updates/7399_01_mangos_mangos_string.sql b/sql/updates/7399_01_mangos_mangos_string.sql index d05a8e853..d029d28d3 100644 --- a/sql/updates/7399_01_mangos_mangos_string.sql +++ b/sql/updates/7399_01_mangos_mangos_string.sql @@ -1,3 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_7393_01_mangos_game_event required_7399_01_mangos_mangos_string bit; + +DELETE FROM mangos_string WHERE entry in (753, 754, 755); INSERT INTO mangos_string VALUES (753,'The battle for Warsong Gulch begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); INSERT INTO mangos_string VALUES (754,'The battle for Arathi Basin begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); INSERT INTO mangos_string VALUES (755,'The battle for Eye of the Storm begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 9857066c0..ea455f781 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -194,6 +194,7 @@ pkgdata_DATA = \ 7388_01_mangos_mangos_string.sql \ 7390_01_mangos_areatrigger_teleport.sql \ 7393_01_mangos_game_event.sql \ + 7399_01_mangos_mangos_string.sql \ README ## Additional files to include when running 'make dist' diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index a07ba6c62..e4c482a03 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -81,7 +81,7 @@ void BattleGroundQueue::SelectionPool::Init() // remove group info from selection pool // returns true when we need to try to add new group to selection pool -// or false when pool is ok +// returns false when selection pool is ok or when we kicked smaller group than we need to kick // sometimes it can be called on empty selection pool bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size) { @@ -105,7 +105,8 @@ bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size) GroupQueueInfo* ginfo = (*groupToKick); SelectedGroups.erase(groupToKick); PlayerCount -= ginfo->Players.size(); - if (abs((int32)(ginfo->Players.size() - size)) <= 1) + //return false if we kicked smaller group or there are enough players in selection pool + if (ginfo->Players.size() <= size + 1) return false; } return true; @@ -113,8 +114,8 @@ bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size) // add group to selection pool // used when building selection pools -// returns true if we can invite more players -// returns false when selection pool is set +// returns true if we can invite more players, or when we added group to selection pool +// returns false when selection pool is full bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 desiredCount) { //if group is larger than desired count - don't allow to add it to pool @@ -123,6 +124,7 @@ bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 de SelectedGroups.push_back(ginfo); // increase selected players count PlayerCount += ginfo->Players.size(); + return true; } if( PlayerCount < desiredCount ) return true; @@ -499,7 +501,7 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel //if ali selection is already empty, then kick horde group, but if there are less horde than ali in bg - break; if( !m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() ) { - if( aliFree <= diffHorde - 1 ) + if( aliFree <= diffHorde + 1 ) break; m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffHorde - diffAli); } @@ -514,7 +516,7 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel } if( !m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() ) { - if( hordeFree <= diffAli - 1 ) + if( hordeFree <= diffAli + 1 ) break; m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffAli - diffHorde); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index eb04afb51..0cbbe03d1 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7400" + #define REVISION_NR "7401" #endif // __REVISION_NR_H__ From 0de4c02fd22ab7cf359f50c1b97f674b74e30671 Mon Sep 17 00:00:00 2001 From: Triply Date: Sat, 7 Mar 2009 21:31:03 +0100 Subject: [PATCH 15/60] [7402] Fixed graveyards in WSG, prevent from cheating. Patch provided by Balrok. Thx. Signed-off-by: Triply --- src/game/BattleGroundWS.cpp | 23 +++++++++++++++++++++++ src/game/BattleGroundWS.h | 7 +++++-- src/shared/revision_nr.h | 2 +- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index e28be3f34..f6e1b8b95 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -648,6 +648,29 @@ void BattleGroundWS::UpdatePlayerScore(Player *Source, uint32 type, uint32 value } } +WorldSafeLocsEntry const* BattleGroundWS::GetClosestGraveYard(Player* player) +{ + //if status in progress, it returns main graveyards with spiritguides + //else it will return the graveyard in the flagroom - this is especially good + //if a player dies in preparation phase - then the player can't cheat + //and teleport to the graveyard outside the flagroom + //and start running around, while the doors are still closed + if(player->GetTeam() == ALLIANCE) + { + if(GetStatus() == STATUS_IN_PROGRESS) + return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE); + else + return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_ALLIANCE); + } + else + { + if(GetStatus() == STATUS_IN_PROGRESS) + return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE); + else + return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_HORDE); + } +} + void BattleGroundWS::FillInitialWorldStates(WorldPacket& data) { data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(ALLIANCE)); diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h index 6a8f5eceb..23ae211a5 100644 --- a/src/game/BattleGroundWS.h +++ b/src/game/BattleGroundWS.h @@ -105,8 +105,10 @@ enum BG_WS_FlagState enum BG_WS_Graveyards { - WS_GRAVEYARD_MAIN_ALLIANCE = 771, - WS_GRAVEYARD_MAIN_HORDE = 772 + WS_GRAVEYARD_FLAGROOM_ALLIANCE = 769, + WS_GRAVEYARD_FLAGROOM_HORDE = 770, + WS_GRAVEYARD_MAIN_ALLIANCE = 771, + WS_GRAVEYARD_MAIN_HORDE = 772 }; enum BG_WS_CreatureTypes @@ -162,6 +164,7 @@ class BattleGroundWS : public BattleGround void HandleKillPlayer(Player *player, Player *killer); bool SetupBattleGround(); virtual void Reset(); + virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); void UpdateFlagState(uint32 team, uint32 value); void UpdateTeamScore(uint32 team); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0cbbe03d1..407f659f9 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7401" + #define REVISION_NR "7402" #endif // __REVISION_NR_H__ From 6c39db38f46fce33ec07f341f35ec2a22847ccc0 Mon Sep 17 00:00:00 2001 From: balrok Date: Fri, 6 Mar 2009 17:40:53 +0100 Subject: [PATCH 16/60] removed unneeded World.h includes this is done by this script: ack -c "World.h" | ack :1 | sed 's/:1//' | xargs grep -c sWorld | grep :0 | sed 's/:0//' | xargs sed -i '/#include "World.h"/d' i didn't checked every change but gcc haven't complained --- src/game/BattleGround.cpp | 1 - src/game/CombatHandler.cpp | 1 - src/game/DuelHandler.cpp | 1 - src/game/ItemHandler.cpp | 1 - src/game/MovementHandler.cpp | 1 - src/game/NPCHandler.cpp | 1 - src/game/PetHandler.cpp | 1 - src/game/PoolHandler.cpp | 1 - src/game/SkillHandler.cpp | 1 - src/game/SpellHandler.cpp | 1 - src/game/TaxiHandler.cpp | 1 - src/game/VoiceChatHandler.cpp | 1 - src/game/debugcmds.cpp | 1 - 13 files changed, 13 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index f19e013c4..7dd0dcc67 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -26,7 +26,6 @@ #include "Chat.h" #include "SpellAuras.h" #include "ArenaTeam.h" -#include "World.h" #include "Group.h" #include "ObjectMgr.h" #include "WorldPacket.h" diff --git a/src/game/CombatHandler.cpp b/src/game/CombatHandler.cpp index 86605c397..12fedd89a 100644 --- a/src/game/CombatHandler.cpp +++ b/src/game/CombatHandler.cpp @@ -20,7 +20,6 @@ #include "Log.h" #include "WorldPacket.h" #include "WorldSession.h" -#include "World.h" #include "ObjectAccessor.h" #include "CreatureAI.h" #include "ObjectDefines.h" diff --git a/src/game/DuelHandler.cpp b/src/game/DuelHandler.cpp index a355931e5..d98b444cc 100644 --- a/src/game/DuelHandler.cpp +++ b/src/game/DuelHandler.cpp @@ -19,7 +19,6 @@ #include "Common.h" #include "WorldPacket.h" #include "WorldSession.h" -#include "World.h" #include "Log.h" #include "Opcodes.h" #include "UpdateData.h" diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index dc92c6539..82ce5c546 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -19,7 +19,6 @@ #include "Common.h" #include "WorldPacket.h" #include "WorldSession.h" -#include "World.h" #include "Opcodes.h" #include "Log.h" #include "ObjectMgr.h" diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index ef7fee4df..d6e974a49 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -21,7 +21,6 @@ #include "WorldSession.h" #include "Opcodes.h" #include "Log.h" -#include "World.h" #include "Corpse.h" #include "Player.h" #include "MapManager.h" diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index d762b9a77..12f7bfb93 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -23,7 +23,6 @@ #include "WorldSession.h" #include "Opcodes.h" #include "Log.h" -#include "World.h" #include "ObjectMgr.h" #include "SpellMgr.h" #include "Player.h" diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index 72921513a..37697ec7c 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -19,7 +19,6 @@ #include "Common.h" #include "WorldPacket.h" #include "WorldSession.h" -#include "World.h" #include "ObjectMgr.h" #include "SpellMgr.h" #include "Log.h" diff --git a/src/game/PoolHandler.cpp b/src/game/PoolHandler.cpp index 0f18aee05..4d040146f 100644 --- a/src/game/PoolHandler.cpp +++ b/src/game/PoolHandler.cpp @@ -17,7 +17,6 @@ */ #include "PoolHandler.h" -#include "World.h" #include "ObjectMgr.h" #include "ProgressBar.h" #include "Language.h" diff --git a/src/game/SkillHandler.cpp b/src/game/SkillHandler.cpp index 8f854dd52..8e20d50df 100644 --- a/src/game/SkillHandler.cpp +++ b/src/game/SkillHandler.cpp @@ -21,7 +21,6 @@ #include "Opcodes.h" #include "Log.h" #include "Player.h" -#include "World.h" #include "WorldPacket.h" #include "WorldSession.h" #include "ObjectAccessor.h" diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 986c39908..26d328e82 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -20,7 +20,6 @@ #include "Database/DBCStores.h" #include "WorldPacket.h" #include "WorldSession.h" -#include "World.h" #include "ObjectMgr.h" #include "SpellMgr.h" #include "Log.h" diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp index b8aa614db..166d833d0 100644 --- a/src/game/TaxiHandler.cpp +++ b/src/game/TaxiHandler.cpp @@ -22,7 +22,6 @@ #include "WorldSession.h" #include "Opcodes.h" #include "Log.h" -#include "World.h" #include "ObjectMgr.h" #include "Player.h" #include "UpdateMask.h" diff --git a/src/game/VoiceChatHandler.cpp b/src/game/VoiceChatHandler.cpp index 741957610..d3b614c52 100644 --- a/src/game/VoiceChatHandler.cpp +++ b/src/game/VoiceChatHandler.cpp @@ -19,7 +19,6 @@ #include "Common.h" #include "WorldPacket.h" #include "WorldSession.h" -#include "World.h" #include "Opcodes.h" #include "Log.h" diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index d04cce6a2..a2271783d 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -20,7 +20,6 @@ #include "Database/DatabaseEnv.h" #include "WorldPacket.h" #include "WorldSession.h" -#include "World.h" #include "Player.h" #include "Opcodes.h" #include "Chat.h" From f3ea479f6e9ef80f8b94847b2ca37a92e8ae7721 Mon Sep 17 00:00:00 2001 From: balrok Date: Fri, 6 Mar 2009 17:43:54 +0100 Subject: [PATCH 17/60] removed duplicated includes i used the following script (i have no awk-skills :-/ i guess with awk it will look much better) for i in `ls *.h` do HEADER="#include \\\""`echo $i | sed 's/\./\\\\./'`"\\\"" #a grep-readable #include "file.h" # following should deletes the first occurence of a duplicated # (#include) line # if an include is more then once in this file this script # has to be run more often - i don't know a better solution grep -cH "$HEADER" *.[hcpp]* | grep -v :1$ | grep -v :0 | sed -r 's/:[0-9]*$//' | xargs sed -i '0,/#include "'$i'"/{//d;}' done Signed-off-by: VladimirMangos Restored build for x64: WorldSession expected to be fist include in WorldSession.cpp --- src/game/CreatureAIRegistry.cpp | 1 - src/game/InstanceSaveMgr.cpp | 1 - src/game/Level2.cpp | 1 - src/game/ObjectAccessor.cpp | 1 - src/game/Player.cpp | 1 - src/game/SpellEffects.cpp | 2 -- src/game/WorldSession.cpp | 3 +-- 7 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/game/CreatureAIRegistry.cpp b/src/game/CreatureAIRegistry.cpp index 7790ff992..fa14bbe43 100644 --- a/src/game/CreatureAIRegistry.cpp +++ b/src/game/CreatureAIRegistry.cpp @@ -16,7 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "CreatureAIRegistry.h" #include "NullCreatureAI.h" #include "ReactorAI.h" #include "AggressorAI.h" diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp index 6c51b2024..cc7b0b116 100644 --- a/src/game/InstanceSaveMgr.cpp +++ b/src/game/InstanceSaveMgr.cpp @@ -16,7 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "InstanceSaveMgr.h" #include "Common.h" #include "Database/SQLStorage.h" diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index be925db6b..a98131145 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -20,7 +20,6 @@ #include "Database/DatabaseEnv.h" #include "WorldPacket.h" #include "WorldSession.h" -#include "World.h" #include "ObjectMgr.h" #include "Player.h" #include "Item.h" diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 8359bd2b9..6750f023b 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -23,7 +23,6 @@ #include "Creature.h" #include "GameObject.h" #include "DynamicObject.h" -#include "Corpse.h" #include "WorldSession.h" #include "WorldPacket.h" #include "Item.h" diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 217a153da..f6547288c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -21,7 +21,6 @@ #include "Database/DatabaseEnv.h" #include "Log.h" #include "Opcodes.h" -#include "ObjectMgr.h" #include "SpellMgr.h" #include "World.h" #include "WorldPacket.h" diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index b9151f3b9..aba08adce 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -17,7 +17,6 @@ */ #include "Common.h" -#include "SharedDefines.h" #include "Database/DatabaseEnv.h" #include "WorldPacket.h" #include "WorldSession.h" @@ -30,7 +29,6 @@ #include "Player.h" #include "SkillExtraItems.h" #include "Unit.h" -#include "CreatureAI.h" #include "Spell.h" #include "DynamicObject.h" #include "SpellAuras.h" diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 73f622d6d..ab27d928d 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -20,12 +20,11 @@ \ingroup u2w */ -#include "WorldSocket.h" +#include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it #include "Common.h" #include "Database/DatabaseEnv.h" #include "Log.h" #include "Opcodes.h" -#include "WorldSocket.h" #include "WorldPacket.h" #include "WorldSession.h" #include "Player.h" From d0696f3a5a1b18cc1d6a2b3c106f8d7aab923957 Mon Sep 17 00:00:00 2001 From: balrok Date: Sat, 7 Mar 2009 00:29:40 +0100 Subject: [PATCH 18/60] removed unneeded creature.h includes found those with: #can't cover everything ack -c Creature | ack ":1$" | sed 's/:1//' | xargs /usr/bin/ack-grep "include \"Creature.h\"" this also doesn't work 100% (had to change one by hand later) --- src/game/BattleGroundAV.cpp | 1 - src/game/BattleGroundBE.cpp | 1 - src/game/BattleGroundNA.cpp | 1 - src/game/BattleGroundRL.cpp | 1 - src/game/DestinationHolderImp.h | 1 - src/game/IdleMovementGenerator.cpp | 2 +- 6 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp index e10020afc..e622ccd86 100644 --- a/src/game/BattleGroundAV.cpp +++ b/src/game/BattleGroundAV.cpp @@ -20,7 +20,6 @@ #include "Player.h" #include "BattleGround.h" #include "BattleGroundAV.h" -#include "Creature.h" #include "MapManager.h" #include "Language.h" diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index ea21320af..6f36fd4b7 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -20,7 +20,6 @@ #include "Player.h" #include "BattleGround.h" #include "BattleGroundBE.h" -#include "Creature.h" #include "ObjectMgr.h" #include "MapManager.h" #include "WorldPacket.h" diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp index 8a4ba7f07..f9b79f2d4 100644 --- a/src/game/BattleGroundNA.cpp +++ b/src/game/BattleGroundNA.cpp @@ -20,7 +20,6 @@ #include "Player.h" #include "BattleGround.h" #include "BattleGroundNA.h" -#include "Creature.h" #include "ObjectMgr.h" #include "MapManager.h" #include "WorldPacket.h" diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index 6794b8263..8f5a5e9b9 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -20,7 +20,6 @@ #include "Player.h" #include "BattleGround.h" #include "BattleGroundRL.h" -#include "Creature.h" #include "ObjectMgr.h" #include "MapManager.h" #include "Language.h" diff --git a/src/game/DestinationHolderImp.h b/src/game/DestinationHolderImp.h index d91eb8bcd..0db69fdde 100644 --- a/src/game/DestinationHolderImp.h +++ b/src/game/DestinationHolderImp.h @@ -19,7 +19,6 @@ #ifndef MANGOS_DESTINATIONHOLDERIMP_H #define MANGOS_DESTINATIONHOLDERIMP_H -#include "Creature.h" #include "MapManager.h" #include "DestinationHolder.h" diff --git a/src/game/IdleMovementGenerator.cpp b/src/game/IdleMovementGenerator.cpp index 370099ebd..085ab46e7 100644 --- a/src/game/IdleMovementGenerator.cpp +++ b/src/game/IdleMovementGenerator.cpp @@ -17,7 +17,7 @@ */ #include "IdleMovementGenerator.h" -#include "Creature.h" +#include "Unit.h" IdleMovementGenerator si_idleMovement; From c947823b66a5297cc915b4f383b19786b12a1658 Mon Sep 17 00:00:00 2001 From: balrok Date: Sat, 7 Mar 2009 00:40:01 +0100 Subject: [PATCH 19/60] removed unneeded Player.h includes with: ack -c Player | ack ":1$" | sed 's/:1//' | xargs /usr/bin/ack-grep "include \"Player.h\"" --- src/game/AggressorAI.cpp | 1 - src/game/TotemAI.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp index 52f7dbf49..c792d0261 100644 --- a/src/game/AggressorAI.cpp +++ b/src/game/AggressorAI.cpp @@ -19,7 +19,6 @@ #include "AggressorAI.h" #include "Errors.h" #include "Creature.h" -#include "Player.h" #include "ObjectAccessor.h" #include "VMapFactory.h" #include "World.h" diff --git a/src/game/TotemAI.cpp b/src/game/TotemAI.cpp index e79804313..b1a0ba475 100644 --- a/src/game/TotemAI.cpp +++ b/src/game/TotemAI.cpp @@ -19,7 +19,6 @@ #include "TotemAI.h" #include "Totem.h" #include "Creature.h" -#include "Player.h" #include "Database/DBCStores.h" #include "MapManager.h" #include "ObjectAccessor.h" From 54f2dbefa08281480986a1031634cc75f2cef0c9 Mon Sep 17 00:00:00 2001 From: balrok Date: Sat, 7 Mar 2009 01:03:18 +0100 Subject: [PATCH 20/60] [7403] much more unneeded includes removed now i extended my script: NAME="Chat"; ack -c $NAME | ack ":1$" | sed 's/:1//' | xargs /usr/bin/ack-grep -l "include \""$NAME".h\"" | xargs /bin/sed -i '/include "'$NAME'.h"/d' Signed-off-by: VladimirMangos --- src/game/ArenaTeamHandler.cpp | 1 - src/game/Bag.cpp | 2 -- src/game/BattleGround.cpp | 3 ++- src/game/BattleGroundAB.cpp | 1 - src/game/BattleGroundAV.cpp | 1 - src/game/BattleGroundBE.cpp | 1 - src/game/BattleGroundEY.cpp | 1 - src/game/BattleGroundHandler.cpp | 1 - src/game/BattleGroundNA.cpp | 1 - src/game/BattleGroundRL.cpp | 1 - src/game/BattleGroundWS.cpp | 1 - src/game/Channel.h | 1 - src/game/CharacterHandler.cpp | 1 - src/game/Chat.cpp | 1 - src/game/ChatHandler.cpp | 1 - src/game/Corpse.cpp | 3 --- src/game/Creature.cpp | 4 +--- src/game/CreatureAIRegistry.cpp | 1 - src/game/DuelHandler.cpp | 1 - src/game/DynamicObject.cpp | 5 ----- src/game/FleeingMovementGenerator.h | 1 - src/game/GameObject.cpp | 2 -- src/game/GridNotifiers.cpp | 1 - src/game/GridStates.cpp | 1 - src/game/GroupHandler.cpp | 2 -- src/game/Guild.cpp | 1 - src/game/GuildHandler.cpp | 1 - src/game/HomeMovementGenerator.cpp | 2 -- src/game/InstanceSaveMgr.cpp | 2 -- src/game/Level0.cpp | 3 --- src/game/Level2.cpp | 2 -- src/game/Level3.cpp | 1 - src/game/Map.cpp | 1 - src/game/MiscHandler.cpp | 2 -- src/game/NPCHandler.cpp | 2 -- src/game/Object.cpp | 1 - src/game/ObjectAccessor.cpp | 1 - src/game/ObjectGridLoader.cpp | 1 - src/game/ObjectMgr.cpp | 2 -- src/game/Pet.cpp | 2 -- src/game/PetHandler.cpp | 2 -- src/game/PetitionsHandler.cpp | 1 - src/game/Player.cpp | 1 - src/game/PointMovementGenerator.cpp | 1 - src/game/PoolHandler.cpp | 1 - src/game/QueryHandler.cpp | 1 - src/game/SkillDiscovery.cpp | 1 - src/game/SkillHandler.cpp | 1 - src/game/SocialMgr.cpp | 1 - src/game/Spell.cpp | 1 - src/game/SpellAuras.cpp | 2 -- src/game/SpellEffects.cpp | 1 - src/game/SpellHandler.cpp | 3 --- src/game/TargetedMovementGenerator.cpp | 1 - src/game/TemporarySummon.cpp | 2 -- src/game/ThreatManager.cpp | 1 - src/game/Totem.cpp | 1 - src/game/TotemAI.cpp | 1 - src/game/Traveller.h | 1 - src/game/Vehicle.cpp | 5 ----- src/game/Weather.cpp | 1 - src/game/WorldSession.cpp | 3 --- src/game/debugcmds.cpp | 3 --- src/shared/revision_nr.h | 2 +- 64 files changed, 4 insertions(+), 97 deletions(-) diff --git a/src/game/ArenaTeamHandler.cpp b/src/game/ArenaTeamHandler.cpp index f2a71f8c1..c31f39514 100644 --- a/src/game/ArenaTeamHandler.cpp +++ b/src/game/ArenaTeamHandler.cpp @@ -25,7 +25,6 @@ #include "ArenaTeam.h" #include "World.h" #include "SocialMgr.h" -#include "Language.h" void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data) { diff --git a/src/game/Bag.cpp b/src/game/Bag.cpp index 2f967752e..eae355166 100644 --- a/src/game/Bag.cpp +++ b/src/game/Bag.cpp @@ -21,9 +21,7 @@ #include "ObjectMgr.h" #include "Database/DatabaseEnv.h" #include "Log.h" -#include "WorldPacket.h" #include "UpdateData.h" -#include "WorldSession.h" Bag::Bag( ): Item() { diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 7dd0dcc67..441cd1bff 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -26,6 +26,7 @@ #include "Chat.h" #include "SpellAuras.h" #include "ArenaTeam.h" +#include "World.h" #include "Group.h" #include "ObjectMgr.h" #include "WorldPacket.h" @@ -1639,4 +1640,4 @@ void BattleGround::SetBgRaid( uint32 TeamID, Group *bg_raid ) WorldSafeLocsEntry const* BattleGround::GetClosestGraveYard( Player* player ) { return objmgr.GetClosestGraveYard( player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), player->GetTeam() ); -} \ No newline at end of file +} diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index e45909788..fe9efde5c 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -23,7 +23,6 @@ #include "Creature.h" #include "Chat.h" #include "ObjectMgr.h" -#include "MapManager.h" #include "Language.h" #include "Util.h" #include "WorldPacket.h" diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp index e622ccd86..af5bd2360 100644 --- a/src/game/BattleGroundAV.cpp +++ b/src/game/BattleGroundAV.cpp @@ -20,7 +20,6 @@ #include "Player.h" #include "BattleGround.h" #include "BattleGroundAV.h" -#include "MapManager.h" #include "Language.h" BattleGroundAV::BattleGroundAV() diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index 6f36fd4b7..d2764c13f 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -21,7 +21,6 @@ #include "BattleGround.h" #include "BattleGroundBE.h" #include "ObjectMgr.h" -#include "MapManager.h" #include "WorldPacket.h" #include "Language.h" diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 9d425fbc1..6428dd428 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -23,7 +23,6 @@ #include "Creature.h" #include "Chat.h" #include "ObjectMgr.h" -#include "MapManager.h" #include "Language.h" #include "WorldPacket.h" #include "Util.h" diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 8cb821cca..5990c4309 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -23,7 +23,6 @@ #include "Player.h" #include "ObjectMgr.h" #include "WorldSession.h" -#include "MapManager.h" #include "ObjectAccessor.h" #include "Object.h" #include "Chat.h" diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp index f9b79f2d4..0207cea84 100644 --- a/src/game/BattleGroundNA.cpp +++ b/src/game/BattleGroundNA.cpp @@ -21,7 +21,6 @@ #include "BattleGround.h" #include "BattleGroundNA.h" #include "ObjectMgr.h" -#include "MapManager.h" #include "WorldPacket.h" #include "Language.h" diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index 8f5a5e9b9..a75ce9a62 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -21,7 +21,6 @@ #include "BattleGround.h" #include "BattleGroundRL.h" #include "ObjectMgr.h" -#include "MapManager.h" #include "Language.h" #include "WorldPacket.h" diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index f6e1b8b95..0e8f4057d 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -23,7 +23,6 @@ #include "Creature.h" #include "GameObject.h" #include "Chat.h" -#include "MapManager.h" #include "ObjectMgr.h" #include "WorldPacket.h" #include "Language.h" diff --git a/src/game/Channel.h b/src/game/Channel.h index 9839a8312..6e2fab2a5 100644 --- a/src/game/Channel.h +++ b/src/game/Channel.h @@ -21,7 +21,6 @@ #include "Common.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "Opcodes.h" #include "Player.h" diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 423866c94..682100d40 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -29,7 +29,6 @@ #include "Guild.h" #include "UpdateMask.h" #include "Auth/md5.h" -#include "MapManager.h" #include "ObjectAccessor.h" #include "Group.h" #include "Database/DatabaseImpl.h" diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index b943865c0..e2eba78ba 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -28,7 +28,6 @@ #include "Player.h" #include "UpdateMask.h" #include "Chat.h" -#include "MapManager.h" #include "GridNotifiersImpl.h" #include "CellImpl.h" #include "AccountMgr.h" diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp index 0edfd30c8..1bde9d37d 100644 --- a/src/game/ChatHandler.cpp +++ b/src/game/ChatHandler.cpp @@ -28,7 +28,6 @@ #include "ChannelMgr.h" #include "Group.h" #include "Guild.h" -#include "MapManager.h" #include "ObjectAccessor.h" #include "ScriptCalls.h" #include "Player.h" diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp index 3fe362a8e..5dc0be3e6 100644 --- a/src/game/Corpse.cpp +++ b/src/game/Corpse.cpp @@ -20,12 +20,9 @@ #include "Corpse.h" #include "Player.h" #include "UpdateMask.h" -#include "MapManager.h" #include "ObjectAccessor.h" #include "Database/DatabaseEnv.h" #include "Opcodes.h" -#include "WorldSession.h" -#include "WorldPacket.h" #include "GossipDef.h" #include "World.h" diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index bfdd2d58a..785d99858 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -19,7 +19,6 @@ #include "Common.h" #include "Database/DatabaseEnv.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "World.h" #include "ObjectMgr.h" #include "SpellMgr.h" @@ -35,7 +34,6 @@ #include "CreatureAI.h" #include "CreatureAISelector.h" #include "Formulas.h" -#include "SpellAuras.h" #include "WaypointMovementGenerator.h" #include "InstanceData.h" #include "BattleGroundMgr.h" @@ -2117,4 +2115,4 @@ void Creature::SetActiveObjectState( bool on ) if(world) map->Add(this); -} \ No newline at end of file +} diff --git a/src/game/CreatureAIRegistry.cpp b/src/game/CreatureAIRegistry.cpp index fa14bbe43..83fd1cbe4 100644 --- a/src/game/CreatureAIRegistry.cpp +++ b/src/game/CreatureAIRegistry.cpp @@ -25,7 +25,6 @@ #include "RandomMovementGenerator.h" #include "CreatureAIImpl.h" #include "MovementGeneratorImpl.h" -#include "MapManager.h" #include "CreatureAIRegistry.h" #include "WaypointMovementGenerator.h" diff --git a/src/game/DuelHandler.cpp b/src/game/DuelHandler.cpp index d98b444cc..e9e1fa0b6 100644 --- a/src/game/DuelHandler.cpp +++ b/src/game/DuelHandler.cpp @@ -22,7 +22,6 @@ #include "Log.h" #include "Opcodes.h" #include "UpdateData.h" -#include "MapManager.h" #include "Player.h" void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket) diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp index 5b11ce800..e41f41668 100644 --- a/src/game/DynamicObject.cpp +++ b/src/game/DynamicObject.cpp @@ -17,16 +17,11 @@ */ #include "Common.h" -#include "GameObject.h" #include "UpdateMask.h" #include "Opcodes.h" -#include "WorldPacket.h" -#include "WorldSession.h" #include "World.h" #include "ObjectAccessor.h" #include "Database/DatabaseEnv.h" -#include "SpellAuras.h" -#include "MapManager.h" #include "GridNotifiers.h" #include "CellImpl.h" #include "GridNotifiersImpl.h" diff --git a/src/game/FleeingMovementGenerator.h b/src/game/FleeingMovementGenerator.h index ec3d3f91a..045f02498 100644 --- a/src/game/FleeingMovementGenerator.h +++ b/src/game/FleeingMovementGenerator.h @@ -22,7 +22,6 @@ #include "MovementGenerator.h" #include "DestinationHolder.h" #include "Traveller.h" -#include "MapManager.h" template class MANGOS_DLL_SPEC FleeingMovementGenerator diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 6a5fb5687..29ed63eaa 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -26,10 +26,8 @@ #include "UpdateMask.h" #include "Opcodes.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "World.h" #include "Database/DatabaseEnv.h" -#include "MapManager.h" #include "LootMgr.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp index 8f49150d3..b1acc2b61 100644 --- a/src/game/GridNotifiers.cpp +++ b/src/game/GridNotifiers.cpp @@ -22,7 +22,6 @@ #include "UpdateData.h" #include "Item.h" #include "Map.h" -#include "MapManager.h" #include "Transports.h" #include "ObjectAccessor.h" diff --git a/src/game/GridStates.cpp b/src/game/GridStates.cpp index 4743860f5..289be47a1 100644 --- a/src/game/GridStates.cpp +++ b/src/game/GridStates.cpp @@ -18,7 +18,6 @@ #include "GridStates.h" #include "GridNotifiers.h" -#include "ObjectAccessor.h" #include "GameSystem/Grid.h" #include "Log.h" diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index 16da66253..44fa9c290 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -26,8 +26,6 @@ #include "ObjectMgr.h" #include "Player.h" #include "Group.h" -#include "ObjectAccessor.h" -#include "MapManager.h" #include "SocialMgr.h" #include "Util.h" diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index 4ff5471e0..239782f9e 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -19,7 +19,6 @@ #include "Database/DatabaseEnv.h" #include "WorldPacket.h" #include "WorldSession.h" -#include "MapManager.h" #include "Player.h" #include "Opcodes.h" #include "ObjectMgr.h" diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index 7a2e17cca..7b77ddf44 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -24,7 +24,6 @@ #include "Log.h" #include "Opcodes.h" #include "Guild.h" -#include "MapManager.h" #include "GossipDef.h" #include "SocialMgr.h" diff --git a/src/game/HomeMovementGenerator.cpp b/src/game/HomeMovementGenerator.cpp index 2c9ae048f..a0c090989 100644 --- a/src/game/HomeMovementGenerator.cpp +++ b/src/game/HomeMovementGenerator.cpp @@ -20,8 +20,6 @@ #include "Creature.h" #include "CreatureAI.h" #include "Traveller.h" -#include "MapManager.h" -#include "ObjectAccessor.h" #include "DestinationHolderImp.h" #include "ObjectMgr.h" #include "WorldPacket.h" diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp index cc7b0b116..200068aa1 100644 --- a/src/game/InstanceSaveMgr.cpp +++ b/src/game/InstanceSaveMgr.cpp @@ -21,7 +21,6 @@ #include "Player.h" #include "GridNotifiers.h" -#include "WorldSession.h" #include "Log.h" #include "GridStates.h" #include "CellImpl.h" @@ -33,7 +32,6 @@ #include "GridNotifiersImpl.h" #include "Config/ConfigEnv.h" #include "Transports.h" -#include "ObjectAccessor.h" #include "ObjectMgr.h" #include "World.h" #include "Group.h" diff --git a/src/game/Level0.cpp b/src/game/Level0.cpp index 15e0747e7..8cea1ee30 100644 --- a/src/game/Level0.cpp +++ b/src/game/Level0.cpp @@ -18,13 +18,10 @@ #include "Common.h" #include "Database/DatabaseEnv.h" -#include "WorldPacket.h" -#include "WorldSession.h" #include "World.h" #include "Player.h" #include "Opcodes.h" #include "Chat.h" -#include "MapManager.h" #include "ObjectAccessor.h" #include "Language.h" #include "AccountMgr.h" diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index a98131145..4d8bc4fae 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -18,8 +18,6 @@ #include "Common.h" #include "Database/DatabaseEnv.h" -#include "WorldPacket.h" -#include "WorldSession.h" #include "ObjectMgr.h" #include "Player.h" #include "Item.h" diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index ec2bd95d5..d1d0c28b0 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -33,7 +33,6 @@ #include "Guild.h" #include "ObjectAccessor.h" #include "MapManager.h" -#include "SpellAuras.h" #include "ScriptCalls.h" #include "Language.h" #include "GridNotifiersImpl.h" diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 0796e3a4f..e86a687da 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -19,7 +19,6 @@ #include "MapManager.h" #include "Player.h" #include "GridNotifiers.h" -#include "WorldSession.h" #include "Log.h" #include "GridStates.h" #include "CellImpl.h" diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index d52d80c10..6b7582cbc 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -34,11 +34,9 @@ #include "Chat.h" #include "ScriptCalls.h" #include -#include "MapManager.h" #include "ObjectAccessor.h" #include "Object.h" #include "BattleGround.h" -#include "SpellAuras.h" #include "Pet.h" #include "SocialMgr.h" diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 12f7bfb93..78308b08c 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -27,12 +27,10 @@ #include "SpellMgr.h" #include "Player.h" #include "GossipDef.h" -#include "SpellAuras.h" #include "UpdateMask.h" #include "ScriptCalls.h" #include "ObjectAccessor.h" #include "Creature.h" -#include "MapManager.h" #include "Pet.h" #include "BattleGroundMgr.h" #include "BattleGround.h" diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 29039ecfc..c6081d5c5 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -26,7 +26,6 @@ #include "Creature.h" #include "Player.h" #include "ObjectMgr.h" -#include "WorldSession.h" #include "UpdateData.h" #include "UpdateMask.h" #include "Util.h" diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 6750f023b..6103d4703 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -23,7 +23,6 @@ #include "Creature.h" #include "GameObject.h" #include "DynamicObject.h" -#include "WorldSession.h" #include "WorldPacket.h" #include "Item.h" #include "Corpse.h" diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp index 04a343d36..de73ee183 100644 --- a/src/game/ObjectGridLoader.cpp +++ b/src/game/ObjectGridLoader.cpp @@ -19,7 +19,6 @@ #include "ObjectGridLoader.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" -#include "MapManager.h" #include "Creature.h" #include "GameObject.h" #include "DynamicObject.h" diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 282da0002..d5d858e2a 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -28,7 +28,6 @@ #include "SpellMgr.h" #include "UpdateMask.h" #include "World.h" -#include "WorldSession.h" #include "Group.h" #include "Guild.h" #include "ArenaTeam.h" @@ -43,7 +42,6 @@ #include "SpellAuras.h" #include "Util.h" #include "WaypointManager.h" -#include "BattleGround.h" INSTANTIATE_SINGLETON_1(ObjectMgr); diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 7cf205f67..7ae39ebb3 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -19,12 +19,10 @@ #include "Common.h" #include "Database/DatabaseEnv.h" #include "Log.h" -#include "WorldSession.h" #include "WorldPacket.h" #include "ObjectMgr.h" #include "SpellMgr.h" #include "Pet.h" -#include "MapManager.h" #include "Formulas.h" #include "SpellAuras.h" #include "CreatureAI.h" diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index 37697ec7c..626bee716 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -25,11 +25,9 @@ #include "Opcodes.h" #include "Spell.h" #include "ObjectAccessor.h" -#include "MapManager.h" #include "CreatureAI.h" #include "Util.h" #include "Pet.h" -#include "Language.h" void WorldSession::HandlePetAction( WorldPacket & recv_data ) { diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index 181c0556a..a4a6594c8 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -26,7 +26,6 @@ #include "Opcodes.h" #include "Guild.h" #include "ArenaTeam.h" -#include "MapManager.h" #include "GossipDef.h" #include "SocialMgr.h" diff --git a/src/game/Player.cpp b/src/game/Player.cpp index f6547288c..7fd006d38 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -46,7 +46,6 @@ #include "Group.h" #include "Guild.h" #include "Pet.h" -#include "SpellAuras.h" #include "Util.h" #include "Transports.h" #include "Weather.h" diff --git a/src/game/PointMovementGenerator.cpp b/src/game/PointMovementGenerator.cpp index 5da26c9bf..fda73463c 100644 --- a/src/game/PointMovementGenerator.cpp +++ b/src/game/PointMovementGenerator.cpp @@ -20,7 +20,6 @@ #include "Errors.h" #include "Creature.h" #include "CreatureAI.h" -#include "MapManager.h" #include "DestinationHolderImp.h" //----- Point Movement Generator diff --git a/src/game/PoolHandler.cpp b/src/game/PoolHandler.cpp index 4d040146f..bd47c7b6a 100644 --- a/src/game/PoolHandler.cpp +++ b/src/game/PoolHandler.cpp @@ -19,7 +19,6 @@ #include "PoolHandler.h" #include "ObjectMgr.h" #include "ProgressBar.h" -#include "Language.h" #include "Log.h" #include "MapManager.h" #include "Policies/SingletonImp.h" diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp index 42ca28e25..b58a63159 100644 --- a/src/game/QueryHandler.cpp +++ b/src/game/QueryHandler.cpp @@ -29,7 +29,6 @@ #include "Player.h" #include "UpdateMask.h" #include "NPCHandler.h" -#include "ObjectAccessor.h" #include "Pet.h" #include "MapManager.h" diff --git a/src/game/SkillDiscovery.cpp b/src/game/SkillDiscovery.cpp index 9e2ba8f6f..242487a38 100644 --- a/src/game/SkillDiscovery.cpp +++ b/src/game/SkillDiscovery.cpp @@ -20,7 +20,6 @@ #include "Log.h" #include "ProgressBar.h" #include "Policies/SingletonImp.h" -#include "ObjectAccessor.h" #include "World.h" #include "Util.h" #include "SkillDiscovery.h" diff --git a/src/game/SkillHandler.cpp b/src/game/SkillHandler.cpp index 8e20d50df..dac37e6b0 100644 --- a/src/game/SkillHandler.cpp +++ b/src/game/SkillHandler.cpp @@ -25,7 +25,6 @@ #include "WorldSession.h" #include "ObjectAccessor.h" #include "UpdateMask.h" -#include "SpellAuras.h" void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data ) { diff --git a/src/game/SocialMgr.cpp b/src/game/SocialMgr.cpp index 82cdf2e64..928411192 100644 --- a/src/game/SocialMgr.cpp +++ b/src/game/SocialMgr.cpp @@ -21,7 +21,6 @@ #include "Database/DatabaseEnv.h" #include "Opcodes.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "Player.h" #include "ObjectMgr.h" #include "World.h" diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index ab28d2cc5..25372e51e 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -33,7 +33,6 @@ #include "Unit.h" #include "Spell.h" #include "DynamicObject.h" -#include "SpellAuras.h" #include "Group.h" #include "UpdateData.h" #include "MapManager.h" diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 9da84e653..d266abf4f 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -29,11 +29,9 @@ #include "Player.h" #include "Unit.h" #include "Spell.h" -#include "SpellAuras.h" #include "DynamicObject.h" #include "Group.h" #include "UpdateData.h" -#include "MapManager.h" #include "ObjectAccessor.h" #include "Policies/SingletonImp.h" #include "Totem.h" diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index aba08adce..cbbf73a05 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -19,7 +19,6 @@ #include "Common.h" #include "Database/DatabaseEnv.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "Opcodes.h" #include "Log.h" #include "UpdateMask.h" diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 26d328e82..89ce47123 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -25,9 +25,6 @@ #include "Log.h" #include "Opcodes.h" #include "Spell.h" -#include "SpellAuras.h" -#include "BattleGround.h" -#include "MapManager.h" #include "ScriptCalls.h" #include "Totem.h" diff --git a/src/game/TargetedMovementGenerator.cpp b/src/game/TargetedMovementGenerator.cpp index e0a25477f..6f4aa4c73 100644 --- a/src/game/TargetedMovementGenerator.cpp +++ b/src/game/TargetedMovementGenerator.cpp @@ -20,7 +20,6 @@ #include "TargetedMovementGenerator.h" #include "Errors.h" #include "Creature.h" -#include "MapManager.h" #include "DestinationHolderImp.h" #include "World.h" diff --git a/src/game/TemporarySummon.cpp b/src/game/TemporarySummon.cpp index d24e3ba83..293ac9d5c 100644 --- a/src/game/TemporarySummon.cpp +++ b/src/game/TemporarySummon.cpp @@ -17,8 +17,6 @@ */ #include "TemporarySummon.h" -#include "WorldPacket.h" -#include "MapManager.h" #include "Log.h" #include "ObjectAccessor.h" #include "CreatureAI.h" diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index 7932d46c4..66ab9c2a6 100644 --- a/src/game/ThreatManager.cpp +++ b/src/game/ThreatManager.cpp @@ -21,7 +21,6 @@ #include "Creature.h" #include "CreatureAI.h" #include "Map.h" -#include "MapManager.h" #include "Player.h" #include "ObjectAccessor.h" #include "UnitEvents.h" diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp index c5043a472..8f0fb902f 100644 --- a/src/game/Totem.cpp +++ b/src/game/Totem.cpp @@ -18,7 +18,6 @@ #include "Totem.h" #include "WorldPacket.h" -#include "MapManager.h" #include "Log.h" #include "Group.h" #include "Player.h" diff --git a/src/game/TotemAI.cpp b/src/game/TotemAI.cpp index b1a0ba475..b91020a23 100644 --- a/src/game/TotemAI.cpp +++ b/src/game/TotemAI.cpp @@ -20,7 +20,6 @@ #include "Totem.h" #include "Creature.h" #include "Database/DBCStores.h" -#include "MapManager.h" #include "ObjectAccessor.h" #include "SpellMgr.h" diff --git a/src/game/Traveller.h b/src/game/Traveller.h index 6aa55eb14..c0531631c 100644 --- a/src/game/Traveller.h +++ b/src/game/Traveller.h @@ -19,7 +19,6 @@ #ifndef MANGOS_TRAVELLER_H #define MANGOS_TRAVELLER_H -#include "MapManager.h" #include "Creature.h" #include "Player.h" #include diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp index b533609d7..cd24472d7 100644 --- a/src/game/Vehicle.cpp +++ b/src/game/Vehicle.cpp @@ -18,13 +18,8 @@ #include "Common.h" #include "Log.h" -#include "WorldSession.h" -#include "WorldPacket.h" #include "ObjectMgr.h" -#include "SpellMgr.h" #include "Vehicle.h" -#include "MapManager.h" -#include "SpellAuras.h" #include "Unit.h" #include "Util.h" diff --git a/src/game/Weather.cpp b/src/game/Weather.cpp index be1aec79c..5065761fd 100644 --- a/src/game/Weather.cpp +++ b/src/game/Weather.cpp @@ -22,7 +22,6 @@ #include "Weather.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "Player.h" #include "World.h" #include "Log.h" diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index ab27d928d..e0f2b29e9 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -32,11 +32,8 @@ #include "Group.h" #include "Guild.h" #include "World.h" -#include "MapManager.h" #include "ObjectAccessor.h" #include "BattleGroundMgr.h" -#include "Language.h" // for CMSG_CANCEL_MOUNT_AURA handler -#include "Chat.h" #include "SocialMgr.h" /// WorldSession constructor diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index a2271783d..9a789c438 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -19,16 +19,13 @@ #include "Common.h" #include "Database/DatabaseEnv.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "Player.h" #include "Opcodes.h" #include "Chat.h" #include "Log.h" #include "Unit.h" -#include "ObjectAccessor.h" #include "GossipDef.h" #include "Language.h" -#include "MapManager.h" #include "BattleGroundMgr.h" #include #include "ObjectMgr.h" diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 407f659f9..87863ccbe 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7402" + #define REVISION_NR "7403" #endif // __REVISION_NR_H__ From 8a9942619b32d6798b3d39bbcf4ecfda5bd039e5 Mon Sep 17 00:00:00 2001 From: Triply Date: Sun, 8 Mar 2009 01:47:04 +0100 Subject: [PATCH 21/60] [7404] Fixed cheating in rated arena matches by alt+f4. Signed-off-by: Triply --- src/game/BattleGround.cpp | 39 +++++++++++++++++++++++++------------ src/game/BattleGround.h | 6 ++++-- src/game/BattleGroundBE.cpp | 16 ++------------- src/game/BattleGroundNA.cpp | 16 ++------------- src/game/BattleGroundRL.cpp | 16 ++------------- src/game/WorldSession.cpp | 2 +- src/shared/revision_nr.h | 2 +- 7 files changed, 39 insertions(+), 58 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 441cd1bff..1231d26cb 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -163,7 +163,7 @@ void BattleGround::Update(uint32 diff) m_RemovedPlayers.clear(); } - // remove offline players from bg after ~5 minutes + // remove offline players from bg after 5 minutes if(GetPlayersSize()) { for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) @@ -172,19 +172,18 @@ void BattleGround::Update(uint32 diff) itr->second.LastOnlineTime += diff; if(plr) - itr->second.LastOnlineTime = 0; // update last online time + itr->second.LastOnlineTime = 0; // update last online time else - if(itr->second.LastOnlineTime >= MAX_OFFLINE_TIME) // 5 minutes - m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) + if(itr->second.LastOnlineTime >= MAX_OFFLINE_TIME) + m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) } } - //TODO: move this system to spell system and ressurect players correclt there! /*********************************************************/ /*** BATTLEGROUND RESSURECTION SYSTEM ***/ /*********************************************************/ - //this should be handled by spell system: + //this should be handled by spell system m_LastResurrectTime += diff; if (m_LastResurrectTime >= RESURRECTION_INTERVAL) { @@ -323,16 +322,13 @@ void BattleGround::Update(uint32 diff) //remove preparation if( isArena() ) { - //TODO : add arena sound (PlaySoundToAll(SOUND_ARENA_START); + //TODO : add arena sound PlaySoundToAll(SOUND_ARENA_START); for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) if(Player *plr = objmgr.GetPlayer(itr->first)) plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); - if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) - EndBattleGround(HORDE); - else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) - EndBattleGround(ALLIANCE); + CheckArenaWinConditions(); } else { @@ -342,7 +338,7 @@ void BattleGround::Update(uint32 diff) for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) if(Player* plr = objmgr.GetPlayer(itr->first)) plr->RemoveAurasDueToSpell(SPELL_PREPARATION); - //Announce BG starting: + //Announce BG starting if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) { sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel()); @@ -1102,6 +1098,17 @@ void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player *plr, uint64 plr_guid, } } +// This method should be called when player logs out from running battleground +void BattleGround::EventPlayerLoggedOut(Player* player) +{ + if( GetStatus() == STATUS_IN_PROGRESS ) + { + if( isBattleGround() ) + EventPlayerDroppedFlag(player); + else + CheckArenaWinConditions(); + } +} /* This method should be called only once ... it adds pointer to queue */ void BattleGround::AddToBGFreeSlotQueue() @@ -1629,6 +1636,14 @@ uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const return count; } +void BattleGround::CheckArenaWinConditions() +{ + if( !GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE) ) + EndBattleGround(HORDE); + else if( GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE) ) + EndBattleGround(ALLIANCE); +} + void BattleGround::SetBgRaid( uint32 TeamID, Group *bg_raid ) { Group* &old_raid = TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 08a703c42..a1667c3cc 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -435,9 +435,10 @@ class BattleGround // used for rated arena battles void SetArenaTeamIdForTeam(uint32 Team, uint32 ArenaTeamId) { m_ArenaTeamIds[GetTeamIndexByTeamId(Team)] = ArenaTeamId; } - uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; } + uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; } void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange) { m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)] = RatingChange; } - int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; } + int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; } + void CheckArenaWinConditions(); /* Triggers handle */ // must be implemented in BG subclass @@ -449,6 +450,7 @@ class BattleGround virtual void EventPlayerDroppedFlag(Player* /*player*/) {} virtual void EventPlayerClickedOnFlag(Player* /*player*/, GameObject* /*target_obj*/) {} virtual void EventPlayerCapturedFlag(Player* /*player*/) {} + void EventPlayerLoggedOut(Player* player); /* Death related */ virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index d2764c13f..2b99d9463 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -92,10 +92,7 @@ void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) - EndBattleGround(HORDE); - else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) - EndBattleGround(ALLIANCE); + CheckArenaWinConditions(); } void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer) @@ -114,16 +111,7 @@ void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer) UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE)) - { - // all opponents killed - EndBattleGround(HORDE); - } - else if(!GetAlivePlayersCountByTeam(HORDE)) - { - // all opponents killed - EndBattleGround(ALLIANCE); - } + CheckArenaWinConditions(); } bool BattleGroundBE::HandlePlayerUnderMap(Player *player) diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp index 0207cea84..070a33f25 100644 --- a/src/game/BattleGroundNA.cpp +++ b/src/game/BattleGroundNA.cpp @@ -89,10 +89,7 @@ void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) - EndBattleGround(HORDE); - else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) - EndBattleGround(ALLIANCE); + CheckArenaWinConditions(); } void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer) @@ -111,16 +108,7 @@ void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer) UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE)) - { - // all opponents killed - EndBattleGround(HORDE); - } - else if(!GetAlivePlayersCountByTeam(HORDE)) - { - // all opponents killed - EndBattleGround(ALLIANCE); - } + CheckArenaWinConditions(); } bool BattleGroundNA::HandlePlayerUnderMap(Player *player) diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index a75ce9a62..02f3b60ae 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -89,10 +89,7 @@ void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) - EndBattleGround(HORDE); - else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) - EndBattleGround(ALLIANCE); + CheckArenaWinConditions(); } void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer) @@ -111,16 +108,7 @@ void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer) UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE)) - { - // all opponents killed - EndBattleGround(HORDE); - } - else if(!GetAlivePlayersCountByTeam(HORDE)) - { - // all opponents killed - EndBattleGround(ALLIANCE); - } + CheckArenaWinConditions(); } bool BattleGroundRL::HandlePlayerUnderMap(Player *player) diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index e0f2b29e9..2a7c292d0 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -300,7 +300,7 @@ void WorldSession::LogoutPlayer(bool Save) } //drop a flag if player is carrying it if(BattleGround *bg = _player->GetBattleGround()) - bg->EventPlayerDroppedFlag(_player); + bg->EventPlayerLoggedOut(_player); ///- Teleport to home if the player is in an invalid instance if(!_player->m_InstanceValid && !_player->isGameMaster()) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 87863ccbe..8bc76cb6e 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7403" + #define REVISION_NR "7404" #endif // __REVISION_NR_H__ From e2e1a9f7d47750cbb85fcbd964f6faede0ded378 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 8 Mar 2009 03:41:15 +0300 Subject: [PATCH 22/60] [7405] Show loaded 100% for case some player/pet/creature level data skipped as unused. This cases have detail log output, but if detail mode disabled it look like strange not 100% load without reason. --- src/game/ObjectMgr.cpp | 12 ++++++++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index d5d858e2a..df059e4da 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -1764,7 +1764,10 @@ void ObjectMgr::LoadPetLevelInfo() if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum sLog.outErrorDb("Wrong (> %u) level %u in `pet_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else + { sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `pet_levelstats` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } continue; } else if(current_level < 1) @@ -2143,7 +2146,10 @@ void ObjectMgr::LoadPlayerInfo() if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum sLog.outErrorDb("Wrong (> %u) level %u in `player_classlevelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else + { sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_classlevelstats` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } continue; } @@ -2238,7 +2244,10 @@ void ObjectMgr::LoadPlayerInfo() if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum sLog.outErrorDb("Wrong (> %u) level %u in `player_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else + { sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_levelstats` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } continue; } @@ -2346,7 +2355,10 @@ void ObjectMgr::LoadPlayerInfo() if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum sLog.outErrorDb("Wrong (> %u) level %u in `player_xp_for_level` table, ignoring.", STRONG_MAX_LEVEL,current_level); else + { sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_xp_for_levels` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } continue; } //PlayerXPperLevel diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 8bc76cb6e..cda1da10d 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7404" + #define REVISION_NR "7405" #endif // __REVISION_NR_H__ From 27a2d88796706659d3f0902f8238049afa6b2d54 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 8 Mar 2009 05:47:03 +0300 Subject: [PATCH 23/60] [7406] Remove string version of BattleGround::SendMessageToAll. Use only string_id versions always. --- src/game/BattleGround.cpp | 12 ++++-------- src/game/BattleGround.h | 1 - src/game/BattleGroundAB.cpp | 4 ++-- src/game/BattleGroundEY.cpp | 2 +- src/game/BattleGroundWS.cpp | 6 +++--- src/shared/revision_nr.h | 2 +- 6 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 1231d26cb..6ec145b8c 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -1474,13 +1474,6 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float return true; } -void BattleGround::SendMessageToAll(char const* text, uint8 type) -{ - WorldPacket data; - ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, text, NULL); - SendPacketToAll(&data); -} - void BattleGround::SendMessageToAll(int32 entry, uint8 type) { char const* text = GetMangosString(entry); @@ -1498,7 +1491,10 @@ void BattleGround::PSendMessageToAll(int32 entry, uint8 type, ...) va_start(ap, type); vsnprintf(str,2048,format, ap ); va_end(ap); - SendMessageToAll(str, type); + + WorldPacket data; + ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, str, NULL); + SendPacketToAll(&data); } void BattleGround::EndNow() diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index a1667c3cc..88fb1ab26 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -412,7 +412,6 @@ class BattleGround void EndBattleGround(uint32 winner); void BlockMovement(Player *plr); - void SendMessageToAll(char const* text, uint8 type); void SendMessageToAll(int32 entry, uint8 type); void PSendMessageToAll(int32 entry, uint8 type, ... ); diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index fe9efde5c..97a50d55b 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -125,9 +125,9 @@ void BattleGroundAB::Update(uint32 diff) if( !m_IsInformedNearVictory && m_TeamScores[team] > 1800 ) { if( team == BG_TEAM_ALLIANCE ) - SendMessageToAll(GetMangosString(LANG_BG_AB_A_NEAR_VICTORY), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); else - SendMessageToAll(GetMangosString(LANG_BG_AB_H_NEAR_VICTORY), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(SOUND_NEAR_VICTORY); m_IsInformedNearVictory = true; } diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 6428dd428..6543962c7 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -519,7 +519,7 @@ void BattleGroundEY::RespawnFlag(bool send_message) if(send_message) { - SendMessageToAll(GetMangosString(LANG_BG_EY_RESETED_FLAG), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_EY_RESETED_FLAG, CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(BG_EY_SOUND_FLAG_RESET); // flags respawned sound... } diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index 0e8f4057d..482727692 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -145,7 +145,7 @@ void BattleGroundWS::RespawnFlag(uint32 Team, bool captured) //when map_update will be allowed for battlegrounds this code will be useless SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(GetMangosString(LANG_BG_WS_F_PLACED), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_WS_F_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); // flag respawned sound... } } @@ -159,12 +159,12 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team) if(team == ALLIANCE) { SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(GetMangosString(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL); } else { SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(GetMangosString(LANG_BG_WS_HORDE_FLAG_RESPAWNED), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_WS_HORDE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL); } PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index cda1da10d..4081ac0e2 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7405" + #define REVISION_NR "7406" #endif // __REVISION_NR_H__ From 28a8e0c9cfa609a1d52df99c038174bc092edf8b Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 8 Mar 2009 08:09:33 +0300 Subject: [PATCH 24/60] [7407] Implement per-client localization support for battleground broadcast messages. --- src/game/BattleGround.cpp | 70 +++++++++++++++++++++++++++++++-------- src/game/BattleGround.h | 13 ++++++-- src/shared/revision_nr.h | 2 +- 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 6ec145b8c..9dd3a4f3c 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -31,6 +31,52 @@ #include "ObjectMgr.h" #include "WorldPacket.h" #include "Util.h" +#include "GridNotifiersImpl.h" + +namespace MaNGOS +{ + class BattleGroundChatBuilder + { + public: + BattleGroundChatBuilder(ChatMsg msgtype, int32 textId, va_list* args = NULL) + : i_msgtype(msgtype), i_textId(textId), i_args(args) {} + void operator()(WorldPacket& data, int32 loc_idx) + { + char const* text = objmgr.GetMangosString(i_textId,loc_idx); + + if(i_args) + { + // we need copy va_list before use or original va_list will corrupted + va_list ap; + va_copy(ap,*i_args); + + char str [2048]; + vsnprintf(str,2048,text, ap ); + va_end(ap); + + do_helper(data,&str[0]); + } + else + do_helper(data,text); + } + private: + void do_helper(WorldPacket& data, char const* text) + { + data << uint8(i_msgtype); + data << uint32(LANG_UNIVERSAL); + data << uint64(0); // there 0 for BG messages + data << uint32(0); // can be chat msg group or something + data << uint64(0); + data << uint32(strlen(text)+1); + data << text; + data << uint8(0); + } + + ChatMsg i_msgtype; + int32 i_textId; + va_list* i_args; + }; +} // namespace MaNGOS BattleGround::BattleGround() { @@ -1474,27 +1520,23 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float return true; } -void BattleGround::SendMessageToAll(int32 entry, uint8 type) +void BattleGround::SendMessageToAll(int32 entry, ChatMsg type) { - char const* text = GetMangosString(entry); - WorldPacket data; - ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, text, NULL); - SendPacketToAll(&data); + MaNGOS::BattleGroundChatBuilder bg_builder(type, entry); + MaNGOS::LocalizedPacketDo bg_do(bg_builder); + BroadcastWorker(bg_do); } -//copied from void ChatHandler::PSendSysMessage(int32 entry, ...) -void BattleGround::PSendMessageToAll(int32 entry, uint8 type, ...) +void BattleGround::PSendMessageToAll(int32 entry, ChatMsg type, ...) { - const char *format = GetMangosString(entry); va_list ap; - char str [2048]; va_start(ap, type); - vsnprintf(str,2048,format, ap ); - va_end(ap); - WorldPacket data; - ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, str, NULL); - SendPacketToAll(&data); + MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, &ap); + MaNGOS::LocalizedPacketDo bg_do(bg_builder); + BroadcastWorker(bg_do); + + va_end(ap); } void BattleGround::EndNow() diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 88fb1ab26..2cd1b1ba9 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -399,6 +399,15 @@ class BattleGround virtual void FillInitialWorldStates(WorldPacket& /*data*/) {} void SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *sender = NULL, bool self = true); void SendPacketToAll(WorldPacket *packet); + + template + void BroadcastWorker(Do& _do) + { + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + if(Player *plr = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER))) + _do(plr); + } + void PlaySoundToTeam(uint32 SoundID, uint32 TeamID); void PlaySoundToAll(uint32 SoundID); void CastSpellOnTeam(uint32 SpellID, uint32 TeamID); @@ -412,8 +421,8 @@ class BattleGround void EndBattleGround(uint32 winner); void BlockMovement(Player *plr); - void SendMessageToAll(int32 entry, uint8 type); - void PSendMessageToAll(int32 entry, uint8 type, ... ); + void SendMessageToAll(int32 entry, ChatMsg type); + void PSendMessageToAll(int32 entry, ChatMsg type, ... ); /* Raid Group */ Group *GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 4081ac0e2..0bb62a1af 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7406" + #define REVISION_NR "7407" #endif // __REVISION_NR_H__ From cdf99bc169264809539f043f6db5a2b96014d4ae Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 8 Mar 2009 08:51:02 +0300 Subject: [PATCH 25/60] [7408] Fixed last hidden non-localized message case in BattleGround.cpp. Note: 1) CHAT_MSG_BG_SYSTEM_NEUTRAL not dependent from target guid so use SendMessageToAll and cleanup code 2) BattleGround.cpp now not dependent from Chat.h --- src/game/BattleGround.cpp | 23 +++++------------------ src/shared/revision_nr.h | 2 +- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 9dd3a4f3c..f8dce99f6 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -23,7 +23,6 @@ #include "Creature.h" #include "MapManager.h" #include "Language.h" -#include "Chat.h" #include "SpellAuras.h" #include "ArenaTeam.h" #include "World.h" @@ -577,15 +576,11 @@ void BattleGround::EndBattleGround(uint32 winner) uint32 loser_rating = 0; uint32 winner_rating = 0; WorldPacket data; - Player *Source = NULL; - const char *winmsg = ""; + int32 winmsg_id = 0; if(winner == ALLIANCE) { - if(isBattleGround()) - winmsg = GetMangosString(LANG_BG_A_WINS); - else - winmsg = GetMangosString(LANG_ARENA_GOLD_WINS); + winmsg_id = isBattleGround() ? LANG_BG_A_WINS : LANG_ARENA_GOLD_WINS; PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound @@ -593,10 +588,7 @@ void BattleGround::EndBattleGround(uint32 winner) } else if(winner == HORDE) { - if(isBattleGround()) - winmsg = GetMangosString(LANG_BG_H_WINS); - else - winmsg = GetMangosString(LANG_ARENA_GREEN_WINS); + winmsg_id = isBattleGround() ? LANG_BG_H_WINS : LANG_ARENA_GREEN_WINS; PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound @@ -681,8 +673,6 @@ void BattleGround::EndBattleGround(uint32 winner) if(team == winner) { - if(!Source) - Source = plr; RewardMark(plr,ITEM_WINNER_COUNT); UpdatePlayerScore(plr, SCORE_BONUS_HONOR, 20); RewardQuest(plr); @@ -722,11 +712,8 @@ void BattleGround::EndBattleGround(uint32 winner) // inform invited players about the removal sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); - if(Source) - { - ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, Source->GetGUID(), winmsg); - SendPacketToAll(&data); - } + if(winmsg_id) + SendMessageToAll(winmsg_id,CHAT_MSG_BG_SYSTEM_NEUTRAL); } uint32 BattleGround::GetBattlemasterEntry() const diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0bb62a1af..fdaaac390 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7407" + #define REVISION_NR "7408" #endif // __REVISION_NR_H__ From 57e715857b111fbc82c4fe3a5c5f98e9096ed9fd Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 8 Mar 2009 09:47:14 +0300 Subject: [PATCH 26/60] [7409] Support localization for messsages in specialized battagorund code BattleGround*.cpp Note: BattleGroundAB still have problems with team/node localization in result wrong way LANG_ strings used. --- src/game/BattleGround.cpp | 27 ++++++----- src/game/BattleGround.h | 4 +- src/game/BattleGroundAB.cpp | 69 +++++++++++++++++++--------- src/game/BattleGroundEY.cpp | 89 ++++++++++++------------------------- src/shared/revision_nr.h | 2 +- 5 files changed, 93 insertions(+), 98 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index f8dce99f6..a838ad10d 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -37,8 +37,8 @@ namespace MaNGOS class BattleGroundChatBuilder { public: - BattleGroundChatBuilder(ChatMsg msgtype, int32 textId, va_list* args = NULL) - : i_msgtype(msgtype), i_textId(textId), i_args(args) {} + BattleGroundChatBuilder(ChatMsg msgtype, int32 textId, Player const* source, va_list* args = NULL) + : i_msgtype(msgtype), i_textId(textId), i_source(source), i_args(args) {} void operator()(WorldPacket& data, int32 loc_idx) { char const* text = objmgr.GetMangosString(i_textId,loc_idx); @@ -61,18 +61,21 @@ namespace MaNGOS private: void do_helper(WorldPacket& data, char const* text) { + uint64 target_guid = i_source ? i_source ->GetGUID() : 0; + data << uint8(i_msgtype); data << uint32(LANG_UNIVERSAL); - data << uint64(0); // there 0 for BG messages - data << uint32(0); // can be chat msg group or something - data << uint64(0); + data << uint64(target_guid); // there 0 for BG messages + data << uint32(0); // can be chat msg group or something + data << uint64(target_guid); data << uint32(strlen(text)+1); data << text; - data << uint8(0); + data << uint8(i_source ? i_source->chatTag() : uint8(0)); } ChatMsg i_msgtype; int32 i_textId; + Player const* i_source; va_list* i_args; }; } // namespace MaNGOS @@ -303,13 +306,13 @@ void BattleGround::Update(uint32 diff) if( newtime > (MINUTE * IN_MILISECONDS) ) { if( newtime / (MINUTE * IN_MILISECONDS) != m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS) ) - PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING, CHAT_MSG_SYSTEM, (uint32)(m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS))); + PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING, CHAT_MSG_SYSTEM, NULL, (uint32)(m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS))); } else { //announce every 15 seconds if( newtime / (15 * IN_MILISECONDS) != m_PrematureCountDownTimer / (15 * IN_MILISECONDS) ) - PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS, CHAT_MSG_SYSTEM, (uint32)(m_PrematureCountDownTimer / IN_MILISECONDS)); + PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS, CHAT_MSG_SYSTEM, NULL, (uint32)(m_PrematureCountDownTimer / IN_MILISECONDS)); } m_PrematureCountDownTimer = newtime; } @@ -1507,19 +1510,19 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float return true; } -void BattleGround::SendMessageToAll(int32 entry, ChatMsg type) +void BattleGround::SendMessageToAll(int32 entry, ChatMsg type, Player const* source) { - MaNGOS::BattleGroundChatBuilder bg_builder(type, entry); + MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, source); MaNGOS::LocalizedPacketDo bg_do(bg_builder); BroadcastWorker(bg_do); } -void BattleGround::PSendMessageToAll(int32 entry, ChatMsg type, ...) +void BattleGround::PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ...) { va_list ap; va_start(ap, type); - MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, &ap); + MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, source, &ap); MaNGOS::LocalizedPacketDo bg_do(bg_builder); BroadcastWorker(bg_do); diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 2cd1b1ba9..1433c9908 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -421,8 +421,8 @@ class BattleGround void EndBattleGround(uint32 winner); void BlockMovement(Player *plr); - void SendMessageToAll(int32 entry, ChatMsg type); - void PSendMessageToAll(int32 entry, ChatMsg type, ... ); + void SendMessageToAll(int32 entry, ChatMsg type, Player const* source = NULL); + void PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ... ); /* Raid Group */ Group *GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; } diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index 97a50d55b..fc227e6a7 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -21,7 +21,6 @@ #include "BattleGround.h" #include "BattleGroundAB.h" #include "Creature.h" -#include "Chat.h" #include "ObjectMgr.h" #include "Language.h" #include "Util.h" @@ -84,13 +83,21 @@ void BattleGroundAB::Update(uint32 diff) _SendNodeUpdate(node); _NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE); // Message to chatlog - char buf[256]; - uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE; - sprintf(buf, GetMangosString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE), _GetNodeName(node)); - WorldPacket data; - ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, buf, NULL); - SendPacketToAll(&data); - PlaySoundToAll((teamIndex == 0) ? SOUND_NODE_CAPTURED_ALLIANCE : SOUND_NODE_CAPTURED_HORDE); + + if(teamIndex == 0) + { + // FIXME: team and node names not localized + PSendMessageToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE,NULL, + GetMangosString(LANG_BG_AB_ALLY), _GetNodeName(node)); + PlaySoundToAll(SOUND_NODE_CAPTURED_ALLIANCE); + } + else + { + // FIXME: team and node names not localized + PSendMessageToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE,NULL, + GetMangosString(LANG_BG_AB_HORDE),_GetNodeName(node)); + PlaySoundToAll(SOUND_NODE_CAPTURED_HORDE); + } } } @@ -415,10 +422,6 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ uint8 teamIndex = GetTeamIndexByTeamId(source->GetTeam()); - // Message to chatlog - char buf[256]; - uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE; - // Check if player really could use this banner, not cheated if( !(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2) ) return; @@ -437,7 +440,13 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); _SendNodeUpdate(node); m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - sprintf(buf, GetMangosString(LANG_BG_AB_NODE_CLAIMED), _GetNodeName(node), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE)); + + // FIXME: team and node names not localized + if(teamIndex == 0) + PSendMessageToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeName(node), GetMangosString(LANG_BG_AB_ALLY)); + else + PSendMessageToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeName(node), GetMangosString(LANG_BG_AB_HORDE)); + sound = SOUND_NODE_CLAIMED; } // If node is contested @@ -455,7 +464,12 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); _SendNodeUpdate(node); m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - sprintf(buf, GetMangosString(LANG_BG_AB_NODE_ASSAULTED), _GetNodeName(node)); + + // FIXME: node names not localized + if(teamIndex == 0) + PSendMessageToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeName(node)); + else + PSendMessageToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeName(node)); } // If contested, change back to occupied else @@ -470,7 +484,12 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ _SendNodeUpdate(node); m_NodeTimers[node] = 0; _NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE); - sprintf(buf, GetMangosString(LANG_BG_AB_NODE_DEFENDED), _GetNodeName(node)); + + // FIXME: node names not localized + if(teamIndex == 0) + PSendMessageToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeName(node)); + else + PSendMessageToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeName(node)); } sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE; } @@ -487,18 +506,24 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ _SendNodeUpdate(node); _NodeDeOccupied(node); m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - sprintf(buf, GetMangosString(LANG_BG_AB_NODE_ASSAULTED), _GetNodeName(node)); + + // FIXME: node names not localized + if(teamIndex == 0) + PSendMessageToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeName(node)); + else + PSendMessageToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeName(node)); + sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE; } - WorldPacket data; - ChatHandler::FillMessageData(&data, source->GetSession(), type, LANG_UNIVERSAL, NULL, source->GetGUID(), buf, NULL); - SendPacketToAll(&data); + // If node is occupied again, send "X has taken the Y" msg. if( m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED ) { - sprintf(buf, GetMangosString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE), _GetNodeName(node)); - ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, buf, NULL); - SendPacketToAll(&data); + // FIXME: team and node names not localized + if(teamIndex == 0) + PSendMessageToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, GetMangosString(LANG_BG_AB_ALLY), _GetNodeName(node)); + else + PSendMessageToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE, NULL, GetMangosString(LANG_BG_AB_HORDE), _GetNodeName(node)); } PlaySoundToAll(sound); } diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 6543962c7..001e8accd 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -21,7 +21,6 @@ #include "BattleGround.h" #include "BattleGroundEY.h" #include "Creature.h" -#include "Chat.h" #include "ObjectMgr.h" #include "Language.h" #include "WorldPacket.h" @@ -568,32 +567,20 @@ void BattleGroundEY::EventPlayerDroppedFlag(Player *Source) if(GetFlagPickerGUID() != Source->GetGUID()) return; - const char *message = ""; - uint8 type = 0; - SetFlagPicker(0); Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); m_FlagState = BG_EY_FLAG_STATE_ON_GROUND; m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME; Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true); Source->CastSpell(Source, BG_EY_PLAYER_DROPPED_FLAG_SPELL, true); - if(Source->GetTeam() == ALLIANCE) - { - message = GetMangosString(LANG_BG_EY_DROPPED_FLAG); - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; - } - else - { - message = GetMangosString(LANG_BG_EY_DROPPED_FLAG); - type = CHAT_MSG_BG_SYSTEM_HORDE; - } //this does not work correctly :( (it should remove flag carrier name) UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_WAIT_RESPAWN); UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_WAIT_RESPAWN); - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + if(Source->GetTeam() == ALLIANCE) + SendMessageToAll(LANG_BG_EY_DROPPED_FLAG,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(LANG_BG_EY_DROPPED_FLAG,CHAT_MSG_BG_SYSTEM_HORDE, Source); } void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj) @@ -601,20 +588,14 @@ void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target if(GetStatus() != STATUS_IN_PROGRESS || IsFlagPickedup() || !Source->IsWithinDistInMap(target_obj, 10)) return; - const char *message; - uint8 type = 0; - message = GetMangosString(LANG_BG_EY_HAS_TAKEN_FLAG); - if(Source->GetTeam() == ALLIANCE) { UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_ON_PLAYER); - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE); } else { UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_ON_PLAYER); - type = CHAT_MSG_BG_SYSTEM_HORDE; PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_HORDE); } @@ -628,9 +609,10 @@ void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target Source->CastSpell(Source, BG_EY_NETHERSTORM_FLAG_SPELL, true); Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + if(Source->GetTeam() == ALLIANCE) + SendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG,CHAT_MSG_BG_SYSTEM_HORDE, Source); } void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) @@ -639,8 +621,6 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) return; //Natural point - uint8 message_type = 0; - const char *message = ""; uint32 Team = m_PointOwnedByTeam[Point]; if(!Team) @@ -649,8 +629,6 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) if (Team == ALLIANCE) { m_TeamPointsCount[BG_TEAM_ALLIANCE]--; - message_type = CHAT_MSG_BG_SYSTEM_ALLIANCE; - message = GetMangosString(m_LoosingPointTypes[Point].MessageIdAlliance); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance, RESPAWN_ONE_DAY); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 1, RESPAWN_ONE_DAY); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 2, RESPAWN_ONE_DAY); @@ -658,8 +636,6 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) else { m_TeamPointsCount[BG_TEAM_HORDE]--; - message_type = CHAT_MSG_BG_SYSTEM_HORDE; - message = GetMangosString(m_LoosingPointTypes[Point].MessageIdHorde); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 1, RESPAWN_ONE_DAY); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 2, RESPAWN_ONE_DAY); @@ -674,9 +650,10 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) m_PointOwnedByTeam[Point] = EY_POINT_NO_OWNER; m_PointState[Point] = EY_POINT_NO_OWNER; - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), message_type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + if (Team == ALLIANCE) + SendMessageToAll(m_LoosingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(m_LoosingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); UpdatePointsIcons(Team, Point); UpdatePointsCount(Team); @@ -687,8 +664,6 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) if(GetStatus() != STATUS_IN_PROGRESS) return; - uint8 type = 0; - const char *message = ""; uint32 Team = Source->GetTeam(); SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType, RESPAWN_ONE_DAY); @@ -698,8 +673,6 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) if (Team == ALLIANCE) { m_TeamPointsCount[BG_TEAM_ALLIANCE]++; - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; - message = GetMangosString(m_CapturingPointTypes[Point].MessageIdAlliance); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 1, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 2, RESPAWN_IMMEDIATELY); @@ -707,8 +680,6 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) else { m_TeamPointsCount[BG_TEAM_HORDE]++; - type = CHAT_MSG_BG_SYSTEM_HORDE; - message = GetMangosString(m_CapturingPointTypes[Point].MessageIdHorde); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 1, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 2, RESPAWN_IMMEDIATELY); @@ -719,9 +690,10 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) m_PointOwnedByTeam[Point] = Team; m_PointState[Point] = EY_POINT_UNDER_CONTROL; - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + if (Team == ALLIANCE) + SendMessageToAll(m_CapturingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(m_CapturingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); if(m_BgCreatures[Point]) DelCreature(Point); @@ -743,38 +715,33 @@ void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType if(GetStatus() != STATUS_IN_PROGRESS || GetFlagPickerGUID() != Source->GetGUID()) return; - uint8 type = 0; - uint8 team_id = 0; - const char *message = ""; - SetFlagPicker(0); m_FlagState = BG_EY_FLAG_STATE_WAIT_RESPAWN; Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + if(Source->GetTeam() == ALLIANCE) - { PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE); - team_id = BG_TEAM_ALLIANCE; - message = GetMangosString(LANG_BG_EY_CAPTURED_FLAG_A); - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; - } else - { PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE); - team_id = BG_TEAM_HORDE; - message = GetMangosString(LANG_BG_EY_CAPTURED_FLAG_H); - type = CHAT_MSG_BG_SYSTEM_HORDE; - } SpawnBGObject(BgObjectType, RESPAWN_IMMEDIATELY); m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME; m_FlagCapturedBgObjectType = BgObjectType; - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + uint8 team_id = 0; + if(Source->GetTeam() == ALLIANCE) + { + team_id = BG_TEAM_ALLIANCE; + SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_A, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + } + else + { + team_id = BG_TEAM_HORDE; + SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_H, CHAT_MSG_BG_SYSTEM_HORDE, Source); + } if(m_TeamPointsCount[team_id] > 0) AddPoints(Source->GetTeam(), BG_EY_FlagPoints[m_TeamPointsCount[team_id] - 1]); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index fdaaac390..212cb95bc 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7408" + #define REVISION_NR "7409" #endif // __REVISION_NR_H__ From c9ca06a630350ef2033a8d5a570fa7469ddabc53 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 8 Mar 2009 12:29:30 +0300 Subject: [PATCH 27/60] [7410] Localization support for some BattleGroundWS.cpp messages not catches in prev time. --- src/game/BattleGroundWS.cpp | 52 ++++++++++++++----------------------- src/shared/revision_nr.h | 2 +- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index 482727692..eb170c881 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -22,7 +22,6 @@ #include "BattleGroundWS.h" #include "Creature.h" #include "GameObject.h" -#include "Chat.h" #include "ObjectMgr.h" #include "WorldPacket.h" #include "Language.h" @@ -183,9 +182,7 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) if(GetStatus() != STATUS_IN_PROGRESS) return; - uint8 type = 0; uint32 winner = 0; - const char *message = ""; //TODO FIX reputation and honor gains for low level players! @@ -199,8 +196,6 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; // Drop Horde Flag from Player Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); - message = GetMangosString(LANG_BG_WS_CAPTURED_HF); - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; if(GetTeamScore(ALLIANCE) < BG_WS_MAX_TEAM_SCORE) AddPoint(ALLIANCE, 1); PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE); @@ -216,8 +211,6 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; // Drop Alliance Flag from Player Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); - message = GetMangosString(LANG_BG_WS_CAPTURED_AF); - type = CHAT_MSG_BG_SYSTEM_HORDE; if(GetTeamScore(HORDE) < BG_WS_MAX_TEAM_SCORE) AddPoint(HORDE, 1); PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE); @@ -228,9 +221,10 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) SpawnBGObject(BG_WS_OBJECT_H_FLAG, BG_WS_FLAG_RESPAWN_TIME); SpawnBGObject(BG_WS_OBJECT_A_FLAG, BG_WS_FLAG_RESPAWN_TIME); - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + if(Source->GetTeam() == ALLIANCE) + SendMessageToAll(LANG_BG_WS_CAPTURED_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(LANG_BG_WS_CAPTURED_AF, CHAT_MSG_BG_SYSTEM_HORDE, Source); UpdateFlagState(Source->GetTeam(), 1); // flag state none UpdateTeamScore(Source->GetTeam()); @@ -287,8 +281,6 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) return; } - const char *message = ""; - uint8 type = 0; bool set = false; if(Source->GetTeam() == ALLIANCE) @@ -300,8 +292,6 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) SetHordeFlagPicker(0); Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_GROUND; - message = GetMangosString(LANG_BG_WS_DROPPED_HF); - type = CHAT_MSG_BG_SYSTEM_HORDE; Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true); set = true; } @@ -315,8 +305,6 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) SetAllianceFlagPicker(0); Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_GROUND; - message = GetMangosString(LANG_BG_WS_DROPPED_AF); - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true); set = true; } @@ -327,14 +315,16 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true); UpdateFlagState(Source->GetTeam(), 1); - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); - if(Source->GetTeam() == ALLIANCE) + { + SendMessageToAll(LANG_BG_WS_DROPPED_HF, CHAT_MSG_BG_SYSTEM_HORDE, Source); UpdateWorldState(BG_WS_FLAG_UNK_HORDE, uint32(-1)); + } else + { + SendMessageToAll(LANG_BG_WS_DROPPED_AF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, uint32(-1)); + } m_FlagsDropTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_DROP_TIME; } @@ -345,14 +335,14 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target if(GetStatus() != STATUS_IN_PROGRESS) return; - const char *message = NULL; - uint8 type = 0; + int32 message_id = 0; + ChatMsg type; //alliance flag picked up from base if(Source->GetTeam() == HORDE && GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE && m_BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID()) { - message = GetMangosString(LANG_BG_WS_PICKEDUP_AF); + message_id = LANG_BG_WS_PICKEDUP_AF; type = CHAT_MSG_BG_SYSTEM_HORDE; PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); @@ -368,7 +358,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target if (Source->GetTeam() == ALLIANCE && GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_BASE && m_BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID()) { - message = GetMangosString(LANG_BG_WS_PICKEDUP_HF); + message_id = LANG_BG_WS_PICKEDUP_HF; type = CHAT_MSG_BG_SYSTEM_ALLIANCE; PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); @@ -385,7 +375,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target { if(Source->GetTeam() == ALLIANCE) { - message = GetMangosString(LANG_BG_WS_RETURNED_AF); + message_id = LANG_BG_WS_RETURNED_AF; type = CHAT_MSG_BG_SYSTEM_ALLIANCE; UpdateFlagState(HORDE, BG_WS_FLAG_STATE_WAIT_RESPAWN); RespawnFlag(ALLIANCE, false); @@ -395,7 +385,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target } else { - message = GetMangosString(LANG_BG_WS_PICKEDUP_AF); + message_id = LANG_BG_WS_PICKEDUP_AF; type = CHAT_MSG_BG_SYSTEM_HORDE; PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); @@ -414,7 +404,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target { if(Source->GetTeam() == HORDE) { - message = GetMangosString(LANG_BG_WS_RETURNED_HF); + message_id = LANG_BG_WS_RETURNED_HF; type = CHAT_MSG_BG_SYSTEM_HORDE; UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_WAIT_RESPAWN); RespawnFlag(HORDE, false); @@ -424,7 +414,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target } else { - message = GetMangosString(LANG_BG_WS_PICKEDUP_HF); + message_id = LANG_BG_WS_PICKEDUP_HF; type = CHAT_MSG_BG_SYSTEM_ALLIANCE; PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); @@ -438,12 +428,10 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target //target_obj->Delete(); } - if (!type) + if (!message_id) return; - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + SendMessageToAll(message_id, type, Source); Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 212cb95bc..aec2bff8e 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7409" + #define REVISION_NR "7410" #endif // __REVISION_NR_H__ From f42815f04ba53124a1f2927f049fdfc3267fc210 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 8 Mar 2009 12:30:56 +0300 Subject: [PATCH 28/60] [7411] Use similar localization classes for World::SendWorldText muti-line message. --- src/game/GridNotifiers.h | 21 +++++++ src/game/GridNotifiersImpl.h | 24 ++++++++ src/game/World.cpp | 105 +++++++++++++++++++++-------------- src/shared/revision_nr.h | 2 +- 4 files changed, 109 insertions(+), 43 deletions(-) diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h index 9c893fd60..6ad2a4703 100644 --- a/src/game/GridNotifiers.h +++ b/src/game/GridNotifiers.h @@ -862,6 +862,27 @@ namespace MaNGOS std::vector i_data_cache; // 0 = default, i => i-1 locale index }; + // Prepare using Builder localized packets with caching and send to player + template + class LocalizedPacketListDo + { + public: + typedef std::vector WorldPacketList; + explicit LocalizedPacketListDo(Builder& builder) : i_builder(builder) {} + + ~LocalizedPacketListDo() + { + for(size_t i = 0; i < i_data_cache.size(); ++i) + for(int j = 0; j < i_data_cache[i].size(); ++j) + delete i_data_cache[i][j]; + } + void operator()( Player* p ); + + private: + Builder& i_builder; + std::vector i_data_cache; + // 0 = default, i => i-1 locale index + }; #ifndef WIN32 template<> void PlayerRelocationNotifier::Visit(CreatureMapType &); diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index 6903fa23d..75d1ef9c9 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -562,4 +562,28 @@ void MaNGOS::LocalizedPacketDo::operator()( Player* p ) p->SendDirectMessage(data); } +template +void MaNGOS::LocalizedPacketListDo::operator()( Player* p ) +{ + uint32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); + uint32 cache_idx = loc_idx+1; + WorldPacketList* data_list; + + // create if not cached yet + if(i_data_cache.size() < cache_idx+1 || i_data_cache[cache_idx].empty()) + { + if(i_data_cache.size() < cache_idx+1) + i_data_cache.resize(cache_idx+1); + + data_list = &i_data_cache[cache_idx]; + + i_builder(*data_list,loc_idx); + } + else + data_list = &i_data_cache[cache_idx]; + + for(size_t i = 0; i < data_list->size(); ++i) + p->SendDirectMessage((*data_list)[i]); +} + #endif // MANGOS_GRIDNOTIFIERSIMPL_H diff --git a/src/game/World.cpp b/src/game/World.cpp index 2b11c417c..6236a2366 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -21,7 +21,6 @@ */ #include "Common.h" -//#include "WorldSocket.h" #include "Database/DatabaseEnv.h" #include "Config/ConfigEnv.h" #include "SystemConfig.h" @@ -2265,58 +2264,80 @@ void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 te } } +namespace MaNGOS +{ + class WorldWorldTextBuilder + { + public: + typedef std::vector WorldPacketList; + explicit WorldWorldTextBuilder(int32 textId, va_list* args = NULL) : i_textId(textId), i_args(args) {} + void operator()(WorldPacketList& data_list, int32 loc_idx) + { + char const* text = objmgr.GetMangosString(i_textId,loc_idx); + + if(i_args) + { + // we need copy va_list before use or original va_list will corrupted + va_list ap; + va_copy(ap,*i_args); + + char str [2048]; + vsnprintf(str,2048,text, ap ); + va_end(ap); + + do_helper(data_list,&str[0]); + } + else + do_helper(data_list,(char*)text); + } + private: + char* lineFromMessage(char*& pos) { char* start = strtok(pos,"\n"); pos = NULL; return start; } + void do_helper(WorldPacketList& data_list, char* text) + { + char* pos = text; + + while(char* line = lineFromMessage(pos)) + { + WorldPacket* data = new WorldPacket(); + + uint32 lineLength = (line ? strlen(line) : 0) + 1; + + data->Initialize(SMSG_MESSAGECHAT, 100); // guess size + *data << uint8(CHAT_MSG_SYSTEM); + *data << uint32(LANG_UNIVERSAL); + *data << uint64(0); + *data << uint32(0); // can be chat msg group or something + *data << uint64(0); + *data << uint32(lineLength); + *data << line; + *data << uint8(0); + + data_list.push_back(data); + } + } + + int32 i_textId; + va_list* i_args; + }; +} // namespace MaNGOS + /// Send a System Message to all players (except self if mentioned) void World::SendWorldText(int32 string_id, ...) { - std::vector > data_cache; // 0 = default, i => i-1 locale index + va_list ap; + va_start(ap, string_id); + MaNGOS::WorldWorldTextBuilder wt_builder(string_id, &ap); + MaNGOS::LocalizedPacketListDo wt_do(wt_builder); for(SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { if(!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld() ) continue; - uint32 loc_idx = itr->second->GetSessionDbLocaleIndex(); - uint32 cache_idx = loc_idx+1; - - std::vector* data_list; - - // create if not cached yet - if(data_cache.size() < cache_idx+1 || data_cache[cache_idx].empty()) - { - if(data_cache.size() < cache_idx+1) - data_cache.resize(cache_idx+1); - - data_list = &data_cache[cache_idx]; - - char const* text = objmgr.GetMangosString(string_id,loc_idx); - - char buf[1000]; - - va_list argptr; - va_start( argptr, string_id ); - vsnprintf( buf,1000, text, argptr ); - va_end( argptr ); - - char* pos = &buf[0]; - - while(char* line = ChatHandler::LineFromMessage(pos)) - { - WorldPacket* data = new WorldPacket(); - ChatHandler::FillMessageData(data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL); - data_list->push_back(data); - } - } - else - data_list = &data_cache[cache_idx]; - - for(int i = 0; i < data_list->size(); ++i) - itr->second->SendPacket((*data_list)[i]); + wt_do(itr->second->GetPlayer()); } - // free memory - for(int i = 0; i < data_cache.size(); ++i) - for(int j = 0; j < data_cache[i].size(); ++j) - delete data_cache[i][j]; + va_end(ap); } /// DEPRICATED, only for debug purpose. Send a System Message to all players (except self if mentioned) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index aec2bff8e..00808c101 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7410" + #define REVISION_NR "7411" #endif // __REVISION_NR_H__ From 42f579f28095ab0843ac4506fd84355efc5b0d4a Mon Sep 17 00:00:00 2001 From: Triply Date: Sun, 8 Mar 2009 10:45:36 +0100 Subject: [PATCH 29/60] [7412] Do not allow player with deserter debuff to be teleported to battleground Signed-off-by: Triply --- src/game/BattleGroundHandler.cpp | 6 ++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 5990c4309..c5b19d798 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -425,6 +425,12 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) sLog.outError("Battleground: Invalid player queue info!"); return; } + //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue + if( arenatype == 0 && !_player->CanJoinToBattleground() ) + { + sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); + action = 0; + } WorldPacket data; switch(action) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 00808c101..157439bbb 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7411" + #define REVISION_NR "7412" #endif // __REVISION_NR_H__ From 722395be75b0275b13ccf923faf79a89c7ae11ad Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 8 Mar 2009 13:56:15 +0300 Subject: [PATCH 30/60] [7413] Fixed finally problems with node names localization in BattleGroundAB messages. Also fix build at some platforms. --- src/game/BattleGround.cpp | 56 +++++++++++++++++++++++++++++++----- src/game/BattleGround.h | 11 +++---- src/game/BattleGroundAB.cpp | 45 ++++++++++++----------------- src/game/BattleGroundAB.h | 2 +- src/game/MovementHandler.cpp | 1 + src/game/Object.cpp | 1 + src/game/ObjectAccessor.cpp | 1 + src/game/ObjectAccessor.h | 2 +- src/game/Player.cpp | 1 + src/game/World.cpp | 1 + src/game/debugcmds.cpp | 1 + src/shared/revision_nr.h | 2 +- 12 files changed, 81 insertions(+), 43 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index a838ad10d..6534fe740 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -78,8 +78,50 @@ namespace MaNGOS Player const* i_source; va_list* i_args; }; + + class BattleGround2ChatBuilder + { + public: + BattleGround2ChatBuilder(ChatMsg msgtype, int32 textId, Player const* source, int32 arg1, int32 arg2) + : i_msgtype(msgtype), i_textId(textId), i_source(source), i_arg1(arg1), i_arg2(arg2) {} + void operator()(WorldPacket& data, int32 loc_idx) + { + char const* text = objmgr.GetMangosString(i_textId,loc_idx); + char const* arg1str = i_arg1 ? objmgr.GetMangosString(i_arg1,loc_idx) : ""; + char const* arg2str = i_arg2 ? objmgr.GetMangosString(i_arg2,loc_idx) : ""; + + char str [2048]; + snprintf(str,2048,text, arg1str, arg2str ); + + uint64 target_guid = i_source ? i_source ->GetGUID() : 0; + + data << uint8(i_msgtype); + data << uint32(LANG_UNIVERSAL); + data << uint64(target_guid); // there 0 for BG messages + data << uint32(0); // can be chat msg group or something + data << uint64(target_guid); + data << uint32(strlen(str)+1); + data << str; + data << uint8(i_source ? i_source->chatTag() : uint8(0)); + } + private: + + ChatMsg i_msgtype; + int32 i_textId; + Player const* i_source; + int32 i_arg1; + int32 i_arg2; + }; } // namespace MaNGOS +template +void BattleGround::BroadcastWorker(Do& _do) +{ + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + if(Player *plr = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER))) + _do(plr); +} + BattleGround::BattleGround() { m_TypeID = BattleGroundTypeId(0); @@ -1529,6 +1571,13 @@ void BattleGround::PSendMessageToAll(int32 entry, ChatMsg type, Player const* so va_end(ap); } +void BattleGround::SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 arg1, int32 arg2) +{ + MaNGOS::BattleGround2ChatBuilder bg_builder(type, entry, source, arg1, arg2); + MaNGOS::LocalizedPacketDo bg_do(bg_builder); + BroadcastWorker(bg_do); +} + void BattleGround::EndNow() { RemoveFromBGFreeSlotQueue(); @@ -1538,13 +1587,6 @@ void BattleGround::EndNow() sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); } -// Battleground messages are localized using the dbc lang, they are not client language dependent -const char *BattleGround::GetMangosString(int32 entry) -{ - // FIXME: now we have different DBC locales and need localized message for each target client - return objmgr.GetMangosStringForDBCLocale(entry); -} - /* important notice: buffs aren't spawned/despawned when players captures anything diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 1433c9908..a96d3df60 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -401,12 +401,7 @@ class BattleGround void SendPacketToAll(WorldPacket *packet); template - void BroadcastWorker(Do& _do) - { - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - if(Player *plr = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER))) - _do(plr); - } + void BroadcastWorker(Do& _do); void PlaySoundToTeam(uint32 SoundID, uint32 TeamID); void PlaySoundToAll(uint32 SoundID); @@ -424,6 +419,9 @@ class BattleGround void SendMessageToAll(int32 entry, ChatMsg type, Player const* source = NULL); void PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ... ); + // specialized version with 2 string id args + void SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 strId1 = 0, int32 strId2 = 0); + /* Raid Group */ Group *GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; } void SetBgRaid(uint32 TeamID, Group *bg_raid); @@ -487,7 +485,6 @@ class BattleGround void DoorOpen(uint32 type); void DoorClose(uint32 type); - const char *GetMangosString(int32 entry); virtual bool HandlePlayerUnderMap(Player * /*plr*/) { return false; } diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index fc227e6a7..15a6c90d0 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -87,15 +87,13 @@ void BattleGroundAB::Update(uint32 diff) if(teamIndex == 0) { // FIXME: team and node names not localized - PSendMessageToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE,NULL, - GetMangosString(LANG_BG_AB_ALLY), _GetNodeName(node)); + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE,NULL,LANG_BG_AB_ALLY,_GetNodeNameId(node)); PlaySoundToAll(SOUND_NODE_CAPTURED_ALLIANCE); } else { // FIXME: team and node names not localized - PSendMessageToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE,NULL, - GetMangosString(LANG_BG_AB_HORDE),_GetNodeName(node)); + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE,NULL,LANG_BG_AB_HORDE,_GetNodeNameId(node)); PlaySoundToAll(SOUND_NODE_CAPTURED_HORDE); } } @@ -274,24 +272,19 @@ void BattleGroundAB::_DelBanner(uint8 node, uint8 type, uint8 teamIndex) SpawnBGObject(obj, RESPAWN_ONE_DAY); } -const char* BattleGroundAB::_GetNodeName(uint8 node) +int32 BattleGroundAB::_GetNodeNameId(uint8 node) { switch (node) { - case BG_AB_NODE_STABLES: - return GetMangosString(LANG_BG_AB_NODE_STABLES); - case BG_AB_NODE_BLACKSMITH: - return GetMangosString(LANG_BG_AB_NODE_BLACKSMITH); - case BG_AB_NODE_FARM: - return GetMangosString(LANG_BG_AB_NODE_FARM); - case BG_AB_NODE_LUMBER_MILL: - return GetMangosString(LANG_BG_AB_NODE_LUMBER_MILL); - case BG_AB_NODE_GOLD_MINE: - return GetMangosString(LANG_BG_AB_NODE_GOLD_MINE); + case BG_AB_NODE_STABLES: return LANG_BG_AB_NODE_STABLES; + case BG_AB_NODE_BLACKSMITH: return LANG_BG_AB_NODE_BLACKSMITH; + case BG_AB_NODE_FARM: return LANG_BG_AB_NODE_FARM; + case BG_AB_NODE_LUMBER_MILL:return LANG_BG_AB_NODE_LUMBER_MILL; + case BG_AB_NODE_GOLD_MINE: return LANG_BG_AB_NODE_GOLD_MINE; default: ASSERT(0); } - return ""; + return 0; } void BattleGroundAB::FillInitialWorldStates(WorldPacket& data) @@ -443,9 +436,9 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ // FIXME: team and node names not localized if(teamIndex == 0) - PSendMessageToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeName(node), GetMangosString(LANG_BG_AB_ALLY)); + SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node), LANG_BG_AB_ALLY); else - PSendMessageToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeName(node), GetMangosString(LANG_BG_AB_HORDE)); + SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node), LANG_BG_AB_HORDE); sound = SOUND_NODE_CLAIMED; } @@ -467,9 +460,9 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ // FIXME: node names not localized if(teamIndex == 0) - PSendMessageToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeName(node)); + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); else - PSendMessageToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeName(node)); + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); } // If contested, change back to occupied else @@ -487,9 +480,9 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ // FIXME: node names not localized if(teamIndex == 0) - PSendMessageToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeName(node)); + SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); else - PSendMessageToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeName(node)); + SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); } sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE; } @@ -509,9 +502,9 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ // FIXME: node names not localized if(teamIndex == 0) - PSendMessageToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeName(node)); + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); else - PSendMessageToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeName(node)); + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE; } @@ -521,9 +514,9 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ { // FIXME: team and node names not localized if(teamIndex == 0) - PSendMessageToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, GetMangosString(LANG_BG_AB_ALLY), _GetNodeName(node)); + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, LANG_BG_AB_ALLY, _GetNodeNameId(node)); else - PSendMessageToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE, NULL, GetMangosString(LANG_BG_AB_HORDE), _GetNodeName(node)); + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE, NULL, LANG_BG_AB_HORDE, _GetNodeNameId(node)); } PlaySoundToAll(sound); } diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h index a54f7233d..90e6287f5 100644 --- a/src/game/BattleGroundAB.h +++ b/src/game/BattleGroundAB.h @@ -265,7 +265,7 @@ class BattleGroundAB : public BattleGround void _NodeOccupied(uint8 node,Team team); void _NodeDeOccupied(uint8 node); - const char* _GetNodeName(uint8 node); + int32 _GetNodeNameId(uint8 node); /* Nodes info: 0: neutral diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index d6e974a49..147b920a7 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -23,6 +23,7 @@ #include "Log.h" #include "Corpse.h" #include "Player.h" +#include "Vehicle.h" #include "MapManager.h" #include "Transports.h" #include "BattleGround.h" diff --git a/src/game/Object.cpp b/src/game/Object.cpp index c6081d5c5..c4c8cea87 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -25,6 +25,7 @@ #include "Object.h" #include "Creature.h" #include "Player.h" +#include "Vehicle.h" #include "ObjectMgr.h" #include "UpdateData.h" #include "UpdateMask.h" diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 6103d4703..07830f15b 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -23,6 +23,7 @@ #include "Creature.h" #include "GameObject.h" #include "DynamicObject.h" +#include "Vehicle.h" #include "WorldPacket.h" #include "Item.h" #include "Corpse.h" diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index 77ffb3d60..270a27e9b 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -31,7 +31,6 @@ #include "GridDefines.h" #include "Object.h" #include "Player.h" -#include "Vehicle.h" #include @@ -40,6 +39,7 @@ class Corpse; class Unit; class GameObject; class DynamicObject; +class Vehicle; class WorldObject; class Map; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 7fd006d38..0ccb2dcac 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -27,6 +27,7 @@ #include "WorldSession.h" #include "UpdateMask.h" #include "Player.h" +#include "Vehicle.h" #include "SkillDiscovery.h" #include "QuestDef.h" #include "GossipDef.h" diff --git a/src/game/World.cpp b/src/game/World.cpp index 6236a2366..c3c2f94ea 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -30,6 +30,7 @@ #include "WorldPacket.h" #include "Weather.h" #include "Player.h" +#include "Vehicle.h" #include "SkillExtraItems.h" #include "SkillDiscovery.h" #include "World.h" diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index 9a789c438..6ff1a90bf 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -19,6 +19,7 @@ #include "Common.h" #include "Database/DatabaseEnv.h" #include "WorldPacket.h" +#include "Vehicle.h" #include "Player.h" #include "Opcodes.h" #include "Chat.h" diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 157439bbb..0079ff50a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7412" + #define REVISION_NR "7413" #endif // __REVISION_NR_H__ From ee5feab3ebda7c6920bc374a49aef712ecdf0ec6 Mon Sep 17 00:00:00 2001 From: Triply Date: Sun, 8 Mar 2009 13:23:32 +0100 Subject: [PATCH 31/60] [7414] Fixed premature finish timer messages for battleground (va_start was broken). Fixed typo with BattleGroundPlayerMap. Optimized implementation for removing offline players from battleground. Fixed typo in BattleGroundMgr::DeleteAllBattleGrounds. Patch is tested and should work. TODO there is a bug if you disable premature finish timer, that can cause battlegrounds to be never ending! TODO rewrite BattleGround::RemovePlayer function - and fix bugs there! I might not have today enough time to fix those bugs. Signed-off-by: Triply --- src/game/BattleGround.cpp | 75 +++++++++++++++++++++-------------- src/game/BattleGround.h | 8 ++-- src/game/BattleGroundMgr.cpp | 4 +- src/game/BattleGroundMgr.h | 2 +- src/game/Player.cpp | 2 +- src/mangosd/WorldRunnable.cpp | 2 +- src/shared/revision_nr.h | 2 +- 7 files changed, 57 insertions(+), 38 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 6534fe740..048ca62bd 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -117,7 +117,7 @@ namespace MaNGOS template void BattleGround::BroadcastWorker(Do& _do) { - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) if(Player *plr = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER))) _do(plr); } @@ -254,18 +254,16 @@ void BattleGround::Update(uint32 diff) } // remove offline players from bg after 5 minutes - if(GetPlayersSize()) + if( !m_OfflineQueue.empty() ) { - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + BattleGroundPlayerMap::iterator itr = m_Players.find(*(m_OfflineQueue.begin())); + if( itr != m_Players.end() ) { - Player *plr = objmgr.GetPlayer(itr->first); - itr->second.LastOnlineTime += diff; - - if(plr) - itr->second.LastOnlineTime = 0; // update last online time - else - if(itr->second.LastOnlineTime >= MAX_OFFLINE_TIME) - m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) + if( itr->second.OfflineRemoveTime <= sWorld.GetGameTime() ) + { + m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) + m_OfflineQueue.pop_front(); // remove from offline queue + } } } @@ -447,7 +445,7 @@ void BattleGround::Update(uint32 diff) m_EndTime += diff; if(m_EndTime >= TIME_TO_AUTOREMOVE) // 2 minutes { - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) } @@ -468,7 +466,7 @@ void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, flo void BattleGround::SendPacketToAll(WorldPacket *packet) { - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); if(plr) @@ -480,7 +478,7 @@ void BattleGround::SendPacketToAll(WorldPacket *packet) void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *sender, bool self) { - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -512,7 +510,7 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID) { WorldPacket data; - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -535,7 +533,7 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID) void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID) { - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -555,7 +553,7 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID) void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID) { - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -580,7 +578,7 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, if(!factionEntry) return; - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -685,7 +683,7 @@ void BattleGround::EndBattleGround(uint32 winner) } } - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); if(!plr) @@ -907,7 +905,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac uint32 team = GetPlayerTeam(guid); bool participant = false; // Remove from lists/maps - std::map::iterator itr = m_Players.find(guid); + BattleGroundPlayerMap::iterator itr = m_Players.find(guid); if(itr != m_Players.end()) { UpdatePlayersCountByTeam(team, true); // -1 player @@ -1084,7 +1082,7 @@ void BattleGround::AddPlayer(Player *plr) uint32 team = plr->GetBGTeam(); BattleGroundPlayer bp; - bp.LastOnlineTime = 0; + bp.OfflineRemoveTime = 0; bp.Team = team; // Add to list/maps @@ -1147,7 +1145,7 @@ void BattleGround::AddPlayer(Player *plr) } // setup BG group membership - PlayerRelogin(plr); + PlayerAddedToBGCheckIfBGIsRunning(plr); AddOrSetPlayerToCorrectBgGroup(plr, guid, team); // Log @@ -1176,9 +1174,28 @@ void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player *plr, uint64 plr_guid, } } +// This method should be called when player logs into running battleground +void BattleGround::EventPlayerLoggedIn(Player* player, uint64 plr_guid) +{ + // player is correct pointer + for(std::deque::iterator itr = m_OfflineQueue.begin(); itr != m_OfflineQueue.end(); ++itr) + { + if( *itr == plr_guid ) + { + m_OfflineQueue.erase(itr); + break; + } + } + m_Players[plr_guid].OfflineRemoveTime = 0; + PlayerAddedToBGCheckIfBGIsRunning(player); +} + // This method should be called when player logs out from running battleground void BattleGround::EventPlayerLoggedOut(Player* player) { + // player is correct pointer, it is checked in WorldSession::LogoutPlayer() + m_OfflineQueue.push_back(player->GetGUID()); + m_Players[player->GetGUID()].OfflineRemoveTime = sWorld.GetGameTime() + MAX_OFFLINE_TIME; if( GetStatus() == STATUS_IN_PROGRESS ) { if( isBattleGround() ) @@ -1562,7 +1579,7 @@ void BattleGround::SendMessageToAll(int32 entry, ChatMsg type, Player const* sou void BattleGround::PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ...) { va_list ap; - va_start(ap, type); + va_start(ap, source); MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, source, &ap); MaNGOS::LocalizedPacketDo bg_do(bg_builder); @@ -1640,7 +1657,7 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer ) UpdatePlayerScore(killer, SCORE_HONORABLE_KILLS, 1); UpdatePlayerScore(killer, SCORE_KILLING_BLOWS, 1); - for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -1660,7 +1677,7 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer ) // used in same faction arena matches mainly uint32 BattleGround::GetPlayerTeam(uint64 guid) { - std::map::const_iterator itr = m_Players.find(guid); + BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid); if(itr!=m_Players.end()) return itr->second.Team; return 0; @@ -1668,13 +1685,13 @@ uint32 BattleGround::GetPlayerTeam(uint64 guid) bool BattleGround::IsPlayerInBattleGround(uint64 guid) { - std::map::const_iterator itr = m_Players.find(guid); - if(itr!=m_Players.end()) + BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid); + if(itr != m_Players.end()) return true; return false; } -void BattleGround::PlayerRelogin(Player* plr) +void BattleGround::PlayerAddedToBGCheckIfBGIsRunning(Player* plr) { if(GetStatus() != STATUS_WAIT_LEAVE) return; @@ -1694,7 +1711,7 @@ void BattleGround::PlayerRelogin(Player* plr) uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const { int count = 0; - for(std::map::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { if(itr->second.Team == Team) { diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index a96d3df60..cf3a94c58 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -89,7 +89,7 @@ enum BattleGroundTimeIntervals INVITATION_REMIND_TIME = 60000, // ms INVITE_ACCEPT_WAIT_TIME = 80000, // ms TIME_TO_AUTOREMOVE = 120000, // ms - MAX_OFFLINE_TIME = 300000, // ms + MAX_OFFLINE_TIME = 300, // secs RESPAWN_ONE_DAY = 86400, // secs RESPAWN_IMMEDIATELY = 0, // secs BUFF_RESPAWN_TIME = 180, // secs @@ -125,7 +125,7 @@ enum BattleGroundStatus struct BattleGroundPlayer { - uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes + time_t OfflineRemoveTime; // for tracking and removing offline players from queue after 5 minutes uint32 Team; // Player's team }; @@ -456,6 +456,7 @@ class BattleGround virtual void EventPlayerDroppedFlag(Player* /*player*/) {} virtual void EventPlayerClickedOnFlag(Player* /*player*/, GameObject* /*target_obj*/) {} virtual void EventPlayerCapturedFlag(Player* /*player*/) {} + void EventPlayerLoggedIn(Player* player, uint64 plr_guid); void EventPlayerLoggedOut(Player* player); /* Death related */ @@ -491,13 +492,13 @@ class BattleGround // since arenas can be AvA or Hvh, we have to get the "temporary" team of a player uint32 GetPlayerTeam(uint64 guid); bool IsPlayerInBattleGround(uint64 guid); - void PlayerRelogin(Player* plr); void SetDeleteThis() {m_SetDeleteThis = true;} protected: //this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround void EndNow(); + void PlayerAddedToBGCheckIfBGIsRunning(Player* plr); /* Scorekeeping */ // Player scores @@ -542,6 +543,7 @@ class BattleGround /* Player lists */ std::vector m_ResurrectQueue; // Player GUID + std::deque m_OfflineQueue; // Player GUID std::map m_RemovedPlayers; // uint8 is remove type (0 - bgqueue, 1 - bg, 2 - resurrect queue) /* Invited counters are useful for player invitation to BG - do not allow, if BG is started to one faction to have 2 more players than another faction */ diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index e4c482a03..d4a7d9093 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -1077,10 +1077,10 @@ BattleGroundMgr::BattleGroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTe BattleGroundMgr::~BattleGroundMgr() { - DeleteAlllBattleGrounds(); + DeleteAllBattleGrounds(); } -void BattleGroundMgr::DeleteAlllBattleGrounds() +void BattleGroundMgr::DeleteAllBattleGrounds() { for(uint32 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; i++) { diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index dc2979267..f807afd1e 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -199,7 +199,7 @@ class BattleGroundMgr void RemoveBattleGround(uint32 instanceID, BattleGroundTypeId bgTypeId) { m_BattleGrounds[bgTypeId].erase(instanceID); } void CreateInitialBattleGrounds(); - void DeleteAlllBattleGrounds(); + void DeleteAllBattleGrounds(); void SendToBattleGround(Player *pl, uint32 InstanceID, BattleGroundTypeId bgTypeId); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 0ccb2dcac..6baea0750 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -14299,7 +14299,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) SetBGTeam(bgteam); //join player to battleground group - currentBg->PlayerRelogin(this); + currentBg->EventPlayerLoggedIn(this, GetGUID()); currentBg->AddOrSetPlayerToCorrectBgGroup(this, GetGUID(), bgteam); SetInviteForBattleGroundQueueType(bgQueueTypeId,currentBg->GetInstanceID()); diff --git a/src/mangosd/WorldRunnable.cpp b/src/mangosd/WorldRunnable.cpp index 929463503..cf652d673 100644 --- a/src/mangosd/WorldRunnable.cpp +++ b/src/mangosd/WorldRunnable.cpp @@ -87,7 +87,7 @@ void WorldRunnable::run() sWorld.UpdateSessions( 1 ); // real players unload required UpdateSessions call // unload battleground templates before different singletons destroyed - sBattleGroundMgr.DeleteAlllBattleGrounds(); + sBattleGroundMgr.DeleteAllBattleGrounds(); sWorldSocketMgr->StopNetwork(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0079ff50a..3be3dea63 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7413" + #define REVISION_NR "7414" #endif // __REVISION_NR_H__ From bd0619ce407d0c780983e0082eea1e850e7c3f98 Mon Sep 17 00:00:00 2001 From: Triply Date: Sun, 8 Mar 2009 22:12:14 +0100 Subject: [PATCH 32/60] [7415] Fixed removing player from battlegrounds Probably fixed bug with not ending battlegrounds - reported in previous commit message Fixed player will loose arena rating if 1. he doesn't click on enter rated arena window - and timer will expire 2. he logs out during time he is invited to rated arena match 3. if he logs out during fight in rated arena match Patch is not tested, i will test it as soon as possible. Signed-off-by: Triply --- src/game/ArenaTeam.cpp | 22 +++++ src/game/ArenaTeam.h | 1 + src/game/BattleGround.cpp | 159 +++++++++++++++-------------------- src/game/BattleGround.h | 3 +- src/game/BattleGroundMgr.cpp | 32 ++++--- src/game/BattleGroundMgr.h | 2 +- src/shared/revision_nr.h | 2 +- 7 files changed, 112 insertions(+), 109 deletions(-) diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp index cc1136171..eb8906f73 100644 --- a/src/game/ArenaTeam.cpp +++ b/src/game/ArenaTeam.cpp @@ -575,6 +575,28 @@ void ArenaTeam::MemberLost(Player * plr, uint32 againstRating) } } +void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstRating) +{ + // called for offline player after ending rated arena match! + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + if(itr->guid == guid) + { + // update personal rating + float chance = GetChanceAgainst(itr->personal_rating, againstRating); + int32 mod = (int32)ceil(32.0f * (0.0f - chance)); + if (int32(itr->personal_rating) + mod < 0) + itr->personal_rating = 0; + else + itr->personal_rating += mod; + // update personal played stats + itr->games_week +=1; + itr->games_season +=1; + return; + } + } +} + void ArenaTeam::MemberWon(Player * plr, uint32 againstRating) { // called for each participant after winning a match diff --git a/src/game/ArenaTeam.h b/src/game/ArenaTeam.h index 42028499c..9ad3ea618 100644 --- a/src/game/ArenaTeam.h +++ b/src/game/ArenaTeam.h @@ -198,6 +198,7 @@ class ArenaTeam void MemberWon(Player * plr, uint32 againstRating); int32 LostAgainst(uint32 againstRating); void MemberLost(Player * plr, uint32 againstRating); + void OfflineMemberLost(uint64 guid, uint32 againstRating); void UpdateArenaPointsHelper(std::map & PlayerPoints); diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 048ca62bd..0d0abcf5f 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -226,33 +226,10 @@ BattleGround::~BattleGround() void BattleGround::Update(uint32 diff) { - if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) + if(!GetPlayersSize() && !GetReviveQueueSize()) //BG is empty return; - if(GetRemovedPlayersSize()) - { - for(std::map::iterator itr = m_RemovedPlayers.begin(); itr != m_RemovedPlayers.end(); ++itr) - { - Player *plr = objmgr.GetPlayer(itr->first); - switch(itr->second) - { - case 1: // currently in bg and was removed from bg - if(plr) - RemovePlayerAtLeave(itr->first, true, true); - else - RemovePlayerAtLeave(itr->first, false, false); - break; - case 2: // revive queue - RemovePlayerFromResurrectQueue(itr->first); - break; - default: - sLog.outError("BattleGround: Unknown remove player case!"); - } - } - m_RemovedPlayers.clear(); - } - // remove offline players from bg after 5 minutes if( !m_OfflineQueue.empty() ) { @@ -261,7 +238,7 @@ void BattleGround::Update(uint32 diff) { if( itr->second.OfflineRemoveTime <= sWorld.GetGameTime() ) { - m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) + RemovePlayerAtLeave(itr->first, true, true);// remove player from BG m_OfflineQueue.pop_front(); // remove from offline queue } } @@ -446,9 +423,7 @@ void BattleGround::Update(uint32 diff) if(m_EndTime >= TIME_TO_AUTOREMOVE) // 2 minutes { for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) - } + RemovePlayerAtLeave(itr->first, true, true);// remove player from BG // do not change any battleground's private variables } } @@ -648,33 +623,17 @@ void BattleGround::EndBattleGround(uint32 winner) // arena rating calculation if(isArena() && isRated()) { - if(winner == ALLIANCE) - { - winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); - loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); - } - else if(winner == HORDE) - { - winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); - loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); - } - if(winner_arena_team && loser_arena_team) + winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(winner)); + loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(winner))); + if( winner_arena_team && loser_arena_team ) { loser_rating = loser_arena_team->GetStats().rating; winner_rating = winner_arena_team->GetStats().rating; int32 winner_change = winner_arena_team->WonAgainst(loser_rating); int32 loser_change = loser_arena_team->LostAgainst(winner_rating); sLog.outDebug("--- Winner rating: %u, Loser rating: %u, Winner change: %u, Losser change: %u ---", winner_rating, loser_rating, winner_change, loser_change); - if(winner == ALLIANCE) - { - SetArenaTeamRatingChangeForTeam(ALLIANCE, winner_change); - SetArenaTeamRatingChangeForTeam(HORDE, loser_change); - } - else - { - SetArenaTeamRatingChangeForTeam(HORDE, winner_change); - SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change); - } + SetArenaTeamRatingChangeForTeam(winner, winner_change); + SetArenaTeamRatingChangeForTeam(GetOtherTeam(winner), loser_change); } else { @@ -686,8 +645,18 @@ void BattleGround::EndBattleGround(uint32 winner) for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); + uint32 team = itr->second.Team; + if(!plr) { + //if rated arena match - make member lost! + if(isArena() && isRated() && winner_arena_team && loser_arena_team) + { + if(team == winner) + winner_arena_team->OfflineMemberLost(itr->first, loser_rating); + else + loser_arena_team->OfflineMemberLost(itr->first, winner_rating); + } sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first); continue; } @@ -702,8 +671,8 @@ void BattleGround::EndBattleGround(uint32 winner) plr->SpawnCorpseBones(); } - uint32 team = itr->second.Team; - if(!team) team = plr->GetTeam(); + //this line is obsolete - team is set ALWAYS + //if(!team) team = plr->GetTeam(); // per player calculation if(isArena() && isRated() && winner_arena_team && loser_arena_team) @@ -937,16 +906,16 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac RemovePlayer(plr, guid); // BG subclass specific code - if(plr) + if(participant) // if the player was a match participant, remove auras, calc rating, update queue { - plr->ClearAfkReports(); - - if(participant) // if the player was a match participant, remove auras, calc rating, update queue + BattleGroundTypeId bgTypeId = GetTypeID(); + BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); + if(plr) { + plr->ClearAfkReports(); + if(!team) team = plr->GetTeam(); - BattleGroundTypeId bgTypeId = GetTypeID(); - BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); // if arena, remove the specific arena auras if(isArena()) { @@ -966,56 +935,56 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac if(isRated() && GetStatus() == STATUS_IN_PROGRESS) { //left a rated match while the encounter was in progress, consider as loser - ArenaTeam * winner_arena_team = 0; - ArenaTeam * loser_arena_team = 0; - if(team == HORDE) - { - winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); - loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); - } - else - { - winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); - loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); - } + ArenaTeam * winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team))); + ArenaTeam * loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(team)); if(winner_arena_team && loser_arena_team) - { loser_arena_team->MemberLost(plr,winner_arena_team->GetRating()); - } } } - - WorldPacket data; if(SendPacket) { + WorldPacket data; sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg plr->RemoveBattleGroundQueueId(bgQueueTypeId); - - DecreaseInvitedCount(team); - //we should update battleground queue, but only if bg isn't ending - if (GetStatus() < STATUS_WAIT_LEAVE) - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueId()); - - Group * group = plr->GetGroup(); - // remove from raid group if exist - if(group && group == GetBgRaid(team)) + } + else + // removing offline participant + { + if(isRated() && GetStatus() == STATUS_IN_PROGRESS) { - if(!group->RemoveMember(guid, 0)) // group was disbanded - { - SetBgRaid(team, NULL); - delete group; - } + //left a rated match while the encounter was in progress, consider as loser + ArenaTeam * others_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team))); + ArenaTeam * players_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(team)); + if( others_arena_team && players_arena_team ) + players_arena_team->OfflineMemberLost(guid, others_arena_team->GetRating()); } - - // Let others know - sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); - SendPacketToTeam(team, &data, plr, false); } + // remove from raid group if player is member + if(Group *group = GetBgRaid(team)) + { + if( !group->RemoveMember(guid, 0) ) // group was disbanded + { + SetBgRaid(team, NULL); + delete group; + } + } + DecreaseInvitedCount(team); + //we should update battleground queue, but only if bg isn't ending + if( isBattleGround() && GetStatus() < STATUS_WAIT_LEAVE ) + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueId()); + // Let others know + WorldPacket data; + sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, guid); + SendPacketToTeam(team, &data, plr, false); + } + + if( plr ) + { // Do next only if found in battleground plr->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG. // reset destination bg team @@ -1024,7 +993,6 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac if(Transport) plr->TeleportTo(plr->GetBattleGroundEntryPoint()); - // Log sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName()); } @@ -1188,6 +1156,8 @@ void BattleGround::EventPlayerLoggedIn(Player* player, uint64 plr_guid) } m_Players[plr_guid].OfflineRemoveTime = 0; PlayerAddedToBGCheckIfBGIsRunning(player); + // if battleground is starting, then add preparation aura + // we don't have to do that, because preparation aura isn't removed when player logs out } // This method should be called when player logs out from running battleground @@ -1683,6 +1653,11 @@ uint32 BattleGround::GetPlayerTeam(uint64 guid) return 0; } +uint32 BattleGround::GetOtherTeam(uint32 teamId) +{ + return (teamId) ? ((teamId == ALLIANCE) ? HORDE : ALLIANCE) : 0; +} + bool BattleGround::IsPlayerInBattleGround(uint64 guid) { BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid); diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index cf3a94c58..5ef2c2c8f 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -367,7 +367,6 @@ class BattleGround typedef std::map BattleGroundPlayerMap; BattleGroundPlayerMap const& GetPlayers() const { return m_Players; } uint32 GetPlayersSize() const { return m_Players.size(); } - uint32 GetRemovedPlayersSize() const { return m_RemovedPlayers.size(); } std::map::const_iterator GetPlayerScoresBegin() const { return m_PlayerScores.begin(); } std::map::const_iterator GetPlayerScoresEnd() const { return m_PlayerScores.end(); } @@ -491,6 +490,7 @@ class BattleGround // since arenas can be AvA or Hvh, we have to get the "temporary" team of a player uint32 GetPlayerTeam(uint64 guid); + uint32 GetOtherTeam(uint32 teamId); bool IsPlayerInBattleGround(uint64 guid); void SetDeleteThis() {m_SetDeleteThis = true;} @@ -544,7 +544,6 @@ class BattleGround /* Player lists */ std::vector m_ResurrectQueue; // Player GUID std::deque m_OfflineQueue; // Player GUID - std::map m_RemovedPlayers; // uint8 is remove type (0 - bgqueue, 1 - bg, 2 - resurrect queue) /* Invited counters are useful for player invitation to BG - do not allow, if BG is started to one faction to have 2 more players than another faction */ /* Invited counters will be changed only when removing already invited player from queue, removing player from battleground and inviting player to BG */ diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index d4a7d9093..a8c8b6421 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -234,7 +234,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou } sLog.outDebug("BattleGroundQueue: Removing player GUID %u, from queue_id %u", GUID_LOPART(guid), (uint32)queue_id); - // ALL variables are corrcetly set + // ALL variables are correctly set // We can ignore leveling up in queue - it should not cause crash // remove player from group // if only one player there, remove group @@ -259,6 +259,22 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou if( (decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty()) ) AnnounceWorld(group, guid, false); + //if player leaves queue and he is invited to rated arena match, then he have to loose + if( group->IsInvitedToBGInstanceGUID && group->IsRated && decreaseInvitedCount ) + { + ArenaTeam * at = objmgr.GetArenaTeamById(group->ArenaTeamId); + if( at ) + { + sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(guid), group->OpponentsTeamRating); + Player *plr = objmgr.GetPlayer(guid); + if( plr ) + at->MemberLost(plr, group->OpponentsTeamRating); + else + at->OfflineMemberLost(guid, group->OpponentsTeamRating); + at->SaveToDB(); + } + } + // remove group queue info if needed if( group->Players.empty() ) { @@ -1032,16 +1048,6 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = qpMap.find(m_PlayerGuid); if (qMapItr != qpMap.end() && qMapItr->second.GroupInfo && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) { - if (qMapItr->second.GroupInfo->IsRated) - { - ArenaTeam * at = objmgr.GetArenaTeamById(qMapItr->second.GroupInfo->ArenaTeamId); - if (at) - { - sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(plr->GetGUID()), qMapItr->second.GroupInfo->OpponentsTeamRating); - at->MemberLost(plr, qMapItr->second.GroupInfo->OpponentsTeamRating); - at->SaveToDB(); - } - } plr->RemoveBattleGroundQueueId(bgQueueTypeId); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(), bg->GetQueueId()); @@ -1388,10 +1394,10 @@ void BattleGroundMgr::BuildPlaySoundPacket(WorldPacket *data, uint32 soundid) *data << uint32(soundid); } -void BattleGroundMgr::BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr) +void BattleGroundMgr::BuildPlayerLeftBattleGroundPacket(WorldPacket *data, const uint64& guid) { data->Initialize(SMSG_BATTLEGROUND_PLAYER_LEFT, 8); - *data << uint64(plr->GetGUID()); + *data << uint64(guid); } void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr) diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index f807afd1e..d173f0303 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -174,7 +174,7 @@ class BattleGroundMgr /* Packet Building */ void BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr); - void BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr); + void BuildPlayerLeftBattleGroundPacket(WorldPacket *data, const uint64& guid); void BuildBattleGroundListPacket(WorldPacket *data, const uint64& guid, Player *plr, BattleGroundTypeId bgTypeId); void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, BattleGroundTypeId bgTypeId); void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3be3dea63..acbff8e2d 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7414" + #define REVISION_NR "7415" #endif // __REVISION_NR_H__ From 18c8e861f455827267dbc44fb5366765a2cff15d Mon Sep 17 00:00:00 2001 From: balrok Date: Sun, 8 Mar 2009 23:23:53 +0100 Subject: [PATCH 33/60] [7416] Fixed minimap icon for battlegrounds and arenas. Patch provided by Balrok. Thx. Signed-off-by: Triply --- src/game/BattleGround.cpp | 6 +++--- src/game/BattleGroundHandler.cpp | 28 ++++++++++------------------ src/game/BattleGroundMgr.cpp | 21 +++++++++------------ src/game/BattleGroundMgr.h | 2 +- src/shared/revision_nr.h | 2 +- 5 files changed, 24 insertions(+), 35 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 0d0abcf5f..fdda6ace6 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -702,7 +702,7 @@ void BattleGround::EndBattleGround(uint32 winner) plr->GetSession()->SendPacket(&data); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); plr->GetSession()->SendPacket(&data); plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1); } @@ -944,7 +944,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac if(SendPacket) { WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } @@ -1679,7 +1679,7 @@ void BattleGround::PlayerAddedToBGCheckIfBGIsRunning(Player* plr) sBattleGroundMgr.BuildPvpLogDataPacket(&data, this); plr->GetSession()->SendPacket(&data); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); plr->GetSession()->SendPacket(&data); } diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index c5b19d798..7be6e3612 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -172,7 +172,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); @@ -193,7 +193,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0); SendPacket(&data); GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, false, 0); @@ -358,7 +358,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) // re - invite player with proper data WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, itrPlayerStatus->second.GroupInfo->Team?itrPlayerStatus->second.GroupInfo->Team:_player->GetTeam(), i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype, israted); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype); SendPacket(&data); } } @@ -451,7 +451,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) } _player->RemoveFromGroup(); queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); _player->GetSession()->SendPacket(&data); // remove battleground queue status from BGmgr sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false); @@ -486,7 +486,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) } } _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); // player left queue, we should update it, maybe now his group fits in sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId,_player->GetBattleGroundQueueIdFromLevel(bgTypeId),arenatype,israted,rating); @@ -541,7 +541,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId_tmp); if((bg->GetStatus() <= STATUS_IN_PROGRESS)) { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); SendPacket(&data); } for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) @@ -566,7 +566,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) { //in this call is small bug, this call should be filled by player's waiting time in queue //this call nulls all timers for client : - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0,arenatype,isRated); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, i, STATUS_WAIT_QUEUE, 0, 0,arenatype); SendPacket(&data); } } @@ -595,19 +595,11 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) } if(bg) { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, 0, 0, arenatype); SendPacket(&data); } } } -/* else // not sure if it needed... - { - for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) - { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0); - SendPacket(&data); - } - }*/ } void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data ) @@ -788,7 +780,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); @@ -809,7 +801,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype); SendPacket(&data); GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index a8c8b6421..81185c38c 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -296,7 +296,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to // queue->removeplayer, it causes bugs WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); plr2->GetSession()->SendPacket(&data); } // then actually delete, this may delete the group as well! @@ -396,7 +396,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b sLog.outDebug("Battleground: invited plr %s (%u) to BG instance %u queueindex %u bgtype %u, I can't help it if they don't press the enter battle button.",plr->GetName(),plr->GetGUIDLow(),bg->GetInstanceID(),queueSlot,bg->GetTypeID()); // send status packet - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, side?side:plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); plr->GetSession()->SendPacket(&data); } return true; @@ -428,7 +428,6 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) { // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop uint32 to_remove = ginfo->Players.size(); - uint32 team = ginfo->Team; for(uint32 j = 0; j < to_remove; j++) { // always remove the first one in the group @@ -454,7 +453,7 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) // 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, team, queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } } @@ -1013,7 +1012,7 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) { WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITATION_REMIND_TIME, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITATION_REMIND_TIME, 0); plr->GetSession()->SendPacket(&data); } } @@ -1052,7 +1051,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(), bg->GetQueueId()); WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, m_PlayersTeam, queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } } @@ -1168,7 +1167,7 @@ void BattleGroundMgr::Update(uint32 diff) } } -void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype, uint8 israted) +void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype) { // we can be in 3 queues in same time... if(StatusID == 0) @@ -1185,7 +1184,8 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro *data << uint64( uint64(arenatype ? arenatype : bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); *data << uint32(0); // unknown // alliance/horde for BG and skirmish/rated for Arenas - *data << uint8(bg->isArena() ? ( israted ? israted : bg->isRated() ) : bg->GetTeamIndexByTeamId(team)); + // following displays the minimap-icon 0 = faction icon 1 = arenaicon + *data << uint8(bg->isArena()); /* *data << uint8(arenatype ? arenatype : bg->GetArenaType()); // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas // NOT PROPER VALUE IF ARENA ISN'T RUNNING YET!!!! switch(bg->GetTypeID()) // value depends on bg id { @@ -1235,10 +1235,7 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro *data << uint16(0x1F90); // unk value 8080 *data << uint32(bg->GetInstanceID()); // instance id - if(bg->isBattleGround()) - *data << uint8(bg->GetTeamIndexByTeamId(team)); // team - else - *data << uint8(israted?israted:bg->isRated()); // is rated battle + *data << uint8(bg->isArena()); // minimap-icon 0=faction 1=arena */ *data << uint32(StatusID); // status switch(StatusID) diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index d173f0303..0ce0b02ae 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -179,7 +179,7 @@ class BattleGroundMgr void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, BattleGroundTypeId bgTypeId); void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value); void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); - void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0); + void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0); void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index acbff8e2d..25a6661fb 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7415" + #define REVISION_NR "7416" #endif // __REVISION_NR_H__ From d440ff3184cb61973f3cef6247f9014d3b03bc6f Mon Sep 17 00:00:00 2001 From: multiplexer Date: Sun, 8 Mar 2009 05:31:58 +0100 Subject: [PATCH 34/60] Restructured/Reordered Npc Commands Signed-off-by: VladimirMangos --- src/game/Chat.cpp | 37 +- src/game/Chat.h | 18 +- src/game/Level1.cpp | 2 + src/game/Level2.cpp | 1586 +++++++++++++++++++++---------------------- src/game/Level3.cpp | 207 +++--- 5 files changed, 928 insertions(+), 922 deletions(-) diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index e2eba78ba..cfc85dbef 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -417,26 +417,25 @@ ChatCommand * ChatHandler::getCommandTable() static ChatCommand npcCommandTable[] = { - { "say", SEC_MODERATOR, false, &ChatHandler::HandleNpcSayCommand, "", NULL }, - { "textemote", SEC_MODERATOR, false, &ChatHandler::HandleNpcTextEmoteCommand, "", NULL }, { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddCommand, "", NULL }, + { "additem", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddVendorItemCommand, "", NULL }, + { "addmove", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddMoveCommand, "", NULL }, + { "changeentry", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcChangeEntryCommand, "", NULL }, + { "changelevel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcChangeLevelCommand, "", NULL }, { "delete", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcDeleteCommand, "", NULL }, + { "factionid", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFactionIdCommand, "", NULL }, + { "flag", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFlagCommand, "", NULL }, + { "follow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFollowCommand, "", NULL }, + { "info", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcInfoCommand, "", NULL }, + { "move", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcMoveCommand, "", NULL }, + { "playemote", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcPlayEmoteCommand, "", NULL }, + { "setmodel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetModelCommand, "", NULL }, + { "setmovetype", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetMoveTypeCommand, "", NULL }, + { "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetPhaseCommand, "", NULL }, { "spawndist", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnDistCommand, "", NULL }, { "spawntime", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnTimeCommand, "", NULL }, - { "factionid", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFactionIdCommand, "", NULL }, - { "addmove", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddMoveCommand, "", NULL }, - { "setmovetype", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetMoveTypeCommand, "", NULL }, - { "move", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcMoveCommand, "", NULL }, - { "changelevel", SEC_GAMEMASTER, false, &ChatHandler::HandleChangeLevelCommand, "", NULL }, - { "setmodel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetModelCommand, "", NULL }, - { "additem", SEC_GAMEMASTER, false, &ChatHandler::HandleAddVendorItemCommand, "", NULL }, - { "delitem", SEC_GAMEMASTER, false, &ChatHandler::HandleDelVendorItemCommand, "", NULL }, - { "flag", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFlagCommand, "", NULL }, - { "changeentry", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcChangeEntryCommand, "", NULL }, - { "info", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcInfoCommand, "", NULL }, - { "playemote", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcPlayEmoteCommand, "", NULL }, - { "follow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFollowCommand, "", NULL }, - { "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetPhaseCommand, "", NULL }, + { "say", SEC_MODERATOR, false, &ChatHandler::HandleNpcSayCommand, "", NULL }, + { "textemote", SEC_MODERATOR, false, &ChatHandler::HandleNpcTextEmoteCommand, "", NULL }, { "unfollow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcUnFollowCommand, "", NULL }, { "whisper", SEC_MODERATOR, false, &ChatHandler::HandleNpcWhisperCommand, "", NULL }, { "yell", SEC_MODERATOR, false, &ChatHandler::HandleNpcYellCommand, "", NULL }, @@ -444,9 +443,9 @@ ChatCommand * ChatHandler::getCommandTable() { "setdeathstate", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetDeathStateCommand, "", NULL }, //{ TODO: fix or remove this commands - { "name", SEC_GAMEMASTER, false, &ChatHandler::HandleNameCommand, "", NULL }, - { "subname", SEC_GAMEMASTER, false, &ChatHandler::HandleSubNameCommand, "", NULL }, - { "addweapon", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAddWeaponCommand, "", NULL }, + { "addweapon", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcAddWeaponCommand, "", NULL }, + { "name", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcNameCommand, "", NULL }, + { "subname", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSubNameCommand, "", NULL }, //} { NULL, 0, false, NULL, "", NULL } diff --git a/src/game/Chat.h b/src/game/Chat.h index 0ab3bd902..b9dc9f01e 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -176,10 +176,14 @@ class ChatHandler bool HandleModifyPhaseCommand(const char* args); bool HandleModifyGenderCommand(const char* args); + //-----------------------Npc Commands----------------------- bool HandleNpcAddCommand(const char* args); bool HandleNpcAddMoveCommand(const char* args); + bool HandleNpcAddVendorItemCommand(const char* args); bool HandleNpcChangeEntryCommand(const char *args); + bool HandleNpcChangeLevelCommand(const char* args); bool HandleNpcDeleteCommand(const char* args); + bool HandleNpcDelVendorItemCommand(const char* args); bool HandleNpcFactionIdCommand(const char* args); bool HandleNpcFlagCommand(const char* args); bool HandleNpcFollowCommand(const char* args); @@ -187,6 +191,7 @@ class ChatHandler bool HandleNpcMoveCommand(const char* args); bool HandleNpcPlayEmoteCommand(const char* args); bool HandleNpcSayCommand(const char* args); + bool HandleNpcSetDeathStateCommand(const char* args); bool HandleNpcSetModelCommand(const char* args); bool HandleNpcSetMoveTypeCommand(const char* args); bool HandleNpcSetPhaseCommand(const char* args); @@ -197,7 +202,12 @@ class ChatHandler bool HandleNpcUnFollowCommand(const char* args); bool HandleNpcWhisperCommand(const char* args); bool HandleNpcYellCommand(const char* args); - bool HandleNpcSetDeathStateCommand(const char* args); + + //TODO: NpcCommands that needs to be fixed : + bool HandleNpcAddWeaponCommand(const char* args); + bool HandleNpcNameCommand(const char* args); + bool HandleNpcSubNameCommand(const char* args); + //---------------------------------------------------------- bool HandleReloadAllCommand(const char* args); bool HandleReloadAllAreaCommand(const char* args); @@ -300,13 +310,8 @@ class ChatHandler bool HandleDebugSpellFailCommand(const char* args); bool HandleGUIDCommand(const char* args); - bool HandleNameCommand(const char* args); - bool HandleSubNameCommand(const char* args); bool HandleItemMoveCommand(const char* args); bool HandleDeMorphCommand(const char* args); - bool HandleAddVendorItemCommand(const char* args); - bool HandleDelVendorItemCommand(const char* args); - bool HandleChangeLevelCommand(const char* args); bool HandleSetPoiCommand(const char* args); bool HandleEquipErrorCommand(const char* args); bool HandleGoCreatureCommand(const char* args); @@ -341,7 +346,6 @@ class ChatHandler bool HandleGoXYZCommand(const char* args); bool HandleGoZoneXYCommand(const char* args); bool HandleGoGridCommand(const char* args); - bool HandleAddWeaponCommand(const char* args); bool HandleAllowMovementCommand(const char* args); bool HandleGoCommand(const char* args); diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 4fd4e4a86..0cd1d08e1 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -36,6 +36,7 @@ #include "VMapFactory.h" #endif +//-----------------------Npc Commands----------------------- bool ChatHandler::HandleNpcSayCommand(const char* args) { if(!*args) @@ -119,6 +120,7 @@ bool ChatHandler::HandleNpcWhisperCommand(const char* args) return true; } +//---------------------------------------------------------- // global announce bool ChatHandler::HandleAnnounceCommand(const char* args) diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 4d8bc4fae..2654ecb15 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -731,134 +731,7 @@ bool ChatHandler::HandleModifyRepCommand(const char * args) return true; } -bool ChatHandler::HandleNameCommand(const char* /*args*/) -{ - /* Temp. disabled - if(!*args) - return false; - - if(strlen((char*)args)>75) - { - PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75); - return true; - } - - for (uint8 i = 0; i < strlen(args); i++) - { - if(!isalpha(args[i]) && args[i]!=' ') - { - SendSysMessage(LANG_CHARS_ONLY); - return false; - } - } - - uint64 guid; - guid = m_session->GetPlayer()->GetSelection(); - if (guid == 0) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); - - if(!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - pCreature->SetName(args); - uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName()); - pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); - - pCreature->SaveToDB(); - */ - - return true; -} - -bool ChatHandler::HandleSubNameCommand(const char* /*args*/) -{ - /* Temp. disabled - - if(!*args) - args = ""; - - if(strlen((char*)args)>75) - { - - PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75); - return true; - } - - for (uint8 i = 0; i < strlen(args); i++) - { - if(!isalpha(args[i]) && args[i]!=' ') - { - SendSysMessage(LANG_CHARS_ONLY); - return false; - } - } - uint64 guid; - guid = m_session->GetPlayer()->GetSelection(); - if (guid == 0) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); - - if(!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID)); - pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); - - pCreature->SaveToDB(); - */ - return true; -} - -//move item to other slot -bool ChatHandler::HandleItemMoveCommand(const char* args) -{ - if(!*args) - return false; - uint8 srcslot, dstslot; - - char* pParam1 = strtok((char*)args, " "); - if (!pParam1) - return false; - - char* pParam2 = strtok(NULL, " "); - if (!pParam2) - return false; - - srcslot = (uint8)atoi(pParam1); - dstslot = (uint8)atoi(pParam2); - - if(srcslot==dstslot) - return true; - - if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) - return false; - - if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) - return false; - - uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); - uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); - - m_session->GetPlayer()->SwapItem( src, dst ); - - return true; -} - +//-----------------------Npc Commands----------------------- //add spawn of creature bool ChatHandler::HandleNpcAddCommand(const char* args) { @@ -910,329 +783,8 @@ bool ChatHandler::HandleNpcAddCommand(const char* args) return true; } -bool ChatHandler::HandleNpcDeleteCommand(const char* args) -{ - Creature* unit = NULL; - - if(*args) - { - // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hcreature"); - if(!cId) - return false; - - uint32 lowguid = atoi(cId); - if(!lowguid) - return false; - - if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid)) - unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); - } - else - unit = getSelectedCreature(); - - if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle()) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // Delete the creature - unit->CombatStop(); - unit->DeleteFromDB(); - unit->CleanupsBeforeDelete(); - unit->AddObjectToRemoveList(); - - SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); - - return true; -} - -//delete object by selection or guid -bool ChatHandler::HandleDelObjectCommand(const char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if(!cId) - return false; - - uint32 lowguid = atoi(cId); - if(!lowguid) - return false; - - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); - - if(!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - uint64 owner_guid = obj->GetOwnerGUID(); - if(owner_guid) - { - Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid); - if(!owner && !IS_PLAYER_GUID(owner_guid)) - { - PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow()); - SetSentErrorMessage(true); - return false; - } - - owner->RemoveGameObject(obj,false); - } - - obj->SetRespawnTime(0); // not save respawn time - obj->Delete(); - obj->DeleteFromDB(); - - PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow()); - - return true; -} - -//turn selected object -bool ChatHandler::HandleTurnObjectCommand(const char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if(!cId) - return false; - - uint32 lowguid = atoi(cId); - if(!lowguid) - return false; - - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); - - if(!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - char* po = strtok(NULL, " "); - float o; - - if (po) - { - o = (float)atof(po); - } - else - { - Player *chr = m_session->GetPlayer(); - o = chr->GetOrientation(); - } - - float rot2 = sin(o/2); - float rot3 = cos(o/2); - - Map* map = obj->GetMap(); - map->Remove(obj,false); - - obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o); - - obj->SetFloatValue(GAMEOBJECT_FACING, o); - obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2); - obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3); - - map->Add(obj); - - obj->SaveToDB(); - obj->Refresh(); - - PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), o); - - return true; -} - -//move selected creature -bool ChatHandler::HandleNpcMoveCommand(const char* args) -{ - uint32 lowguid = 0; - - Creature* pCreature = getSelectedCreature(); - - if(!pCreature) - { - // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hcreature"); - if(!cId) - return false; - - uint32 lowguid = atoi(cId); - - /* FIXME: impossibel without entry - if(lowguid) - pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); - */ - - // Attempting creature load from DB data - if(!pCreature) - { - CreatureData const* data = objmgr.GetCreatureData(lowguid); - if(!data) - { - PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - uint32 map_id = data->mapid; - - if(m_session->GetPlayer()->GetMapId()!=map_id) - { - PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); - SetSentErrorMessage(true); - return false; - } - } - else - { - lowguid = pCreature->GetDBTableGUIDLow(); - } - } - else - { - lowguid = pCreature->GetDBTableGUIDLow(); - } - - float x = m_session->GetPlayer()->GetPositionX(); - float y = m_session->GetPlayer()->GetPositionY(); - float z = m_session->GetPlayer()->GetPositionZ(); - float o = m_session->GetPlayer()->GetOrientation(); - - if (pCreature) - { - if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow())) - { - const_cast(data)->posX = x; - const_cast(data)->posY = y; - const_cast(data)->posZ = z; - const_cast(data)->orientation = o; - } - pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o); - pCreature->GetMotionMaster()->Initialize(); - if(pCreature->isAlive()) // dead creature will reset movement generator at respawn - { - pCreature->setDeathState(JUST_DIED); - pCreature->Respawn(); - } - } - - WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid); - PSendSysMessage(LANG_COMMAND_CREATUREMOVED); - return true; -} - -//move selected object -bool ChatHandler::HandleMoveObjectCommand(const char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if(!cId) - return false; - - uint32 lowguid = atoi(cId); - if(!lowguid) - return false; - - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); - - if(!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - char* px = strtok(NULL, " "); - char* py = strtok(NULL, " "); - char* pz = strtok(NULL, " "); - - if (!px) - { - Player *chr = m_session->GetPlayer(); - - Map* map = obj->GetMap(); - map->Remove(obj,false); - - obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation()); - obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX()); - obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY()); - obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ()); - - map->Add(obj); - } - else - { - if(!py || !pz) - return false; - - float x = (float)atof(px); - float y = (float)atof(py); - float z = (float)atof(pz); - - if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId()); - SetSentErrorMessage(true); - return false; - } - - Map* map = obj->GetMap(); - map->Remove(obj,false); - - obj->Relocate(x, y, z, obj->GetOrientation()); - obj->SetFloatValue(GAMEOBJECT_POS_X, x); - obj->SetFloatValue(GAMEOBJECT_POS_Y, y); - obj->SetFloatValue(GAMEOBJECT_POS_Z, z); - - map->Add(obj); - } - - obj->SaveToDB(); - obj->Refresh(); - - PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow()); - - return true; -} - -//demorph player or unit -bool ChatHandler::HandleDeMorphCommand(const char* /*args*/) -{ - Unit *target = getSelectedUnit(); - if(!target) - target = m_session->GetPlayer(); - - - // check online security - else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) - return false; - - target->DeMorph(); - - return true; -} - //add item in vendorlist -bool ChatHandler::HandleAddVendorItemCommand(const char* args) +bool ChatHandler::HandleNpcAddVendorItemCommand(const char* args) { if (!*args) return false; @@ -1279,7 +831,7 @@ bool ChatHandler::HandleAddVendorItemCommand(const char* args) } //del item from vendor list -bool ChatHandler::HandleDelVendorItemCommand(const char* args) +bool ChatHandler::HandleNpcDelVendorItemCommand(const char* args) { if (!*args) return false; @@ -1377,7 +929,188 @@ bool ChatHandler::HandleNpcAddMoveCommand(const char* args) return true; } -/** +//change level of creature or pet +bool ChatHandler::HandleNpcChangeLevelCommand(const char* args) +{ + if (!*args) + return false; + + uint8 lvl = (uint8) atoi((char*)args); + if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if(pCreature->isPet()) + { + ((Pet*)pCreature)->GivePetLevel(lvl); + } + else + { + pCreature->SetMaxHealth( 100 + 30*lvl); + pCreature->SetHealth( 100 + 30*lvl); + pCreature->SetLevel( lvl); + pCreature->SaveToDB(); + } + + return true; +} + +//set npcflag of creature +bool ChatHandler::HandleNpcFlagCommand(const char* args) +{ + if (!*args) + return false; + + uint32 npcFlags = (uint32) atoi((char*)args); + + Creature* pCreature = getSelectedCreature(); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags); + + WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry()); + + SendSysMessage(LANG_VALUE_SAVED_REJOIN); + + return true; +} + +bool ChatHandler::HandleNpcDeleteCommand(const char* args) +{ + Creature* unit = NULL; + + if(*args) + { + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid)) + unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); + } + else + unit = getSelectedCreature(); + + if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // Delete the creature + unit->CombatStop(); + unit->DeleteFromDB(); + unit->CleanupsBeforeDelete(); + unit->AddObjectToRemoveList(); + + SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); + + return true; +} + +//move selected creature +bool ChatHandler::HandleNpcMoveCommand(const char* args) +{ + uint32 lowguid = 0; + + Creature* pCreature = getSelectedCreature(); + + if(!pCreature) + { + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + + /* FIXME: impossibel without entry + if(lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ + + // Attempting creature load from DB data + if(!pCreature) + { + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + uint32 map_id = data->mapid; + + if(m_session->GetPlayer()->GetMapId()!=map_id) + { + PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); + } + + float x = m_session->GetPlayer()->GetPositionX(); + float y = m_session->GetPlayer()->GetPositionY(); + float z = m_session->GetPlayer()->GetPositionZ(); + float o = m_session->GetPlayer()->GetOrientation(); + + if (pCreature) + { + if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow())) + { + const_cast(data)->posX = x; + const_cast(data)->posY = y; + const_cast(data)->posZ = z; + const_cast(data)->orientation = o; + } + pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o); + pCreature->GetMotionMaster()->Initialize(); + if(pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + } + + WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid); + PSendSysMessage(LANG_COMMAND_CREATUREMOVED); + return true; +} + +/**HandleNpcSetMoveTypeCommand * Set the movement type for an NPC.
*
* Valid movement types are: @@ -1516,69 +1249,6 @@ bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args) PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str); } - return true; -} // HandleNpcSetMoveTypeCommand - -//change level of creature or pet -bool ChatHandler::HandleChangeLevelCommand(const char* args) -{ - if (!*args) - return false; - - uint8 lvl = (uint8) atoi((char*)args); - if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Creature* pCreature = getSelectedCreature(); - if(!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if(pCreature->isPet()) - { - ((Pet*)pCreature)->GivePetLevel(lvl); - } - else - { - pCreature->SetMaxHealth( 100 + 30*lvl); - pCreature->SetHealth( 100 + 30*lvl); - pCreature->SetLevel( lvl); - pCreature->SaveToDB(); - } - - return true; -} - -//set npcflag of creature -bool ChatHandler::HandleNpcFlagCommand(const char* args) -{ - if (!*args) - return false; - - uint32 npcFlags = (uint32) atoi((char*)args); - - Creature* pCreature = getSelectedCreature(); - - if(!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags); - - WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry()); - - SendSysMessage(LANG_VALUE_SAVED_REJOIN); - return true; } @@ -1606,28 +1276,6 @@ bool ChatHandler::HandleNpcSetModelCommand(const char* args) return true; } - -//morph creature or player -bool ChatHandler::HandleMorphCommand(const char* args) -{ - if (!*args) - return false; - - uint16 display_id = (uint16)atoi((char*)args); - - Unit *target = getSelectedUnit(); - if(!target) - target = m_session->GetPlayer(); - - // check online security - else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) - return false; - - target->SetDisplayId(display_id); - - return true; -} - //set faction of creature bool ChatHandler::HandleNpcFactionIdCommand(const char* args) { @@ -1668,6 +1316,614 @@ bool ChatHandler::HandleNpcFactionIdCommand(const char* args) return true; } +//set spawn dist of creature +bool ChatHandler::HandleNpcSpawnDistCommand(const char* args) +{ + if(!*args) + return false; + + float option = atof((char*)args); + if (option < 0.0f) + { + SendSysMessage(LANG_BAD_VALUE); + return false; + } + + MovementGeneratorType mtype = IDLE_MOTION_TYPE; + if (option >0.0f) + mtype = RANDOM_MOTION_TYPE; + + Creature *pCreature = getSelectedCreature(); + uint32 u_guidlow = 0; + + if (pCreature) + u_guidlow = pCreature->GetDBTableGUIDLow(); + else + return false; + + pCreature->SetRespawnRadius((float)option); + pCreature->SetDefaultMovementType(mtype); + pCreature->GetMotionMaster()->Initialize(); + if(pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + + WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow); + PSendSysMessage(LANG_COMMAND_SPAWNDIST,option); + return true; +} +//spawn time handling +bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args) +{ + if(!*args) + return false; + + char* stime = strtok((char*)args, " "); + + if (!stime) + return false; + + int i_stime = atoi((char*)stime); + + if (i_stime < 0) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature *pCreature = getSelectedCreature(); + uint32 u_guidlow = 0; + + if (pCreature) + u_guidlow = pCreature->GetDBTableGUIDLow(); + else + return false; + + WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow); + pCreature->SetRespawnDelay((uint32)i_stime); + PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime); + + return true; +} +//npc follow handling +bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/) +{ + Player *player = m_session->GetPlayer(); + Creature *creature = getSelectedCreature(); + + if(!creature) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // Follow player - Using pet's default dist and angle + creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + + PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName()); + return true; +} +//npc unfollow handling +bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/) +{ + Player *player = m_session->GetPlayer(); + Creature *creature = getSelectedCreature(); + + if(!creature) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (creature->GetMotionMaster()->empty() || + creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE) + { + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); + SetSentErrorMessage(true); + return false; + } + + TargetedMovementGenerator const* mgen + = static_cast const*>((creature->GetMotionMaster()->top())); + + if(mgen->GetTarget()!=player) + { + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); + SetSentErrorMessage(true); + return false; + } + + // reset movement + creature->GetMotionMaster()->MovementExpired(true); + + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName()); + return true; +} +//npc tame handling +bool ChatHandler::HandleNpcTameCommand(const char* /*args*/) +{ + Creature *creatureTarget = getSelectedCreature (); + if (!creatureTarget || creatureTarget->isPet ()) + { + PSendSysMessage (LANG_SELECT_CREATURE); + SetSentErrorMessage (true); + return false; + } + + Player *player = m_session->GetPlayer (); + + if(player->GetPetGUID ()) + { + SendSysMessage (LANG_YOU_ALREADY_HAVE_PET); + SetSentErrorMessage (true); + return false; + } + + CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo(); + + if (!cInfo->isTameable ()) + { + PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); + SetSentErrorMessage (true); + return false; + } + + // Everything looks OK, create new pet + Pet* pet = player->CreateTamedPetFrom (creatureTarget); + if (!pet) + { + PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); + SetSentErrorMessage (true); + return false; + } + + // place pet before player + float x,y,z; + player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE); + pet->Relocate (x,y,z,M_PI-player->GetOrientation ()); + + // set pet to defensive mode by default (some classes can't control controlled pets in fact). + pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE); + + // calculate proper level + uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel(); + + // prepare visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); + + // add to world + pet->GetMap()->Add((Creature*)pet); + + // visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); + + // caster have pet now + player->SetPet(pet); + + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + player->PetSpellInitialize(); + + return true; +} +//npc phasemask handling +//change phasemask of creature or pet +bool ChatHandler::HandleNpcSetPhaseCommand(const char* args) +{ + if (!*args) + return false; + + uint32 phasemask = (uint32) atoi((char*)args); + if ( phasemask == 0 ) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetPhaseMask(phasemask,true); + + if(!pCreature->isPet()) + pCreature->SaveToDB(); + + return true; +} +//npc deathstate handling +bool ChatHandler::HandleNpcSetDeathStateCommand(const char* args) +{ + if (!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + if(!pCreature || pCreature->isPet()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (strncmp(args, "on", 3) == 0) + pCreature->SetDeadByDefault(true); + else if (strncmp(args, "off", 4) == 0) + pCreature->SetDeadByDefault(false); + else + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + pCreature->SaveToDB(); + pCreature->Respawn(); + + return true; +} + +//TODO: NpcCommands that need to be fixed : + +bool ChatHandler::HandleNpcNameCommand(const char* /*args*/) +{ + /* Temp. disabled + if(!*args) + return false; + + if(strlen((char*)args)>75) + { + PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75); + return true; + } + + for (uint8 i = 0; i < strlen(args); i++) + { + if(!isalpha(args[i]) && args[i]!=' ') + { + SendSysMessage(LANG_CHARS_ONLY); + return false; + } + } + + uint64 guid; + guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + pCreature->SetName(args); + uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName()); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + + return true; +} + +bool ChatHandler::HandleNpcSubNameCommand(const char* /*args*/) +{ + /* Temp. disabled + + if(!*args) + args = ""; + + if(strlen((char*)args)>75) + { + + PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75); + return true; + } + + for (uint8 i = 0; i < strlen(args); i++) + { + if(!isalpha(args[i]) && args[i]!=' ') + { + SendSysMessage(LANG_CHARS_ONLY); + return false; + } + } + uint64 guid; + guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID)); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + return true; +} + +//move item to other slot +bool ChatHandler::HandleItemMoveCommand(const char* args) +{ + if(!*args) + return false; + uint8 srcslot, dstslot; + + char* pParam1 = strtok((char*)args, " "); + if (!pParam1) + return false; + + char* pParam2 = strtok(NULL, " "); + if (!pParam2) + return false; + + srcslot = (uint8)atoi(pParam1); + dstslot = (uint8)atoi(pParam2); + + if(srcslot==dstslot) + return true; + + if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) + return false; + + if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) + return false; + + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); + uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); + + m_session->GetPlayer()->SwapItem( src, dst ); + + return true; +} + +//delete object by selection or guid +bool ChatHandler::HandleDelObjectCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if(!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + uint64 owner_guid = obj->GetOwnerGUID(); + if(owner_guid) + { + Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid); + if(!owner && !IS_PLAYER_GUID(owner_guid)) + { + PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow()); + SetSentErrorMessage(true); + return false; + } + + owner->RemoveGameObject(obj,false); + } + + obj->SetRespawnTime(0); // not save respawn time + obj->Delete(); + obj->DeleteFromDB(); + + PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow()); + + return true; +} + +//turn selected object +bool ChatHandler::HandleTurnObjectCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if(!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* po = strtok(NULL, " "); + float o; + + if (po) + { + o = (float)atof(po); + } + else + { + Player *chr = m_session->GetPlayer(); + o = chr->GetOrientation(); + } + + float rot2 = sin(o/2); + float rot3 = cos(o/2); + + Map* map = obj->GetMap(); + map->Remove(obj,false); + + obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o); + + obj->SetFloatValue(GAMEOBJECT_FACING, o); + obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2); + obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3); + + map->Add(obj); + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), o); + + return true; +} + +//move selected object +bool ChatHandler::HandleMoveObjectCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if(!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* px = strtok(NULL, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + + if (!px) + { + Player *chr = m_session->GetPlayer(); + + Map* map = obj->GetMap(); + map->Remove(obj,false); + + obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation()); + obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX()); + obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY()); + obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ()); + + map->Add(obj); + } + else + { + if(!py || !pz) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + float z = (float)atof(pz); + + if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId()); + SetSentErrorMessage(true); + return false; + } + + Map* map = obj->GetMap(); + map->Remove(obj,false); + + obj->Relocate(x, y, z, obj->GetOrientation()); + obj->SetFloatValue(GAMEOBJECT_POS_X, x); + obj->SetFloatValue(GAMEOBJECT_POS_Y, y); + obj->SetFloatValue(GAMEOBJECT_POS_Z, z); + + map->Add(obj); + } + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow()); + + return true; +} + +//demorph player or unit +bool ChatHandler::HandleDeMorphCommand(const char* /*args*/) +{ + Unit *target = getSelectedUnit(); + if(!target) + target = m_session->GetPlayer(); + + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + target->DeMorph(); + + return true; +} + +//morph creature or player +bool ChatHandler::HandleMorphCommand(const char* args) +{ + if (!*args) + return false; + + uint16 display_id = (uint16)atoi((char*)args); + + Unit *target = getSelectedUnit(); + if(!target) + target = m_session->GetPlayer(); + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + target->SetDisplayId(display_id); + + return true; +} //kick player bool ChatHandler::HandleKickPlayerCommand(const char *args) @@ -2111,79 +2367,6 @@ bool ChatHandler::HandleDelTicketCommand(const char *args) return true; } -//set spawn dist of creature -bool ChatHandler::HandleNpcSpawnDistCommand(const char* args) -{ - if(!*args) - return false; - - float option = atof((char*)args); - if (option < 0.0f) - { - SendSysMessage(LANG_BAD_VALUE); - return false; - } - - MovementGeneratorType mtype = IDLE_MOTION_TYPE; - if (option >0.0f) - mtype = RANDOM_MOTION_TYPE; - - Creature *pCreature = getSelectedCreature(); - uint32 u_guidlow = 0; - - if (pCreature) - u_guidlow = pCreature->GetDBTableGUIDLow(); - else - return false; - - pCreature->SetRespawnRadius((float)option); - pCreature->SetDefaultMovementType(mtype); - pCreature->GetMotionMaster()->Initialize(); - if(pCreature->isAlive()) // dead creature will reset movement generator at respawn - { - pCreature->setDeathState(JUST_DIED); - pCreature->Respawn(); - } - - WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow); - PSendSysMessage(LANG_COMMAND_SPAWNDIST,option); - return true; -} - -bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args) -{ - if(!*args) - return false; - - char* stime = strtok((char*)args, " "); - - if (!stime) - return false; - - int i_stime = atoi((char*)stime); - - if (i_stime < 0) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Creature *pCreature = getSelectedCreature(); - uint32 u_guidlow = 0; - - if (pCreature) - u_guidlow = pCreature->GetDBTableGUIDLow(); - else - return false; - - WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow); - pCreature->SetRespawnDelay((uint32)i_stime); - PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime); - - return true; -} - /** * Add a waypoint to a creature. * @@ -4123,158 +4306,6 @@ bool ChatHandler::HandleWaterwalkCommand(const char* args) return true; } -bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/) -{ - Player *player = m_session->GetPlayer(); - Creature *creature = getSelectedCreature(); - - if(!creature) - { - PSendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // Follow player - Using pet's default dist and angle - creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - - PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName()); - return true; -} - -bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/) -{ - Player *player = m_session->GetPlayer(); - Creature *creature = getSelectedCreature(); - - if(!creature) - { - PSendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (creature->GetMotionMaster()->empty() || - creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE) - { - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); - SetSentErrorMessage(true); - return false; - } - - TargetedMovementGenerator const* mgen - = static_cast const*>((creature->GetMotionMaster()->top())); - - if(mgen->GetTarget()!=player) - { - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); - SetSentErrorMessage(true); - return false; - } - - // reset movement - creature->GetMotionMaster()->MovementExpired(true); - - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName()); - return true; -} - -bool ChatHandler::HandleNpcTameCommand(const char* /*args*/) -{ - Creature *creatureTarget = getSelectedCreature (); - if (!creatureTarget || creatureTarget->isPet ()) - { - PSendSysMessage (LANG_SELECT_CREATURE); - SetSentErrorMessage (true); - return false; - } - - Player *player = m_session->GetPlayer (); - - if(player->GetPetGUID ()) - { - SendSysMessage (LANG_YOU_ALREADY_HAVE_PET); - SetSentErrorMessage (true); - return false; - } - - CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo(); - - if (!cInfo->isTameable ()) - { - PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); - SetSentErrorMessage (true); - return false; - } - - // Everything looks OK, create new pet - Pet* pet = player->CreateTamedPetFrom (creatureTarget); - if (!pet) - { - PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); - SetSentErrorMessage (true); - return false; - } - - // place pet before player - float x,y,z; - player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE); - pet->Relocate (x,y,z,M_PI-player->GetOrientation ()); - - // set pet to defensive mode by default (some classes can't control controlled pets in fact). - pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE); - - // calculate proper level - uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel(); - - // prepare visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); - - // add to world - pet->GetMap()->Add((Creature*)pet); - - // visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); - - // caster have pet now - player->SetPet(pet); - - pet->SavePetToDB(PET_SAVE_AS_CURRENT); - player->PetSpellInitialize(); - - return true; -} - -//change phasemask of creature or pet -bool ChatHandler::HandleNpcSetPhaseCommand(const char* args) -{ - if (!*args) - return false; - - uint32 phasemask = (uint32) atoi((char*)args); - if ( phasemask == 0 ) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Creature* pCreature = getSelectedCreature(); - if(!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->SetPhaseMask(phasemask,true); - - if(!pCreature->isPet()) - pCreature->SaveToDB(); - - return true; -} - //set pahsemask for selected object bool ChatHandler::HandleGOPhaseCommand(const char* args) { @@ -4313,34 +4344,3 @@ bool ChatHandler::HandleGOPhaseCommand(const char* args) obj->SaveToDB(); return true; } - -bool ChatHandler::HandleNpcSetDeathStateCommand(const char* args) -{ - if (!*args) - return false; - - Creature* pCreature = getSelectedCreature(); - if(!pCreature || pCreature->isPet()) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (strncmp(args, "on", 3) == 0) - pCreature->SetDeadByDefault(true); - else if (strncmp(args, "off", 4) == 0) - pCreature->SetDeadByDefault(false); - else - { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; - } - - pCreature->SaveToDB(); - pCreature->Respawn(); - - return true; -} - diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index d1d0c28b0..ab342f252 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3260,77 +3260,6 @@ bool ChatHandler::HandleGetDistanceCommand(const char* args) return true; } -// FIX-ME!!! - -bool ChatHandler::HandleAddWeaponCommand(const char* /*args*/) -{ - /*if (!*args) - return false; - - uint64 guid = m_session->GetPlayer()->GetSelection(); - if (guid == 0) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature *pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); - - if(!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - char* pSlotID = strtok((char*)args, " "); - if (!pSlotID) - return false; - - char* pItemID = strtok(NULL, " "); - if (!pItemID) - return false; - - uint32 ItemID = atoi(pItemID); - uint32 SlotID = atoi(pSlotID); - - ItemPrototype* tmpItem = objmgr.GetItemPrototype(ItemID); - - bool added = false; - if(tmpItem) - { - switch(SlotID) - { - case 1: - pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, ItemID); - added = true; - break; - case 2: - pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, ItemID); - added = true; - break; - case 3: - pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, ItemID); - added = true; - break; - default: - PSendSysMessage(LANG_ITEM_SLOT_NOT_EXIST,SlotID); - added = false; - break; - } - if(added) - { - PSendSysMessage(LANG_ITEM_ADDED_TO_SLOT,ItemID,tmpItem->Name1,SlotID); - } - } - else - { - PSendSysMessage(LANG_ITEM_NOT_FOUND,ItemID); - return true; - } - */ - return true; -} - bool ChatHandler::HandleDieCommand(const char* /*args*/) { Unit* target = getSelectedUnit(); @@ -3664,21 +3593,28 @@ bool ChatHandler::HandleNearGraveCommand(const char* args) return true; } -//play npc emote -bool ChatHandler::HandleNpcPlayEmoteCommand(const char* args) +//-----------------------Npc Commands----------------------- +bool ChatHandler::HandleNpcChangeEntryCommand(const char *args) { - uint32 emote = atoi((char*)args); + if(!args) + return false; - Creature* target = getSelectedCreature(); - if(!target) + uint32 newEntryNum = atoi(args); + if(!newEntryNum) + return false; + + Unit* unit = getSelectedUnit(); + if(!unit || unit->GetTypeId() != TYPEID_UNIT) { SendSysMessage(LANG_SELECT_CREATURE); SetSentErrorMessage(true); return false; } - - target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote); - + Creature* creature = (Creature*)unit; + if(creature->UpdateEntry(newEntryNum)) + SendSysMessage(LANG_DONE); + else + SendSysMessage(LANG_ERROR); return true; } @@ -3727,6 +3663,95 @@ bool ChatHandler::HandleNpcInfoCommand(const char* /*args*/) return true; } +//play npc emote +bool ChatHandler::HandleNpcPlayEmoteCommand(const char* args) +{ + uint32 emote = atoi((char*)args); + + Creature* target = getSelectedCreature(); + if(!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote); + + return true; +} + +//TODO: NpcCommands that needs to be fixed : + +bool ChatHandler::HandleNpcAddWeaponCommand(const char* /*args*/) +{ + /*if (!*args) + return false; + + uint64 guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature *pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + char* pSlotID = strtok((char*)args, " "); + if (!pSlotID) + return false; + + char* pItemID = strtok(NULL, " "); + if (!pItemID) + return false; + + uint32 ItemID = atoi(pItemID); + uint32 SlotID = atoi(pSlotID); + + ItemPrototype* tmpItem = objmgr.GetItemPrototype(ItemID); + + bool added = false; + if(tmpItem) + { + switch(SlotID) + { + case 1: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, ItemID); + added = true; + break; + case 2: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, ItemID); + added = true; + break; + case 3: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, ItemID); + added = true; + break; + default: + PSendSysMessage(LANG_ITEM_SLOT_NOT_EXIST,SlotID); + added = false; + break; + } + + if(added) + PSendSysMessage(LANG_ITEM_ADDED_TO_SLOT,ItemID,tmpItem->Name1,SlotID); + } + else + { + PSendSysMessage(LANG_ITEM_NOT_FOUND,ItemID); + return true; + } + */ + return true; +} +//---------------------------------------------------------- + bool ChatHandler::HandleExploreCheatCommand(const char* args) { if (!*args) @@ -5685,30 +5710,6 @@ bool ChatHandler::HandleLoadPDumpCommand(const char *args) return true; } -bool ChatHandler::HandleNpcChangeEntryCommand(const char *args) -{ - if(!args) - return false; - - uint32 newEntryNum = atoi(args); - if(!newEntryNum) - return false; - - Unit* unit = getSelectedUnit(); - if(!unit || unit->GetTypeId() != TYPEID_UNIT) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - Creature* creature = (Creature*)unit; - if(creature->UpdateEntry(newEntryNum)) - SendSysMessage(LANG_DONE); - else - SendSysMessage(LANG_ERROR); - return true; -} - bool ChatHandler::HandleWritePDumpCommand(const char *args) { if(!args) From ba1cfbf121553689bc16b1abf5f1080629887099 Mon Sep 17 00:00:00 2001 From: multiplexer Date: Sun, 8 Mar 2009 05:55:22 +0100 Subject: [PATCH 35/60] Flat Modifier for Glyph of Spiritual Attunement --- src/game/Unit.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 0d79bde04..37f0a5fbe 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -5516,6 +5516,17 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu break; } + // Glyph of Spiritual Attunement + case 54924: + { + // if healed by another unit (pVictim) + if(this == pVictim) + return false; + target = this; + triggered_spell_id = 55111; + basepoints0 = triggerAmount*damage/100; + break; + } // Glyph of Divinity case 54939: { From ebccd69b2f236987d68095fbed9f20c1650ae4ca Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 9 Mar 2009 05:44:49 +0300 Subject: [PATCH 36/60] [7417] Fixed crash at access by unexpected NULL pointer in quest templates map. Never never use operator[] for _access_ to elements std::map. --- src/game/ObjectMgr.cpp | 16 ++++++++++------ src/shared/revision_nr.h | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index df059e4da..9e296453e 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3282,14 +3282,15 @@ void ObjectMgr::LoadQuests() if(qinfo->NextQuestInChain) { - if(mQuestTemplates.find(qinfo->NextQuestInChain) == mQuestTemplates.end()) + QuestMap::iterator qNextItr = mQuestTemplates.find(qinfo->NextQuestInChain); + if(qNextItr == mQuestTemplates.end()) { sLog.outErrorDb("Quest %u has `NextQuestInChain` = %u but quest %u does not exist, quest chain will not work.", qinfo->GetQuestId(),qinfo->NextQuestInChain ,qinfo->NextQuestInChain ); qinfo->NextQuestInChain = 0; } else - mQuestTemplates[qinfo->NextQuestInChain]->prevChainQuests.push_back(qinfo->GetQuestId()); + qNextItr->second->prevChainQuests.push_back(qinfo->GetQuestId()); } // fill additional data stores @@ -3307,14 +3308,15 @@ void ObjectMgr::LoadQuests() if(qinfo->NextQuestId) { - if (mQuestTemplates.find(abs(qinfo->GetNextQuestId())) == mQuestTemplates.end()) + QuestMap::iterator qNextItr = mQuestTemplates.find(abs(qinfo->GetNextQuestId())); + if (qNextItr == mQuestTemplates.end()) { sLog.outErrorDb("Quest %d has NextQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId()); } else { int32 signedQuestId = qinfo->NextQuestId < 0 ? -int32(qinfo->GetQuestId()) : int32(qinfo->GetQuestId()); - mQuestTemplates[abs(qinfo->GetNextQuestId())]->prevQuests.push_back(signedQuestId); + qNextItr->second->prevQuests.push_back(signedQuestId); } } @@ -4949,7 +4951,8 @@ void ObjectMgr::LoadAreaTriggerTeleports() if(at.requiredQuest) { - if(!mQuestTemplates[at.requiredQuest]) + QuestMap::iterator qReqItr = mQuestTemplates.find(at.requiredQuest); + if(qReqItr != mQuestTemplates.end()) { sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",at.requiredQuest,Trigger_ID); at.requiredQuest = 0; @@ -4958,7 +4961,8 @@ void ObjectMgr::LoadAreaTriggerTeleports() if(at.requiredQuestHeroic) { - if(!mQuestTemplates[at.requiredQuestHeroic]) + QuestMap::iterator qReqItr = mQuestTemplates.find(at.requiredQuestHeroic); + if(qReqItr != mQuestTemplates.end()) { sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",at.requiredQuestHeroic,Trigger_ID); at.requiredQuestHeroic = 0; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 25a6661fb..278a8f916 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7416" + #define REVISION_NR "7417" #endif // __REVISION_NR_H__ From 44f3c15710ab04d9664fde3bc75647bc0325e8fc Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 9 Mar 2009 06:43:26 +0300 Subject: [PATCH 37/60] Revert "Flat Modifier for Glyph of Spiritual Attunement" This reverts commit 332371c284a6513693786ab6c3fa933570953159. Signed-off-by: VladimirMangos unexpectadly cpushed, sorry. --- src/game/Unit.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 37f0a5fbe..0d79bde04 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -5516,17 +5516,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu break; } - // Glyph of Spiritual Attunement - case 54924: - { - // if healed by another unit (pVictim) - if(this == pVictim) - return false; - target = this; - triggered_spell_id = 55111; - basepoints0 = triggerAmount*damage/100; - break; - } // Glyph of Divinity case 54939: { From bf718ea9615a6bc2bd088e77b6fffc532df428f5 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 9 Mar 2009 07:57:06 +0300 Subject: [PATCH 38/60] [7418] Implement new log filter LogFilter_AchievementUpdates that let avoid achievments updates spam in logs if not needed. Enabled by default. --- src/game/AchievementMgr.cpp | 12 +++++++++--- src/mangosd/mangosd.conf.dist.in | 6 ++++-- src/shared/Log.cpp | 2 ++ src/shared/Log.h | 3 ++- src/shared/revision_nr.h | 2 +- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 6048c8ea7..b98b1290e 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -308,7 +308,10 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) { - sLog.outDebug("AchievementMgr::SendAchievementEarned(%u)", achievement->ID); + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_ACHIEVEMENT_UPDATES)==0) + sLog.outDebug("AchievementMgr::SendAchievementEarned(%u)", achievement->ID); + #endif if(Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId())) { @@ -392,7 +395,8 @@ static const uint32 achievIdForDangeon[][4] = */ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, Unit *unit, uint32 time) { - sLog.outDetail("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time); + if((sLog.getLogFilter() & LOG_FILTER_ACHIEVEMENT_UPDATES)==0) + sLog.outDetail("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time); if (!sWorld.getConfig(CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS) && m_player->GetSession()->GetSecurity() > SEC_PLAYER) return; @@ -1023,7 +1027,9 @@ AchievementCompletionState AchievementMgr::GetAchievementCompletionState(Achieve void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype) { - sLog.outDetail("AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue); + if((sLog.getLogFilter() & LOG_FILTER_ACHIEVEMENT_UPDATES)==0) + sLog.outDetail("AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue); + CriteriaProgress *progress = NULL; CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID); diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index a6a7f29bd..86c600194 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -219,8 +219,9 @@ AddonChannel = 1 # 0 = Minimum; 1 = Error; 2 = Detail; 3 = Full/Debug # Default: 0 # -# LogFilter_TransportMoves +# LogFilter_AchievementUpdates # LogFilter_CreatureMoves +# LogFilter_TransportMoves # LogFilter_VisibilityChanges # Log filters # Default: 1 - not include with any log level @@ -288,8 +289,9 @@ LogTime = 0 LogFile = "Server.log" LogTimestamp = 0 LogFileLevel = 0 -LogFilter_TransportMoves = 1 +LogFilter_AchievementUpdates = 1 LogFilter_CreatureMoves = 1 +LogFilter_TransportMoves = 1 LogFilter_VisibilityChanges = 1 WorldLogFile = "" DBErrorLogFile = "DBErrors.log" diff --git a/src/shared/Log.cpp b/src/shared/Log.cpp index 904ac704a..97c2e7164 100644 --- a/src/shared/Log.cpp +++ b/src/shared/Log.cpp @@ -243,6 +243,8 @@ void Log::Initialize() m_logFilter |= LOG_FILTER_CREATURE_MOVES; if(sConfig.GetBoolDefault("LogFilter_VisibilityChanges", true)) m_logFilter |= LOG_FILTER_VISIBILITY_CHANGES; + if(sConfig.GetBoolDefault("LogFilter_AchievementUpdates", true)) + m_logFilter |= LOG_FILTER_ACHIEVEMENT_UPDATES; // Char log settings m_charLog_Dump = sConfig.GetBoolDefault("CharLogDump", false); diff --git a/src/shared/Log.h b/src/shared/Log.h index 85fac5ed3..0c637b975 100644 --- a/src/shared/Log.h +++ b/src/shared/Log.h @@ -29,7 +29,8 @@ enum LogFilters { LOG_FILTER_TRANSPORT_MOVES = 1, LOG_FILTER_CREATURE_MOVES = 2, - LOG_FILTER_VISIBILITY_CHANGES = 4 + LOG_FILTER_VISIBILITY_CHANGES = 4, + LOG_FILTER_ACHIEVEMENT_UPDATES= 8 }; enum Color diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 278a8f916..377261b73 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7417" + #define REVISION_NR "7418" #endif // __REVISION_NR_H__ From 4dad8f40d0c547f7d33af1aee3aadfe6d930d0cb Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 9 Mar 2009 08:22:29 +0300 Subject: [PATCH 39/60] [7419] Fixed some type convertion warnings. --- src/game/SpellAuras.cpp | 4 ++-- src/game/SpellEffects.cpp | 2 +- src/game/Unit.cpp | 26 +++++++++++++++----------- src/shared/revision_nr.h | 2 +- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index d266abf4f..0bdbbda25 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3108,7 +3108,7 @@ void Aura::HandleModPossessPet(bool apply, bool Real) else pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); - ((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : NULL); + ((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : 0); ((Player*)caster)->SetCharm(apply ? pet : NULL); ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0); @@ -4181,7 +4181,7 @@ void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) { // Explosive Shot if (apply && !loading && caster) - m_modifier.m_amount +=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100; + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100); break; } } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index cbbf73a05..abfc1cd64 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1255,7 +1255,7 @@ void Spell::EffectDummy(uint32 i) if (m_spellInfo->SpellFamilyFlags & 0x0000000000040000LL) { // In 303 exist spirit depend - uint32 spirit = m_caster->GetStat(STAT_SPIRIT); + uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT)); switch (m_spellInfo->Id) { case 1454: damage+=spirit; break; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 0d79bde04..04b83a9de 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -6029,7 +6029,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB //else if (auraSpellInfo->Id==47300) // Dark Flame Aura else if (auraSpellInfo->Id==57345) // Darkmoon Card: Greatness { - uint32 stat = 0; + float stat = 0.0f; // strength if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 60229;stat = GetStat(STAT_STRENGTH); } // agility @@ -7618,10 +7618,12 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 coeff = bonus->dot_damage * LvlPenalty * stack; else coeff = bonus->direct_damage * LvlPenalty * stack; + if (bonus->ap_bonus) - DoneTotal+=bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack; - DoneTotal += DoneAdvertisedBenefit * coeff * SpellModSpellDamage; - TakenTotal+= TakenAdvertisedBenefit * coeff; + DoneTotal += int32(bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack); + + DoneTotal += int32(DoneAdvertisedBenefit * coeff * SpellModSpellDamage); + TakenTotal += int32(TakenAdvertisedBenefit * coeff); } // Default calculation else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit) @@ -7671,8 +7673,8 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 break; } } - DoneTotal += DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * SpellModSpellDamage; - TakenTotal+= TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty; + DoneTotal += int32(DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * SpellModSpellDamage); + TakenTotal+= int32(TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty); } float tmpDamage = (pdamage + DoneTotal) * DoneTotalMod; @@ -8034,10 +8036,12 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint coeff = bonus->dot_damage * LvlPenalty * stack; else coeff = bonus->direct_damage * LvlPenalty * stack; + if (bonus->ap_bonus) - DoneTotal+=bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack; - DoneTotal += DoneAdvertisedBenefit * coeff * SpellModSpellDamage; - TakenTotal+= TakenAdvertisedBenefit * coeff; + DoneTotal += int32(bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack); + + DoneTotal += int32(DoneAdvertisedBenefit * coeff * SpellModSpellDamage); + TakenTotal += int32(TakenAdvertisedBenefit * coeff); } // Default calculation else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit) @@ -8087,8 +8091,8 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint break; } } - DoneTotal += DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * SpellModSpellDamage * 1.88f; - TakenTotal+= TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * 1.88f; + DoneTotal += int32(DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * SpellModSpellDamage * 1.88f); + TakenTotal += int32(TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * 1.88f); } // use float as more appropriate for negative values and percent applying diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 377261b73..b22640c2f 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7418" + #define REVISION_NR "7419" #endif // __REVISION_NR_H__ From 8bb451c85cae5416d7ff8f70f7d51e8f66ed0cdf Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 9 Mar 2009 10:07:41 +0300 Subject: [PATCH 40/60] [7420] Not set cdecl calling convention for x64 platform for Unic/Linux. This will prevent generation "warning: 'cdecl' attribute ignored" --- src/framework/Platform/Define.h | 2 ++ src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/framework/Platform/Define.h b/src/framework/Platform/Define.h index 5602bb365..831849369 100644 --- a/src/framework/Platform/Define.h +++ b/src/framework/Platform/Define.h @@ -55,6 +55,8 @@ # define MANGOS_GET_PROC_ADDR dlsym # if defined(__APPLE_CC__) && defined(BIG_ENDIAN) # define MANGOS_IMPORT __attribute__ ((longcall)) +# elif defined(__x86_64__) +# define MANGOS_IMPORT # else # define MANGOS_IMPORT __attribute__ ((cdecl)) # endif //__APPLE_CC__ && BIG_ENDIAN diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b22640c2f..8c833b0df 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7419" + #define REVISION_NR "7420" #endif // __REVISION_NR_H__ From 60a3366892c06853940c5d87fa50d4771bf36847 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 9 Mar 2009 10:11:20 +0300 Subject: [PATCH 41/60] [7421] Check fread result at DBC file loading. This is more safe in general and prevent "warning: ignoring return value of 'size_t fread(void*, size_t, size_t, FILE*)', declared with attribute warn_unused_result" --- src/shared/Database/dbcfile.cpp | 33 ++++++++++++++++++++++++--------- src/shared/revision_nr.h | 2 +- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/shared/Database/dbcfile.cpp b/src/shared/Database/dbcfile.cpp index 0cfc7ada3..519e77de7 100644 --- a/src/shared/Database/dbcfile.cpp +++ b/src/shared/Database/dbcfile.cpp @@ -37,23 +37,35 @@ bool DBCFile::Load(const char *filename, const char *fmt) delete [] data; data=NULL; } + FILE * f=fopen(filename,"rb"); if(!f)return false; - fread(&header,4,1,f); // Number of records + if(fread(&header,4,1,f)!=1) // Number of records + return false; + EndianConvert(header); if(header!=0x43424457) - { - //printf("not dbc file"); return false; //'WDBC' - } - fread(&recordCount,4,1,f); // Number of records + + if(fread(&recordCount,4,1,f)!=1) // Number of records + return false; + EndianConvert(recordCount); - fread(&fieldCount,4,1,f); // Number of fields + + if(fread(&fieldCount,4,1,f)!=1) // Number of fields + return false; + EndianConvert(fieldCount); - fread(&recordSize,4,1,f); // Size of a record + + if(fread(&recordSize,4,1,f)!=1) // Size of a record + return false; + EndianConvert(recordSize); - fread(&stringSize,4,1,f); // String size + + if(fread(&stringSize,4,1,f)!=1) // String size + return false; + EndianConvert(stringSize); fieldsOffset = new uint32[fieldCount]; @@ -69,7 +81,10 @@ bool DBCFile::Load(const char *filename, const char *fmt) data = new unsigned char[recordSize*recordCount+stringSize]; stringTable = data + recordSize*recordCount; - fread(data,recordSize*recordCount+stringSize,1,f); + + if(fread(data,recordSize*recordCount+stringSize,1,f)!=1) + return false; + fclose(f); return true; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 8c833b0df..6af72ad25 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7420" + #define REVISION_NR "7421" #endif // __REVISION_NR_H__ From eac584eb89e6c76c656f7e76ce3f42af8f74aa75 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 9 Mar 2009 11:40:18 +0300 Subject: [PATCH 42/60] [7422] Allow localization base at guildmaster locale default guild rank names at guild creating. --- sql/mangos.sql | 7 +++- sql/updates/7422_01_mangos_mangos_string.sql | 9 ++++++ sql/updates/Makefile.am | 2 ++ src/game/Guild.cpp | 34 ++++++++------------ src/game/Guild.h | 2 +- src/game/GuildHandler.cpp | 2 +- src/game/Language.h | 7 +++- src/game/Level3.cpp | 2 +- src/game/PetitionsHandler.cpp | 2 +- src/shared/revision_nr.h | 2 +- 10 files changed, 42 insertions(+), 27 deletions(-) create mode 100644 sql/updates/7422_01_mangos_mangos_string.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 3de564fca..0fbc1a574 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7399_01_mangos_mangos_string` bit(1) default NULL + `required_7422_01_mangos_mangos_string` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -2849,6 +2849,11 @@ INSERT INTO `mangos_string` VALUES (808,'Player %s not found or offline',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (809,'Account for character %s not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (810,'|Hplayer:$N|h[$N]|h has earned the achievement $a!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(811,'Guild Master',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(812,'Officer',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(813,'Veteran',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(814,'Member',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(815,'Initiate',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1000,'Exiting daemon...',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1001,'Account deleted: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1002,'Account %s NOT deleted (probably sql file format was updated)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), diff --git a/sql/updates/7422_01_mangos_mangos_string.sql b/sql/updates/7422_01_mangos_mangos_string.sql new file mode 100644 index 000000000..affe8f747 --- /dev/null +++ b/sql/updates/7422_01_mangos_mangos_string.sql @@ -0,0 +1,9 @@ +ALTER TABLE db_version CHANGE COLUMN required_7399_01_mangos_mangos_string required_7422_01_mangos_mangos_string bit; + +DELETE FROM mangos_string WHERE entry in (811, 812, 813, 814, 815); +INSERT INTO mangos_string VALUES + (811,'Guild Master',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), + (812,'Officer',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), + (813,'Veteran',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), + (814,'Member',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), + (815,'Initiate',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index ea455f781..c1ea02a7b 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -195,6 +195,7 @@ pkgdata_DATA = \ 7390_01_mangos_areatrigger_teleport.sql \ 7393_01_mangos_game_event.sql \ 7399_01_mangos_mangos_string.sql \ + 7422_01_mangos_mangos_string.sql \ README ## Additional files to include when running 'make dist' @@ -370,4 +371,5 @@ EXTRA_DIST = \ 7390_01_mangos_areatrigger_teleport.sql \ 7393_01_mangos_game_event.sql \ 7399_01_mangos_mangos_string.sql \ + 7422_01_mangos_mangos_string.sql \ README diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index 239782f9e..a13fc049d 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -26,6 +26,7 @@ #include "Chat.h" #include "SocialMgr.h" #include "Util.h" +#include "Language.h" Guild::Guild() { @@ -49,27 +50,25 @@ Guild::~Guild() } -bool Guild::create(uint64 lGuid, std::string gname) +bool Guild::create(Player* leader, std::string gname) { - std::string rname; - std::string lName; - - if(!objmgr.GetPlayerNameByGUID(lGuid, lName)) - return false; if(objmgr.GetGuildByName(gname)) return false; - sLog.outDebug("GUILD: creating guild %s to leader: %u", gname.c_str(), GUID_LOPART(lGuid)); + WorldSession* lSession = leader->GetSession(); + if(!lSession) + return false; - leaderGuid = lGuid; + leaderGuid = leader->GetGUID(); name = gname; GINFO = ""; MOTD = "No message set."; guildbank_money = 0; purchased_tabs = 0; - Id = objmgr.GenerateGuildId(); + sLog.outDebug("GUILD: creating guild %s to leader: %u", gname.c_str(), GUID_LOPART(leaderGuid)); + // gname already assigned to Guild::name, use it to encode string for DB CharacterDatabase.escape_string(gname); @@ -87,18 +86,13 @@ bool Guild::create(uint64 lGuid, std::string gname) Id, gname.c_str(), GUID_LOPART(leaderGuid), dbGINFO.c_str(), dbMOTD.c_str(), EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor, guildbank_money); CharacterDatabase.CommitTransaction(); - rname = "Guild Master"; - CreateRank(rname,GR_RIGHT_ALL); - rname = "Officer"; - CreateRank(rname,GR_RIGHT_ALL); - rname = "Veteran"; - CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); - rname = "Member"; - CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); - rname = "Initiate"; - CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + CreateRank(lSession->GetMangosString(LANG_GUILD_MASTER), GR_RIGHT_ALL); + CreateRank(lSession->GetMangosString(LANG_GUILD_OFFICER), GR_RIGHT_ALL); + CreateRank(lSession->GetMangosString(LANG_GUILD_VETERAN), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + CreateRank(lSession->GetMangosString(LANG_GUILD_MEMBER), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + CreateRank(lSession->GetMangosString(LANG_GUILD_INITIATE),GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); - return AddMember(lGuid, (uint32)GR_GUILDMASTER); + return AddMember(leaderGuid, (uint32)GR_GUILDMASTER); } bool Guild::AddMember(uint64 plGuid, uint32 plRank) diff --git a/src/game/Guild.h b/src/game/Guild.h index ec764bef6..8890baf44 100644 --- a/src/game/Guild.h +++ b/src/game/Guild.h @@ -267,7 +267,7 @@ class Guild Guild(); ~Guild(); - bool create(uint64 lGuid, std::string gname); + bool create(Player* leader, std::string gname); void Disband(); typedef std::map MemberList; diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index 7b77ddf44..f9bde8849 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -62,7 +62,7 @@ void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket) return; Guild *guild = new Guild; - if(!guild->create(GetPlayer()->GetGUID(),gname)) + if(!guild->create(GetPlayer(),gname)) { delete guild; return; diff --git a/src/game/Language.h b/src/game/Language.h index a2d5500f8..a0fb566e2 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -708,7 +708,12 @@ enum MangosStrings LANG_PLAYER_NOT_EXIST_OR_OFFLINE = 808, LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND = 809, LANG_ACHIEVEMENT_EARNED = 810, - // Room for in-game strings 811-999 not used + LANG_GUILD_MASTER = 811, + LANG_GUILD_OFFICER = 812, + LANG_GUILD_VETERAN = 813, + LANG_GUILD_MEMBER = 814, + LANG_GUILD_INITIATE = 815, + // Room for in-game strings 816-999 not used // Level 4 (CLI only commands) LANG_COMMAND_EXIT = 1000, diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index ab342f252..eaaebeb49 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3065,7 +3065,7 @@ bool ChatHandler::HandleGuildCreateCommand(const char* args) } Guild *guild = new Guild; - if (!guild->create (player->GetGUID (),guildname)) + if (!guild->create (player,guildname)) { delete guild; SendSysMessage (LANG_GUILD_NOT_CREATED); diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index a4a6594c8..a3d50441f 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -824,7 +824,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) if(type == 9) // create guild { Guild* guild = new Guild; - if(!guild->create(_player->GetGUID(), name)) + if(!guild->create(_player, name)) { delete guild; delete result; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6af72ad25..b78c81a04 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7421" + #define REVISION_NR "7422" #endif // __REVISION_NR_H__ From 186e0e14e3cd02e911bffe6539bf0a2d812256fb Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 9 Mar 2009 13:54:46 +0300 Subject: [PATCH 43/60] [7423] Disable incremental limking for binaries in debug mode. Anyway it always fail and back to non-incremental way. --- src/shared/revision_nr.h | 2 +- win/VC71/ACE_vc71.vcproj | 2 +- win/VC71/realmd.vcproj | 2 +- win/VC71/script.vcproj | 2 +- win/VC80/ACE_vc8.vcproj | 4 ++-- win/VC80/mangosd.vcproj | 4 ++-- win/VC80/realmd.vcproj | 4 ++-- win/VC80/script.vcproj | 4 ++-- win/VC90/ACE_vc9.vcproj | 4 ++-- win/VC90/mangosd.vcproj | 4 ++-- win/VC90/realmd.vcproj | 4 ++-- win/VC90/script.vcproj | 5 +++-- 12 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b78c81a04..ff2d069c8 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7422" + #define REVISION_NR "7423" #endif // __REVISION_NR_H__ diff --git a/win/VC71/ACE_vc71.vcproj b/win/VC71/ACE_vc71.vcproj index 862ef1a83..9ab6be08d 100644 --- a/win/VC71/ACE_vc71.vcproj +++ b/win/VC71/ACE_vc71.vcproj @@ -45,7 +45,7 @@ Name="VCLinkerTool" AdditionalDependencies="" OutputFile="$(OutDir)\ACEd.dll" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="TRUE" AdditionalLibraryDirectories="" GenerateDebugInformation="TRUE" diff --git a/win/VC71/realmd.vcproj b/win/VC71/realmd.vcproj index 1eb41decc..e6edec8e4 100644 --- a/win/VC71/realmd.vcproj +++ b/win/VC71/realmd.vcproj @@ -112,7 +112,7 @@ AdditionalOptions="/MACHINE:I386" AdditionalDependencies="zthread.lib libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib advapi32.lib dbghelp.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\realmd.exe" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="TRUE" AdditionalLibraryDirectories=""..\..\dep\lib\$(PlatformName)_$(ConfigurationName)";".\zthread__$(PlatformName)_$(ConfigurationName)"" GenerateDebugInformation="TRUE" diff --git a/win/VC71/script.vcproj b/win/VC71/script.vcproj index a88a9dd07..617991188 100644 --- a/win/VC71/script.vcproj +++ b/win/VC71/script.vcproj @@ -35,7 +35,7 @@ Name="VCLinkerTool" AdditionalDependencies="mangosd.lib zlib.lib zthread.lib libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\MaNGOSScript.dll" - LinkIncremental="2" + LinkIncremental="1" AdditionalLibraryDirectories="".\mangosd__$(PlatformName)_$(ConfigurationName)";"..\..\dep\lib\$(PlatformName)_$(ConfigurationName)";".\zlib__$(PlatformName)_$(ConfigurationName)";".\zthread__$(PlatformName)_$(ConfigurationName)"" GenerateDebugInformation="TRUE" ProgramDatabaseFile="$(OutDir)/MaNGOSScript.pdb" diff --git a/win/VC80/ACE_vc8.vcproj b/win/VC80/ACE_vc8.vcproj index 767a03b43..c948be1a7 100644 --- a/win/VC80/ACE_vc8.vcproj +++ b/win/VC80/ACE_vc8.vcproj @@ -77,7 +77,7 @@ Name="VCLinkerTool" AdditionalDependencies="" OutputFile="$(OutDir)\ACEd.dll" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories="" GenerateDebugInformation="true" @@ -171,7 +171,7 @@ AdditionalOptions="/machine:AMD64" AdditionalDependencies="" OutputFile="$(OutDir)\ACEd.dll" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories="" GenerateDebugInformation="true" diff --git a/win/VC80/mangosd.vcproj b/win/VC80/mangosd.vcproj index 892a33b4a..1b9c416d7 100644 --- a/win/VC80/mangosd.vcproj +++ b/win/VC80/mangosd.vcproj @@ -282,7 +282,7 @@ AdditionalDependencies="libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib advapi32.lib dbghelp.lib msvcrtd.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\mangosd.exe" Version="" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories="..\..\dep\lib\$(PlatformName)_$(ConfigurationName)" GenerateDebugInformation="true" @@ -383,7 +383,7 @@ AdditionalDependencies="libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib advapi32.lib dbghelp.lib msvcrtd.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\mangosd.exe" Version="" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories="..\..\dep\lib\$(PlatformName)_$(ConfigurationName)" GenerateDebugInformation="true" diff --git a/win/VC80/realmd.vcproj b/win/VC80/realmd.vcproj index c096efc78..0fed5e5ae 100644 --- a/win/VC80/realmd.vcproj +++ b/win/VC80/realmd.vcproj @@ -275,7 +275,7 @@ AdditionalOptions="/MACHINE:I386" AdditionalDependencies="zthread.lib libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib advapi32.lib dbghelp.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\realmd.exe" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories=""..\..\dep\lib\$(PlatformName)_$(ConfigurationName)";".\zthread__$(PlatformName)_$(ConfigurationName)"" GenerateDebugInformation="true" @@ -373,7 +373,7 @@ Name="VCLinkerTool" AdditionalDependencies="zthread.lib libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib advapi32.lib dbghelp.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\realmd.exe" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories=""..\..\dep\lib\$(PlatformName)_$(ConfigurationName)";".\zthread__$(PlatformName)_$(ConfigurationName)"" GenerateDebugInformation="true" diff --git a/win/VC80/script.vcproj b/win/VC80/script.vcproj index 683cf5e8f..886ac699e 100644 --- a/win/VC80/script.vcproj +++ b/win/VC80/script.vcproj @@ -67,7 +67,7 @@ Name="VCLinkerTool" AdditionalDependencies="mangosd.lib zlib.lib zthread.lib libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\MaNGOSScript.dll" - LinkIncremental="2" + LinkIncremental="1" AdditionalLibraryDirectories="".\mangosd__$(PlatformName)_$(ConfigurationName)";"..\..\dep\lib\$(PlatformName)_$(ConfigurationName)";".\zlib__$(PlatformName)_$(ConfigurationName)";".\zthread__$(PlatformName)_$(ConfigurationName)"" GenerateDebugInformation="true" ProgramDatabaseFile="$(OutDir)\MaNGOSScript.pdb" @@ -150,7 +150,7 @@ Name="VCLinkerTool" AdditionalDependencies="mangosd.lib zlib.lib zthread.lib libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\MaNGOSScript.dll" - LinkIncremental="2" + LinkIncremental="1" AdditionalLibraryDirectories="".\mangosd__$(PlatformName)_$(ConfigurationName)";"..\..\dep\lib\$(PlatformName)_$(ConfigurationName)";".\zlib__$(PlatformName)_$(ConfigurationName)";".\zthread__$(PlatformName)_$(ConfigurationName)"" GenerateDebugInformation="true" ProgramDatabaseFile="$(OutDir)\MaNGOSScript.pdb" diff --git a/win/VC90/ACE_vc9.vcproj b/win/VC90/ACE_vc9.vcproj index 628615606..446539c56 100644 --- a/win/VC90/ACE_vc9.vcproj +++ b/win/VC90/ACE_vc9.vcproj @@ -77,7 +77,7 @@ Name="VCLinkerTool" AdditionalDependencies="" OutputFile="$(OutDir)\ACEd.dll" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories="" GenerateDebugInformation="true" @@ -168,7 +168,7 @@ AdditionalOptions="/machine:AMD64" AdditionalDependencies="" OutputFile="$(OutDir)\ACEd.dll" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories="" GenerateDebugInformation="true" diff --git a/win/VC90/mangosd.vcproj b/win/VC90/mangosd.vcproj index f9a4f6682..c9715e11f 100644 --- a/win/VC90/mangosd.vcproj +++ b/win/VC90/mangosd.vcproj @@ -283,7 +283,7 @@ AdditionalDependencies="libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib advapi32.lib dbghelp.lib MSVCPRTD.LIB msvcrtd.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\mangosd.exe" Version="" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories="..\..\dep\lib\$(PlatformName)_$(ConfigurationName)" GenerateDebugInformation="true" @@ -384,7 +384,7 @@ AdditionalDependencies="libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib advapi32.lib dbghelp.lib MSVCPRTD.LIB msvcrtd.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\mangosd.exe" Version="" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories="..\..\dep\lib\$(PlatformName)_$(ConfigurationName)" GenerateDebugInformation="true" diff --git a/win/VC90/realmd.vcproj b/win/VC90/realmd.vcproj index 5016cd66f..73eecacc8 100644 --- a/win/VC90/realmd.vcproj +++ b/win/VC90/realmd.vcproj @@ -276,7 +276,7 @@ AdditionalOptions="/MACHINE:I386" AdditionalDependencies="zthread.lib libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib advapi32.lib dbghelp.lib MSVCPRTD.LIB msvcrtd.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\realmd.exe" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories=""..\..\dep\lib\$(PlatformName)_$(ConfigurationName)";".\zthread__$(PlatformName)_$(ConfigurationName)"" GenerateDebugInformation="true" @@ -374,7 +374,7 @@ Name="VCLinkerTool" AdditionalDependencies="zthread.lib libmySQL.lib libeay32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib advapi32.lib dbghelp.lib MSVCPRTD.LIB msvcrtd.lib" OutputFile="..\..\bin\$(PlatformName)_$(ConfigurationName)\realmd.exe" - LinkIncremental="2" + LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories=""..\..\dep\lib\$(PlatformName)_$(ConfigurationName)";".\zthread__$(PlatformName)_$(ConfigurationName)"" GenerateDebugInformation="true" diff --git a/win/VC90/script.vcproj b/win/VC90/script.vcproj index 0efd5cee2..db9c20167 100644 --- a/win/VC90/script.vcproj +++ b/win/VC90/script.vcproj @@ -6,6 +6,7 @@ ProjectGUID="{4205C8A9-79B7-4354-8064-F05FB9CA0C96}" RootNamespace="script" Keyword="Win32Proj" + TargetFrameworkVersion="0" > Date: Mon, 9 Mar 2009 14:19:17 +0300 Subject: [PATCH 44/60] [7424] Codestyle: removed not needed \n in log output. Signed-off-by: VladimirMangos --- src/game/Creature.cpp | 4 ++-- src/game/GMTicketHandler.cpp | 2 +- src/game/Map.cpp | 2 +- src/game/ObjectAccessor.cpp | 2 +- src/game/PetHandler.cpp | 32 ++++++++++++++++---------------- src/game/Player.cpp | 4 ++-- src/game/SkillHandler.cpp | 2 +- src/game/Spell.cpp | 4 ++-- src/game/SpellEffects.cpp | 12 ++++++------ src/game/Unit.cpp | 2 +- src/game/WorldSocket.cpp | 2 +- src/shared/revision_nr.h | 2 +- 12 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 785d99858..2d9a48981 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1562,7 +1562,7 @@ SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim) SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_spells[i] ); if(!spellInfo) { - sLog.outError("WORLD: unknown spell id %i\n", m_spells[i]); + sLog.outError("WORLD: unknown spell id %i", m_spells[i]); continue; } @@ -1612,7 +1612,7 @@ SpellEntry const *Creature::reachWithSpellCure(Unit *pVictim) SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_spells[i] ); if(!spellInfo) { - sLog.outError("WORLD: unknown spell id %i\n", m_spells[i]); + sLog.outError("WORLD: unknown spell id %i", m_spells[i]); continue; } diff --git a/src/game/GMTicketHandler.cpp b/src/game/GMTicketHandler.cpp index c33968221..3a1aefdfd 100644 --- a/src/game/GMTicketHandler.cpp +++ b/src/game/GMTicketHandler.cpp @@ -119,7 +119,7 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data ) data.Initialize( SMSG_GMTICKET_CREATE, 4 ); data << uint32(2); SendPacket( &data ); - DEBUG_LOG("update the ticket\n"); + DEBUG_LOG("update the ticket"); //TODO: Guard player map HashMapHolder::MapType &m = ObjectAccessor::Instance().GetPlayers(); diff --git a/src/game/Map.cpp b/src/game/Map.cpp index e86a687da..d4134f710 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1937,7 +1937,7 @@ void InstanceMap::PermBindAllPlayers(Player *player) InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); if(!save) { - sLog.outError("Cannot bind players, no instance save available for map!\n"); + sLog.outError("Cannot bind players, no instance save available for map!"); return; } diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 07830f15b..25dcffd44 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -408,7 +408,7 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia) return NULL; } - DEBUG_LOG("Deleting Corpse and spawning bones.\n"); + DEBUG_LOG("Deleting Corpse and spawning bones."); // remove corpse from player_guid -> corpse map RemoveCorpse(corpse); diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index 626bee716..f8610ccfd 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -44,16 +44,16 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) // used also for charmed creature Unit* pet= ObjectAccessor::GetUnit(*_player, guid1); - sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.\n", uint32(GUID_LOPART(guid1)), flag, spellid, uint32(GUID_LOPART(guid2)) ); + sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.", uint32(GUID_LOPART(guid1)), flag, spellid, uint32(GUID_LOPART(guid2)) ); if(!pet) { - sLog.outError( "Pet %u not exist.\n", uint32(GUID_LOPART(guid1)) ); + sLog.outError( "Pet %u not exist.", uint32(GUID_LOPART(guid1)) ); return; } if(pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm()) { - sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.\n", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName() ); + sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName() ); return; } @@ -143,7 +143,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) _player->Uncharm(); break; default: - sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.\n", flag, spellid); + sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", flag, spellid); } break; case ACT_REACTION: // 0x600 @@ -171,7 +171,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid ); if(!spellInfo) { - sLog.outError("WORLD: unknown PET spell id %i\n", spellid); + sLog.outError("WORLD: unknown PET spell id %i", spellid); return; } @@ -261,7 +261,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) break; } default: - sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.\n", flag, spellid); + sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", flag, spellid); } } @@ -269,7 +269,7 @@ void WorldSession::HandlePetNameQuery( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,4+8); - sLog.outDetail( "HandlePetNameQuery. CMSG_PET_NAME_QUERY\n" ); + sLog.outDetail( "HandlePetNameQuery. CMSG_PET_NAME_QUERY" ); uint32 petnumber; uint64 petguid; @@ -309,7 +309,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8+4+2+2); - sLog.outDetail( "HandlePetSetAction. CMSG_PET_SET_ACTION\n" ); + sLog.outDetail( "HandlePetSetAction. CMSG_PET_SET_ACTION" ); uint64 petguid; uint32 position; @@ -328,7 +328,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) { - sLog.outError( "HandlePetSetAction: Unknown pet or pet owner.\n" ); + sLog.outError( "HandlePetSetAction: Unknown pet or pet owner." ); return; } @@ -346,7 +346,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) recv_data >> spell_id; recv_data >> act_state; - sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X\n", _player->GetName(), position, spell_id, act_state); + sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position, spell_id, act_state); //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id))) @@ -378,7 +378,7 @@ void WorldSession::HandlePetRename( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8+1); - sLog.outDetail( "HandlePetRename. CMSG_PET_RENAME\n" ); + sLog.outDetail( "HandlePetRename. CMSG_PET_RENAME" ); uint64 petguid; uint8 isdeclined; @@ -496,7 +496,7 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) if(guid != pet->GetGUID()) { - sLog.outError( "HandlePetUnlearnOpcode.Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); + sLog.outError( "HandlePetUnlearnOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } @@ -530,7 +530,7 @@ void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) { - sLog.outError( "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); + sLog.outError( "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } @@ -582,7 +582,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) if(!pet || (pet != _player->GetPet() && pet!= _player->GetCharm())) { - sLog.outError( "HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); + sLog.outError( "HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } @@ -592,7 +592,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); if(!spellInfo) { - sLog.outError("WORLD: unknown PET spell id %i\n", spellid); + sLog.outError("WORLD: unknown PET spell id %i", spellid); return; } @@ -778,5 +778,5 @@ void WorldSession::HandlePetLearnTalent( WorldPacket & recv_data ) // learn! (other talent ranks will unlearned at learning) pet->learnSpell(spellid); - sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid); + sLog.outDetail("TalentID: %u Rank: %u Spell: %u", talent_id, requested_rank, spellid); } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 6baea0750..8a1cbfa55 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -15657,7 +15657,7 @@ bool Player::_LoadHomeBind(QueryResult *result) CharacterDatabase.PExecute("INSERT INTO character_homebind (guid,map,zone,position_x,position_y,position_z) VALUES ('%u', '%u', '%u', '%f', '%f', '%f')", GetGUIDLow(), m_homebindMapId, (uint32)m_homebindZoneId, m_homebindX, m_homebindY, m_homebindZ); } - DEBUG_LOG("Setting player home position: mapid is: %u, zoneid is %u, X is %f, Y is %f, Z is %f\n", + DEBUG_LOG("Setting player home position: mapid is: %u, zoneid is %u, X is %f, Y is %f, Z is %f", m_homebindMapId, m_homebindZoneId, m_homebindX, m_homebindY, m_homebindZ); return true; @@ -19872,4 +19872,4 @@ void Player::HandleFall(MovementInfo const& movementInfo) void Player::UpdateAchievementCriteria( AchievementCriteriaTypes type, uint32 miscvalue1/*=0*/, uint32 miscvalue2/*=0*/, Unit *unit/*=NULL*/, uint32 time/*=0*/ ) { GetAchievementMgr().UpdateAchievementCriteria(type, miscvalue1,miscvalue2,unit,time); -} \ No newline at end of file +} diff --git a/src/game/SkillHandler.cpp b/src/game/SkillHandler.cpp index dac37e6b0..1a79923d7 100644 --- a/src/game/SkillHandler.cpp +++ b/src/game/SkillHandler.cpp @@ -126,7 +126,7 @@ void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data ) // learn! (other talent ranks will unlearned at learning) GetPlayer( )->learnSpell(spellid,false); - sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid); + sLog.outDetail("TalentID: %u Rank: %u Spell: %u", talent_id, requested_rank, spellid); // update free talent points GetPlayer()->SetFreeTalentPoints(CurTalentPoints - 1); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 25372e51e..821b67e36 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2044,7 +2044,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) } } else - sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id ); + sLog.outError( "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id ); }break; case TARGET_BEHIND_VICTIM: { @@ -3530,7 +3530,7 @@ void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTar EffectEnchantItemTmp(i); else { - sLog.outError("SPELL: unknown effect %u spell id %u\n", + sLog.outError("SPELL: unknown effect %u spell id %u", eff, m_spellInfo->Id); } } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index abfc1cd64..5a738426b 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -802,7 +802,7 @@ void Spell::EffectDummy(uint32 i) creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view - DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n"); + DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy"); map->Add(pGameObj); WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); @@ -1653,7 +1653,7 @@ void Spell::EffectDummy(uint32 i) if(!spellInfo) { - sLog.outError("WORLD: unknown spell id %i\n", spell_id); + sLog.outError("WORLD: unknown spell id %i", spell_id); return; } @@ -1752,7 +1752,7 @@ void Spell::EffectTriggerSpellWithValue(uint32 i) if(!spellInfo) { - sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id); + sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id); return; } @@ -2015,7 +2015,7 @@ void Spell::EffectTeleportUnits(uint32 i) SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id); if(!st) { - sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo->Id ); + sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id ); return; } ((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0); @@ -2055,7 +2055,7 @@ void Spell::EffectTeleportUnits(uint32 i) // If not exist data for dest location - return if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) { - sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id ); + sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id ); return; } // Init dest coordinates @@ -6290,7 +6290,7 @@ void Spell::EffectTransmitted(uint32 effIndex) pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); pGameObj->SetSpellId(m_spellInfo->Id); - DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n"); + DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted"); //m_caster->AddGameObject(pGameObj); //m_ObjToDel.push_back(pGameObj); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 04b83a9de..9efece118 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -901,7 +901,7 @@ void Unit::CastCustomSpell(Unit* Victim,uint32 spellId, int32 const* bp0, int32 if(!spellInfo) { - sLog.outError("CastCustomSpell: unknown spell id %i\n", spellId); + sLog.outError("CastCustomSpell: unknown spell id %i", spellId); return; } diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index 5b7574b27..3955f41da 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -315,7 +315,7 @@ int WorldSocket::handle_input (ACE_HANDLE) } case 0: { - DEBUG_LOG ("WorldSocket::handle_input: Peer has closed connection\n"); + DEBUG_LOG ("WorldSocket::handle_input: Peer has closed connection"); errno = ECONNRESET; return -1; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ff2d069c8..3c5eab9d3 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7423" + #define REVISION_NR "7424" #endif // __REVISION_NR_H__ From 1c8f8a2e1384d48c2bf5b97bab8f68b357c66ba1 Mon Sep 17 00:00:00 2001 From: Triply Date: Mon, 9 Mar 2009 15:10:01 +0100 Subject: [PATCH 45/60] [7425] Fixed crash in BattleGround::Update() Signed-off-by: Triply --- src/game/BattleGround.cpp | 11 +++++++++-- src/shared/revision_nr.h | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index fdda6ace6..c0cd15729 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -240,6 +240,7 @@ void BattleGround::Update(uint32 diff) { RemovePlayerAtLeave(itr->first, true, true);// remove player from BG m_OfflineQueue.pop_front(); // remove from offline queue + //do not use itr for anything, because it is erased in RemovePlayerAtLeave() } } } @@ -422,9 +423,15 @@ void BattleGround::Update(uint32 diff) m_EndTime += diff; if(m_EndTime >= TIME_TO_AUTOREMOVE) // 2 minutes { - for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + BattleGroundPlayerMap::iterator itr, next; + for(itr = m_Players.begin(); itr != m_Players.end(); itr = next) + { + next = itr; + ++next; + //itr is erased here! RemovePlayerAtLeave(itr->first, true, true);// remove player from BG - // do not change any battleground's private variables + // do not change any battleground's private variables + } } } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3c5eab9d3..b95fe701d 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7424" + #define REVISION_NR "7425" #endif // __REVISION_NR_H__ From 52696ce02966664137794eba4db3697896638508 Mon Sep 17 00:00:00 2001 From: Triply Date: Mon, 9 Mar 2009 16:38:10 +0100 Subject: [PATCH 46/60] [7426] Mounted players now can capture tower point in Eye of Storm. Renamed function isAllowUseBattleGroundObject to CanUseBattleGroundObject Signed-off-by: Triply --- src/game/BattleGroundEY.cpp | 4 ++-- src/game/GameObject.cpp | 4 ++-- src/game/Player.cpp | 13 +++++++++++-- src/game/Player.h | 3 ++- src/game/Spell.cpp | 2 +- src/game/SpellEffects.cpp | 4 ++-- src/shared/revision_nr.h | 2 +- 7 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 001e8accd..f353595b1 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -147,7 +147,7 @@ void BattleGroundEY::CheckSomeoneJoinedPoint() ++j; continue; } - if (plr->isAllowUseBattleGroundObject() && plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) + if (plr->CanCaptureTowerPoint() && plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) { //player joined point! //show progress bar @@ -190,7 +190,7 @@ void BattleGroundEY::CheckSomeoneLeftPoint() ++j; continue; } - if (!plr->isAllowUseBattleGroundObject() || !plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) + if (!plr->CanCaptureTowerPoint() || !plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) //move player out of point (add him to players that are out of points { m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 29ed63eaa..0aaa575ad 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -1193,7 +1193,7 @@ void GameObject::Use(Unit* user) Player* player = (Player*)user; - if( player->isAllowUseBattleGroundObject() ) + if( player->CanUseBattleGroundObject() ) { // in battleground check BattleGround *bg = player->GetBattleGround(); @@ -1218,7 +1218,7 @@ void GameObject::Use(Unit* user) Player* player = (Player*)user; - if( player->isAllowUseBattleGroundObject() ) + if( player->CanUseBattleGroundObject() ) { // in battleground check BattleGround *bg = player->GetBattleGround(); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 8a1cbfa55..bf6fba258 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -19396,13 +19396,22 @@ bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const return false; } -bool Player::isAllowUseBattleGroundObject() +bool Player::CanUseBattleGroundObject() { return ( //InBattleGround() && // in battleground - not need, check in other cases - !IsMounted() && // not mounted + //!IsMounted() && - not correct, player is dismounted when he clicks on flag !HasStealthAura() && // not stealthed !HasInvisibilityAura() && // not invisible !HasAura(SPELL_RECENTLY_DROPPED_FLAG, 0) && // can't pickup + //TODO player cannot use object when he is invulnerable (immune) - (ice block, divine shield, divine protection, divine intervention ...) + isAlive() // live player + ); +} + +bool Player::CanCaptureTowerPoint() +{ + return ( !HasStealthAura() && // not stealthed + !HasInvisibilityAura() && // not invisible isAlive() // live player ); } diff --git a/src/game/Player.h b/src/game/Player.h index 69ac16476..3dc26cd79 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1973,7 +1973,8 @@ class MANGOS_DLL_SPEC Player : public Unit void ClearAfkReports() { m_bgAfkReporter.clear(); } bool GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const; - bool isAllowUseBattleGroundObject(); + bool CanUseBattleGroundObject(); + bool CanCaptureTowerPoint(); /*********************************************************/ /*** REST SYSTEM ***/ diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 821b67e36..742682f81 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4108,7 +4108,7 @@ uint8 Spell::CanCast(bool strict) // In BattleGround players can use only flags and banners if( ((Player*)m_caster)->InBattleGround() && - !((Player*)m_caster)->isAllowUseBattleGroundObject() ) + !((Player*)m_caster)->CanUseBattleGroundObject() ) return SPELL_FAILED_TRY_AGAIN; // get the lock entry diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 5a738426b..c415edbd1 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2916,7 +2916,7 @@ void Spell::EffectOpenLock(uint32 /*i*/) if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune || goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK ) { - //isAllowUseBattleGroundObject() already called in CanCast() + //CanUseBattleGroundObject() already called in CanCast() // in battleground check if(BattleGround *bg = player->GetBattleGround()) { @@ -2928,7 +2928,7 @@ void Spell::EffectOpenLock(uint32 /*i*/) } else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND) { - //isAllowUseBattleGroundObject() already called in CanCast() + //CanUseBattleGroundObject() already called in CanCast() // in battleground check if(BattleGround *bg = player->GetBattleGround()) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b95fe701d..53ea02679 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7425" + #define REVISION_NR "7426" #endif // __REVISION_NR_H__ From 95379309e591953350e00b2e9c4361ce0dc47aa5 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 9 Mar 2009 18:55:00 +0300 Subject: [PATCH 47/60] [7427] Sort ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE achievements by normal/heroic and check current player mode fit. Also ignore any ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE achievements with not implemented custom requirements. --- src/game/AchievementMgr.cpp | 48 +++++++++++++++++++++++++++++++++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index b98b1290e..3acf2caa5 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -459,6 +459,54 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; if(achievementCriteria->kill_creature.creatureID != miscvalue1) continue; + + // LOT achievement->ID required special custom checks + switch(achievement->ID) + { + // Just heroic + case 489: case 490: case 491: case 492: case 493: case 494: case 495: + case 496: case 497: case 498: case 499: case 500: case 563: case 565: + case 567: case 569: case 573: case 575: case 577: case 623: case 625: + case 667: case 668: case 669: case 670: case 671: case 672: case 673: + case 674: case 675: case 676: case 677: case 678: case 679: case 680: + case 681: case 682: case 1367: case 1368: case 1378: case 1379: + case 1380: case 1381: case 1382: case 1383: case 1384: case 1385: + case 1386: case 1387: case 1388: case 1389: case 1390: case 1393: + case 1394: case 1400: case 1402: case 1504: case 1505: case 1506: + case 1507: case 1508: case 1509: case 1510: case 1511: case 1512: + case 1513: case 1514: case 1515: case 1721: case 1754: case 1756: + case 1768: case 1817: case 1865: + if(GetPlayer()->GetDifficulty()!=DIFFICULTY_HEROIC) + continue; + break; + // Heroic + other + case 579: case 1296: case 1297: case 1816: case 1834: case 1857: case 1859: + case 1860: case 1861: case 1862: case 1864: case 1866: case 1867: case 1868: + case 1870: case 1871: case 1872: case 1873: case 1875: case 1877: case 1919: + case 2036: case 2037: case 2038: case 2039: case 2040: case 2041: case 2042: + case 2043: case 2044: case 2045: case 2046: case 2048: case 2052: case 2053: + case 2054: case 2056: case 2057: case 2058: case 2139: case 2140: case 2147: + case 2149: case 2150: case 2151: case 2152: case 2154: case 2155: case 2156: + case 2157: case 2179: case 2181: case 2183: case 2185: case 2186: + if(GetPlayer()->GetDifficulty()!=DIFFICULTY_HEROIC) + continue; + // FIX ME: mark as fail always until implement + continue; + // Normal + other + case 578: case 624: case 1790: case 1856: case 1858: case 1869: case 1874: + case 1996: case 1997: case 2047: case 2049: case 2050: case 2051: case 2146: + case 2148: case 2153: case 2178: case 2180: case 2182: case 2184: case 2187: + if(GetPlayer()->GetDifficulty()!=DIFFICULTY_NORMAL) + continue; + // FIX ME: mark as fail always until implement + continue; + // Just Normal + default: + if(GetPlayer()->GetDifficulty()!=DIFFICULTY_NORMAL) + continue; + break; + }; + SetCriteriaProgress(achievementCriteria, miscvalue2, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 53ea02679..9c6e60a2b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7426" + #define REVISION_NR "7427" #endif // __REVISION_NR_H__ From 6a90d603275125955bc933e5ab9e31117e7f64d0 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Mon, 9 Mar 2009 19:37:12 +0300 Subject: [PATCH 48/60] [7428] Add new .map file format use more compact data store and use Rewrite .map extractor + extract more useful data + add "-f 0" option for disable size/accuracy optimisation + Compatability vs 2.4.3 client data More fast get .map data Implement fatigue timer Rewrite breath timer Allow absorb/resist for lava/slime environmental damage Need re-extract map for work. Signed-off-by: DiSlord --- contrib/extractor/CMakeLists.txt | 9 +- contrib/extractor/System.cpp | 707 ++++++++++++++++++++-- contrib/extractor/VC71_ad.vcproj | 10 +- contrib/extractor/VC80_ad.vcproj | 10 +- contrib/extractor/VC90_ad.vcproj | 10 +- contrib/extractor/ad.exe | Bin 159744 -> 163328 bytes contrib/extractor/adt.cpp | 380 ------------ contrib/extractor/adt.h | 128 ---- contrib/extractor/loadlib/CMakeLists.txt | 13 + contrib/extractor/loadlib/adt.cpp | 131 ++++ contrib/extractor/loadlib/adt.h | 289 +++++++++ contrib/extractor/loadlib/loadlib.cpp | 63 ++ contrib/extractor/loadlib/loadlib.h | 57 ++ contrib/extractor/loadlib/wdt.cpp | 62 ++ contrib/extractor/loadlib/wdt.h | 68 +++ contrib/extractor/mpq_libmpq.h | 2 +- src/game/Map.cpp | 724 +++++++++++++++++------ src/game/Map.h | 138 ++++- src/game/Player.cpp | 317 ++++++---- src/game/Player.h | 25 +- src/game/SpellAuras.cpp | 12 +- src/shared/revision_nr.h | 2 +- 22 files changed, 2280 insertions(+), 877 deletions(-) delete mode 100644 contrib/extractor/adt.cpp delete mode 100644 contrib/extractor/adt.h create mode 100644 contrib/extractor/loadlib/CMakeLists.txt create mode 100644 contrib/extractor/loadlib/adt.cpp create mode 100644 contrib/extractor/loadlib/adt.h create mode 100644 contrib/extractor/loadlib/loadlib.cpp create mode 100644 contrib/extractor/loadlib/loadlib.h create mode 100644 contrib/extractor/loadlib/wdt.cpp create mode 100644 contrib/extractor/loadlib/wdt.h diff --git a/contrib/extractor/CMakeLists.txt b/contrib/extractor/CMakeLists.txt index a00dda120..9052903b1 100644 --- a/contrib/extractor/CMakeLists.txt +++ b/contrib/extractor/CMakeLists.txt @@ -12,10 +12,15 @@ cmake_minimum_required (VERSION 2.6) project (MANGOS_MAP_EXTRACTOR) add_subdirectory (libmpq) +add_subdirectory (loadlib) include_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/libmpq) -link_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/libmpq) +include_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/loadlib) -add_executable (ad adt.cpp dbcfile.cpp mpq_libmpq.cpp System.cpp) +link_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/libmpq) +link_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/loadlib) + +add_executable (ad dbcfile.cpp mpq_libmpq.cpp System.cpp) target_link_libraries (ad libmpq) +target_link_libraries (ad loadlib) diff --git a/contrib/extractor/System.cpp b/contrib/extractor/System.cpp index f9f684014..49190f65b 100644 --- a/contrib/extractor/System.cpp +++ b/contrib/extractor/System.cpp @@ -14,10 +14,10 @@ #include "dbcfile.h" #include "mpq_libmpq.h" -extern unsigned int iRes; -extern ArchiveSet gOpenArchives; +#include "loadlib/adt.h" +#include "loadlib/wdt.h" -bool ConvertADT(char*, char*); +extern ArchiveSet gOpenArchives; typedef struct { @@ -25,10 +25,6 @@ typedef struct uint32 id; } map_id; -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; - map_id *map_ids; uint16 *areas; uint16 *LiqType; @@ -36,18 +32,44 @@ char output_path[128] = "."; char input_path[128] = "."; uint32 maxAreaId = 0; +//************************************************** +// Extractor options +//************************************************** enum Extract { EXTRACT_MAP = 1, EXTRACT_DBC = 2 }; -int extract = EXTRACT_MAP | EXTRACT_DBC; + +// Select data for extract +int CONF_extract = EXTRACT_MAP | EXTRACT_DBC; +// This option allow limit minimum height to some value (Allow save some memory) +bool CONF_allow_height_limit = true; +float CONF_use_minHeight = -500.0f; + +// This option allow use float to int conversion +bool CONF_allow_float_to_int = true; +float CONF_float_to_int8_limit = 2.0f; // Max accuracy = val/256 +float CONF_float_to_int16_limit = 2048.0f; // Max accuracy = val/65536 +float CONF_flat_height_delta_limit = 0.005f; // If max - min less this value - surface is flat +float CONF_flat_liquid_delta_limit = 0.001f; // If max - min less this value - liquid surface is flat + +// List MPQ for extract from +char *CONF_mpq_list[]={ + "common.MPQ", + "common-2.MPQ", + "lichking.MPQ", + "expansion.MPQ", + "patch.MPQ", + "patch-2.MPQ", + "patch-3.MPQ", + "patch-4.MPQ", + "patch-5.MPQ", +}; static char* const langs[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; #define LANG_COUNT 12 -#define ADT_RES 64 - void CreateDir( const std::string& Path ) { #ifdef WIN32 @@ -70,7 +92,14 @@ bool FileExists( const char* FileName ) void Usage(char* prg) { - printf("Usage:\n%s -[var] [value]\n-i set input path\n-o set output path\n-e extract only MAP(1)/DBC(2) - standard: both(3)\nExample: %s -r 256 -i \"c:\\games\\game\"", prg, prg); + printf( + "Usage:\n"\ + "%s -[var] [value]\n"\ + "-i set input path\n"\ + "-o set output path\n"\ + "-e extract only MAP(1)/DBC(2) - standard: both(3)\n"\ + "-f height stored as int (less map size but lost some accuracy) 1 by default\n"\ + "Example: %s -f 0 -i \"c:\\games\\game\"", prg, prg); exit(1); } @@ -80,8 +109,9 @@ void HandleArgs(int argc, char * arg[]) { // i - input path // o - output path - // r - resolution, array of (r * r) heights will be created // e - extract only MAP(1)/DBC(2) - standard both(3) + // f - use float to int conversion + // h - limit minimum height if(arg[c][0] != '-') Usage(arg[0]); @@ -99,11 +129,17 @@ void HandleArgs(int argc, char * arg[]) else Usage(arg[0]); break; + case 'f': + if(c + 1 < argc) // all ok + CONF_allow_float_to_int=atoi(arg[(c++) + 1])!=0; + else + Usage(arg[0]); + break; case 'e': if(c + 1 < argc) // all ok { - extract=atoi(arg[(c++) + 1]); - if(!(extract > 0 && extract < 4)) + CONF_extract=atoi(arg[(c++) + 1]); + if(!(CONF_extract > 0 && CONF_extract < 4)) Usage(arg[0]); } else @@ -165,10 +201,602 @@ void ReadLiquidTypeTableDBC() printf("Done! (%u LiqTypes loaded)\n", LiqType_count); } +// +// Adt file convertor function and data +// + +// Map file format data +#define MAP_MAGIC 'SPAM' +#define MAP_VERSION_MAGIC '0.1v' +#define MAP_AREA_MAGIC 'AERA' +#define MAP_HEIGTH_MAGIC 'TGHM' +#define MAP_LIQUID_MAGIC 'QILM' + +struct map_fileheader{ + uint32 mapMagic; + uint32 versionMagic; + uint32 areaMapOffset; + uint32 areaMapSize; + uint32 heightMapOffset; + uint32 heightMapSize; + uint32 liquidMapOffset; + uint32 liquidMapSize; +}; + +#define MAP_AREA_NO_AREA 0x0001 +struct map_areaHeader{ + uint32 fourcc; + uint16 flags; + uint16 gridArea; +}; + +#define MAP_HEIGHT_NO_HIGHT 0x0001 +#define MAP_HEIGHT_AS_INT16 0x0002 +#define MAP_HEIGHT_AS_INT8 0x0004 + +struct map_heightHeader{ + uint32 fourcc; + uint32 flags; + float gridHeight; + float gridMaxHeight; +}; + +#define MAP_LIQUID_TYPE_NO_WATER 0x00 +#define MAP_LIQUID_TYPE_WATER 0x01 +#define MAP_LIQUID_TYPE_OCEAN 0x02 +#define MAP_LIQUID_TYPE_MAGMA 0x04 +#define MAP_LIQUID_TYPE_SLIME 0x08 + +#define MAP_LIQUID_TYPE_DARK_WATER 0x10 +#define MAP_LIQUID_TYPE_WMO_WATER 0x20 + + +#define MAP_LIQUID_NO_TYPE 0x0001 +#define MAP_LIQUID_NO_HIGHT 0x0002 + +struct map_liquidHeader{ + uint32 fourcc; + uint16 flags; + uint16 liquidType; + uint8 offsetX; + uint8 offsetY; + uint8 width; + uint8 height; + float liquidLevel; +}; + +float selectUInt8StepStore(float maxDiff) +{ + return 255 / maxDiff; +} + +float selectUInt16StepStore(float maxDiff) +{ + return 65535 / maxDiff; +} +// Temporary grid data store +uint16 area_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]; + +float V8[ADT_GRID_SIZE][ADT_GRID_SIZE]; +float V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]; +uint16 uint16_V8[ADT_GRID_SIZE][ADT_GRID_SIZE]; +uint16 uint16_V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]; +uint8 uint8_V8[ADT_GRID_SIZE][ADT_GRID_SIZE]; +uint8 uint8_V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]; + +uint8 liquid_type[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]; +bool liquid_show[ADT_GRID_SIZE][ADT_GRID_SIZE]; +float liquid_height[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]; + +bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x) +{ + ADT_file adt; + + if (!adt.loadFile(filename)) + return false; + + adt_MCIN *cells = adt.a_grid->getMCIN(); + if (!cells) + { + printf("Can't find cells in '%s'\n", filename); + return false; + } + + memset(liquid_show, 0, sizeof(liquid_show)); + memset(liquid_type, 0, sizeof(liquid_type)); + memset(liquid_height, 0, sizeof(liquid_height)); + + // Prepare map header + map_fileheader map; + map.mapMagic = MAP_MAGIC; + map.versionMagic = MAP_VERSION_MAGIC; + + // Get area flags data + for (int i=0;igetMCNK(i,j); + uint32 areaid = cell->areaid; + if(areaid && areaid <= maxAreaId) + { + if(areas[areaid] != 0xffff) + { + area_flags[i][j] = areas[areaid]; + continue; + } + printf("File: filename\nCan't find area flag for areaid %u [%d, %d].\n", filename, areaid, cell->ix, cell->iy); + } + area_flags[i][j] = 0xffff; + } + } + //============================================ + // Try pack area data + //============================================ + bool fullAreaData = false; + uint32 areaflag = area_flags[0][0]; + for (int y=0;ygetMCNK(i,j); + if (!cell) + continue; + // Height values for triangles stored in order: + // 1 2 3 4 5 6 7 8 9 + // 10 11 12 13 14 15 16 17 + // 18 19 20 21 22 23 24 25 26 + // 27 28 29 30 31 32 33 34 + // . . . . . . . . + // For better get height values merge it to V9 and V8 map + // V9 height map: + // 1 2 3 4 5 6 7 8 9 + // 18 19 20 21 22 23 24 25 26 + // . . . . . . . . + // V8 height map: + // 10 11 12 13 14 15 16 17 + // 27 28 29 30 31 32 33 34 + // . . . . . . . . + + // Set map height as grid height + for (int y=0; y <= ADT_CELL_SIZE; y++) + { + int cy = i*ADT_CELL_SIZE + y; + for (int x=0; x <= ADT_CELL_SIZE; x++) + { + int cx = j*ADT_CELL_SIZE + x; + V9[cy][cx]=cell->ypos; + } + } + for (int y=0; y < ADT_CELL_SIZE; y++) + { + int cy = i*ADT_CELL_SIZE + y; + for (int x=0; x < ADT_CELL_SIZE; x++) + { + int cx = j*ADT_CELL_SIZE + x; + V8[cy][cx]=cell->ypos; + } + } + // Get custom height + adt_MCVT *v = cell->getMCVT(); + if (!v) + continue; + // get V9 height map + for (int y=0; y <= ADT_CELL_SIZE; y++) + { + int cy = i*ADT_CELL_SIZE + y; + for (int x=0; x <= ADT_CELL_SIZE; x++) + { + int cx = j*ADT_CELL_SIZE + x; + V9[cy][cx]+=v->height_map[y*(ADT_CELL_SIZE*2+1)+x]; + } + } + // get V8 height map + for (int y=0; y < ADT_CELL_SIZE; y++) + { + int cy = i*ADT_CELL_SIZE + y; + for (int x=0; x < ADT_CELL_SIZE; x++) + { + int cx = j*ADT_CELL_SIZE + x; + V8[cy][cx]+=v->height_map[y*(ADT_CELL_SIZE*2+1)+ADT_CELL_SIZE+1+x]; + } + } + } + } + //============================================ + // Try pack height data + //============================================ + float maxHeight = -20000; + float minHeight = 20000; + for (int y=0; y h) minHeight = h; + } + } + for (int y=0; y<=ADT_GRID_SIZE; y++) + { + for(int x=0;x<=ADT_GRID_SIZE;x++) + { + float h = V9[y][x]; + if (maxHeight < h) maxHeight = h; + if (minHeight > h) minHeight = h; + } + } + + // Check for allow limit minimum height (not store height in deep ochean - allow save some memory) + if (CONF_allow_height_limit && minHeight < CONF_use_minHeight) + { + for (int y=0; ygetMH2O(); + if (h2o) + { + for (int i=0;igetLiquidData(i,j); + if (!h) + continue; + + int count = 0; + uint64 show = h2o->getLiquidShowMap(h); + for (int y=0; y < h->height;y++) + { + int cy = i*ADT_CELL_SIZE + y + h->yOffset; + for (int x=0; x < h->width; x++) + { + int cx = j*ADT_CELL_SIZE + x + h->xOffset; + if (show & 1) + { + liquid_show[cy][cx] = true; + ++count; + } + show>>=1; + } + } + + uint32 type = LiqType[h->liquidType]; + switch (type) + { + case LIQUID_TYPE_WATER: liquid_type[i][j] |= MAP_LIQUID_TYPE_WATER; break; + case LIQUID_TYPE_OCEAN: liquid_type[i][j] |= MAP_LIQUID_TYPE_OCEAN; break; + case LIQUID_TYPE_MAGMA: liquid_type[i][j] |= MAP_LIQUID_TYPE_MAGMA; break; + case LIQUID_TYPE_SLIME: liquid_type[i][j] |= MAP_LIQUID_TYPE_SLIME; break; + default: + printf("\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->liquidType, filename, i, j); + break; + } + // Dark water detect + if (type == LIQUID_TYPE_OCEAN) + { + uint8 *lm = h2o->getLiquidLightMap(h); + if (!lm) + liquid_type[i][j]|=MAP_LIQUID_TYPE_DARK_WATER; + } + + if (!count && liquid_type[i][j]) + printf("Wrong liquid detect in MH2O chunk"); + + float *height = h2o->getLiquidHeightMap(h); + int pos = 0; + for (int y=0; y<=h->height;y++) + { + int cy = i*ADT_CELL_SIZE + y + h->yOffset; + for (int x=0; x<= h->width; x++) + { + int cx = j*ADT_CELL_SIZE + x + h->xOffset; + if (height) + liquid_height[cy][cx] = height[pos]; + else + liquid_height[cy][cx] = h->heightLevel1; + pos++; + } + } + } + } + } + else + { + // Get from MCLQ chunk (old) + for (int i=0;igetMCNK(i, j); + if (!cell) + continue; + + adt_MCLQ *liquid = cell->getMCLQ(); + int count = 0; + if (!liquid || cell->sizeMCLQ <= 8) + continue; + + for (int y=0; y < ADT_CELL_SIZE; y++) + { + int cy = i*ADT_CELL_SIZE + y; + for (int x=0; x < ADT_CELL_SIZE; x++) + { + int cx = j*ADT_CELL_SIZE + x; + if (liquid->flags[y][x] != 0x0F) + { + liquid_show[cy][cx] = true; + if (liquid->flags[y][x]&(1<<7)) + liquid_type[i][j]|=MAP_LIQUID_TYPE_DARK_WATER; + ++count; + } + } + } + + uint32 c_flag = cell->flags; + if(c_flag & (1<<2)) + liquid_type[i][j]|=MAP_LIQUID_TYPE_WATER; // water + if(c_flag & (1<<3)) + liquid_type[i][j]|=MAP_LIQUID_TYPE_OCEAN; // ochean + if(c_flag & (1<<4)) + liquid_type[i][j]|=MAP_LIQUID_TYPE_MAGMA; // magma/slime + + if (!count && liquid_type[i][j]) + printf("Wrong liquid detect in MCLQ chunk"); + + for (int y=0; y <= ADT_CELL_SIZE; y++) + { + int cy = i*ADT_CELL_SIZE + y; + for (int x=0; x<= ADT_CELL_SIZE; x++) + { + int cx = j*ADT_CELL_SIZE + x; + liquid_height[cy][cx] = liquid->liquid[y][x].height; + } + } + } + } + } + + //============================================ + // Pack liquid data + //============================================ + uint8 type = liquid_type[0][0]; + bool fullType = false; + for (int y=0;y x) minX = x; + if (maxX < x) maxX = x; + if (minY > y) minY = y; + if (maxY < y) maxY = y; + float h = liquid_height[y][x]; + if (maxHeight < h) maxHeight = h; + if (minHeight > h) minHeight = h; + } + } + } + map.liquidMapOffset = map.heightMapOffset + map.heightMapSize; + map.liquidMapSize = sizeof(map_liquidHeader); + liquidHeader.fourcc = MAP_LIQUID_MAGIC; + liquidHeader.flags = 0; + liquidHeader.liquidType = 0; + liquidHeader.offsetX = minX; + liquidHeader.offsetY = minY; + liquidHeader.width = maxX - minX + 1; + liquidHeader.height = maxY - minY + 1; + liquidHeader.liquidLevel = minHeight; + + if (maxHeight == minHeight) + liquidHeader.flags|=MAP_LIQUID_NO_HIGHT; + + // Not need store if flat surface + if (CONF_allow_float_to_int && (maxHeight - minHeight) < CONF_flat_liquid_delta_limit) + liquidHeader.flags|=MAP_LIQUID_NO_HIGHT; + + if (!fullType) + liquidHeader.flags|=MAP_LIQUID_NO_TYPE; + + if (liquidHeader.flags&MAP_LIQUID_NO_TYPE) + liquidHeader.liquidType = type; + else + map.liquidMapSize+=sizeof(liquid_type); + + if (!(liquidHeader.flags&MAP_LIQUID_NO_HIGHT)) + map.liquidMapSize+=sizeof(float)*liquidHeader.width*liquidHeader.height; + } + + // Ok all data prepared - store it + FILE *output=fopen(filename2, "wb"); + if(!output) + { + printf("Can't create the output file '%s'\n", filename2); + return false; + } + fwrite(&map, sizeof(map), 1, output); + // Store area data + fwrite(&areaHeader, sizeof(areaHeader), 1, output); + if (!(areaHeader.flags&MAP_AREA_NO_AREA)) + fwrite(area_flags, sizeof(area_flags), 1, output); + + // Store height data + fwrite(&heightHeader, sizeof(heightHeader), 1, output); + if (!(heightHeader.flags&MAP_HEIGHT_NO_HIGHT)) + { + if (heightHeader.flags&MAP_HEIGHT_AS_INT16) + { + fwrite(uint16_V9, sizeof(uint16_V9), 1, output); + fwrite(uint16_V8, sizeof(uint16_V8), 1, output); + } + else if (heightHeader.flags&MAP_HEIGHT_AS_INT8) + { + fwrite(uint8_V9, sizeof(uint8_V9), 1, output); + fwrite(uint8_V8, sizeof(uint8_V8), 1, output); + } + else + { + fwrite(V9, sizeof(V9), 1, output); + fwrite(V8, sizeof(V8), 1, output); + } + } + + // Store liquid data if need + if (map.liquidMapOffset) + { + fwrite(&liquidHeader, sizeof(liquidHeader), 1, output); + if (!(liquidHeader.flags&MAP_LIQUID_NO_TYPE)) + fwrite(liquid_type, sizeof(liquid_type), 1, output); + if (!(liquidHeader.flags&MAP_LIQUID_NO_HIGHT)) + { + for (int y=0; yadt_list[y][x].exist) + continue; sprintf(mpq_filename, "World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y); sprintf(output_filename, "%s/maps/%03u%02u%02u.map", output_path, map_ids[z].id, y, x); - ConvertADT(mpq_filename, output_filename); - done++; + ConvertADT(mpq_filename, output_filename, y, x); } // draw progress bar - printf("Processing........................%d%%\r", (100 * done) / total); + printf("Processing........................%d%%\r", (100 * (y+1)) / WDT_MAP_SIZE); } } - delete [] areas; delete [] map_ids; } -//bool WMO(char* filename); - void ExtractDBCFiles(int locale, bool basicLocale) { printf("Extracting dbc files...\n"); @@ -277,21 +911,10 @@ void LoadLocaleMPQFiles(int const locale) void LoadCommonMPQFiles() { char filename[512]; - - sprintf(filename,"%s/Data/common-2.MPQ", input_path); - new MPQArchive(filename); - sprintf(filename,"%s/Data/lichking.MPQ", input_path); - new MPQArchive(filename); - sprintf(filename,"%s/Data/expansion.MPQ", input_path); - new MPQArchive(filename); - - for(int i = 1; i < 5; ++i) + int count = sizeof(CONF_mpq_list)/sizeof(char*); + for(int i = 0; i < count; ++i) { - char ext[3] = ""; - if(i > 1) - sprintf(ext, "-%i", i); - - sprintf(filename, "%s/Data/patch%s.MPQ", input_path, ext); + sprintf(filename, "%s/Data/%s", input_path, CONF_mpq_list[i]); if(FileExists(filename)) new MPQArchive(filename); } @@ -323,7 +946,7 @@ int main(int argc, char * arg[]) //Open MPQs LoadLocaleMPQFiles(i); - if((extract & EXTRACT_DBC) == 0) + if((CONF_extract & EXTRACT_DBC) == 0) { FirstLocale = i; break; @@ -349,7 +972,7 @@ int main(int argc, char * arg[]) return 0; } - if (extract & EXTRACT_MAP) + if (CONF_extract & EXTRACT_MAP) { printf("Using locale: %s\n", langs[FirstLocale]); diff --git a/contrib/extractor/VC71_ad.vcproj b/contrib/extractor/VC71_ad.vcproj index fd2d16120..541540cea 100644 --- a/contrib/extractor/VC71_ad.vcproj +++ b/contrib/extractor/VC71_ad.vcproj @@ -213,7 +213,15 @@ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" > + + + + + + @@ -253,6 +257,10 @@ /> + + diff --git a/contrib/extractor/VC90_ad.vcproj b/contrib/extractor/VC90_ad.vcproj index 59fdf6d21..9a039a0fb 100644 --- a/contrib/extractor/VC90_ad.vcproj +++ b/contrib/extractor/VC90_ad.vcproj @@ -216,7 +216,15 @@ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" > + + + + @p$4J&Sn^7xtpaF9{ zPFdR=E4yh}d8?b2=0_g}qM&7ErUhw5Wwi+_yOmOz^ZwR31EO{R@BhBf^Wt;n?6daT zYp=cbT5GTUagHSo?Mkk++c-vScxdbdcfrXdQ;(PIQ(CT&FRQ0?z;no#XQph%{ic;e zru03b8~$t=f{-n0geNjynbeZiAcTk= z#CC%4g=iFnEh@Ngm?#JaN=qzS?Ad->xFBc*VbV5<;wX1xxUg4brP57N z%km__N}$$1Nth!()Vn)t5VfObHw5W@fjbDb{fiZZ`9qg4xY>ELAQatBIg%jUf!o)t zr_{Y;apzD$SOySPID=(Mz1pEx!V!x1+#x+IK9rz!H{N!WAe^}NCs$dH*9zyvG{Kvt z@n&hgS-R?LxhGB(1sslVQ-uZFK}E26E*R|j+qZer1j`YdFWnropn~A?k8+r7(*#b* z#pd{YU$)u6&8ViN*sK$3)6HhWadydf>=xZ=0zdS!Ab5^w8%wEVy4hs&W@`B-FA-4V z&D4}vIw#9hwYfIXG4dhFf`EjM??pn6k|p`wz{#>o=Kul{?EwC`ADO#FIU5XlBdE55 zd4--MF^4rmzT*hm#wV+F`rJgSNF|k~AzIhbu_0$f{D7*o2m3l2%FA^v)QJz&z)e>Jf!Z*Rg0-27`pGpd^iI^KDv-u>P$c}) z1No6AaEDzm)}Jv8IcI^ufZ}zt83{Z^pHVqmi&I{O;e@@S#ry1G0*{>PiNpWP!65_ zt(@j)0o|;EKH4p|5lL=o^3+Kaa=bdTQ!}EnpgM1+-SVBUK%4K|p(vjvApazXfkY=? zw)O??Q)%=DH-?Fx8iOZbC~n9otrlQ&9`_%H;*;|V=k69~7gXauq7rwAymZ|3^sF4B zUs&x~qp`X!$(cHkjPPYAX!*S=$uH#0gjU%7XfU{ccemKuHPjvSM_st?56X5)h1DP= zXK7@+#+Thm>-J7H1Ub|{g1XcK=);`+HeFJhoStR7?s@8@)HcslLG$l{fThx#Y4Bzm zy_u%ku%DqWK|KLH)!%E_iGYkdezO z=mXdTgbI*}&r(1t*U*_`|2v%_u1HA~omm*@bDh%c15bZa8g{nxb5g`!c7K<5rLlWh zzVUhE>o9OReZM9XPNclj^?g2n?&UpEk)fhA{N+78qM}4;{HttaS4-4W2Y~oMTqJ%s zYtY~Mxzo9BKU>o^I;2iYV_UnfG|oFnnL1=n_pXfxCeJy@2AC|;zjv`YCR5br{X~K? zu8|P-vGt~u5DpT@Og~A}_OUm*^^yL$mwn#tG3miq*y`@Rqzil4Kf0GlGxo9A=>9#9 z>=guWc?@cS6EwpXJl^A14k0)>!SlH~-~K1&&6s^te0z;0fyZ-zNx zI{1w8PVFowbkdo_wKi|eTDGn_@rCPt? zF8GadX6e;!f(Zre{H7Kj^yS~7D{V!RQklc7|edQrp!^&hryZBF4x^ej|K~eL&@3Mnlq1bvdyu%j$$R}0T$>LlfFqw-`0xNN4}pV zP-H9;LpwsuHpeyvV^Rx-v+L~ZMYrZ@HZRuH_XPz_4>Z}YP-tHymL8r=%HcSmW?WGTI;Mor(LihcGxOJz$}jN8GU>>W9BKroBUx>nSM!1LQ*2@c6H!rCwb z@d*H3N;hjoXFEH;=M~o2`?=1|*UZUt!Awq=J>6%A6#WF7(s!;g?J25K<5^=eEZ50X zHM#uRJ*=dEEIZdXPa3h84L1+y){H^caU?&D`dO0;o6{azD!c z-G7PHX*ZiYV6)WI#eNxZOp3j0&zo_5LZsQxurCMSE?s$?O^<)p9lJbD_~~i+cmC~f z@EH*T9=-C<3Fx>;4bnajrM)(d9HFJGEUg@=Blv5HgCQ0Jk_Tzr^xAaX0Sens-U%#^ zW;h5$oTjv_rF3K+rI`-t?dKE}1CqYih8S@>s0D>X4FLc2w9m7bDsNV(9Wd!M7D3*(B0fY} zv)l~pG1$CO{H6QY6T^D+J+K|tpp)zPE=ri>i~JcR98Sb-MM9q3%Lof;9^80jmB6s&J0O=< zC#~4?fMsELcCUX>X{|cu+H$#7F{LMM9;Lp*p8BA_}jIfOd=mAAM7ZMP6jZcYccX zfEhk2m%qCn>CNPArt`y;UP~i`jo0m9?Z-}*##ots?1$YQTZJ8d1(^W(Bs1mw|}Id8V* z!~u-j0e+~A^-Ap;p7|Us1=Po;4w801$(E!>OZjDNZEDfbCJz~EouVm75A~5CUoy{|9!2s6YI!p<$URV?9K_jBKABA2CV3BJGZ>R zo|q6Loq3MEHerzD^RaIx3=2;uRekoKtVephRQN2LlJ1qhy^npE9w$}a_i)CYCK0_K zY>m^|+LEL9F>l5!=^>eYnUU9FT`94sv2%AROU+y;T`1YJGjpyejb6{fvldEgR@ zhS+smU~3Tu{Mti~<;xdSs#dh;5ATFvm7K9Z`{9#{%?3o_#-{LK)GJ3)0bin&QnMnI zF93FVz^P49ke#7CZzuaPD>JqO;Fe0uad}cqNR}xXldk2V{1PM@fc1bp%bzqr`g#Q` znRH9L1!yo_!^D-WX;O?kF2^d^9m_}vJy$A%o>wSW&&JSUckCdj_D1Mwg8qBO4Y+~^ z&~rCJlL%UKBXlW2cPmi0woP>ee(Xl%(*!NM5o!zt^o|>$*#w<+BXk`>)2@dqj`ZNq z{$z-J4yLHf!l3lQhJT)I72d}63a%${d2!u^Yc8&dxQ643&SvALL`#iNv)NP3QuWiU zbjm{M-VKaT8PF{i*8UeG^tKHwE<3C1kI03tr2M|}D>>6JFQuAX+qw1Z{_KGd=S&({ zQ6C7vV;rZfvf2CTke7iW|~rJ?~0Y}#_9R;yIfbtmgi(hq3hYfoI$p%YeV>d zp4joV>qtp_Q+2gr2OyH70HzMLsU|%v)CNBsvo2LbF4x9iWtOS&?jyjtE{ISf8!G8p zW2X2d(_rI6yh>{BIM1CU6*N)-z{u>548oOkKpaE%6|teNTY3e`CU-p8>5la z8a>sjXf5opB~wSHyo(WaUJFF20@Ibc@7e@2>22n?S?V0OsFUMFXd0`Z8tq<%@=yZ} ztx=c}N6i5H&=W-7jw`d2@XAc#RUFBIFGM@rv<5Y;YAf@$>nVmdvuPbVF*cv~z8{i5 zRTOBIy>Ft9-8Ic9o%xV?r;Q3h73}b|x#I0C)|M(|-Op~d4U%H+XAj!ON}sG{@7e}R zFRx|4+ImPG)-qGBL)yNU-ItrKH^Mb=?>5C0D~uTHbNlw&syymSexKtC3xpDe97(_V z(|PJO%zo1?($1&Z-=?3J-hGN$^P7P%t&3Q@Eh#l-?URSBx4%V2r zSo&@Un?7SumoFg>J72$@D%CYjax{SV2WRw)m=%QdvhxEatZGKT=u=o%f>VxzQ-)r} z03C`A_sq90W8%!n@cx_C8hgyNN@wn6^JYd%)fKFGX0Fkq4B51b)LDPXE@n>Wy`N&A z&rF(e9+lhpcTd8=Xu%FWH^!dJ=OP?epJ$k}rpt#NKPzaLFm?7Eq43M(X%=17&+!f+ zj3!32k%gH};&k5C&u+JOml`%PuYFbY7^PwiLi+NJw9?@;#~@-rd;hVW#pK6I^X_2d z@}G^24JS4#ATbO~;1Xk%eKY$lzlS>xIsCLk5l)fFQ=Vy28_eZ2b|t(@c~}3y`%tx+ zh=C0GzBOV~h;I@k^omfDG(=yHsjZ+tWEDM?k9(Ti>+gq<1pU5}O|z{+z+7H}TgtC` z-{XMF*{^6aUp-KgCQOtA>&10aYML8s5to`469$ImAVv~lY*Z1H{D~>QuAYes5vadZ zOsr}$CsK%26PjF_CWuV~)P&H~6Nuwf#C1TdNCc%U1>Msut&FCnm&}PNKk7G(N2oAw zZeg`s&Vh9QO`@BLxTld484y(i5+lL74%gd%vkDh*5V0&tQ?0?LMP40AGGs@Bn8zBJ-=32c#nHh>AsOIV0V5WTj(JNqauX!)h zcEAu?3bkeC-MG;oZ{DLU|Cr@6^EN!oSvp@aR#S@2apeJ5yxnm{i~jy*k)jAF?k1Wj z{{n6hNq{$k{D{iN*Se5~S}81dn8;|~N0jfNr78fD7G?^(k^maSWdOu|GC|GCEs>0hpGy2I2C zZ0ePk84oDP-Y`$C!BZo7nnc$lrB_YeCt!S#-_viPHA4OVk>JcNj5zx$acBuBT5YM6 z-_q|NnDV`=gVj?dd72Hy7n`I#qUUgI>2E}!_!BH$r<+&BqE_6Cwd#FN>hz4%Mc!=l z{IavoPL@-PFhRLR$(ID7Nq+!>6Bfa+=PyFAbPMz_4qamO7Q4-{NSJUXc&fB8E36=9 zh@cbGA|fQ^cIC(QWd}e>l~kt}=y|95oB*4T4LMWwMQG{a#Lv@(H?dbB)TgfU%}EHa z|J#+)no{+-^soj6JU@u_k6pn)0*v~{gsbjgN&|gYK-!jst|eh;Nf?8Pm?siYk83NK zF`;r}u<|jBGKDuu97^S3VO05H0d?Zp^L>d@v(Q4Tr9Ss#|EmgJ+8=v?G54hSaAW`x8)8pLXI;z|i`%lYat+)u)}l5$G1f>(lB=tEiJ8q3g5t zx^8ZI44bs0YSxc+$k3tP+18?-Dud@+QD5E;LN5K49H)LmGc4^O`GZ%n&h($f;l4p0 zf7Ph}pW<*Uz3>;cda86vn`k?!^w-2MF$g?hK{_ci2}8cV>>+AZ=oqA_8_~b|^1*Nh z2TAK*Eul=YuAVYN?~&>|d8#y^=4vYaH3`xw{`4TZhF76o?*D|BfEw3)8l>$a4S}~K z4T0XM3Z*Z94b>=0MS4iucO2SW48$4r$32y?NX+tNkA8I9;1d+{ztofuqw?4+q=U#^O%rPe-9#T|&QH9jsXD7#WffxN`F)O=-{E)trLV- zsiXcYia~E%Kee!Xz4?3am(freHFtk(Bm%R~ejM4(NF$a?nc^o2+ z>m@V>Evk}kY?0@C@w(>3FMh4XnK5t zu;yTEOFCmk@sqkHeXwChjPh_|^}+b>le%O_g1+ou6f0yU_|g#y!q280)t5a6kawvY zE0#;)fh)C5Vd~%lziYOfs`^}m2qp%BNF44a6f(91B=8uXdo(b??nLykEMW3c){)XQ z5IeP6T1C4GHO73~atfsrQw}>j%1gCcIbEv*rKL^bo_7MMc4^5Px1LslHbRY~o(9np2zjeRt+SI{UDXhdwW7qDGA+fYv<<&h zzb~_+{)KnM_Z!nvPJ;EN#ntGJBoNSBQ>svNQt=l3{xCU`6imNACe8D^J7nebfcc3T z%d9lzi^J?Ures4Bb(+|SN!yJ;sVV0MG)>dJH$b#aONb1~5z#5d>DcYFIc8CKT0UDL zImUCu==oiAS@rJycInb#(KSq-YAiqQjJtGLQsUuQ+LUdI)bF!*gk zl;te-Op@EKUtWNDoe8pw2!S3dDQXx|pax|nWANbfbZwx-iS8ImI%7a%V@t+p_0AqD zPB&7`OB(HsD8*V)rQ-&n?g~=6R{S%Tq<8khP8hVjS4(x$4OpH^ji*-QY1ZmD6vCGy zmP#z~95!G!futE@#CSjipwm{T6i=P*=Z2opvj~5z4=&VzIHVTA zPv+Qls0X?ej~+vq_#^ZOVPq18kq|-*#g@ikY-u8vJVyEv{cT$80V;;f2 zbu$*KRKBgBS4^1*xRrahBr;NM8;?SXl2a zaR&tFGGFG^Wa!iy4O$k9RNQJx#bLobW{p-RGmB}`pf6%l>Q_s0eaO*zjbfCjL_^Vo#dfs0Xrq-+0=+g{Em1gwJ|F+8OYIGx@C~=E|b5Sy; zv1lfKk)meeH{~xYBQ^Mcs!XX%Qrag5+vmPctpB-zq~ZUsb$V(v=tdZ+;{Nm-`XMw= zEj>z#Sn3XRtHXk4t$ss0K(Y8(0w@B?CGHp1JD$;qCSi&B};*@+Zswx`7eT99y? zttDeA*c6=IK5eWI&2AHE>J}jqv`S5yPwLP~@PmRYOaY0g&bm`{>KEzvjU*$XMUAv3 z-9ZCP%B$A8Q*w3D@2l4DJEh-s*rzE4^JE(G>&kkK<1}1KKJVi}{6%|Jh#6cR@*Q=6 zHkN&dgF!_i7C%=N#pZGwR=DVKhS^!9#gZ@{Jx5{@|IQa(k;rh+5`%-5aCko@&p_B% z9WTOae-}W&?0g(_*(thiL(Wdg+0!B2M@0~gareKOLf#>i07MaA(>Qp^o(?e;&lG|3 zlPwrlDumu@ic!|R92A=Jms@h-P8<~e@@;^CLyzhb1m{ZPC)=D}WXR=ZN}d7STUGAe z%9@(GqUN}kDY?=t0f>B}up(Iw==Y_YGxYn=fBJnO6jHmSl9b0jJ*3KKRLs3dGo24a zal*`>h}Nbw7azCtax@BIfKOdIM1*hE-$eK4UVp-c}b41f> zFnTN2VeLRm)a@2S$YZbv&Hu54Wfa6p-+as#7bIlOQF5PFR`+zl;t;AX7c>+SIBnpV z52We51W2G5Z{sI9t*6J}G~8&Fre+EI3^a2-X5!yQxZ~`!6-&%v-4;#ieW7(Lrt|_e z;#!kv0K0YovCK^KF11C6Y_J$w4i5`5g4G&FF&N3^yB2~GxaR3R@C`9yyvB&dfvG2Y z2DYn3w-68XhcHd2v`Rk4i?Od3%)$U3fDO@_|o8=8^{lQKv#53`SeTw{<)FLAu zs!w2u)Oc1YM_{Z}kEStzwO&LEO8Tdb0vkTZlr`^Kn>`mCEe(dnsK;trj@+(N8|%>0 z>aoS9XjM_zi){fpyqB_!f z?ru0utt`rsgyT)`YNgBsH8WAo#Mzrk8aXW?1ZPBm#R}(|!jq^SBd0w)FS6(Qmq4N# zEUjueB08^dHXi3gp8v{YyXSUu`~N#3*@*ZamHVP-%UMNCj-`NtXA|0*fF0a;xZ)Vz z?&G!++p0>;4364L%-t%ojSEzJZV?$G5RftQid|?!v3U;3lJ}>FiL zH&$J)?{F-a=jA{nvqwp}4hlE=5csL@t-=lm%5BgD;L%JWs&rTo?0 zmQ5&lw1{h)%cU2xumaO!;AQ4?Jl(L@GzXxdonN7d|4p<9Lgo{&_b4~RK4bWSD{kx& zSrDpNE*+q4Is_Lplx=jU*#_&i3O<{-UTZBo?)r7`VH~t1?@oq#@xwr%D9mAKuReSC znwO$BPA&`vJI2O$;qaTogls-Zsa6X+F{ND9ubqOJ!t$MBx6YX7g<@FVkS?n1P&J{^&g7JQg*_^4iCt1e?sWkV|@Ph8uFAYLUO|S587l64tsh z^8(_h`&P_6--2ye0%(~L<|fFWSuRz5*-qKM!hF!}DGt#J&N;0NX$GS9O=brcsU1sE z`*a?I+7-s+>^Q4EKUbB)CUXg>Io2sCzZTLE=_^yV^oaRQD4xqNd;#4&V$JkaYdu%3 z%Qqq(HCBBaHr=s<8a!e$xIw@grOB^uLA9%gOB9vk zNE+a#{NCm`(od@}`v}}{-k%o)&6)tefMGIGG^BRJS1~&NYIk?!eTRV?`?vx^K zTdu6-Q+q*-PV<};r+Ge(zB~egSWmG*`16zDGyu8}pp+(OSPH;60d?0ZR&{F^cOjsb z%9LdW9DJINbdd(K;}8T6%Zv#Fk>->p*8)De4ccI&ah}HWttRC+ml@fUxv5RI4rvHl#ECQtd0UO03@|fuyxtkktQyJe5~mscmx)`a6o*}>YY3naw-aS zTtutDk`vlVv1JHvgtmjxr8cf-cP#84f?$xz3wuO12NC(>gfPRrbULs4g}t#bPRd!q zzF9b=*Q)0O0Z>6yFKDoz9m6AVN(yarm|US;T)`}hQngn=#KzN|tawpuxPVBEyE9nD zqW{si1aphM_534sZI#m!SkMW`6I90L9)|1c`R%*R1t4zU*kGlFl#Ay9QG&X>)y77y-eCVqCNQ$a0e z2p}bp!DXA5eCt%jzWRT0{byg8*T07qZyri=*7?+fWF$Y4&5sc>sz? zG58Ys2#|Mdqf`h|vKn66ZG1SwGcfLX56)ZGyb_GSmFSs*)&nS!%Ws*bNFG7!%ZN=p zM@$G>(_63|r-|ynCI}sI!sLUCl&`xKnpnch9Er&nDDTz@icFd;1jgEzbC9f4V*Ol) z1{(x?0`l|u616C=`Vpf^Jp0iRB^{Z_+AX<7s$I@*Uy>|sSk87XNt9d#?9(L!x~1f! zL4Q6${#XI)S#-NW#3&Cw5Ic94-{ZILV2>Bg6rW{37LAe?e#8de*3fC-GKe8lQ?hEH z;0!Bl?7ob3Uph}Z_;+^i(r(f}{?0Zp{ae4Zzhml}scCuh<%BHSc+O0`(-j;}i{kk> zJBz%1nrLAQZ|@&}dMv{Av--8qqX*?R#*p9DlW%VTte$-9g=JS8oqSvT6x)CM0x5L{ z>v6}E@fBlG?mPWj9I#T#{h^lI0B}pW;EB0W+Zn$jSL&O`QvTlGeeEo!=Ylq`&3ViN zOIzGu59K`O9J5Zo+Ik2Rqqafud=CMw{46}5f(18J0zk@D=S@&w9lyN>Hmv1e9}Wb{ z&$?pyt;oD~JTv9j6^LrtNYF?ETAmg*cFyCg7;FwlStweeJ7dnrMel)V4Wb zKYTh4*hfaRp777bz`)X%EtX=f>|e`b()XZzZP*y-$c-oDc3vA#{_|Nuc<#*UEa%P` z@k>^8=cNAs*JE{^9qBsdSlv>Nci`ZRZa7x=G9>aB$Lh}Hww#Yr8ah+H0I%KY`__r0 z=R)v>1k9X{+I$&5t0SCu;YBErC6~=#K0zAzBzt;!|Bf}&6jQOB&CBDxa#{WIzS1Mp z*wy9zB9q$EOAij4Ea|RZ8M7cCbXW|6lf+=ym4L7-R^YcCQCeXn-=B!_Zvjt6yINY1 zNCyLxl!JkDY;5aY&xx6AqO*s%iY;^w5hpX|+!*O-TWeNptuAxOQb=l^tLw-`P!CAT zq>L}9!@(1)QHObs!c-E~F@}1O=OZcrAIoIUA7;k8v!!44!o z4ms=Q#VPJvC+A>U<#R+v7`19Mlp~$B8L==fVP;K+0cUw9vv*czxATB?MZH*`RmrAN zLHytm(85^zxKW}H{3$U@ZG&SOV}C3NSbol z^`p{-TPL$QcX#hp-?msHDf#_(-x~1+Vomshnv5$VU&}7v-D}*aOV<}aNzu=0PRCSp zPUrGDSxSp=Tq)=0YoowyIp>1q9e!{Wn{m%FNqdad+%reA-OSAQCX3Tp;k|Lkt)D?H9k8ZC8qvf~ta(!EKY`uuwst(9 zrZj_&B=WK8>^1jbspetE-T&;k5CegnvD4(-!X#U`sQ3p(ZHq>-h`Qr}dztkft)q_VZ8lOvz{8;YZ;cop-wQR6{5 zsX14E4|PssGX2aC(&vrWNk6B=N}v`IiuM52bW4SqV`PRI13C#vKJmope6Wyd{Qb-&rPQmOf?+?$|DhZ%RH;*ELNTA|YTT-NX6J zJ$LOmD@kv(W433zN;}%^S@P^`QK~bsnw@d(x>%gH*>_4dK2jHhG3|_8heC#`CX*ch zL>)-V1scnlegQCOF_zbvf%1WTxQZL}`#vQMl*ZW`{k}?BQ?3v=Dt`c#uD~9Q_jyK@N_}@d^(pZ#inImfa_jQaEW5 z0X1L0@0`V`G)}H-BZ_YS7fD=W!2&U~DF_)V9Q|1gZuulC3(DX+KIA&fnLl-f+7V~u zc%>_-5oi9?AJ@1bL0sd4M4~bv$Ef{q)KkU2eXiF~>P5BL#pcfPm^Y{+QT-p+%BuDL zVHtyZ+34rvNPBL6ew_Q?T`{puKd=*il*eNTaquL>3ORM$`~Zf(g;xY$MjeKL-F$(s zC0NPWZR4>fL|HB6e#S`QXbzUU0KB&4t|07D0}v|5QQZkSkXtJn@tzFtE2gtfwcRuY zQG&pR)^>9*1`C(#3Zg3utaA~G7U>+T3V|0lLy2}TCA+kEjXb5s)q}rPFTdC)S|0*&3--VYV_=1j&cHC58U-PY3{A8eAjGE2;2iZziYf?n8*6J7Q#Iao^jtW%ntN_$^InP>eg6U#o~3CzrI7brFsZUw z$e}#kQYGhTy%`r#t2g6kIm2kJ&A4#l2z&XZKJF4KdrZ#Y!4bLYcy&qyO_p8KPt}bt zQZ6w(w{dBwU{cPY_l#@sbqu`0e=C1`KC!NqvzB^0%2^KYRE^v*CBpPzntg=aC`d<Y1E z!gd{eO%l@B(pUHC)CRU!TE>RH_EPuV=yt)$*JB_0E&U-cJ>uw81V5a`etqqBBk-X_ zkV#^TFcxRAdtQJ4dP4bcY&8M1D6|lMp(}q4wjFG5btda@$m~8q-E)ePGA`xX&4AplcR_xQL9Fso7-a68O>NE%eQ+ouJH4#!P|R*0=(_r zi7#m-E!WB)HBAnE%kkS-=W2ug{_SXAUcNk*l+rVnY+G=d__7i>{+|5M8Vr>bN%4;d zp=iN&cnmhPDsi&n13r@Lu(&g{NLQE~y7P{Sf-{nOd@72PW74CB#(POALNMS$Ew8|O zyb1I0Zf%p%&Ib@0=V|PNs?noWHxZR@_k5%Ge63HpS~$;z_nqf9t^wBNT8u)1E3&Fl z@_Z5E`Bl4o&`(bX%#R#7!%`1-?OAu4-V5`cK7(TgxX+?H2h4~>(iyhm@Bj&zPaZZ; zI6_%{-(MfLF5FWi61iHD$gK;Kv(mo%Ye3qGYa6aDQ~=jHTqU?xonc|sSw^BG2dKhx zxHzsWXV@*(3+B%Mh%zqMgAD_cw2NQ+DlzZ*RkK{@X$Tp73~#V4_)uY(kT*J!-h!(V z*ZRzmzVEM_7=kmv#M=)FZ!iDx)6-Yb*!dr^zDMFD+;Wa2^rNz%Zp1AHml;<)u0&j8 zaHZqQ|A;+xB+IC>vD8z7}@q zXt$ffA^w5_ETGZAT;-Xs5j^v?u#Ol+L#k2d$#b>#eEHYfaDvGp==lCN{;wgdQ%yI? zRLbIO1|%yv?WiQa&ZWHAOGBnol0FrpWKYmykSwp1Cus7W!$D+#jgJ_@Hq>;NwwAD+ zHNCnMma|>pP7U{Au@^2S6>mqnLJyde+2=K;G_3C6c{=cv!5O-4%!dtM zcHuSKriIC?wQ#BrVqvu?s?eLD+ODS?E3J+0w-&pG^j2pTBBFfK=5lpqIeE3gxi8tJ zyQ?F&j%8J~aqg(=%eTiOJFR!rGz}!&hU5&w{Sm9MMSTjqTKUJOk8Bh^f#j3j2~}sQ z#LgFlNJozLmO*wu@@)9f)^C@n^2PdJQv{Xz3_DGVS<%D4n`c7?5YyMkt1pGxu(vB7 zO2@COnOqFeNZ=Rz!nE%`;- zfzBICgd@eCd?JHXmO?5rFvCD7q!TWhKu@$ARBQ@Axu~VG*_t!%-|U zA9`z$^hz;%?_mw6Tvte%!Z6Ws!PKjPm&h_>n>HT}z_P678 zqba;2<>1c`VD)boPac#6wi9??+@MAnr<9Og%kQA^6JH8x=2~RoG$t7sc-&q7tl!uN=*KywfZ742|<1KEElH&&HtPE#E@TD?fl=Oj;txKtA5` zy?F982lV9)=xxU=BITm4RgbfzEM^-iQR6g7)07A7m1PF>&?1!)pH_s%eB z;oU6a-O*A5XPNH~HwWc@8oKN&-$Awc%D2)@=^;h>2iWlUMoCYuVjsMF6LqQnz3y}y z{N5O;-72=^y_G2V%B-u!r#pFm_H3fcp&P$PNmJuLQQ zGVx>M6B8kfwn(r8IR`O_<(=8Q<~&<{GDdo!j6Hs`S4YcIl3R1YY1@v-g&jND!>t9V zNJNhYXe38u3(^wuvL_ zJ0eoMw%UrxHfpJscGz z@Oii?L9FUr_;h7iil)tthr*P=WwlnWC7+N;ksq7(fhC$gWQ4=~37o!^)VA<9I`+f| z-QyCQ$PX#5cw!l(Lbm+`d4;e`>EW6Zec47l@SD@vXCL(G6I6})0Abqfi~TBqkB^k$ zO;H;lfyitqQs2`{r8j4=hfc>yqhMC2`$(NV?6cD&NXfdK89=u&XY%Rx$eDRkuM&3Y z%wXx?Zr1n1s|4)((Wi6^sjH>iiMnB`gK+9XUWrF-DWAIEZqlifkS_J(dn*h%Bjs|+ z^gM0FFDxqww-&6s>iflfgK#Z4t@r^+Z$i`fz$=8ye;UO0)|(@qRS;s(vwYVe_Emka zzmLUkE@EVZV;1Sf0pz#p#a(#tKrLn|g~(M?2R!j-wU`V9s6|36o~jmo(N!26|5`0R zzJ+c0xPQbu16w&hGmyRcu}PlSc>&jX-UNQ~ zcnS!5Ga69*W*ht9Z0~mJv>Bbt{y1yu;3uSjtAQJBEcV=Bx0*Wxy$hS}jE10rV319v zrpv3(m&0qm3BHoYDv@@)oo6gW7Ie4#6viBW6_e%U)eWwt*QVnC1gO9p)-;dGdQg_v zt4K~qtw8hLraK`mG1Hz`B;49Etyej~Q3!i5rcbo*5zu|JLg&|lC;oP%YeScmGSv`d*f zk8`x0cfFSmHPrD>m)wH{e+Iuce)ms`A1JR}9STxSc&#Z0-Ps=NZ8#}g;9V2rU89rn z?M&2*8P^ulythyl1rrnmX(^&q!=N5~5i;7wKLrwd=;f~M-T}DU&b21?(#w65>?X*K zXdNJ0Q;~<4rsh&awOX6%zD5bfz8>z%*1Xbp zM8yn5kU<%jUWmikuPl;bB{}1Y=jl4UDlOy{W&6s{AyowV4X$HHKiRtoDqDor+d$+3 zqfk$H@l&wJvo0)8@q7vo99=a+Wgv16vM`d(!VQBW4T)8!$@M6m8yHDk@c9@T zDAEX-8)!grlbe0^sk!U2`;gTiS%HyDk;ECo)mM0wg?0ZdMyg%Il0NI>KAn$(DCvsw zO*Ev`F1MoLSNNeI)H%HBcgf~U+`@-r6e_47f)r2p#S=d6P=gOxnUoBLe1^6lsCmSk z9S5pnc^oLo7w!B<3^EX`LZO1NVM?JzCeti@R<%ElIuuer*HJ%5_l4z6V?Tb@H+(db z)qE(6Zs^CxH7xzl)80?#{pV@#f=kM@chxUen)W&`VHSydGafgt!_Qt^b-yUnUSQI+ zcLAaN$7wI+Vk$Wsw=7&%TuHbRaK+(@#bvsrOnV7a4p4=~xYps?dP$k~3eA+EOnY}< zR;c~ev{!>HFiOZ9jYucqnvd&$oc0RM%Cr|Zn)Xsz@VXbJUdMF=*9lywah=0;9@pi| z%CuKy$pCy4t~gv{n)m$U%e7+kyKp-h7d;1Ffc1!Lx{#?9X-EeO)7bd0hIGVgDHa<# zW9-8h79V8yd^Irooxdoer6QlDqDT}w{Z-c+i~ai5pdp(vx~e{b;;zM>h95ku4Wc(w z=jv$ZyD*&-GjyJX229QP>&uw!>x8TU%b=7tzF`#w8_+I_l^>~^Bv(DQu0#5+&BEPgeaFDj)NF z-mB{Kun^rNvwCHXY$A{}K zBC}d{owM`Db$b@_X<`R>3Wz%pxfFxvn~gD%@6Ch@fc#@-kSnOf`v0wWc-NJ9-aiM*@p5b&>39V9=X058%?=j!uV?DTxEK^h0_ z^Z6!ZC5Jh`OSwE~`Q*ST{s5ja=U9WAH!Sc`km@Q08l-kxe^%XO?ur&3D5GZ1L*P;1 z*h0^n#58ubDS9BWi#CK}aioBHh`tPic0ln3rxqC(#vr4bx9iH%F66p5Vgw>*nw3YR zvV#U`{wWq*>^w(FCn>+N=n*@IQs6gYFnZ!`0Yd-6Ob*ywLA_sCU43B3{i#Al_Cx4| zP#b>bHK|C=Kx({_nuXLVB{c`B&sPI^{#2xDLl@vT28C-w9Z3CwoZ8T(NX=7H%aFQI zoElv1;+xU4{I0dAdbL)l*ofBR^v7@If^hbWxvc)>SYvYJ^}$FyP9(C3JKMyXwsB%ZZ)ZCaGfZ4XoX?|xDN`&bot(l z)94PC@ZDp{ld4-sa?jYU5RU};+&WD)*WEcStH~#RB@2S?8y%~tZI5?mA>U7PKROyU z5-UY9{0=fQ{tJ3p0T}pP1@Q5mkUflpf1OD=tF=YZyrCJWfyfeYU$KB}Z4o-CViRiT z+tD=&mX^OtSlom_SOK)-|0Do*N9PkWXmYsQ#y1mey8}flmg2`27z{oj7Ed6d0 zD)tB)Jgd*+-9;P!2+M{1Dt?-V${82%;!rzp&N+N>_40Bw1X5ne<&1M}@ZTW(Pw*4m zFOf4E_~V@@C};x9p^ZCWQEcuH&x9+-agW-V^`epWyr_KgH0ffDy9jY8$t%kMSJ9D= zA$gHB5RGEv6RI?9`wnpW>NfnSTX>z4wXS%4mfbrU-#WVuht>)LD=_b&glCZkd$sDm zO?y}u9}TM2^2w&7ARRsmq+8znP>v?z%#5GS6wBQQ8enqO+vh{l_99~;x+nYqof>Wm zOQ~5MF4t60P7$gLz^xV(R9LYy0i>Qq8oPHSLAf=3f)flUY+Er zip5tlN`IYyKi*OMw&-dhFfIZ^myd%O&7ta64}0#9-fmktFy6(7T??zZ8FQ18vE(7i zGWVB}e@L4Mn0CkT_IECyJQ6PN8 zrzRFFSY^;IWxW?xp#m@!jO*BVSIYz~2St?jrBp5N zHCCz7R61W5a0dc|X-QL|^cx~u6j#fxLwzk}X~onCs;j#M%P3sF9YpV`)YS%`+Gpp( zZl+1j(fRC~s{_qDA&|?NIvr+IuBmyni~0f}p7FwK^z|55Y#u*pWr+d1^v!&>A%G87 z=dfde2e3@|$SiTDH0||Ac8T4j+21_!mKdj{*HH>ywQYRlH!&szW4phbDE3tn<3(|9 z_4r z|4n>GTz1~;g$O8PhIL~BgT@#moXHDT8TM;5api;~hMuK+*8zSvqHDWnP&te}Fei#}#buC`P+0UsM@rsbDuf<1__6 zP5u#of0iJ;3a=JO&eQ43rXvv~@HTHmR$~kxO55zd46O}&Am1FKJrE-*5ANpR>$vyFkES-%(r>c7PnE)<0J-zAQfGHyFg* z!x{+mh2LWk2S(hxv(*dpAN_dK{EhHxI#o39TmR}#;!Pd(;NwJ5ykpkQD6`Ffw38Ss z{rFG+H=SS)nv`H`3NINbs(dm=~;QTj(jkj{lqH)R~;YwPyhFw#hE?dL@hM7 zbfD=s?+5L~umCS!LR2;Wo4bg)U3T3G^#zi??B7s@JbY^NPXEy^;>a$GTQiA)F(f1}u2-#v)nycwk;?)2M@Vy^*<&nTl*Q!@X8rV~{AKxCh3d58(DH1XPH z{;fuFRL75S=(xH_>)1y8l=~ZuV(x%T*g0x4`7*UO!rbsX@oWpMFy--c$Y~idru%0_ ziese5D*T%x#T3b0;r}2~{F`*B!apoZjF-Zm-aj`=j25NF+x_=+6<39ygC+28+x)+F z6=O{?=ssW0X+9cyU^rB9#QUv3ini<0L_|G&D4cWR%)Hz=vk z{r$U(m-7WLbYtWO_{YG9Xk72@S3sKPB3&_DQ)b}9z)56i<&tLjyQTq$#-KX5a7-V_ zDiLmN|48i?lOrBk>I}i}j26xR4e=}gfq4H`;z*HQ zNA3jkkgmQoKt1CO&*xEu-6Gq3wKpoLBw*-COp}(PaNm5s4hzBsDPxs$X~xok73b2N zI>ZMq5ZQ$2u$4$pl(O?fPl7J5fU_liR=R1qn}%Ub+_mVcMQR#d^=Eaf`GCaKj8*Bf zLhvAuB;9hXgRSHTK6Dh*y<#uA4iC$e2QmyiIFtwK)WChGR1MNbK1N^m z8UVZ*8W0#s#d#NaMHN9|m51Q@j(|!~vE!c*)b(mr?ZmdK?JtQHyM;iH{acX;%OaJ0&i`7h*njB5 z2!eSvwz;bL1uWLe)?(Bq1x_~Z1yfL82jLbXKQQvhqKSTeZ!xap;lUXE&d^k-f?yfF z#X-`*MgBW`i?QzTMS?K5VD|CDIyLN3SBEQ3E=Hgpae{s$kI`?BBlJ76l77d&j^9Na zBDr#lIH%lt98hkddzBlGffCA)7jWD9U}ytw_*QboY2~h|sKXsWLB)AD0m>WDlG@N% zq(%JOPPrAQ(HFI$$MD+@OUt#PCy*kwRu-Aksm-Y(h!M_4{+DD0^-?$2#hf zP57z@4?!2m&D)i8pA(lkdwASS1!q@zr2~V677Ng0-X-g);V%HW8h+q!*m70E!;?#9bS-X0g0 zV1jVm%St%e3Kn{`M6Jl@-_2?G= zh@oPJaSbFU=bXnh{I=r>SkdymWb^sup<=W&#^>KTRLqppeg2C>#iC)vw7z^6{5{q% zT6f=#k0=s1I(Cx8A3TrToQ44Z?H9jyn7Ggqlo$4b9Aj09+4w>%`V@Ez9eMIt8ruRN zUCLZ0>C3-`K=4xP1ODC#Vz;y_s7;=rtq`z$EKkr?XmH2J;WEy9nnPC`7RlKY42!(F zjEg|CHgP3qEVXWR#QJPg%(`_6vcEV%>^?MULmCji4k-Q7+J9Y?4r}G;1vH|-+at;6 zKawE!3xf0b3Ig-Dzkr=6C(WBQo`nrCsRlmrODKzHtP_)OtZf(l!R<5*)`kM$?>`)o z?XrjcS;NIXnSX48Q`q-9dAoORhGG@SYxm*-Z?AVvHo3as|7o~}uvkF|?AuM)N3OvS zZu0LQF7|S70Z3j;uJp|k{0y$O@p1)pGWfJoDN~6jz7$EgN8h2-c#^}%?#7f2Rc@im zU3$DZi}^`lG|vE9L4j|Ltu{j&hOAO|a}teIo#b$^*a0kJgp4Jm#DW$-xwa1-92Ugfu*dG)V=xGjPv)hi0M+&1O9hMh&dt934c$Em=Oe6 z{97#I@I}f9iQuV#;tRPJ3mBCY*dHUcife!&`?2yTUsMe_bD6V`XAKNFhL;d{+0vjj zzm2y-$(mD8f{ytXZuXSbZqmw!y|5f629 zCFSKIXv%k(Q{d3ZVDkczm5MnzwcfFW(iEviPM+pfuJ*N|0QqYZ#UUY-xSS{s#R&xe zfRSQalju^caIdugn*>~&`7bUTMiUJ{yF6*XHjh!A$e-F zP2Hg)kNQ(biGvipJ4V6kf&b7b(JDPz=>K4pIIznbg*4eT;jBF>I4zHS9SHi-;xK9S ze7|+H7%A0k@#l|*R<3!_fA?rHQPLIqca0W@W&;sXUh>?ZaS+h;Gr#u%5?;ndP|+o4 zm?%1OD4-hO!Up>24(%@TD zfr1?o5%nCUQV#_sbi`21v9glvcD-fgykuMWjZDRLl9E@T*G}sX8ub zCM*%}5?_mV1=0`;ND4L1H!ndY5BVOZe4j-Rp=X4>Zwe%I*!w;K(U9zYLnNiH0fn0l zX|5_lWI1}M!4WI*MFqY}KN8q+oW$=&cO~!=-#?iJOkGN=7I<8vPnPnS8BvuVo2egi z#al`?6MZVDwn3EKNo*3pkkuqC06&rU`l>qcY#7tA*sl4zu{FaG# zXyDueQ606x>u1)@jX~2gRjj7EaxZTto^DYHG)Fe#x%HAxl8$}l?vUjA2C3)L(<~R& z@LG!UI><}Uf8Q%rBW}$)4>hpt*@_bgl5E&pNeQYq$)oh11j*P7wy?JZ2H#D!81qfA zp|BLYS}qElrPu?vb{i$kYIZ5b)u+A8-pIEU(ugBjuccKbd8MT)(U{?)$}p^11Zj*D z(Qb4sTch!!r$l3)WCSpSk=7|(B%a)G} zlm<*T$tbX-%!#6Tm_@7uM7H|6mxG|!pNKhqZW6K>7qi)AE_Lze^WfpdzwC%?U zsq={mEX-Lv;U!+3z8yzjprU|~kNXRtVV==*%)Otv~&i)7JFtNJFq##%|jeG{{80JpY(SIQxk;I0FxI82H65~)90~`KN z+zm-=gefSshdW|;{GVb-8y!ffX~%@$_?G#UFzCzB2h%f$o}t$plkKX+eNY8l#)DYj zw*p;(c1fo4otOcWofAzk4$$IkWu)smHj@vU#l{Ie?wnaHqmKw+Wwf`1zc7nU5oWoY zpKNnBPa)L5XR#3xV2&Ox){Jcwv^&STCr6m#(VK0?QsTo76*C+~zgRT`i%J*9^1G5* zkVs}zG8^OF3?3*{nAIhq`0#W0O!>EbPQ0%ch(y=PPEj;rbRz(xuYR z8J~h{8=#D7q>hR@BP9~vGA&uRskYgq>rc_7V}1NgX4d9Ks%i3ubYX>T{`n7kk*@2| zcSn{*Sqxz!wI64*p(Zu8GFN8{-aK#R?{qGOn%c|oR{Dy>Y_?6*2Vl>SuTq0B@jF$6A~nj!`Czfyz8$9)|6aaIHp=;t@lj!^6rT zxV6bel0*$>AqXM+2y0674g0F(@6W-UB_x!0&OwDyyQrETFGQ>b;=@zv{zea%U}IfX@w=%g~Co|m@YIKG8g{Jj(wCHseP$GI%Xqa5{f zeFlnhFa#KI;nBc~7Lz-djk~R3J~5ZYh>%Mlku%=ia~B(Ks>VoZ=!FrktIXoF{zv?{ zmu-SLRN$cG&nEe*lew2isE7kuRV)BHu@uA64Hnv z<9{$WMMWYPp5fQkd^{jnn7putdtHARgz3m^!X24iqNZa`?1F%>8$|`819uWdt3-Ma zElwe=0H-YFc#>e$Hld)yqQ14wF<%%0%YL^Q{PE4*#7@{%{fGFOU`-H!Y(r^05fwOH zf<}!tkf8WmXQ{<+@W#z$xz1gAXkRLYA{skbqptH z(523ml&*bz_dJ%&9;y3s9-Gc&{o6b!gKe5f_CQ7#y%xer8;e zUh9XpjNJ$`T(b{8K%4rG^25Wi-nIWIKQo-g1uwu73|94G+6}JC9O2htoW`~eSLG~J zK~xBsNj#OvBLX3V@2KH4bb-r!^3m>AOg+(vc7#HDbp|682lXZh&s`Bvb{MZ8KJ1hBh+oU+W zq4g=Wtpb*%M9)EzP<(eGMuaj_kdVCE_L+H$2g-4f(jPccgw{slyoU#5vymE8A)1|X z;WeI?%?A7C&|PaBWLCUXv|C5mmgmgo<=Jde()}>uwW_9P>K&oQgY%+pS?L`&&ES4lEa8@7^`^kwptxu=|l~$U`$& ze+JRKw4VQMA)AU_Lg8^a7kCrfFc`m6iE_fkJ+rZn=<*r zOxYE?q?OBh9<+#M$X%cD`xdd~lLJ6yHg;eZu|xwIkhYL(lp|t>-nt#dh=v(+#u%&& zt-HMtJ!|+^A2KfXnA@=ks$hs6%=dPNM4eJ#qD@S!P-V2o$yck=m* z*)@j+&{0lb!qUe?K?@JlO$b7Rl$s;9SR3IxCHW#3V)p_%5A&3El+uYMOmCtW%YKXK zEp<|iPlzK{w$eNtBm>8 zcvz_b>XhV04eJ2D8fWA$EM)^CPJfS7oXt%%fWvmqOW4e1WAw~^IK@(WnpMn^9q$b1 z|6a<%BU{8K3z(rOki7>g7Id}uN0ouSAq73J#)K0me?!y2A<>Cl=z=R2cPYk|eDN~o z+fP>eaCC#m)6+p**0*lkGS-KU{m*K8O+EU&V>pG9M#wcFhQ9+8O4hx62k~Q{`zVRS`WjXT~Bm5^e&&}m5QeeifV6?k}FI>R} znNYj5{?)Vj`UE;!6yP5uBuFQYrP^D_K;C!AW9wch-chw5^oUVv+o*KxE3Ci8zTs*T zVK_KqV~J5%Y|~ky!uV>i5&^th!GNWeQR*-pY~GW{R>-L@^ZYy(;7-lWmgppL369x~n3mnN7@o#{3o(2_V6+6;nUff*$8mh6_WDv zHhvVV7V@ekTp7mZ%DuE zk*c#LMpz}OAB+^%M^%o8qoWK<%rIBQ{(;QYOy$%*G?nb|kK!xmcL@@+<6(RX@%phc z!?@`A8Y9$W$#@6&kl`${57`@8A`WLNP5b!b;cV#ex1T5N9#d+Xz=b^iptZ_1W!F4v zJBw#>If#Yy`|2OJca;|&teY0Z%*@3VdIHxe()jZRSw=yypSpv93F7AGyP$1z+Otc&U!{FNr@*JwDyC8iHi*TB!&h=oK zG3g(qf-%PN-oaQdy%%=X==$BuAG48*Li-gOe(W@-LPQ~p8o;?HN;0imWY1{ZNj9!m z+Vsb+$^}u%qn`q6b|YfEuOgDe$!K50EHUFWivv)UANr`ntq6u}5aFz7vn@lg3?kzB zIkycqJ39B6Y!RCOPcRFgSpOVNHN}Hgo<&M9h@$})2iw46#|x(-`Ocr0nwF-2c3rnA z50tZf@F+INee5uNJ&ax>EDI>QVSM8#$aW!_{JBvqPd010>u5GmGkbj;&d78q;bX9j zlwB62!E1x9`X2gDD(e3{i=uA8P9R9GU)r{sJPD*KjtKEpsV)_DNfWws+mRko*gEva z8DtnuJYBhRh8Nw<##r|lNsN@J&^f;aMp$JBd$aKhB2>OdPpB$Kp!dsE?!62I^{E~T z6N%CUlF~`R)@agj8EKm5MV$;y;Qwer`ZMO5V$My5sajVSED zb)c*u1~25JR2)Ld2?wVM2{xYuSjI zGP-cJ9&9u2UpJ`@=B1;=x|V+01{|e~)Y4B|@1vBJTKYMacm*6`PdSd?TFd;P0klLX zUZE9-&)(r9idnQLJraz6&2HkMy$w5gaWV5_oL3cNWnS&kZq12tjy1 zml@O6^J@SWj%!MP4e$#^zQaGmd=hI9zRFjaKHBC5&FgE9{+cRJpIGD3F;4cH zSrgZh81&r?RMQr(Ee@4iyf9J6ygx*_foUb?6XLbRe4=e#%?ll49A5*r=5ogldGv&u z!hc_tf5C~E*XPMkO{_VHZ=PM8QPX~Xv^;uZjo*y~*(tIn_eP-nWkk(3IIl(2ym%wg z@4f`F>v4>-XO~svwY9Q}qME*)&&eK%_7CzAcA51&$TqC+*&bx;ni}7m)8ya7YO-&J zc%H+o(z-LQ>{=LJyqZUE2Kf1O$Nm*3S)8r5#g0;r7uKA=86!^*tMT})Nd8z?Q~KM# zra)uwKx%u2{R5d|uiI_ftHA~0H6W8G=vm6H`F`$HkE;57ar@^^hvRChe;*xu8TYUV z#mIq5^VT=u7CpZ~6(OB45;Pre#rSODo7b_Z&@t#qv1I_3LHg_p7`O-v3+UZ#3(!tV z1Kwh+x9-Lyu4NtbF)i4Fx4O#U%pP{e_qo3>aGaT?=-;7t8uRlhWR4Hr@EH+7N^gtD z=`o04ZcZqjIwjjMzJR4GlR*ty7vyg)?b+Q9QA>TwZdJq?%vaHL(9b#iT8ee1*DRC) zN!g+sgMc9NOJyTrPol>%Ilb-S4cS;@Ic|xh3@BMTqJoznSkD%-&pF$`uCPvibps1v zAM;)YmOO?Q*de~hLX1mi=`~A!WmpoIS~bAxovpQ8)Jj$OoGHu|5DJVC{Z|22aP`&$tyZLxq4yLI%+4Q*a z0SxcxXTCAAVN*sQ74?BP&lNKa4^XxyqRMeN6ZVzPohgdj8bEpk+fi;L-(tLo+sKAR zktt5wGFbZ3c}}5}ma!`w=gxTt!yn$RTIG=&DDG)*9*%K91|COjaYXrzihdhQQmng)XwC|3+`RkF6%Y&Cwb`-9UFf`eSk?=od3Im%`jb!K!t78C|?NIRk#H0k zccM}!ZnetG!VOgZF5F<{Y2k({T)1J%Bf^bPwh7lyF$p(H*(BUpWi4EMCd6Xes8jL; zZn}~q+$1GKxO0>_!o_zGgqxwn3U`4LA>14#RJhBOK;h;oe!|r&UcxO@T!mY#I11OG zbfFw98%vZ9;ciy0!8K7PUM;29;R`~)T29{c!dpS!M&TvpqVksTR+IN%!n>Qie;3}p znU01vIek z#rcc|D<(!@HfmxbO9UoU8AX^om~6$eK#bF7YaADqi${!8sTK3@34*Uzj8nPEiuy)H z`N9goiuq8*_+d5Lig{bbXk(nJt(X@DW@BJXy> zEes6PiZNP!_cQ`^ju`&=t7hio`Lf9>!3dE=Ik1R-VP+G3^n|u99=u{*JV1ZKgSWHI zo*!dwWVhgOdLe&hJ6k0$+RC+6%xiY{ds^U3>LGZyw@`LG5G}lu{2C@|#uA2AQMztR3iW zriAfzJJ^KrAVy!Xta5Qn+amK2(uzfIxqvglaG__ug4wLAEdd)3}rm4)Y5; zFyM?DhiqUJY3ozAIMPX&74uDIDE8hW2wC#}>3K@DKm!#?LW{u7ewN zMt`OAJ{l@$c|wS;N?R7Md4vUrs%Lo4E<1^X^RUs^6;q}dCvh0yB+TirVh&460P2IU zJ;g!zX)ha$z`6Z54pH}iHw4|6k+bE4HFM#3|d2kQBRYApReT+0_%Ghcc4eSA|j z^Pl|9z1=fo%8+s~lQ?3xX(+c;Lj{lOhbLEkx#1W-rOwUXiZXbcTj!|`hf zg5fwRlDvRTRYJi7JFzbl{s6JDTufDbRAeI|a}R`Cv9gLiBuK-o$R98QXCH{d9U6_7 zez(d$Rry%pBY>}^A6T8;6+MK=3^P-eaBzarChpAb$_RdHCyR=sR6rG$s(eFH!7a$r zgux0PzgkKSfiQMDX$^!OQI`mZ;SK_omnyh!7mFIP4>Dm}a4k8NZsKOJ@n=9lrI}h-P6;1YgLTQ+r+I7*mJnZ@$CuIlu6g`E zxF&qMn(9$`<^~ijiDzL0jC|m9P8f6V!k9PZFn;xp>ELwF5NI&WXm2Ml&~1(yYAC5~ zS088?X-gr0(E65p`7G3kEd+gN%P0h7Dw9^yEK+f&xqS8kHKKd@5EFb7;|!e0YafLj#6>6zvX7TeootK(_DUqb_$b7X6OsJ- zqik${r*3{;YN1@bi%;4Eb4$IEFWkej-K(MZZ|eiiTZ?QyoKwT!*~9j^?It9?QRHea zT~@5hL^k&yl!nHUF)}oayUBc7$vLMr=DS~0N zvCHU!HQNO!8*`QyOmPxoyr~^xI`2)b(!JalLD7*^vF_#dC_(o+r>k^R=hgxz6}MNc z?$_k5jE-!EYxG9IWq2});tL9ym)_=T^WUABIWH48)C$s-EG$pqW*2V2b~_v#JwWlQ zDIVM%V9)DY=&8^NS$Q?0 zFe)`-DX0D{{KxB?#4q8G*Dt8yo1egLL%eLyKfyvmi@@uYJP)YkCACz+qNd?;w zXdI_Jj$r%JteVBYe3JR{h9{X@zZG``W{SWNS>wrFpJG|E|4yF&6x%NEtmeNyg;k16 zt9ka*Y~9d!KOvcj)%=C4yUSG+SjtSUJk5qX25WGvpZk8cd+5zT8a))TdR#gG8cnXV z$#jJzfX@T@vHfglq%pT{sp{$Efy1}M)9OtHrC%ttwG6# zf7bdC)!*x@&`P45jD3_RSMf({SqRI z_&b&JJ7{TRlrj~ZtZiflyw(%TxaJu)MBX%xO3XOi|Gwg_Ig#Py89f)*#8molW z8*5`F?O%Zd{`JVMPM?H9)8b8Q)CXue_Ba-IF-W3IZSp^gScP)H(YZB6Q7)WRH+?|gvy zBnItAk&w#A<@$7ISlNxIa(e7(wVaYrPNHYNZK2 z8Sac#iZJF|-&WD8a^v~OWh}5?)E)Sc__{vj>~-dw4;vcF^&)hH^Tbl`|spjKXhkIvQiec@fq$)8W$0$Kk(ApZ$x&Yp{g!Q4r__<#R z3z4Dq__>7nj7;oD$G~1rrEfl^W7`;gzXEzMOPK(AY|C|0Mu~``@3*R^ZTb?k z8?QdVmU8V0Hht(-S5p6}?daB`+bjO(NmRiD_}&w&Z@A3sMVq9!r)4lbV7BnBPFaPsBC+tdGOB2PFD%hbVI zUT~cGd(}a*zCD${-QZ6iXQNHR&M+EZ48dG)3b@#J;$ag-N!25+scj@30d)EPEgp2Y z>HLz#t@opxFuy|Kh?n5iTSV<)Q$v(ZA$>M=Hl)TD_WvugFrEyKjw}Ykkghzhl_YFT zHYTeis01AyZ)BKE9m6Y0X!SUga%8IVJb7bIZ5(KJE{%Wp&n2^4OASwXiG`|(x7#Ov z&6+rnB5^gaMeeXBu872OClXihy6#B4%bIw{pC{fa5+6&i#+H{@T))Th&e->2Rik;+ zOE7HibFQxU%WS7ChxO-A{*%QFly;+&Z(UZIcqrx__wrT<(_7qbG{3g&(Yl}ii7gKC z-*w)iGe|yfjFZNnj+3?lUI$nJlirJyW&@rB>;!n6iIbcFN8q=ohMBZBE%gOtiL>2@XzeqxGph zw2^xUF35=)ukL|U&{_!*iuY5hP>=>JG{4deB7u&bq>P!1_BlEuNl{*3tqT{D=4O6a;=mi?17seWVAwsl# zS7>k1^4lg_iX90D(C8WInu=XTr}__P-v2bq2%&}#ff>67Pa5)7jSxM10nVz<#3=`f zoxo=lz}(kk4c~Q|4fp;5oT=~M;)w|f4y4AJl9_G%z0=IUUu4@YOLkkkwe0D`GIejf z%idxm%COS{!kx1)*tyOoBN@SCwmhrDtWfBeas014T-d zr4p>#6|hVt6cY~}6gA3Bq-H(JHwXF~FDpJvsm3IdCNJG8j}Lo^8o=gp^Qn-N4vE() ze0Av0`N9ubZ<8u{x|gMNSd`OaNt&gFu`FfzS7;p3i#rY2#nYu^;0`iyHXbUmqg9Ww zj<8d^v6$ec18HkF5Jf#`2LyyTH7LbdIo5befYpKrw?T3`FtGB_4Ny z^-pQMlVkvq>?e}{xpd27pXOOgRMVYkvpM+!SYEvhdhG(xmtEq=&NIJ=ql76Z%pw~H zNY<^bKirX-Jw(?`bm3}dOs{p5beNOd!F(l=f8adN0a)*fAj$e@1iMWnx+~+B-LUCszZdJ&*8K3Z_(iVId`czdp+4(N6u5v;}(EId0+FbnwA}hG4rj1YdwI+3QJ7i8i2(sshOv(XSf;B=Wi|I-mU~2~HuhMk4$4V_Skvt@Y8!e&UH#b4o*+^2D9--UNFm#G|&; zsQiuwQy;b%9QFzhRVhuaC5VsD&$bp5AJJd9nr9{N1N8@>R^y$Zcm|4>YfZVkh?Umn z-L{DB=HzRLw}+@Zi8}ma&YD?&lct;Z33GA-NLGTRyKQ6>ec%$%U%xM(fvav*2 z9|HYEB1t8Z^B}QhQ=~SSg2HkURF9yuXEBiM`2LoKjv{u9IcCtDk~;Jpf+Q@f^jhTG!mZd;I1V9JK1S|&_0HuIkfad`x0AB-s0Z4jTas~JS z#sXpiNq{AQB0wo%2jCgNtALLH?EuGBvg8ZU0ww@-t7Mau0nbXnR=^&>vw*{Zqku+0 z3!oj~Tp&wB0iyvC03Bc+U^!qtpcJqJ@EqV(KqH_T@IBx+fX8Y)C?FP)3|I&#UTs1| zc(w!f0Zss#0lxrx7a{^+DqsOX57-LW3wR#zCg1~r0_X(vUV{t*!T|9A+tq?Y?`)U0 zLnn>Z#7UbXaL(cEIOz#bm~Yvx*)PXQUuyV{&se~mxofo>j4Slom8%N#wLu$t6HVg! z^=sE_3)kl6ttz@3NW#@)@}Tq7Ny`9IM!a;mzfSV#r<3Nuuk*qw=}80@BDbFI8`Sdo~x7cy8V1&3!BU&p8Gjoh81hqtXW$$HYGJpl2reg z3F@6B6|P#LUyYpD?(<8EbBi{tvXM*0xrP;bYoPF3qpJRJ5u*Ad?EI0!pIq-XF3jJsLAxfmSi51>z4_YZMgvN81E|)n$=BwtSYceByW*Zv+VR@u_h|F- zSLPZE4ZRafa@Q0W=1)eMYr!{6J7$$OV8!H|yK~p%ZxFu$(!BiKJZ(yD@z}iOD^P3v z?XTFkqZ4wAMjCKel&4*hUsy;v(2fk+Fp{cs25NS)sNW*6;a->7a5wFupuA9RP~PIP zpx`fk#s=jE8MP}>>y%+MgB5yX(P|Kc2IYYwYyDa@gu+$pjH~jHSwsE`1Er9XG~q6- zphPnNJDP+!X(|m*`G!rnn_3jo*f4f1k{(CCagvm7#w6y-z;E;1Gt3NPQq^|zMp(=pGI_~bXFEF-aJgstyB8TuFgEKzZ}Rr2g)T*`5|FpVLYgx z98+fql=nKB3~1AZfMtLTKoTGp5C#Ya_yIfs^lTaNI0gz32yg@_aq*G{VG=-#X=>Mu zc&QW60cZzY11NyYfM&o2Koj6Bpb>ClM!ZRCfags>J>Ur7FyIj2AmCZRe!xD!UchcZ zHDEiS0#FVp1#AYC01SX)Kp{X6$O9|`WB`%?IzR-#58wglN;DyNiO2w8A7C>e2M`7D z19VPD&H;x3y8-2ZQa}kn510;!1%v^#07t-;1n>jw1{4BxfIxr*xQtRe3@8Wa0cP1J zzHaRx*{L_L4v`C4QqBExj4*jTjGEO_J=$HN#V9-Ut+tE7a~bzntT+m{T@dyxVj@rdpk zcpb_>o!BnQ*_&Y0NX!6q5z(J9JA`n}x}Lc9nU?U%+AfOgfqNT28=l<#NITSIM@$)r z#eI@p1S0yg420UnBW4YtE3w02eO#)*{a%1QKcb^_=%P%E^4HY?pm;+DD>rQS5dZBi!W*ypMLw zDMRJBuLjtPo@oA9l6Zbw#Iq+P>EgTSe0`Yo>^dej?8LzY-!o}1pb^js(6%ut2~Yw! z2>2E->>87n0yy9t!0iVntpFSZGy^<;WKtAB52yuP0(krcK7f+m_&EqT{uASG=gZ#i z%f6430-S0FQdV_Y@jHik^WyQc#=Y7OUucJKu*2_F@gC!3&5EYsI&hGr3t4LYw7~5G z&_%79E?Y5^g;n(k9ih5gwSCxyW}TpIw@b@+fyi6+IN77$TO)On8e6cC<_7bBjgv?B z&Rd|SeQ*K4I!+D<$-uqsq6SLOI2|}jOV`%(+)XNPdXBrpAfM6Yipe*{@q-%$ussVk zXu53q4W^rUI{FoF7`gUgrD^K36x*ejk=;|y`|a?hJ$Rqfz!RTOtl={F9_k5q?|-c) z|1CXu|GR*vD+?~gCztA%p2c-xce?)DtaOi9>BzOwCE3xvZKXS9r6boySKdSCbHhp} z|Dc9bejC*A)CsbygYTm5v?s-YhOPvwJKO4}!=-#Kf=hYd54XE*_QZE@vcngucxo33 z&sFM(t*B>8pXz%r=HSGO@Z$PW9=$^2o^ zQ0Di+wO-sOLiSGn77QtXO2XFquUQ#3fRXJYnnt^OdT>YJJTOV8u&x~5H$omdGKt@w z;rsUJL?MwOP6KEuoxO|W`P+H2H*dlbcZ>3XrIZPXBXP?B&Q=V!xj$iohH$!UE`@7= zCszm8RweC=yW5g`u^rxTNe_O%9X?6LQx)=-XxZ1H<+zT27A+5P34TvU3G%n2<$(^5 ze5m8U1M4v6yc#@g%XtwjkxG{6%B`;Legpq%qU`TdcSVp1E-nxK&~xK(^GB7FL;s(x zo@Se8TZa|1?ROo2V=|KcpiA}0PfGmLXnCmof&>38S{~&5ty7$I(@Ef5%r2tlL|T0V zAtuvxbx@qtK8XJ~NggoZec&zvL@q?ABpvbNgQDaBpRQ%`q7bQoU31my^@Cx8s4{(& z?A!O+5S3#N-25SYN0dCE&v}1*HvoW(|1?SVo?57llZpX!Jq!t*uCriAY@6ZQ`bruC z>7x20m-_vHAn_c17X`<47i&Q|`)n$IeX=~% zyr_wrXUyT1>?S!!k)l0h5RUT>Eeu?(Uco%GmP=L7_@+FgNmc#33{U> zPC5sm%hpmF?r1qfcx{Y4*y%-lhv$Uw(pw}=+rcMKmi_s#SlOS|@i=l;^IUQc3CAV) zA3ce?+;zAo)xl4+#7T94H}k0))GJ45MPv->|G%r97W}_bJJrQcl{4hJ=XLTDx&L)G zGvAQ1HqTg?pOjmaSC}6sahC-77{8n#ukRPfW)vDX=t&O|Z(O-DfBgnNXS#f4rUsQ& z9HtYmk8Zr$X*a+v1>OU$4sHv=_cKgwqSaSw?6kN{Vl)TJsr>aiBH*u1gZR&j1Ct$wNGq$Zr;+|!osyHbQ=tL$ca}pKRQDmBs39! zfg$+S-I^gk?wIypQWgm#gMTHLg0?s2qqpk5nF4#)s30~7*E0ObHw+V`0lk)Tj=&XTXP(B>#853FEc+lG6J^OvqF zTDcZAJ@=~ajeib&dpfev$eXfdU5qUTk{1_!_RNT_O&b7|I|{eImcg=sF1U3Y7RpB1 z`B}98-O+VF=E&=rGm#@_E0@R>JHs?}KQ58qbD)FEUtca?@0B+P2hX6_P2k5OY>8F7jZY*4wxk;{Y`@vPF#!LO-z6sYCZaLh6aC6|& zH{=504u*Se3KTnVPrw}t_gT39aCLCCa5Zp;p)e(nScm~Y6hp670yhWlJ#gp1y%%mQ zTspTd3N8)Y!Ej}`0Y@N%{deH!SIXl}R4&U=2Xs}>gI)_z0VoHQ0yYCm0L1`3U>P6- zkOa^HA^>54P(Uys5TFJ40ek^o01tpGKm%|DbfrN#2T;;5(Qko=A~eHo0yF~N1RMbz z1ndLs1?&b?01N;<07v7C3Z#rvg^q<=xCgDGh Sxu!^tldE0oW*5n?u>S?1nnR5M delta 49116 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≪Hv*~p1647BZuw`(8n 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

f9N;B?N8oH0`CeS86AzW584WJ529zF>=OFp1~3 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 diff --git a/contrib/extractor/adt.cpp b/contrib/extractor/adt.cpp deleted file mode 100644 index 74293624b..000000000 --- a/contrib/extractor/adt.cpp +++ /dev/null @@ -1,380 +0,0 @@ -#define _CRT_SECURE_NO_DEPRECATE - -#ifdef WIN32 -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "adt.h" -#include "mpq_libmpq.h" - -extern uint16 *areas; -extern uint16 *LiqType; -extern uint32 maxAreaId; - -vec wmoc; - -Cell *cell; -mcell *mcells; -int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; -int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; - -bool LoadADT(char* filename) -{ - size_t size; - MPQFile mf(filename); - - if(mf.isEof()) - { - //printf("No such file %s\n", filename); - return false; - } - - MapLiqFlag = new uint8[256]; - for(uint32 j = 0; j < 256; ++j) - MapLiqFlag[j] = 0; // no water - - MapLiqHeight = new float[16384]; - for(uint32 j = 0; j < 16384; ++j) - MapLiqHeight[j] = -999999; // no water - - mcells = new mcell; - - wmoc.x = 65 * TILESIZE; - wmoc.z = 65 * TILESIZE; - - size_t mcnk_offsets[256], mcnk_sizes[256]; - - chunk_num = 0; - k = 0; - m = 0; - while (!mf.isEof()) - { - uint32 fourcc; - mf.read(&fourcc, 4); - mf.read(&size, 4); - - size_t nextpos = mf.getPos() + size; - - //if(fourcc==0x4d484452) // MHDR header - //if(fourcc==0x4d564552) // MVER - if(fourcc == 0x4d43494e) // MCIN - { - for (uint32 i = 0; i < 256; ++i) - { - mf.read(&mcnk_offsets[i], 4); - mf.read(&mcnk_sizes[i], 4); - mf.seekRelative(8); - } - } - //if(fourcc == 0x4d544558) // MTEX textures (strings) - //if(fourcc == 0x4d4d4458) // MMDX m2 models (strings) - //if(fourcc == 0x4d4d4944) // MMID offsets for strings in MMDX - //if(fourcc == 0x4d574d4f) // MWMO - //if(fourcc == 0x4d574944) // MWID offsets for strings in MWMO - //if(fourcc == 0x4d444446) // MDDF - //if(fourcc == 0x4d4f4446) // MODF - if(fourcc == 0x4d48324f) // MH2O new in WotLK - { - // çäåñü íàäî çàïîìíèòü áàçîâóþ ïîçèöèþ â ôàéëå òê âñå ñìåùåíèÿ áóäóò îò íåãî - uint32 base_pos = mf.getPos(); - uint32 header_pos = 0; - MH2O_offsData *LiqOffsData = new MH2O_offsData; - MH2O_Data1 *LiqChunkData1 = new MH2O_Data1; - float *ChunkLiqHeight = new float[81]; - for(chunk_num = 0; chunk_num < 256; ++chunk_num) - { - mf.read(LiqOffsData, 0x0C); - header_pos = mf.getPos(); - if(LiqOffsData->offsData1 != 0) // åñëè äàííûå â Data1 î âîäå åñòü, òî èõ íàäî êîíâåðòèðîâàòü - { - // ïåðåõîäèì ïî ñìåùåíèþ èç offsData1 ÎÒ ÍÀ×ÀËÀ êóñêà - mf.seek(base_pos + LiqOffsData->offsData1); - mf.read(LiqChunkData1, 0x18); // ñ÷èòûâàåì ñàìè äàííûå â ñòðóêòóðó òèïà MH2O_Data1 - // çàíîñèì äàííûå ôëàãà äëÿ êóñêà - if(LiqType[LiqChunkData1->LiquidTypeId] == 0xffff) - printf("\nCan't find Liquid type for map %s\nchunk %d\n", filename, chunk_num); - else if(LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_WATER || LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_OCEAN) - MapLiqFlag[chunk_num] |= 1; // water/ocean - else if(LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_MAGMA || LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_SLIME) - MapLiqFlag[chunk_num] |= 2; // magma/slime - // ïðåäâàðèòåëüíî çàïîëíÿåì âåñü êóñîê äàííûìè - íåò âîäû - for(int j = 0; j < 81; ++j) - { - ChunkLiqHeight[j] = -999999; // no liquid/water - } - // òåïåðü âû÷èñëÿåì òå ÷òî ñ âîäîé è ïåðåçàïèñûâàåì èõ â êóñêå - for(int b = 0; b <= LiqChunkData1->height; ++b) - { - for(int c = LiqChunkData1->xOffset; c <= (LiqChunkData1->xOffset + LiqChunkData1->width); ++c) - { - int n = (9 * (LiqChunkData1->yOffset + b)) + c; - ChunkLiqHeight[n] = LiqChunkData1->heightLevel1; - } - } - mf.seek(header_pos); // è íå çàáûòü âåðíóòüñÿ íà èñõîäíóþ ïîçèöèþ èìåííî  ÕÈÄÅÐÅ - } - else // åñëè äàííûõ â Data1 íåò, òî íàäî çàïîëíèòü âåñü êóñîê, íî äàííûìè - íåò âîäû - { - for(int j = 0; j < 81; ++j) - ChunkLiqHeight[j] = -999999; // no liquid/water - } - - if(!(chunk_num % 16)) - m = 1024 * (chunk_num / 16); // ñìåùåíèå ïî ðÿäàì êóñêîâ ñ ïåðåêðûòèåì = 1024 - k = m + (chunk_num % 16) * 8; // óñòàíàâëèâàåìñÿ íà íà÷àëüíûé èíäåêñ äëÿ çàïîëíåíèÿ ðÿäà - // çàíîñèì äàííûå êóñêà â ìàññèâ äëÿ êàðòû, ñ ïåðåêðûòèåì è îáðåçàíèåì êóñêîâ òê äàííûõ 81 - // ýòî àíàëîã ñòàðîãî îáðåçàíèÿ ãðàíè÷íûõ ïðàâûõ-áîêîâûõ è íèæíèõ äàííûõ - for(int p = 0; p < 72; p += 9) // íèæíèå 8 íå çàíîñèì òê îíè äóáëèðóåòñÿ ñëåä êóñêîì - { - for(int s = 0; s < 8; ++s) // 9 çíà÷åíèå â ñòðîêå íå çàíîñèì òê îíî äóáëèðóåòñÿ ñëåä êóñêîì, à â ïðàâûõ-áîêîâûõ îáðåçàåòñÿ äëÿ 128õ128 - { - MapLiqHeight[k] = ChunkLiqHeight[p + s]; - ++k; - } - k = k + 120; - } - } - delete LiqOffsData; - delete LiqChunkData1; - delete []ChunkLiqHeight; - - } - //case 0x4d434e4b: // MCNK - //case 0x4d46424f: // MFBO new in BC - //case 0x4d545846: // MTXF new in WotLK - mf.seek(nextpos); - } - - //printf("Loading chunks info\n"); - // read individual map chunks - chunk_num = 0; - k = 0; - m = 0; - for (int j = 0; j < 16; ++j) - { - for (int i = 0; i < 16; ++i) - { - mf.seek((int)mcnk_offsets[j * 16 + i]); - LoadMapChunk(mf, &(mcells->ch[i][j])); - ++chunk_num; - } - } - mf.close(); - return true; -} - -bool isHole(int holes, int i, int j) -{ - int testi = i / 2; - int testj = j / 4; - if(testi > 3) testi = 3; - if(testj > 3) testj = 3; - return (holes & holetab_h[testi] & holetab_v[testj]) != 0; -} - -inline void LoadMapChunk(MPQFile &mf, chunk *_chunk) -{ - float h; - uint32 fourcc; - uint32 size; - MapChunkHeader header; - - mf.seekRelative(4); - mf.read(&size, 4); - - size_t lastpos = mf.getPos() + size; - mf.read(&header, 0x80); // what if header size got changed? - _chunk->area_id = header.areaid; - - float xbase = header.xpos; - float ybase = header.ypos; - float zbase = header.zpos; - zbase = TILESIZE * 32 - zbase; - xbase = TILESIZE * 32 - xbase; - if(wmoc.x > xbase) wmoc.x = xbase; - if(wmoc.z > zbase) wmoc.z = zbase; - int chunkflags = header.flags; - //printf("LMC: flags %X\n", chunkflags); - float zmin = 999999999.0f; - float zmax = -999999999.0f; - // must be there, bl!zz uses some crazy format - while (mf.getPos() < lastpos) - { - mf.read(&fourcc, 4); - mf.read(&size, 4); - size_t nextpos = mf.getPos() + size; - if(fourcc == 0x4d435654) // MCVT - { - for (int j = 0; j < 17; ++j) - { - for (int i = 0; i < ((j % 2) ? 8 : 9); ++i) - { - mf.read(&h, 4); - float z = h + ybase; - if (j % 2) - { - if(isHole(header.holes, i, j)) - _chunk->v8[i][j / 2] = -1000; - else - _chunk->v8[i][j / 2] = z; - } - else - { - if(isHole(header.holes, i, j)) - _chunk->v9[i][j / 2] = -1000; - else - _chunk->v9[i][j / 2] = z; - } - - if(z > zmax) zmax = z; - //if(z < zmin) zmin = z; - } - } - } - else if(fourcc == 0x4d434e52) // MCNR - { - nextpos = mf.getPos() + 0x1C0; // size fix - } - else if(fourcc == 0x4d434c51) // íå áóäåì ó÷èòûâàòü åñëè óæå áûëè äàííûå â MH2O, ïåðåñòðàõîâêà :) // MCLQ - { - // liquid / water level - char fcc1[5]; - mf.read(fcc1, 4); - flipcc(fcc1); - fcc1[4] = 0; - float *ChunkLiqHeight = new float[81]; - - if (!strcmp(fcc1, "MCSE")) - { - for(int j = 0; j < 81; ++j) - { - ChunkLiqHeight[j] = -999999; // no liquid/water - } - } - else - { - float maxheight; - mf.read(&maxheight, 4); - for(int j = 0; j < 81; ++j) - { - LiqData liq; - mf.read(&liq, 8); - - if(liq.height > maxheight) - ChunkLiqHeight[j] = -999999; - else - ChunkLiqHeight[j] = h; - } - - if(chunkflags & 4 || chunkflags & 8) - MapLiqFlag[chunk_num] |= 1; // water - if(chunkflags & 16) - MapLiqFlag[chunk_num] |= 2; // magma/slime - } - // çàïîëíåì òàê æå êàê â MH2O - if(!(chunk_num % 16)) - m = 1024 * (chunk_num / 16); - k = m + (chunk_num % 16) * 8; - - for(int p = 0; p < 72; p += 9) - { - for(int s = 0; s < 8; ++s) - { - MapLiqHeight[k] = ChunkLiqHeight[p + s]; - ++k; - } - k = k + 120; - } - delete []ChunkLiqHeight; - break; - } - mf.seek(nextpos); - } -} - -inline void TransformData() -{ - cell = new Cell; - - for(uint32 x = 0; x < 128; ++x) - { - for(uint32 y = 0; y < 128; ++y) - { - cell->v8[y][x] = (float)mcells->ch[x / 8][y / 8].v8[x % 8][y % 8]; - cell->v9[y][x] = (float)mcells->ch[x / 8][y / 8].v9[x % 8][y % 8]; - } - - // extra 1 point on bounds - cell->v9[128][x] = (float)mcells->ch[x / 8][15].v9[x % 8][8]; - // x == y - cell->v9[x][128] = (float)mcells->ch[15][x / 8].v9[8][x % 8]; - - } - - // and the last 1 - cell->v9[128][128] = (float)mcells->ch[15][15].v9[8][8]; - - delete mcells; -} - -const char MAP_MAGIC[] = "MAP_3.00"; - -bool ConvertADT(char *filename, char *filename2) -{ - if(!LoadADT(filename)) - return false; - - FILE *output=fopen(filename2, "wb"); - if(!output) - { - printf("Can't create the output file '%s'\n", filename2); - delete [] MapLiqHeight; - delete [] MapLiqFlag; - return false; - } - - // write magic header - fwrite(MAP_MAGIC, 1, 8, output); - - for(uint32 x = 0; x < 16; ++x) - { - for(uint32 y = 0; y < 16; ++y) - { - if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id <= maxAreaId) - { - if(areas[mcells->ch[y][x].area_id] == 0xffff) - printf("\nCan't find area flag for areaid %u.\n", mcells->ch[y][x].area_id); - - fwrite(&areas[mcells->ch[y][x].area_id], 1, 2, output); - } - else - { - uint16 flag = 0xffff; - fwrite(&flag, 1, 2, output); - } - } - } - - fwrite(MapLiqFlag, 1, 256, output); - delete [] MapLiqFlag; - - fwrite(MapLiqHeight, sizeof(float), 16384, output); - delete [] MapLiqHeight; - - TransformData(); - - fwrite(&cell->v9, 1, sizeof(cell->v9), output); - fwrite(&cell->v8, 1, sizeof(cell->v8), output); - fclose(output); - delete cell; - - return true; -} diff --git a/contrib/extractor/adt.h b/contrib/extractor/adt.h deleted file mode 100644 index 52196c4e7..000000000 --- a/contrib/extractor/adt.h +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef ADT_H -#define ADT_H - -#define TILESIZE (533.33333f) -#define CHUNKSIZE ((TILESIZE) / 16.0f) -#define UNITSIZE (CHUNKSIZE / 8.0f) - -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; -class Liquid; -typedef struct -{ - float x; - float y; - float z; -} svec; - -typedef struct -{ - double x; - double y; - double z; -} vec; - -typedef struct -{ - vec v[3]; -} triangle; - -typedef struct -{ - float v9[16 * 8 + 1][16 * 8 + 1]; - float v8[16 * 8][16 * 8]; -} Cell; - -typedef struct -{ - double v9[9][9]; - double v8[8][8]; - uint16 area_id; -} chunk; - -typedef struct -{ - chunk ch[16][16]; -} mcell; - -struct MapChunkHeader -{ - uint32 flags; - uint32 ix; - uint32 iy; - uint32 nLayers; - uint32 nDoodadRefs; - uint32 ofsHeight; - uint32 ofsNormal; - uint32 ofsLayer; - uint32 ofsRefs; - uint32 ofsAlpha; - uint32 sizeAlpha; - uint32 ofsShadow; - uint32 sizeShadow; - uint32 areaid; - uint32 nMapObjRefs; - uint32 holes; - uint16 s1; - uint16 s2; - uint32 d1; - uint32 d2; - uint32 d3; - uint32 predTex; - uint32 nEffectDoodad; - uint32 ofsSndEmitters; - uint32 nSndEmitters; - uint32 ofsLiquid; // not use in WotLK - uint32 sizeLiquid; // not use in WotLK - float zpos; - float xpos; - float ypos; - uint32 textureId; // new offsColorValues in WotLK - uint32 props; - uint32 effectId; -}; - -typedef struct -{ - uint32 offsData1; - uint32 used; - uint32 offsData2; -} MH2O_offsData; - -typedef struct -{ - uint16 LiquidTypeId; - uint16 type; - float heightLevel1; - float heightLevel2; - uint8 xOffset; - uint8 yOffset; - uint8 width; - uint8 height; - uint32 ofsData2a; - uint32 ofsData2b; -} MH2O_Data1; - -typedef struct -{ - uint16 unk1; - uint16 unk2; - float height; -} LiqData; - -enum LiquidType -{ - LIQUID_TYPE_WATER = 0, - LIQUID_TYPE_OCEAN = 1, - LIQUID_TYPE_MAGMA = 2, - LIQUID_TYPE_SLIME = 3 -}; - -class MPQFile; - -float *MapLiqHeight; -uint8 *MapLiqFlag; -uint32 k, m, chunk_num; -void LoadMapChunk(MPQFile &, chunk*); -#endif diff --git a/contrib/extractor/loadlib/CMakeLists.txt b/contrib/extractor/loadlib/CMakeLists.txt new file mode 100644 index 000000000..5680c61d4 --- /dev/null +++ b/contrib/extractor/loadlib/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2005-2009 MaNGOS project +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +add_library (loadlib loadlib.cpp adt.cpp wdt.cpp) +# link loadlib with zlib +target_link_libraries (loadlib z) diff --git a/contrib/extractor/loadlib/adt.cpp b/contrib/extractor/loadlib/adt.cpp new file mode 100644 index 000000000..fde706811 --- /dev/null +++ b/contrib/extractor/loadlib/adt.cpp @@ -0,0 +1,131 @@ +#define _CRT_SECURE_NO_DEPRECATE + +#include "adt.h" + +// Helper +int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; +int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; + +bool isHole(int holes, int i, int j) +{ + int testi = i / 2; + int testj = j / 4; + if(testi > 3) testi = 3; + if(testj > 3) testj = 3; + return (holes & holetab_h[testi] & holetab_v[testj]) != 0; +} + +// +// Adt file loader class +// +ADT_file::ADT_file() +{ + a_grid = 0; +} + +ADT_file::~ADT_file() +{ + free(); +} + +void ADT_file::free() +{ + a_grid = 0; + FileLoader::free(); +} + +// +// Adt file check function +// +bool ADT_file::prepareLoadedData() +{ + // Check parent + if (!FileLoader::prepareLoadedData()) + return false; + + // Check and prepare MHDR + a_grid = (adt_MHDR *)(GetData()+8+version->size); + if (!a_grid->prepareLoadedData()) + return false; + + return true; +} + +bool adt_MHDR::prepareLoadedData() +{ + if (fcc != 'MHDR') + return false; + + if (size!=sizeof(adt_MHDR)-8) + return false; + + // Check and prepare MCIN + if (offsMCIN && !getMCIN()->prepareLoadedData()) + return false; + + // Check and prepare MH2O + if (offsMH2O && !getMH2O()->prepareLoadedData()) + return false; + + return true; +} + +bool adt_MCIN::prepareLoadedData() +{ + if (fcc != 'MCIN') + return false; + + // Check cells data + for (int i=0; iprepareLoadedData()) + return false; + + return true; +} + +bool adt_MH2O::prepareLoadedData() +{ + if (fcc != 'MH2O') + return false; + + // Check liquid data +// for (int i=0; iprepareLoadedData()) + return false; + // Check liquid data + if (offsMCLQ && !getMCLQ()->prepareLoadedData()) + return false; + + return true; +} + +bool adt_MCVT::prepareLoadedData() +{ + if (fcc != 'MCVT') + return false; + + if (size != sizeof(adt_MCVT)-8) + return false; + + return true; +} + +bool adt_MCLQ::prepareLoadedData() +{ + if (fcc != 'MCLQ') + return false; + + return true; +} \ No newline at end of file diff --git a/contrib/extractor/loadlib/adt.h b/contrib/extractor/loadlib/adt.h new file mode 100644 index 000000000..725c5b994 --- /dev/null +++ b/contrib/extractor/loadlib/adt.h @@ -0,0 +1,289 @@ +#ifndef ADT_H +#define ADT_H + +#include "loadlib.h" + +#define TILESIZE (533.33333f) +#define CHUNKSIZE ((TILESIZE) / 16.0f) +#define UNITSIZE (CHUNKSIZE / 8.0f) + +enum LiquidType +{ + LIQUID_TYPE_WATER = 0, + LIQUID_TYPE_OCEAN = 1, + LIQUID_TYPE_MAGMA = 2, + LIQUID_TYPE_SLIME = 3 +}; + +//************************************************************************************** +// ADT file class +//************************************************************************************** +#define ADT_CELLS_PER_GRID 16 +#define ADT_CELL_SIZE 8 +#define ADT_GRID_SIZE (ADT_CELLS_PER_GRID*ADT_CELL_SIZE) + +// +// Adt file height map chunk +// +class adt_MCVT +{ + union{ + uint32 fcc; + char fcc_txt[4]; + }; + uint32 size; +public: + float height_map[(ADT_CELL_SIZE+1)*(ADT_CELL_SIZE+1)+ADT_CELL_SIZE*ADT_CELL_SIZE]; + + bool prepareLoadedData(); +}; + +// +// Adt file liquid map chunk (old) +// +class adt_MCLQ +{ + union{ + uint32 fcc; + char fcc_txt[4]; + }; + uint32 size; +public: + float height1; + float height2; + struct liquid_data{ + uint32 light; + float height; + } liquid[ADT_CELL_SIZE+1][ADT_CELL_SIZE+1]; + + // 1<<0 - ochen + // 1<<1 - lava/slime + // 1<<2 - water + // 1<<6 - all water + // 1<<7 - dark water + // == 0x0F - not show liquid + uint8 flags[ADT_CELL_SIZE][ADT_CELL_SIZE]; + uint8 data[84]; + bool prepareLoadedData(); +}; + +// +// Adt file cell chunk +// +class adt_MCNK +{ + union{ + uint32 fcc; + char fcc_txt[4]; + }; + uint32 size; +public: + uint32 flags; + uint32 ix; + uint32 iy; + uint32 nLayers; + uint32 nDoodadRefs; + uint32 offsMCVT; // height map + uint32 offsMCNR; // Normal vectors for each vertex + uint32 offsMCLY; // Texture layer definitions + uint32 offsMCRF; // A list of indices into the parent file's MDDF chunk + uint32 offsMCAL; // Alpha maps for additional texture layers + uint32 sizeMCAL; + uint32 offsMCSH; // Shadow map for static shadows on the terrain + uint32 sizeMCSH; + uint32 areaid; + uint32 nMapObjRefs; + uint32 holes; + uint16 s[2]; + uint32 data1; + uint32 data2; + uint32 data3; + uint32 predTex; + uint32 nEffectDoodad; + uint32 offsMCSE; + uint32 nSndEmitters; + uint32 offsMCLQ; // Liqid level (old) + uint32 sizeMCLQ; // + float zpos; + float xpos; + float ypos; + uint32 offsMCCV; // offsColorValues in WotLK + uint32 props; + uint32 effectId; + + bool prepareLoadedData(); + adt_MCVT *getMCVT() + { + if (offsMCVT) + return (adt_MCVT *)((uint8 *)this + offsMCVT); + return 0; + } + adt_MCLQ *getMCLQ() + { + if (offsMCLQ) + return (adt_MCLQ *)((uint8 *)this + offsMCLQ); + return 0; + } +}; + +// +// Adt file grid chunk +// +class adt_MCIN +{ + union{ + uint32 fcc; + char fcc_txt[4]; + }; + uint32 size; +public: + struct adt_CELLS{ + uint32 offsMCNK; + uint32 size; + uint32 flags; + uint32 asyncId; + } cells[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]; + + bool prepareLoadedData(); + // offset from begin file (used this-84) + adt_MCNK *getMCNK(int x, int y) + { + if (cells[x][y].offsMCNK) + return (adt_MCNK *)((uint8 *)this + cells[x][y].offsMCNK - 84); + return 0; + } +}; + +#define ADT_LIQUID_HEADER_FULL_LIGHT 0x01 +#define ADT_LIQUID_HEADER_NO_HIGHT 0x02 + +struct adt_liquid_header{ + uint16 liquidType; // Index from LiquidType.dbc + uint16 formatFlags; + float heightLevel1; + float heightLevel2; + uint8 xOffset; + uint8 yOffset; + uint8 width; + uint8 height; + uint32 offsData2a; + uint32 offsData2b; +}; + +// +// Adt file liquid data chunk (new) +// +class adt_MH2O +{ +public: + union{ + uint32 fcc; + char fcc_txt[4]; + }; + uint32 size; + + struct adt_LIQUID{ + uint32 offsData1; + uint32 used; + uint32 offsData2; + } liquid[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]; + + bool prepareLoadedData(); + + adt_liquid_header *getLiquidData(int x, int y) + { + if (liquid[x][y].used && liquid[x][y].offsData1) + return (adt_liquid_header *)((uint8*)this + 8 + liquid[x][y].offsData1); + return 0; + } + + float *getLiquidHeightMap(adt_liquid_header *h) + { + if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT) + return 0; + if (h->offsData2b) + return (float *)((uint8*)this + 8 + h->offsData2b); + return 0; + } + + uint8 *getLiquidLightMap(adt_liquid_header *h) + { + if (h->formatFlags&ADT_LIQUID_HEADER_FULL_LIGHT) + return 0; + if (h->offsData2b) + { + if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT) + return (uint8 *)((uint8*)this + 8 + h->offsData2b); + return (uint8 *)((uint8*)this + 8 + h->offsData2b + (h->width+1)*(h->height+1)*4); + } + return 0; + } + + uint32 *getLiquidFullLightMap(adt_liquid_header *h) + { + if (!(h->formatFlags&ADT_LIQUID_HEADER_FULL_LIGHT)) + return 0; + if (h->offsData2b) + { + if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT) + return (uint32 *)((uint8*)this + 8 + h->offsData2b); + return (uint32 *)((uint8*)this + 8 + h->offsData2b + (h->width+1)*(h->height+1)*4); + } + return 0; + } + + uint64 getLiquidShowMap(adt_liquid_header *h) + { + if (h->offsData2a) + return *((uint64 *)((uint8*)this + 8 + h->offsData2a)); + else + return 0xFFFFFFFFFFFFFFFFLL; + } + +}; + +// +// Adt file header chunk +// +class adt_MHDR +{ + union{ + uint32 fcc; + char fcc_txt[4]; + }; + uint32 size; + + uint32 pad; + uint32 offsMCIN; // MCIN + uint32 offsTex; // MTEX + uint32 offsModels; // MMDX + uint32 offsModelsIds; // MMID + uint32 offsMapObejcts; // MWMO + uint32 offsMapObejctsIds; // MWID + uint32 offsDoodsDef; // MDDF + uint32 offsObjectsDef; // MODF + uint32 offsMFBO; // MFBO + uint32 offsMH2O; // MH2O + uint32 data1; + uint32 data2; + uint32 data3; + uint32 data4; + uint32 data5; +public: + bool prepareLoadedData(); + adt_MCIN *getMCIN(){ return (adt_MCIN *)((uint8 *)&pad+offsMCIN);} + adt_MH2O *getMH2O(){ return offsMH2O ? (adt_MH2O *)((uint8 *)&pad+offsMH2O) : 0;} + +}; + +class ADT_file : public FileLoader{ +public: + bool prepareLoadedData(); + ADT_file(); + ~ADT_file(); + void free(); + + adt_MHDR *a_grid; +}; + +#endif diff --git a/contrib/extractor/loadlib/loadlib.cpp b/contrib/extractor/loadlib/loadlib.cpp new file mode 100644 index 000000000..2ff045ed7 --- /dev/null +++ b/contrib/extractor/loadlib/loadlib.cpp @@ -0,0 +1,63 @@ +#define _CRT_SECURE_NO_DEPRECATE + +#include "loadlib.h" +#include "../mpq_libmpq.h" + +class MPQFile; + +FileLoader::FileLoader() +{ + data = 0; + data_size = 0; + version = 0; +} + +FileLoader::~FileLoader() +{ + free(); +} + +bool FileLoader::loadFile(char *filename) +{ + free(); + MPQFile mf(filename); + if(mf.isEof()) + { + printf("No such file %s\n", filename); + return false; + } + + data_size = mf.getSize(); + + data = new uint8 [data_size]; + if (data) + { + mf.read(data, data_size); + mf.close(); + if (prepareLoadedData()) + return true; + } + printf("Error loading %s", filename); + mf.close(); + free(); + return false; +} + +bool FileLoader::prepareLoadedData() +{ + // Check version + version = (file_MVER *) data; + if (version->fcc != 'MVER') + return false; + if (version->ver != FILE_FORMAT_VERSION) + return false; + return true; +} + +void FileLoader::free() +{ + if (data) delete[] data; + data = 0; + data_size = 0; + version = 0; +} \ No newline at end of file diff --git a/contrib/extractor/loadlib/loadlib.h b/contrib/extractor/loadlib/loadlib.h new file mode 100644 index 000000000..7f38768cf --- /dev/null +++ b/contrib/extractor/loadlib/loadlib.h @@ -0,0 +1,57 @@ +#ifndef LOAD_LIB_H +#define LOAD_LIB_H + +#ifdef WIN32 +typedef __int64 int64; +typedef long int32; +typedef short int16; +typedef char int8; +typedef unsigned __int64 uint64; +typedef unsigned long uint32; +typedef unsigned short uint16; +typedef unsigned char uint8; +#else +#include +#ifndef uint64_t +#include +#endif +typedef int64_t int64; +typedef long int32; +typedef short int16; +typedef char int8; +typedef uint64_t uint64; +typedef unsigned long uint32; +typedef unsigned short uint16; +typedef unsigned char uint8; +#endif + +#define FILE_FORMAT_VERSION 18 + +// +// File version chunk +// +struct file_MVER +{ + union{ + uint32 fcc; + char fcc_txt[4]; + }; + uint32 size; + uint32 ver; +}; + +class FileLoader{ + uint8 *data; + uint32 data_size; +public: + virtual bool prepareLoadedData(); + uint8 *GetData() {return data;} + uint32 GetDataSize() {return data_size;} + + file_MVER *version; + FileLoader(); + ~FileLoader(); + bool loadFile(char *filename); + virtual void free(); +}; +#endif diff --git a/contrib/extractor/loadlib/wdt.cpp b/contrib/extractor/loadlib/wdt.cpp new file mode 100644 index 000000000..dedefbb64 --- /dev/null +++ b/contrib/extractor/loadlib/wdt.cpp @@ -0,0 +1,62 @@ +#define _CRT_SECURE_NO_DEPRECATE + +#include "wdt.h" + +bool wdt_MWMO::prepareLoadedData() +{ + if (fcc != 'MWMO') + return false; + return true; +} + +bool wdt_MPHD::prepareLoadedData() +{ + if (fcc != 'MPHD') + return false; + return true; +} + +bool wdt_MAIN::prepareLoadedData() +{ + if (fcc != 'MAIN') + return false; + return true; +} + +WDT_file::WDT_file() +{ + mphd = 0; + main = 0; + wmo = 0; +} + +WDT_file::~WDT_file() +{ + free(); +} + +void WDT_file::free() +{ + mphd = 0; + main = 0; + wmo = 0; + FileLoader::free(); +} + +bool WDT_file::prepareLoadedData() +{ + // Check parent + if (!FileLoader::prepareLoadedData()) + return false; + + mphd = (wdt_MPHD *)((uint8*)version+version->size+8); + if (!mphd->prepareLoadedData()) + return false; + main = (wdt_MAIN *)((uint8*)mphd + mphd->size+8); + if (!main->prepareLoadedData()) + return false; + wmo = (wdt_MWMO *)((uint8*)main+ main->size+8); + if (!wmo->prepareLoadedData()) + return false; + return true; +} \ No newline at end of file diff --git a/contrib/extractor/loadlib/wdt.h b/contrib/extractor/loadlib/wdt.h new file mode 100644 index 000000000..fcee8ac64 --- /dev/null +++ b/contrib/extractor/loadlib/wdt.h @@ -0,0 +1,68 @@ +#ifndef WDT_H +#define WDT_H +#include "loadlib.h" + +//************************************************************************************** +// WDT file class and structures +//************************************************************************************** +#define WDT_MAP_SIZE 64 + +class wdt_MWMO{ + union{ + uint32 fcc; + char fcc_txt[4]; + }; +public: + uint32 size; + bool prepareLoadedData(); +}; + +class wdt_MPHD{ + union{ + uint32 fcc; + char fcc_txt[4]; + }; +public: + uint32 size; + + uint32 data1; + uint32 data2; + uint32 data3; + uint32 data4; + uint32 data5; + uint32 data6; + uint32 data7; + uint32 data8; + bool prepareLoadedData(); +}; + +class wdt_MAIN{ + union{ + uint32 fcc; + char fcc_txt[4]; + }; +public: + uint32 size; + + struct adtData{ + uint32 exist; + uint32 data1; + } adt_list[64][64]; + + bool prepareLoadedData(); +}; + +class WDT_file : public FileLoader{ +public: + bool prepareLoadedData(); + + WDT_file(); + ~WDT_file(); + void free(); + + wdt_MPHD *mphd; + wdt_MAIN *main; + wdt_MWMO *wmo; +}; + +#endif \ No newline at end of file diff --git a/contrib/extractor/mpq_libmpq.h b/contrib/extractor/mpq_libmpq.h index 9b4984a50..7b5258e6a 100644 --- a/contrib/extractor/mpq_libmpq.h +++ b/contrib/extractor/mpq_libmpq.h @@ -4,6 +4,7 @@ #ifndef MPQ_H #define MPQ_H +#include "loadlib/loadlib.h" #include "libmpq/mpq.h" #include #include @@ -13,7 +14,6 @@ using namespace std; -typedef unsigned int uint32; class MPQArchive { diff --git a/src/game/Map.cpp b/src/game/Map.cpp index d4134f710..da32317e5 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -41,9 +41,6 @@ #define DEFAULT_GRID_EXPIRY 300 #define MAX_GRID_LOAD_TIME 50 -// magic *.map header -const char MAP_MAGIC[] = "MAP_3.00"; - GridState* si_GridStates[MAX_GRID_STATE]; Map::~Map() @@ -66,9 +63,9 @@ bool Map::ExistMap(uint32 mapid,int x,int y) return false; } - char magic[8]; - fread(magic,1,8,pf); - if(strncmp(MAP_MAGIC,magic,8)) + map_fileheader header; + fread(&header, sizeof(header), 1, pf); + if (header.mapMagic != MAP_MAGIC || header.versionMagic != MAP_VERSION_MAGIC) { sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp); delete [] tmp; @@ -78,7 +75,6 @@ bool Map::ExistMap(uint32 mapid,int x,int y) delete [] tmp; fclose(pf); - return true; } @@ -157,29 +153,13 @@ void Map::LoadMap(uint32 mapid, uint32 instanceid, int x,int y) snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),mapid,x,y); sLog.outDetail("Loading map %s",tmp); // loading data - FILE *pf=fopen(tmp,"rb"); - if(!pf) + GridMaps[x][y] = new GridMap(); + if (!GridMaps[x][y]->loadData(tmp)) { - delete [] tmp; - return; + sLog.outError("Error load map file: \n %s\n", tmp); } - - char magic[8]; - fread(magic,1,8,pf); - if(strncmp(MAP_MAGIC,magic,8)) - { - sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp); - delete [] tmp; - fclose(pf); //close file before return - return; - } - delete [] tmp; - - GridMap * buf= new GridMap; - fread(buf,1,sizeof(GridMap),pf); - fclose(pf); - - GridMaps[x][y] = buf; + delete [] tmp; + return; } void Map::LoadMapAndVMap(uint32 mapid, uint32 instanceid, int x,int y) @@ -1031,7 +1011,11 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce) { if (i_InstanceId == 0) { - if(GridMaps[gx][gy]) delete (GridMaps[gx][gy]); + if(GridMaps[gx][gy]) + { + GridMaps[gx][gy]->unloadData(); + delete GridMaps[gx][gy]; + } // x and y are swapped VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gy, gx); } @@ -1056,94 +1040,527 @@ void Map::UnloadAll(bool pForce) } } -float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const +//***************************** +// Grid function +//***************************** +GridMap::GridMap() { - GridPair p = MaNGOS::ComputeGridPair(x, y); + m_flags = 0; + // Area data + m_gridArea = 0; + m_area_map = NULL; + // Height level data + m_gridHeight = INVALID_HEIGHT; + m_gridGetHeight = &GridMap::getHeightFromFlat; + m_V9 = NULL; + m_V8 = NULL; + // Liquid data + m_liquidType = 0; + m_liquid_offX = 0; + m_liquid_offY = 0; + m_liquid_width = 0; + m_liquid_height = 0; + m_liquidLevel = INVALID_HEIGHT; + m_liquid_type = NULL; + m_liquid_map = NULL; +} +GridMap::~GridMap() +{ + unloadData(); +} + +bool GridMap::loadData(char *filename) +{ + // Unload old data if exist + unloadData(); + + map_fileheader header; + // Not return error if file not found + FILE *in = fopen(filename, "rb"); + if (!in) + return true; + fread(&header, sizeof(header),1,in); + if (header.mapMagic == MAP_MAGIC && header.versionMagic == MAP_VERSION_MAGIC) + { + // loadup area data + if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize)) + { + sLog.outError("Error loading map area data\n"); + fclose(in); + return false; + } + // loadup height data + if (header.heightMapOffset && !loadHeihgtData(in, header.heightMapOffset, header.heightMapSize)) + { + sLog.outError("Error loading map height data\n"); + fclose(in); + return false; + } + // loadup liquid data + if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize)) + { + sLog.outError("Error loading map liquids data\n"); + fclose(in); + return false; + } + fclose(in); + return true; + } + sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.", filename); + fclose(in); + return false; +} + +void GridMap::unloadData() +{ + if (m_area_map) delete[] m_area_map; + if (m_V9) delete[] m_V9; + if (m_V8) delete[] m_V8; + if (m_liquid_type) delete[] m_liquid_type; + if (m_liquid_map) delete[] m_liquid_map; + m_area_map = NULL; + m_V9 = NULL; + m_V8 = NULL; + m_liquid_type = NULL; + m_liquid_map = NULL; + m_gridGetHeight = &GridMap::getHeightFromFlat; +} + +bool GridMap::loadAreaData(FILE *in, uint32 offset, uint32 size) +{ + map_areaHeader header; + fseek(in, offset, SEEK_SET); + fread(&header, sizeof(header), 1, in); + if (header.fourcc != MAP_AREA_MAGIC) + return false; + + m_gridArea = header.gridArea; + if (!(header.flags&MAP_AREA_NO_AREA)) + { + m_area_map = new uint16 [16*16]; + fread(m_area_map, sizeof(uint16), 16*16, in); + } + return true; +} + +bool GridMap::loadHeihgtData(FILE *in, uint32 offset, uint32 size) +{ + map_heightHeader header; + fseek(in, offset, SEEK_SET); + fread(&header, sizeof(header), 1, in); + if (header.fourcc != MAP_HEIGTH_MAGIC) + return false; + + m_gridHeight = header.gridHeight; + if (!(header.flags&MAP_HEIGHT_NO_HIGHT)) + { + if ((header.flags&MAP_HEIGHT_AS_INT16)) + { + m_uint16_V9 = new uint16 [129*129]; + m_uint16_V8 = new uint16 [128*128]; + fread(m_uint16_V9, sizeof(uint16), 129*129, in); + fread(m_uint16_V8, sizeof(uint16), 128*128, in); + m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535; + m_gridGetHeight = &GridMap::getHeightFromUint16; + } + else if ((header.flags&MAP_HEIGHT_AS_INT8)) + { + m_uint8_V9 = new uint8 [129*129]; + m_uint8_V8 = new uint8 [128*128]; + fread(m_uint8_V9, sizeof(uint8), 129*129, in); + fread(m_uint8_V8, sizeof(uint8), 128*128, in); + m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255; + m_gridGetHeight = &GridMap::getHeightFromUint8; + } + else + { + m_V9 = new float [129*129]; + m_V8 = new float [128*128]; + fread(m_V9, sizeof(float), 129*129, in); + fread(m_V8, sizeof(float), 128*128, in); + m_gridGetHeight = &GridMap::getHeightFromFloat; + } + } + else + m_gridGetHeight = &GridMap::getHeightFromFlat; + return true; +} + +bool GridMap::loadLiquidData(FILE *in, uint32 offset, uint32 size) +{ + map_liquidHeader header; + fseek(in, offset, SEEK_SET); + fread(&header, sizeof(header), 1, in); + if (header.fourcc != MAP_LIQUID_MAGIC) + return false; + + m_liquidType = header.liquidType; + m_liquid_offX = header.offsetX; + m_liquid_offY = header.offsetY; + m_liquid_width = header.width; + m_liquid_height= header.height; + m_liquidLevel = header.liquidLevel; + + if (!(header.flags&MAP_LIQUID_NO_TYPE)) + { + m_liquid_type = new uint8 [16*16]; + fread(m_liquid_type, sizeof(uint8), 16*16, in); + } + if (!(header.flags&MAP_LIQUID_NO_HIGHT)) + { + m_liquid_map = new float [m_liquid_width*m_liquid_height]; + fread(m_liquid_map, sizeof(float), m_liquid_width*m_liquid_height, in); + } + return true; +} + +uint16 GridMap::getArea(float x, float y) +{ + if (!m_area_map) + return m_gridArea; + + x = 16 * (32 - x/SIZE_OF_GRIDS); + y = 16 * (32 - y/SIZE_OF_GRIDS); + int lx = (int)x & 15; + int ly = (int)y & 15; + return m_area_map[lx*16 + ly]; +} + +float GridMap::getHeightFromFlat(float x, float y) const +{ + return m_gridHeight; +} + +float GridMap::getHeightFromFloat(float x, float y) const +{ + if (!m_V8 || !m_V9) + return m_gridHeight; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int&=(MAP_RESOLUTION - 1); + y_int&=(MAP_RESOLUTION - 1); + + // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid + // +--------------> X + // | h1-------h2 Coordinates is: + // | | \ 1 / | h1 0,0 + // | | \ / | h2 0,1 + // | | 2 h5 3 | h3 1,0 + // | | / \ | h4 1,1 + // | | / 4 \ | h5 1/2,1/2 + // | h3-------h4 + // V Y + // For find height need + // 1 - detect triangle + // 2 - solve linear equation from triangle points + // Calculate coefficients for solve h = a*x + b*y + c + + float a,b,c; + // Select triangle: + if (x+y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + float h1 = m_V9[(x_int )*129 + y_int]; + float h2 = m_V9[(x_int+1)*129 + y_int]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h2-h1; + b = h5-h1-h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + float h1 = m_V9[x_int*129 + y_int ]; + float h3 = m_V9[x_int*129 + y_int+1]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + float h2 = m_V9[(x_int+1)*129 + y_int ]; + float h4 = m_V9[(x_int+1)*129 + y_int+1]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + float h3 = m_V9[(x_int )*129 + y_int+1]; + float h4 = m_V9[(x_int+1)*129 + y_int+1]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return a * x + b * y + c; +} + +float GridMap::getHeightFromUint8(float x, float y) const +{ + if (!m_uint8_V8 || !m_uint8_V9) + return m_gridHeight; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int&=(MAP_RESOLUTION - 1); + y_int&=(MAP_RESOLUTION - 1); + + int32 a, b, c; + uint8 *V9_h1_ptr = &m_uint8_V9[x_int*128 + x_int + y_int]; + if (x+y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + int32 h1 = V9_h1_ptr[ 0]; + int32 h2 = V9_h1_ptr[129]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h2-h1; + b = h5-h1-h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + int32 h1 = V9_h1_ptr[0]; + int32 h3 = V9_h1_ptr[1]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + int32 h2 = V9_h1_ptr[129]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + int32 h3 = V9_h1_ptr[ 1]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight; +} + +float GridMap::getHeightFromUint16(float x, float y) const +{ + if (!m_uint16_V8 || !m_uint16_V9) + return m_gridHeight; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int&=(MAP_RESOLUTION - 1); + y_int&=(MAP_RESOLUTION - 1); + + int32 a, b, c; + uint16 *V9_h1_ptr = &m_uint16_V9[x_int*128 + x_int + y_int]; + if (x+y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + int32 h1 = V9_h1_ptr[ 0]; + int32 h2 = V9_h1_ptr[129]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h2-h1; + b = h5-h1-h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + int32 h1 = V9_h1_ptr[0]; + int32 h3 = V9_h1_ptr[1]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + int32 h2 = V9_h1_ptr[129]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + int32 h3 = V9_h1_ptr[ 1]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight; +} + +float GridMap::getLiquidLevel(float x, float y) +{ + if (!m_liquid_map) + return m_liquidLevel; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int cx_int = ((int)x & (MAP_RESOLUTION-1)) - m_liquid_offY; + int cy_int = ((int)y & (MAP_RESOLUTION-1)) - m_liquid_offX; + + if (cx_int < 0 || cx_int >=m_liquid_height) + return INVALID_HEIGHT; + if (cy_int < 0 || cy_int >=m_liquid_width ) + return INVALID_HEIGHT; + + return m_liquid_map[cx_int*m_liquid_width + cy_int]; +} + +uint8 GridMap::getTerrainType(float x, float y) +{ + if (!m_liquid_type) + return m_liquidType; + + x = 16 * (32 - x/SIZE_OF_GRIDS); + y = 16 * (32 - y/SIZE_OF_GRIDS); + int lx = (int)x & 15; + int ly = (int)y & 15; + return m_liquid_type[lx*16 + ly]; +} + +// Get water state on map +inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data) +{ + // Check water type (if no water return) + if (!m_liquid_type && !m_liquidType) + return LIQUID_MAP_NO_WATER; + + // Get cell + float cx = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + float cy = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)cx & (MAP_RESOLUTION-1); + int y_int = (int)cy & (MAP_RESOLUTION-1); + + // Check water type in cell + uint8 type = m_liquid_type ? m_liquid_type[(x_int>>3)*16 + (y_int>>3)] : m_liquidType; + if (type == 0) + return LIQUID_MAP_NO_WATER; + + // Check req liquid type mask + if (ReqLiquidType && !(ReqLiquidType&type)) + return LIQUID_MAP_NO_WATER; + + // Check water level: + // Check water height map + int lx_int = x_int - m_liquid_offY; + int ly_int = y_int - m_liquid_offX; + if (lx_int < 0 || lx_int >=m_liquid_height) + return LIQUID_MAP_NO_WATER; + if (ly_int < 0 || ly_int >=m_liquid_width ) + return LIQUID_MAP_NO_WATER; + + // Get water level + float liquid_level = m_liquid_map ? m_liquid_map[lx_int*m_liquid_width + ly_int] : m_liquidLevel; + // Get ground level (sub 0.2 for fix some errors) + float ground_level = getHeight(x, y); + + // Check water level and ground level + if (liquid_level < ground_level || z < ground_level - 2) + return LIQUID_MAP_NO_WATER; + + // All ok in water -> store data + if (data) + { + data->type = type; + data->level = liquid_level; + data->depth_level = ground_level; + } + + // For speed check as int values + int delta = (liquid_level - z) * 10; + + // Get position delta + if (delta > 20) // Under water + return LIQUID_MAP_UNDER_WATER; + if (delta > 0 ) // In water + return LIQUID_MAP_IN_WATER; + if (delta > -1) // Walk on water + return LIQUID_MAP_WATER_WALK; + // Above water + return LIQUID_MAP_ABOVE_WATER; +} + +inline GridMap *Map::GetGrid(float x, float y) +{ // half opt method int gx=(int)(32-x/SIZE_OF_GRIDS); //grid x int gy=(int)(32-y/SIZE_OF_GRIDS); //grid y - float lx=MAP_RESOLUTION*(32 -x/SIZE_OF_GRIDS - gx); - float ly=MAP_RESOLUTION*(32 -y/SIZE_OF_GRIDS - gy); - // ensure GridMap is loaded - const_cast(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); + EnsureGridCreated(GridPair(63-gx,63-gy)); + return GridMaps[gx][gy]; +} + +float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const +{ // find raw .map surface under Z coordinates float mapHeight; - if(GridMap* gmap = GridMaps[gx][gy]) + if(GridMap *gmap = const_cast(this)->GetGrid(x, y)) { - int lx_int = (int)lx; - int ly_int = (int)ly; - lx -= lx_int; - ly -= ly_int; - - // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid - // +--------------> X - // | h1-------h2 Coordinates is: - // | | \ 1 / | h1 0,0 - // | | \ / | h2 0,1 - // | | 2 h5 3 | h3 1,0 - // | | / \ | h4 1,1 - // | | / 4 \ | h5 1/2,1/2 - // | h3-------h4 - // V Y - // For find height need - // 1 - detect triangle - // 2 - solve linear equation from triangle points - - // Calculate coefficients for solve h = a*x + b*y + c - float a,b,c; - // Select triangle: - if (lx+ly < 1) - { - if (lx > ly) - { - // 1 triangle (h1, h2, h5 points) - float h1 = gmap->v9[lx_int][ly_int]; - float h2 = gmap->v9[lx_int+1][ly_int]; - float h5 = 2 * gmap->v8[lx_int][ly_int]; - a = h2-h1; - b = h5-h1-h2; - c = h1; - } - else - { - // 2 triangle (h1, h3, h5 points) - float h1 = gmap->v9[lx_int][ly_int]; - float h3 = gmap->v9[lx_int][ly_int+1]; - float h5 = 2 * gmap->v8[lx_int][ly_int]; - a = h5 - h1 - h3; - b = h3 - h1; - c = h1; - } - } - else - { - if (lx > ly) - { - // 3 triangle (h2, h4, h5 points) - float h2 = gmap->v9[lx_int+1][ly_int]; - float h4 = gmap->v9[lx_int+1][ly_int+1]; - float h5 = 2 * gmap->v8[lx_int][ly_int]; - a = h2 + h4 - h5; - b = h4 - h2; - c = h5 - h4; - } - else - { - // 4 triangle (h3, h4, h5 points) - float h3 = gmap->v9[lx_int][ly_int+1]; - float h4 = gmap->v9[lx_int+1][ly_int+1]; - float h5 = 2 * gmap->v8[lx_int][ly_int]; - a = h4 - h3; - b = h3 + h4 - h5; - c = h5 - h4; - } - } - // Calculate height - float _mapheight = a * lx + b * ly + c; + float _mapheight = gmap->getHeight(x,y); // look from a bit higher pos to find the floor, ignore under surface case if(z + 2.0f > _mapheight) @@ -1202,25 +1619,9 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const uint16 Map::GetAreaFlag(float x, float y, float z) const { - //local x,y coords - float lx,ly; - int gx,gy; - GridPair p = MaNGOS::ComputeGridPair(x, y); - - // half opt method - gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x - gy=(int)(32-y/SIZE_OF_GRIDS); //grid y - - lx=16*(32 -x/SIZE_OF_GRIDS - gx); - ly=16*(32 -y/SIZE_OF_GRIDS - gy); - //DEBUG_LOG("my %d %d si %d %d",gx,gy,p.x_coord,p.y_coord); - - // ensure GridMap is loaded - const_cast(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); - uint16 areaflag; - if(GridMaps[gx][gy]) - areaflag = GridMaps[gx][gy]->area_flag[(int)(lx)][(int)(ly)]; + if(GridMap *gmap = const_cast(this)->GetGrid(x, y)) + areaflag = gmap->getArea(x, y); // this used while not all *.map files generated (instances) else areaflag = GetAreaFlagByMapId(i_id); @@ -1251,44 +1652,24 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const uint8 Map::GetTerrainType(float x, float y ) const { - //local x,y coords - float lx,ly; - int gx,gy; - - // half opt method - gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x - gy=(int)(32-y/SIZE_OF_GRIDS); //grid y - - lx=16*(32 -x/SIZE_OF_GRIDS - gx); - ly=16*(32 -y/SIZE_OF_GRIDS - gy); - - // ensure GridMap is loaded - const_cast(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); - - if(GridMaps[gx][gy]) - return GridMaps[gx][gy]->terrain_type[(int)(lx)][(int)(ly)]; + if(GridMap *gmap = const_cast(this)->GetGrid(x, y)) + return gmap->getTerrainType(x, y); else return 0; } +ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data) const +{ + if(GridMap* gmap = const_cast(this)->GetGrid(x, y)) + return gmap->getLiquidStatus(x, y, z, ReqLiquidType, data); + else + return LIQUID_MAP_NO_WATER; +} + float Map::GetWaterLevel(float x, float y ) const { - //local x,y coords - float lx,ly; - int gx,gy; - - // half opt method - gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x - gy=(int)(32-y/SIZE_OF_GRIDS); //grid y - - lx=128*(32 -x/SIZE_OF_GRIDS - gx); - ly=128*(32 -y/SIZE_OF_GRIDS - gy); - - // ensure GridMap is loaded - const_cast(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); - - if(GridMaps[gx][gy]) - return GridMaps[gx][gy]->liquid_level[(int)(lx)][(int)(ly)]; + if(GridMap* gmap = const_cast(this)->GetGrid(x, y)) + return gmap->getLiquidLevel(x, y); else return 0; } @@ -1315,24 +1696,27 @@ uint32 Map::GetZoneId(uint16 areaflag,uint32 map_id) bool Map::IsInWater(float x, float y, float pZ) const { - // This method is called too often to use vamps for that (4. parameter = false). - // The pZ pos is taken anyway for future use - float z = GetHeight(x,y,pZ,false); // use .map base surface height - - // underground or instance without vmap - if(z <= INVALID_HEIGHT) - return false; - - float water_z = GetWaterLevel(x,y); - uint8 flag = GetTerrainType(x,y); - return (z < (water_z-2)) && (flag & 0x01); + // Check surface in x, y point for liquid + if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + { + LiquidData liquid_status; + if (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, &liquid_status)) + { + if (liquid_status.level - liquid_status.depth_level > 2) + return true; + } + } + return false; } bool Map::IsUnderWater(float x, float y, float z) const { - float water_z = GetWaterLevel(x,y); - uint8 flag = GetTerrainType(x,y); - return (z < (water_z-2)) && (flag & 0x01); + if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + { + if (getLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER|MAP_LIQUID_TYPE_OCEAN)&LIQUID_MAP_UNDER_WATER) + return true; + } + return false; } bool Map::CheckGridIntegrity(Creature* c, bool moved) const diff --git a/src/game/Map.h b/src/game/Map.h index 80f042674..8019534ed 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -68,14 +68,135 @@ typedef RGuard GridReadGuard; typedef WGuard GridWriteGuard; typedef MaNGOS::SingleThreaded::Lock NullGuard; -typedef struct +//****************************************** +// Map file format defines +//****************************************** +#define MAP_MAGIC 'SPAM' +#define MAP_VERSION_MAGIC '0.1v' +#define MAP_AREA_MAGIC 'AERA' +#define MAP_HEIGTH_MAGIC 'TGHM' +#define MAP_LIQUID_MAGIC 'QILM' + +struct map_fileheader{ + uint32 mapMagic; + uint32 versionMagic; + uint32 areaMapOffset; + uint32 areaMapSize; + uint32 heightMapOffset; + uint32 heightMapSize; + uint32 liquidMapOffset; + uint32 liquidMapSize; +}; + +#define MAP_AREA_NO_AREA 0x0001 +struct map_areaHeader{ + uint32 fourcc; + uint16 flags; + uint16 gridArea; +}; + +#define MAP_HEIGHT_NO_HIGHT 0x0001 +#define MAP_HEIGHT_AS_INT16 0x0002 +#define MAP_HEIGHT_AS_INT8 0x0004 + +struct map_heightHeader{ + uint32 fourcc; + uint32 flags; + float gridHeight; + float gridMaxHeight; +}; + +#define MAP_LIQUID_NO_TYPE 0x0001 +#define MAP_LIQUID_NO_HIGHT 0x0002 +struct map_liquidHeader{ + uint32 fourcc; + uint16 flags; + uint16 liquidType; + uint8 offsetX; + uint8 offsetY; + uint8 width; + uint8 height; + float liquidLevel; +}; + +enum ZLiquidStatus{ + LIQUID_MAP_NO_WATER = 0x00000000, + LIQUID_MAP_ABOVE_WATER = 0x00000001, + LIQUID_MAP_WATER_WALK = 0x00000002, + LIQUID_MAP_IN_WATER = 0x00000004, + LIQUID_MAP_UNDER_WATER = 0x00000008 +}; + +#define MAP_LIQUID_TYPE_NO_WATER 0x00 +#define MAP_LIQUID_TYPE_WATER 0x01 +#define MAP_LIQUID_TYPE_OCEAN 0x02 +#define MAP_LIQUID_TYPE_MAGMA 0x04 +#define MAP_LIQUID_TYPE_SLIME 0x08 + +#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME) + +#define MAP_LIQUID_TYPE_DARK_WATER 0x10 +#define MAP_LIQUID_TYPE_WMO_WATER 0x20 + +struct LiquidData{ + uint32 type; + float level; + float depth_level; +}; + +class GridMap { - uint16 area_flag[16][16]; - uint8 terrain_type[16][16]; - float liquid_level[128][128]; - float v9[MAP_RESOLUTION + 1][MAP_RESOLUTION + 1]; - float v8[MAP_RESOLUTION][MAP_RESOLUTION]; -}GridMap; + uint32 m_flags; + // Area data + uint16 m_gridArea; + uint16 *m_area_map; + // Height level data + float m_gridHeight; + float m_gridIntHeightMultiplier; + union{ + float *m_V9; + uint16 *m_uint16_V9; + uint8 *m_uint8_V9; + }; + union{ + float *m_V8; + uint16 *m_uint16_V8; + uint8 *m_uint8_V8; + }; + // Liquid data + uint16 m_liquidType; + uint8 m_liquid_offX; + uint8 m_liquid_offY; + uint8 m_liquid_width; + uint8 m_liquid_height; + float m_liquidLevel; + uint8 *m_liquid_type; + float *m_liquid_map; + + bool loadAreaData(FILE *in, uint32 offset, uint32 size); + bool loadHeihgtData(FILE *in, uint32 offset, uint32 size); + bool loadLiquidData(FILE *in, uint32 offset, uint32 size); + + // Get height functions and pointers + typedef float (GridMap::*pGetHeightPtr) (float x, float y) const; + pGetHeightPtr m_gridGetHeight; + float getHeightFromFloat(float x, float y) const; + float getHeightFromUint16(float x, float y) const; + float getHeightFromUint8(float x, float y) const; + float getHeightFromFlat(float x, float y) const; + +public: + GridMap(); + ~GridMap(); + bool loadData(char *filaname); + void unloadData(); + + uint16 getArea(float x, float y); + inline float getHeight(float x, float y) {return (this->*m_gridGetHeight)(x, y);} + float getLiquidLevel(float x, float y); + uint8 getTerrainType(float x, float y); + ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0); +}; struct CreatureMover { @@ -190,6 +311,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj float GetHeight(float x, float y, float z, bool pCheckVMap=true) const; bool IsInWater(float x, float y, float z) const; // does not use z pos. This is for future use + ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0) const; + uint16 GetAreaFlag(float x, float y, float z) const; uint8 GetTerrainType(float x, float y ) const; float GetWaterLevel(float x, float y ) const; @@ -277,6 +400,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj private: void LoadVMap(int pX, int pY); void LoadMap(uint32 mapid, uint32 instanceid, int x,int y); + GridMap *GetGrid(float x, float y); void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; } //uint64 CalculateGridMask(const uint32 &y) const; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index bf6fba258..af71a306d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -351,8 +351,11 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) m_regenTimer = 0; m_weaponChangeTimer = 0; - m_breathTimer = 0; - m_isunderwater = UNDERWATER_NONE; + for (int i=0; iSendPacket(&data); -} - -void Player::ModifyMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, uint32 Regen) -{ - if(Type==BREATH_TIMER) - m_breathTimer = ((MaxValue + 1*IN_MILISECONDS) - CurrentValue) / Regen; - + if (MaxValue == DISABLED_MIRROR_TIMER) + { + if (CurrentValue!=DISABLED_MIRROR_TIMER) + StopMirrorTimer(Type); + return; + } WorldPacket data(SMSG_START_MIRROR_TIMER, (21)); data << (uint32)Type; data << CurrentValue; @@ -828,9 +820,7 @@ void Player::ModifyMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 Cur void Player::StopMirrorTimer(MirrorTimerType Type) { - if(Type==BREATH_TIMER) - m_breathTimer = 0; - + m_MirrorTimer[Type] = DISABLED_MIRROR_TIMER; WorldPacket data(SMSG_STOP_MIRROR_TIMER, 4); data << (uint32)Type; GetSession()->SendPacket( &data ); @@ -841,12 +831,22 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da if(!isAlive() || isGameMaster()) return; + // Absorb, resist some environmental damage type + uint32 absorb = 0; + uint32 resist = 0; + if (type == DAMAGE_LAVA) + CalcAbsorbResist(this, SPELL_SCHOOL_MASK_FIRE, DIRECT_DAMAGE, damage, &absorb, &resist); + else if (type == DAMAGE_SLIME) + CalcAbsorbResist(this, SPELL_SCHOOL_MASK_NATURE, DIRECT_DAMAGE, damage, &absorb, &resist); + + damage-=absorb+resist; + WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21)); data << (uint64)guid; data << (uint8)(type!=DAMAGE_FALL_TO_VOID ? type : DAMAGE_FALL); data << (uint32)damage; - data << (uint32)0; - data << (uint32)0; + data << (uint32)absorb; // absorb + data << (uint32)resist; // resist SendMessageToSet(&data, true); DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); @@ -866,96 +866,153 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da } } -void Player::HandleDrowning() +int32 Player::getMaxTimer(MirrorTimerType timer) { - if(!(m_isunderwater&~UNDERWATER_INLAVA)) - return; - - //if player is GM, have waterbreath, is dead or if breathing is disabled then return - if(isGameMaster() || !isAlive() || HasAuraType(SPELL_AURA_WATER_BREATHING) || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING)) + switch (timer) { - StopMirrorTimer(BREATH_TIMER); - // drop every flag _except_ LAVA - otherwise waterbreathing will prevent lava damage - m_isunderwater &= UNDERWATER_INLAVA; - return; - } - - uint32 UnderWaterTime = 3*MINUTE*IN_MILISECONDS; // default duration - - AuraList const& mModWaterBreathing = GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING); - for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i) - UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f); - - if ((m_isunderwater & UNDERWATER_INWATER) && !(m_isunderwater & UNDERWATER_INLAVA) && isAlive()) - { - //single trigger timer - if (!(m_isunderwater & UNDERWATER_WATER_TRIGGER)) + case FATIGUE_TIMER: + return MINUTE*IN_MILISECONDS; + case BREATH_TIMER: { - m_isunderwater|= UNDERWATER_WATER_TRIGGER; - m_breathTimer = UnderWaterTime + 1*IN_MILISECONDS; + if (!isAlive() || HasAuraType(SPELL_AURA_WATER_BREATHING) || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING)) + return DISABLED_MIRROR_TIMER; + int32 UnderWaterTime = 3*MINUTE*IN_MILISECONDS; + AuraList const& mModWaterBreathing = GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING); + for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i) + UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f); + return UnderWaterTime; } - //single trigger "show Breathbar" - if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & UNDERWATER_WATER_BREATHB)) + case FIRE_TIMER: { - m_isunderwater|= UNDERWATER_WATER_BREATHB; - StartMirrorTimer(BREATH_TIMER, UnderWaterTime); - } - //continuous trigger drowning "Damage" - if ((m_breathTimer == 0) && (m_isunderwater & UNDERWATER_INWATER)) - { - //TODO: Check this formula - uint64 guid = GetGUID(); - uint32 damage = GetMaxHealth() / 5 + urand(0, getLevel()-1); - - EnvironmentalDamage(guid, DAMAGE_DROWNING,damage); - m_breathTimer = 2000; + if (!isAlive()) + return DISABLED_MIRROR_TIMER; + return 1*IN_MILISECONDS; } + default: + return 0; } - //single trigger retract bar - else if (!(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater & UNDERWATER_WATER_TRIGGER) && (m_breathTimer > 0) && isAlive()) - { - uint32 BreathRegen = 10; - // m_breathTimer will be reduced in ModifyMirrorTimer - ModifyMirrorTimer(BREATH_TIMER, UnderWaterTime, m_breathTimer,BreathRegen); - m_isunderwater = UNDERWATER_WATER_BREATHB_RETRACTING; - } - //remove bar - else if ((m_breathTimer < 50) && !(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater == UNDERWATER_WATER_BREATHB_RETRACTING)) - { - StopMirrorTimer(BREATH_TIMER); - m_isunderwater = UNDERWATER_NONE; - } + return 0; } -void Player::HandleLava() +void Player::UpdateMirrorTimers() { - if ((m_isunderwater & UNDERWATER_INLAVA) && isAlive()) + // Desync flags for update on next HandleDrowning + if (m_MirrorTimerFlags) + m_MirrorTimerFlagsLast = ~m_MirrorTimerFlags; +} + +void Player::HandleDrowning(uint32 time_diff) +{ + if (!m_MirrorTimerFlags) + return; + + // In water + if (m_MirrorTimerFlags & UNDERWATER_INWATER) { - /* - * arrai: how is this supposed to work? UNDERWATER_INLAVA is always set in this scope! - // Single trigger Set BreathTimer - if (!(m_isunderwater & UNDERWATER_INLAVA)) + // Breath timer not activated - activate it + if (m_MirrorTimer[BREATH_TIMER] == DISABLED_MIRROR_TIMER) { - m_isunderwater|= UNDERWATER_WATER_BREATHB; - m_breathTimer = 1*IN_MILISECONDS; + m_MirrorTimer[BREATH_TIMER] = getMaxTimer(BREATH_TIMER); + SendMirrorTimer(BREATH_TIMER, m_MirrorTimer[BREATH_TIMER], m_MirrorTimer[BREATH_TIMER], -1); } - */ - // Reset BreathTimer and still in the lava - if (!m_breathTimer) + else // If activated - do tick { - uint64 guid = GetGUID(); - uint32 damage = urand(600, 700); // TODO: Get more detailed information about lava damage - - EnvironmentalDamage(guid, DAMAGE_LAVA, damage); - - m_breathTimer = 1*IN_MILISECONDS; + m_MirrorTimer[BREATH_TIMER]-=time_diff; + // Timer limit - need deal damage + if (m_MirrorTimer[BREATH_TIMER] < 0) + { + m_MirrorTimer[BREATH_TIMER]+= 1*IN_MILISECONDS; + // Calculate and deal damage + // TODO: Check this formula + uint32 damage = GetMaxHealth() / 5 + urand(0, getLevel()-1); + EnvironmentalDamage(GetGUID(), DAMAGE_DROWNING, damage); + } + else if (!(m_MirrorTimerFlagsLast & UNDERWATER_INWATER)) // Update time in client if need + SendMirrorTimer(BREATH_TIMER, getMaxTimer(BREATH_TIMER), m_MirrorTimer[BREATH_TIMER], -1); } } - else if (!isAlive()) // Disable breath timer and reset underwater flags + else if (m_MirrorTimer[BREATH_TIMER] != DISABLED_MIRROR_TIMER) // Regen timer { - m_breathTimer = 0; - m_isunderwater = UNDERWATER_NONE; + int32 UnderWaterTime = getMaxTimer(BREATH_TIMER); + // Need breath regen + m_MirrorTimer[BREATH_TIMER]+=10*time_diff; + if (m_MirrorTimer[BREATH_TIMER] >= UnderWaterTime || !isAlive()) + StopMirrorTimer(BREATH_TIMER); + else if (m_MirrorTimerFlagsLast & UNDERWATER_INWATER) + SendMirrorTimer(BREATH_TIMER, UnderWaterTime, m_MirrorTimer[BREATH_TIMER], 10); } + + // In dark water + if (m_MirrorTimerFlags & UNDERWARER_INDARKWATER) + { + // Fatigue timer not activated - activate it + if (m_MirrorTimer[FATIGUE_TIMER] == DISABLED_MIRROR_TIMER) + { + m_MirrorTimer[FATIGUE_TIMER] = getMaxTimer(FATIGUE_TIMER); + SendMirrorTimer(FATIGUE_TIMER, m_MirrorTimer[FATIGUE_TIMER], m_MirrorTimer[FATIGUE_TIMER], -1); + } + else + { + m_MirrorTimer[FATIGUE_TIMER]-=time_diff; + // Timer limit - need deal damage or teleport ghost to graveyard + if (m_MirrorTimer[FATIGUE_TIMER] < 0) + { + m_MirrorTimer[FATIGUE_TIMER]+= 1*IN_MILISECONDS; + if (isAlive()) // Calculate and deal damage + { + uint32 damage = GetMaxHealth() / 5 + urand(0, getLevel()-1); + EnvironmentalDamage(GetGUID(), DAMAGE_EXHAUSTED, damage); + } + else if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) // Teleport ghost to graveyard + RepopAtGraveyard(); + } + else if (!(m_MirrorTimerFlagsLast & UNDERWARER_INDARKWATER)) + SendMirrorTimer(FATIGUE_TIMER, getMaxTimer(FATIGUE_TIMER), m_MirrorTimer[FATIGUE_TIMER], -1); + } + } + else if (m_MirrorTimer[FATIGUE_TIMER] != DISABLED_MIRROR_TIMER) // Regen timer + { + int32 DarkWaterTime = getMaxTimer(FATIGUE_TIMER); + m_MirrorTimer[FATIGUE_TIMER]+=10*time_diff; + if (m_MirrorTimer[FATIGUE_TIMER] >= DarkWaterTime || !isAlive()) + StopMirrorTimer(FATIGUE_TIMER); + else if (m_MirrorTimerFlagsLast & UNDERWARER_INDARKWATER) + SendMirrorTimer(FATIGUE_TIMER, DarkWaterTime, m_MirrorTimer[FATIGUE_TIMER], 10); + } + + if (m_MirrorTimerFlags & (UNDERWATER_INLAVA|UNDERWATER_INSLIME)) + { + // Breath timer not activated - activate it + if (m_MirrorTimer[FIRE_TIMER] == DISABLED_MIRROR_TIMER) + m_MirrorTimer[FIRE_TIMER] = getMaxTimer(FIRE_TIMER); + else + { + m_MirrorTimer[FIRE_TIMER]-=time_diff; + if (m_MirrorTimer[FIRE_TIMER] < 0) + { + m_MirrorTimer[FIRE_TIMER]+= 1*IN_MILISECONDS; + // Calculate and deal damage + // TODO: Check this formula + uint32 damage = urand(600, 700); + if (m_MirrorTimerFlags&UNDERWATER_INLAVA) + EnvironmentalDamage(GetGUID(), DAMAGE_LAVA, damage); + else + EnvironmentalDamage(GetGUID(), DAMAGE_SLIME, damage); + } + } + } + else + m_MirrorTimer[FIRE_TIMER] = DISABLED_MIRROR_TIMER; + + // Recheck timers flag + m_MirrorTimerFlags&=~UNDERWATER_EXIST_TIMERS; + for (int i = 0; i< MAX_TIMERS; ++i) + if (m_MirrorTimer[i]!=DISABLED_MIRROR_TIMER) + { + m_MirrorTimerFlags|=UNDERWATER_EXIST_TIMERS; + break; + } + m_MirrorTimerFlagsLast = m_MirrorTimerFlags; } ///The player sobers by 256 every 10 seconds @@ -1227,21 +1284,8 @@ void Player::Update( uint32 p_time ) } } - //Breathtimer - if(m_breathTimer > 0) - { - if(p_time >= m_breathTimer) - m_breathTimer = 0; - else - m_breathTimer -= p_time; - - } - //Handle Water/drowning - HandleDrowning(); - - //Handle lava - HandleLava(); + HandleDrowning(p_time); //Handle detect stealth players if (m_DetectInvTimer > 0) @@ -19352,21 +19396,48 @@ PartyResult Player::CanUninviteFromGroup() const void Player::UpdateUnderwaterState( Map* m, float x, float y, float z ) { - float water_z = m->GetWaterLevel(x,y); - float terrain_z = m->GetHeight(x,y,z, false); // use .map base surface height - uint8 flag1 = m->GetTerrainType(x,y); + LiquidData liquid_status; + ZLiquidStatus res = m->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquid_status); + if (!res) + { + m_MirrorTimerFlags &= ~(UNDERWATER_INWATER|UNDERWATER_INLAVA|UNDERWATER_INSLIME|UNDERWARER_INDARKWATER); + // Small hack for enable breath in WMO + if (IsInWater()) + m_MirrorTimerFlags|=UNDERWATER_INWATER; + return; + } - //!Underwater check, not in water if underground or above water level - take UC royal quater for example - if (terrain_z <= INVALID_HEIGHT || z < (terrain_z-2) || z > (water_z - 2) ) - m_isunderwater &= ~UNDERWATER_INWATER; - else if ((z < (water_z - 2)) && (flag1 & 0x01)) - m_isunderwater |= UNDERWATER_INWATER; + // All liquids type - check under water position + if (liquid_status.type&(MAP_LIQUID_TYPE_WATER|MAP_LIQUID_TYPE_OCEAN|MAP_LIQUID_TYPE_MAGMA|MAP_LIQUID_TYPE_SLIME)) + { + if ( res & LIQUID_MAP_UNDER_WATER) + m_MirrorTimerFlags |= UNDERWATER_INWATER; + else + m_MirrorTimerFlags &= ~UNDERWATER_INWATER; + } - //!in lava check, anywhere under lava level - if ((terrain_z <= INVALID_HEIGHT || z < (terrain_z - 0)) && (flag1 == 0x00) && IsInWater()) - m_isunderwater |= UNDERWATER_INLAVA; + // Allow travel in dark water on taxi or transport + if (liquid_status.type & MAP_LIQUID_TYPE_DARK_WATER && !isInFlight() && !(GetUnitMovementFlags()&MOVEMENTFLAG_ONTRANSPORT)) + m_MirrorTimerFlags |= UNDERWARER_INDARKWATER; else - m_isunderwater &= ~UNDERWATER_INLAVA; + m_MirrorTimerFlags &= ~UNDERWARER_INDARKWATER; + + // in lava check, anywhere in lava level + if (liquid_status.type&MAP_LIQUID_TYPE_MAGMA) + { + if (res & (LIQUID_MAP_UNDER_WATER|LIQUID_MAP_IN_WATER|LIQUID_MAP_WATER_WALK)) + m_MirrorTimerFlags |= UNDERWATER_INLAVA; + else + m_MirrorTimerFlags &= ~UNDERWATER_INLAVA; + } + // in slime check, anywhere in slime level + if (liquid_status.type&MAP_LIQUID_TYPE_SLIME) + { + if (res & (LIQUID_MAP_UNDER_WATER|LIQUID_MAP_IN_WATER|LIQUID_MAP_WATER_WALK)) + m_MirrorTimerFlags |= UNDERWATER_INSLIME; + else + m_MirrorTimerFlags &= ~UNDERWATER_INSLIME; + } } void Player::SetCanParry( bool value ) diff --git a/src/game/Player.h b/src/game/Player.h index 3dc26cd79..63681ada0 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -69,10 +69,11 @@ enum PlayerUnderwaterState { UNDERWATER_NONE = 0x00, UNDERWATER_INWATER = 0x01, // terrain type is water and player is afflicted by it - UNDERWATER_WATER_TRIGGER = 0x02, // m_breathTimer has been initialized - UNDERWATER_WATER_BREATHB = 0x04, // breathbar has been send to client - UNDERWATER_WATER_BREATHB_RETRACTING = 0x10, // breathbar is currently refilling - the player is above water level - UNDERWATER_INLAVA = 0x80 // terrain type is lava and player is afflicted by it + UNDERWATER_INLAVA = 0x02, // terrain type is lava and player is afflicted by it + UNDERWATER_INSLIME = 0x04, // terrain type is lava and player is afflicted by it + UNDERWARER_INDARKWATER = 0x08, // terrain type is dark water and player is afflicted by it + + UNDERWATER_EXIST_TIMERS = 0x10 }; enum PlayerSpellState @@ -500,6 +501,8 @@ enum MirrorTimerType BREATH_TIMER = 1, FIRE_TIMER = 2 }; +#define MAX_TIMERS 3 +#define DISABLED_MIRROR_TIMER -1 // 2^n values enum PlayerExtraFlags @@ -1709,6 +1712,7 @@ class MANGOS_DLL_SPEC Player : public Unit uint32 DurabilityRepairAll(bool cost, float discountMod, bool guildBank); uint32 DurabilityRepair(uint16 pos, bool cost, float discountMod, bool guildBank); + void UpdateMirrorTimers(); void StopMirrorTimers() { StopMirrorTimer(FATIGUE_TIMER); @@ -2020,8 +2024,6 @@ class MANGOS_DLL_SPEC Player : public Unit bool IsFlying() const { return HasUnitMovementFlag(MOVEMENTFLAG_FLYING); } bool IsAllowUseFlyMountsHere() const; - void HandleDrowning(); - void SetClientControl(Unit* target, uint8 allowMove); void EnterVehicle(Vehicle *vehicle); @@ -2236,12 +2238,14 @@ class MANGOS_DLL_SPEC Player : public Unit /*********************************************************/ /*** ENVIRONMENTAL SYSTEM ***/ /*********************************************************/ - void HandleLava(); void HandleSobering(); - void StartMirrorTimer(MirrorTimerType Type, uint32 MaxValue); - void ModifyMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, uint32 Regen); + void SendMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, int32 Regen); void StopMirrorTimer(MirrorTimerType Type); - uint8 m_isunderwater; + void HandleDrowning(uint32 time_diff); + int32 getMaxTimer(MirrorTimerType timer); + int32 m_MirrorTimer[MAX_TIMERS]; + uint8 m_MirrorTimerFlags; + uint8 m_MirrorTimerFlagsLast; bool m_isInWater; /*********************************************************/ @@ -2325,7 +2329,6 @@ class MANGOS_DLL_SPEC Player : public Unit bool m_DailyQuestChanged; time_t m_lastDailyQuestTime; - uint32 m_breathTimer; uint32 m_drunkTimer; uint16 m_drunk; uint32 m_weaponChangeTimer; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 0bdbbda25..0f6cae650 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2490,15 +2490,9 @@ void Aura::HandleAuraHover(bool apply, bool Real) void Aura::HandleWaterBreathing(bool apply, bool Real) { - if(!apply && !m_target->HasAuraType(SPELL_AURA_WATER_BREATHING)) - { - // update for enable timer in case not moving target - if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld()) - { - ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ()); - ((Player*)m_target)->HandleDrowning(); - } - } + // update timers in client + if(m_target->GetTypeId()==TYPEID_PLAYER) + ((Player*)m_target)->UpdateMirrorTimers(); } void Aura::HandleAuraModShapeshift(bool apply, bool Real) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 9c6e60a2b..c10f61e60 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7427" + #define REVISION_NR "7428" #endif // __REVISION_NR_H__ From acce72403cae90f6fe95fc33539050bd54359644 Mon Sep 17 00:00:00 2001 From: Lightguard Date: Mon, 9 Mar 2009 22:28:57 +0300 Subject: [PATCH 49/60] [7429] Fix one warrior ability bonus Signed-off-by: DiSlord --- src/game/SpellEffects.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index c415edbd1..eaae76043 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -369,7 +369,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100); } // Shield Slam - else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) + else if(m_spellInfo->SpellFamilyFlags & 0x0000020000000000LL) damage += int32(m_caster->GetShieldBlockValue()); // Victory Rush else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c10f61e60..8f9e2b5d9 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7428" + #define REVISION_NR "7429" #endif // __REVISION_NR_H__ From 2240fc49aa4f2dec91f460233ce6da227b3d54b8 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Mon, 9 Mar 2009 23:00:54 +0300 Subject: [PATCH 50/60] [7430] Fix warror ability heal amount Signed-off-by: DiSlord --- src/game/Unit.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 9efece118..42815fdd5 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -6588,7 +6588,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB // Bloodthirst (($m/100)% of max health) case 23880: { - basepoints0 = int32(GetMaxHealth() * triggerAmount / 10000); + basepoints0 = int32(GetMaxHealth() * triggerAmount / 100); break; } // Shamanistic Rage triggered spell diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 8f9e2b5d9..119926096 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7429" + #define REVISION_NR "7430" #endif // __REVISION_NR_H__ From 82e0e0b02798e6352c96bf109fd33a7a8555980c Mon Sep 17 00:00:00 2001 From: Lightguard Date: Mon, 9 Mar 2009 23:30:24 +0300 Subject: [PATCH 51/60] [7431] Fix the gnome racial spell Signed-off-by: DiSlord --- src/game/SpellEffects.cpp | 11 +++++++++-- src/shared/revision_nr.h | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index eaae76043..431713024 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4768,7 +4768,7 @@ void Spell::EffectScriptEffect(uint32 effIndex) unitTarget->CastSpell(unitTarget, 25863, false); else unitTarget->CastSpell(unitTarget, 26655, false); - break; + return; } // Piccolo of the Flaming Fire case 17512: @@ -4776,7 +4776,14 @@ void Spell::EffectScriptEffect(uint32 effIndex) if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); - break; + return; + } + // Escape artist + case 20589: + { + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED); + return; } // Mirren's Drinking Hat case 29830: diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 119926096..3c7f5d4a6 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7430" + #define REVISION_NR "7431" #endif // __REVISION_NR_H__ From aebcf212dc7ec3219d4e58619f4e28a135ff2e97 Mon Sep 17 00:00:00 2001 From: balrok Date: Mon, 9 Mar 2009 22:27:35 +0100 Subject: [PATCH 52/60] [7432] Fixed BattleGround's bonus_honor based on player level and reputation rewards. Implement functions for BattleGroundWeekends. Patch originally provided by Balrok. Thx Correctly assigned some comments. Signed-off-by: Triply --- src/game/BattleGround.cpp | 28 ++++++++++++++++++++-------- src/game/BattleGround.h | 2 +- src/game/BattleGroundAB.cpp | 28 +++++++++++++++++++++++----- src/game/BattleGroundAB.h | 28 +++++++++++++++++++--------- src/game/BattleGroundEY.cpp | 22 +++++++++++++++++++--- src/game/BattleGroundEY.h | 5 +++++ src/game/BattleGroundWS.cpp | 31 +++++++++++++++++++++++-------- src/game/BattleGroundWS.h | 5 +++++ src/shared/revision_nr.h | 2 +- 9 files changed, 116 insertions(+), 35 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index c0cd15729..c790dd5bd 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -30,6 +30,7 @@ #include "ObjectMgr.h" #include "WorldPacket.h" #include "Util.h" +#include "Formulas.h" #include "GridNotifiersImpl.h" namespace MaNGOS @@ -314,7 +315,13 @@ void BattleGround::Update(uint32 diff) else if(m_PrematureCountDownTimer < diff) { // time's up! - EndBattleGround(0); // noone wins + uint32 winner = 0; + if( GetPlayersCountByTeam(ALLIANCE) >= GetMinPlayersPerTeam() ) + winner = ALLIANCE; + else if( GetPlayersCountByTeam(HORDE) >= GetMinPlayersPerTeam() ) + winner = HORDE; + + EndBattleGround(winner); m_PrematureCountDown = false; } else @@ -693,7 +700,6 @@ void BattleGround::EndBattleGround(uint32 winner) if(team == winner) { RewardMark(plr,ITEM_WINNER_COUNT); - UpdatePlayerScore(plr, SCORE_BONUS_HONOR, 20); RewardQuest(plr); } else @@ -732,7 +738,13 @@ void BattleGround::EndBattleGround(uint32 winner) sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); if(winmsg_id) - SendMessageToAll(winmsg_id,CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(winmsg_id, CHAT_MSG_BG_SYSTEM_NEUTRAL); +} + +uint32 BattleGround::GetBonusHonorFromKill(uint32 kills) const +{ + //variable kills means how many honorable kills you scored (so we need kills * honor_for_one_kill) + return MaNGOS::Honor::hk_honor_at_level(GetMaxLevel(), kills); } uint32 BattleGround::GetBattlemasterEntry() const @@ -884,7 +896,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac BattleGroundPlayerMap::iterator itr = m_Players.find(guid); if(itr != m_Players.end()) { - UpdatePlayersCountByTeam(team, true); // -1 player + UpdatePlayersCountByTeam(team, true); // -1 player m_Players.erase(itr); // check if the player was a participant of the match, or only entered through gm command (goname) participant = true; @@ -926,8 +938,8 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac // if arena, remove the specific arena auras if(isArena()) { - plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out - bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing) + plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out + bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing) // summon old pet if there was one and there isn't a current pet if(!plr->GetPet() && plr->GetTemporaryUnsummonedPetNumber()) @@ -974,7 +986,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac // remove from raid group if player is member if(Group *group = GetBgRaid(team)) { - if( !group->RemoveMember(guid, 0) ) // group was disbanded + if( !group->RemoveMember(guid, 0) ) // group was disbanded { SetBgRaid(team, NULL); delete group; @@ -993,7 +1005,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac if( plr ) { // Do next only if found in battleground - plr->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG. + plr->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG. // reset destination bg team plr->SetBGTeam(0); diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 5ef2c2c8f..81f4dc78a 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -93,7 +93,6 @@ enum BattleGroundTimeIntervals RESPAWN_ONE_DAY = 86400, // secs RESPAWN_IMMEDIATELY = 0, // secs BUFF_RESPAWN_TIME = 180, // secs - BG_HONOR_SCORE_TICKS = 330 // points }; enum BattleGroundStartTimeIntervals @@ -315,6 +314,7 @@ class BattleGround uint8 GetArenaType() const { return m_ArenaType; } uint8 GetWinner() const { return m_Winner; } uint32 GetBattlemasterEntry() const; + uint32 GetBonusHonorFromKill(uint32 kills) const; // Set methods: void SetName(char const* Name) { m_Name = Name; } diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index 15a6c90d0..dae2b20de 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -117,15 +117,15 @@ void BattleGroundAB::Update(uint32 diff) m_TeamScores[team] += BG_AB_TickPoints[points]; m_HonorScoreTics[team] += BG_AB_TickPoints[points]; m_ReputationScoreTics[team] += BG_AB_TickPoints[points]; - if( m_ReputationScoreTics[team] >= 200 ) + if( m_ReputationScoreTics[team] >= m_ReputationTics ) { (team == BG_TEAM_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE); - m_ReputationScoreTics[team] -= 200; + m_ReputationScoreTics[team] -= m_ReputationTics; } - if( m_HonorScoreTics[team] >= BG_HONOR_SCORE_TICKS ) + if( m_HonorScoreTics[team] >= m_HonorTics ) { - (team == BG_TEAM_ALLIANCE) ? RewardHonorToTeam(20, ALLIANCE) : RewardHonorToTeam(20, HORDE); - m_HonorScoreTics[team] -= BG_HONOR_SCORE_TICKS; + RewardHonorToTeam(GetBonusHonorFromKill(1), (team == BG_TEAM_ALLIANCE) ? ALLIANCE : HORDE); + m_HonorScoreTics[team] -= m_HonorTics; } if( !m_IsInformedNearVictory && m_TeamScores[team] > 1800 ) { @@ -573,6 +573,10 @@ void BattleGroundAB::Reset() m_ReputationScoreTics[BG_TEAM_ALLIANCE] = 0; m_ReputationScoreTics[BG_TEAM_HORDE] = 0; m_IsInformedNearVictory = false; + bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + m_HonorTics = (isBGWeekend) ? BG_AB_ABBGWeekendHonorTicks : BG_AB_NotABBGWeekendHonorTicks; + m_ReputationTics = (isBGWeekend) ? BG_AB_ABBGWeekendReputationTicks : BG_AB_NotABBGWeekendReputationTicks; + for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) { m_Nodes[i] = 0; @@ -586,6 +590,20 @@ void BattleGroundAB::Reset() DelCreature(i); } +void BattleGroundAB::EndBattleGround(uint32 winner) +{ + //win reward + if( winner == ALLIANCE ) + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + if( winner == HORDE ) + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + //complete map_end rewards (even if no team wins) + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + + BattleGround::EndBattleGround(winner); +} + WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player) { uint8 teamIndex = GetTeamIndexByTeamId(player->GetTeam()); diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h index 90e6287f5..644556d0e 100644 --- a/src/game/BattleGroundAB.h +++ b/src/game/BattleGroundAB.h @@ -170,6 +170,11 @@ enum BG_AB_Sounds SOUND_NEAR_VICTORY = 8456 }; +#define BG_AB_NotABBGWeekendHonorTicks 330 +#define BG_AB_ABBGWeekendHonorTicks 200 +#define BG_AB_NotABBGWeekendReputationTicks 200 +#define BG_AB_ABBGWeekendReputationTicks 150 + // x, y, z, o const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { {1166.785f, 1200.132f, -56.70859f, 0.9075713f}, // stables @@ -244,6 +249,7 @@ class BattleGroundAB : public BattleGround void HandleAreaTrigger(Player *Source, uint32 Trigger); virtual bool SetupBattleGround(); virtual void Reset(); + void EndBattleGround(uint32 winner); virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); /* Scorekeeping */ @@ -273,14 +279,18 @@ class BattleGroundAB : public BattleGround 2: horde contested 3: ally occupied 4: horde occupied */ - uint8 m_Nodes[BG_AB_DYNAMIC_NODES_COUNT]; - uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT]; - BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT]; - int32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT]; - uint32 m_TeamScores[2]; - uint32 m_lastTick[2]; - uint32 m_HonorScoreTics[2]; - uint32 m_ReputationScoreTics[2]; - bool m_IsInformedNearVictory; + uint8 m_Nodes[BG_AB_DYNAMIC_NODES_COUNT]; + uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT]; + BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT]; + int32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT]; + uint32 m_TeamScores[2]; + uint32 m_lastTick[2]; + uint32 m_HonorScoreTics[2]; + uint32 m_ReputationScoreTics[2]; + bool m_IsInformedNearVictory; + uint32 m_HonorTics; + uint32 m_ReputationTics; + + }; #endif diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index f353595b1..4ba6953fb 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -121,10 +121,10 @@ void BattleGroundEY::AddPoints(uint32 Team, uint32 Points) uint8 team_index = GetTeamIndexByTeamId(Team); m_TeamScores[team_index] += Points; m_HonorScoreTics[team_index] += Points; - if (m_HonorScoreTics[team_index] >= BG_HONOR_SCORE_TICKS) + if (m_HonorScoreTics[team_index] >= m_HonorTics ) { - RewardHonorToTeam(20, Team); - m_HonorScoreTics[team_index] -= BG_HONOR_SCORE_TICKS; + RewardHonorToTeam(GetBonusHonorFromKill(1), Team); + m_HonorScoreTics[team_index] -= m_HonorTics; } UpdateTeamScore(Team); } @@ -270,6 +270,20 @@ void BattleGroundEY::UpdateTeamScore(uint32 Team) UpdateWorldState(EY_HORDE_RESOURCES, score); } +void BattleGroundEY::EndBattleGround(uint32 winner) +{ + //win reward + if( winner == ALLIANCE ) + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + if( winner == HORDE ) + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + //complete map reward + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + + BattleGround::EndBattleGround(winner); +} + void BattleGroundEY::UpdatePointsCount(uint32 Team) { if(Team == ALLIANCE) @@ -494,6 +508,8 @@ void BattleGroundEY::Reset() m_DroppedFlagGUID = 0; m_PointAddingTimer = 0; m_TowerCapCheckTimer = 0; + bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + uint32 m_HonorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks; for(uint8 i = 0; i < EY_POINTS_MAX; ++i) { diff --git a/src/game/BattleGroundEY.h b/src/game/BattleGroundEY.h index ed3958401..17b678e8f 100644 --- a/src/game/BattleGroundEY.h +++ b/src/game/BattleGroundEY.h @@ -210,6 +210,9 @@ enum EYBattleGroundObjectTypes BG_EY_OBJECT_MAX = 59 }; +#define BG_EY_NotEYWeekendHonorTicks 330 +#define BG_EY_EYWeekendHonorTicks 200 + enum BG_EY_FlagState { BG_EY_FLAG_STATE_ON_BASE = 0, @@ -321,6 +324,7 @@ class BattleGroundEY : public BattleGround virtual bool SetupBattleGround(); virtual void Reset(); void UpdateTeamScore(uint32 Team); + void EndBattleGround(uint32 winner); void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); virtual void FillInitialWorldStates(WorldPacket& data); void SetDroppedFlagGUID(uint64 guid) { m_DroppedFlagGUID = guid;} @@ -370,5 +374,6 @@ class BattleGroundEY : public BattleGround uint8 m_CurrentPointPlayersCount[2*EY_POINTS_MAX]; int32 m_PointAddingTimer; + uint32 m_HonorTics; }; #endif diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index eb170c881..bf9185e51 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -184,8 +184,6 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) uint32 winner = 0; - //TODO FIX reputation and honor gains for low level players! - Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); if(Source->GetTeam() == ALLIANCE) { @@ -199,8 +197,7 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) if(GetTeamScore(ALLIANCE) < BG_WS_MAX_TEAM_SCORE) AddPoint(ALLIANCE, 1); PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE); - RewardReputationToTeam(890, 35, ALLIANCE); // +35 reputation - RewardHonorToTeam(40, ALLIANCE); // +40 bonushonor + RewardReputationToTeam(890, m_ReputationCapture, ALLIANCE); } else { @@ -214,9 +211,10 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) if(GetTeamScore(HORDE) < BG_WS_MAX_TEAM_SCORE) AddPoint(HORDE, 1); PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE); - RewardReputationToTeam(889, 35, HORDE); // +35 reputation - RewardHonorToTeam(40, HORDE); // +40 bonushonor + RewardReputationToTeam(889, m_ReputationCapture, HORDE); } + //for flag capture is reward 2 honorable kills + RewardHonorToTeam(GetBonusHonorFromKill(2), Source->GetTeam()); SpawnBGObject(BG_WS_OBJECT_H_FLAG, BG_WS_FLAG_RESPAWN_TIME); SpawnBGObject(BG_WS_OBJECT_A_FLAG, BG_WS_FLAG_RESPAWN_TIME); @@ -229,7 +227,7 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) UpdateFlagState(Source->GetTeam(), 1); // flag state none UpdateTeamScore(Source->GetTeam()); // only flag capture should be updated - UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures... + UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures if(GetTeamScore(ALLIANCE) == BG_WS_MAX_TEAM_SCORE) winner = ALLIANCE; @@ -593,16 +591,33 @@ void BattleGroundWS::Reset() m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; m_TeamScores[BG_TEAM_ALLIANCE] = 0; m_TeamScores[BG_TEAM_HORDE] = 0; + bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + m_ReputationCapture = (isBGWeekend) ? 45 : 35; + m_HonorWinKills = (isBGWeekend) ? 3 : 1; + m_HonorEndKills = (isBGWeekend) ? 4 : 2; /* Spirit nodes is static at this BG and then not required deleting at BG reset. if(m_BgCreatures[WS_SPIRIT_MAIN_ALLIANCE]) DelCreature(WS_SPIRIT_MAIN_ALLIANCE); - if(m_BgCreatures[WS_SPIRIT_MAIN_HORDE]) DelCreature(WS_SPIRIT_MAIN_HORDE); */ } +void BattleGroundWS::EndBattleGround(uint32 winner) +{ + //win reward + if( winner == ALLIANCE ) + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), ALLIANCE); + if( winner == HORDE ) + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), HORDE); + //complete map_end rewards (even if no team wins) + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), ALLIANCE); + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), HORDE); + + BattleGround::EndBattleGround(winner); +} + void BattleGroundWS::HandleKillPlayer(Player *player, Player *killer) { if(GetStatus() != STATUS_IN_PROGRESS) diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h index 23ae211a5..093da3e53 100644 --- a/src/game/BattleGroundWS.h +++ b/src/game/BattleGroundWS.h @@ -164,6 +164,7 @@ class BattleGroundWS : public BattleGround void HandleKillPlayer(Player *player, Player *killer); bool SetupBattleGround(); virtual void Reset(); + void EndBattleGround(uint32 winner); virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); void UpdateFlagState(uint32 team, uint32 value); @@ -186,5 +187,9 @@ class BattleGroundWS : public BattleGround uint32 m_TeamScores[2]; int32 m_FlagsTimer[2]; int32 m_FlagsDropTimer[2]; + + uint32 m_ReputationCapture; + uint32 m_HonorWinKills; + uint32 m_HonorEndKills; }; #endif diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3c7f5d4a6..b7514b0de 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7431" + #define REVISION_NR "7432" #endif // __REVISION_NR_H__ From 6dcb0099d96f794aca1743517d6685c40ebb2f52 Mon Sep 17 00:00:00 2001 From: Triply Date: Mon, 9 Mar 2009 22:56:49 +0100 Subject: [PATCH 53/60] [7433] Fixed death runes counting. Patch provided by Rastikzzz. Thx. Signed-off-by: Triply --- src/game/Spell.cpp | 4 ++-- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 742682f81..0e99e9190 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3354,7 +3354,7 @@ uint8 Spell::CheckRuneCost(uint32 runeCostID) runeCost[i] = src->RuneCost[i]; } - runeCost[RUNE_DEATH] = 0; // calculated later + runeCost[RUNE_DEATH] = MAX_RUNES; // calculated later for(uint32 i = 0; i < MAX_RUNES; ++i) { @@ -3373,7 +3373,7 @@ uint8 Spell::CheckRuneCost(uint32 runeCostID) } } - if(runeCost[RUNE_DEATH] > 0) + if(runeCost[RUNE_DEATH] > MAX_RUNES) return SPELL_FAILED_NO_POWER; // not sure if result code is correct return 0; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b7514b0de..cf0c8d683 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7432" + #define REVISION_NR "7433" #endif // __REVISION_NR_H__ From bdd7b4f74b9dc5ae2763876ab2484a7e9fe68b57 Mon Sep 17 00:00:00 2001 From: rechapa79 Date: Tue, 10 Mar 2009 02:47:11 +0300 Subject: [PATCH 54/60] [7434] Fix one paladin spell bonus Signed-off-by: DiSlord --- src/game/SpellEffects.cpp | 5 +++++ src/shared/revision_nr.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 431713024..1a51403b4 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -589,6 +589,11 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget); damage += count * int32(averange * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK); } + // Shield of Righteousness + else if(m_spellInfo->SpellFamilyFlags&0x0010000000000000LL) + { + damage+=int32(m_caster->GetShieldBlockValue()); + } break; } } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index cf0c8d683..eceadf300 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7433" + #define REVISION_NR "7434" #endif // __REVISION_NR_H__ From 2c787373c5e6a1f7dc161aef608cc35d13d30be3 Mon Sep 17 00:00:00 2001 From: Triply Date: Tue, 10 Mar 2009 11:00:21 +0100 Subject: [PATCH 55/60] [7435] Fixed Spell::EffectAddHonor to corrcetly add honor based on player's level Signed-off-by: Triply --- src/game/SpellEffects.cpp | 16 +++++++++++----- src/shared/revision_nr.h | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 1a51403b4..7c78f05ba 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -53,6 +53,7 @@ #include "TemporarySummon.h" #include "ScriptCalls.h" #include "SkillDiscovery.h" +#include "Formulas.h" pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= { @@ -3769,13 +3770,18 @@ void Spell::EffectAddHonor(uint32 /*i*/) if(unitTarget->GetTypeId() != TYPEID_PLAYER) return; - sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow()); + uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage); + sLog.outDebug("SpellEffect::AddHonor called for spell_id %u, that rewards %u honor points to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow()); - // TODO: find formula for honor reward based on player's level! - - // now fixed only for level 70 players: - if (((Player*)unitTarget)->getLevel() == 70) + // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80 + if( damage <= 50 ) + ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward); + else + { + //maybe we have correct honor_gain in damage already ((Player*)unitTarget)->RewardHonor(NULL, 1, damage); + sLog.outError("SpellEffect::AddHonor called for spell_id %u, that rewards %d * honor for one honorable kill and it is too much (%u of honor) for player: %u", m_spellInfo->Id, damage, honor_reward, ((Player*)unitTarget)->GetGUIDLow()); + } } void Spell::EffectTradeSkill(uint32 /*i*/) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index eceadf300..62782da3d 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7434" + #define REVISION_NR "7435" #endif // __REVISION_NR_H__ From 6a24242cb526763bafe10180bd4bba436c827858 Mon Sep 17 00:00:00 2001 From: balrok Date: Tue, 10 Mar 2009 15:36:21 +0100 Subject: [PATCH 56/60] [7436] Fixed Average Wait time for all BG/arena queue types. Patch has been made together with Balrok. Thx for help. Signed-off-by: Triply --- src/game/BattleGroundHandler.cpp | 125 ++++++++++--------------------- src/game/BattleGroundMgr.cpp | 69 +++++++++++++++-- src/game/BattleGroundMgr.h | 9 ++- src/shared/revision_nr.h | 2 +- 4 files changed, 110 insertions(+), 95 deletions(-) diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 7be6e3612..fa428e10b 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -156,10 +156,11 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) // if we're here, then the conditions to join a bg are met. We can proceed in joining. // _player->GetGroup() was already checked, grp is already initialized + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0); + uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); if(joinAsGroup /* && _player->GetGroup()*/) { sLog.outDebug("Battleground: the following players are joining as group:"); - GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); @@ -172,7 +173,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); @@ -180,9 +181,6 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } sLog.outDebug("Battleground: group end"); - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); - if(!ginfo->IsInvitedToBGInstanceGUID) - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } else { @@ -193,16 +191,15 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0); SendPacket(&data); - GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, false, 0); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); - if(!ginfo->IsInvitedToBGInstanceGUID) - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); + if(!ginfo->IsInvitedToBGInstanceGUID) + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket & /*recv_data*/ ) @@ -319,22 +316,16 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); - // if the player is not in queue, continue - if(itrPlayerStatus == qpMap.end()) - continue; - - // no group information, this should never happen - if(!itrPlayerStatus->second.GroupInfo) + // if the player is not in queue, continue or no group information - this should never happen + if(itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo) continue; BattleGround * bg = NULL; - // get possibly needed data from groupinfo uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated; uint8 status = 0; - if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) { // not invited to bg, get template @@ -530,75 +521,40 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) sLog.outDebug( "WORLD: Battleground status" ); WorldPacket data; + uint32 queueSlot = PLAYER_MAX_BATTLEGROUND_QUEUES; - // TODO: we must put player back to battleground in case disconnect (< 5 minutes offline time) or teleport player on login(!) from battleground map to entry point if(_player->InBattleGround()) { BattleGround *bg = _player->GetBattleGround(); - if(bg) + if(!bg) + return; + BattleGroundQueueTypeId bgQueueTypeId_tmp = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId_tmp); + if((bg->GetStatus() <= STATUS_IN_PROGRESS)) { - BattleGroundQueueTypeId bgQueueTypeId_tmp = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); - uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId_tmp); - if((bg->GetStatus() <= STATUS_IN_PROGRESS)) - { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); - SendPacket(&data); - } - for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) - { - BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); - if (i == queueSlot || !bgQueueTypeId) - continue; - BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); - uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId); - uint8 isRated = 0; - BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; - BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); - if(itrPlayerStatus == qpMap.end()) - continue; - if(itrPlayerStatus->second.GroupInfo) - { - arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; - isRated = itrPlayerStatus->second.GroupInfo->IsRated; - } - BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - if(bg2) - { - //in this call is small bug, this call should be filled by player's waiting time in queue - //this call nulls all timers for client : - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, i, STATUS_WAIT_QUEUE, 0, 0,arenatype); - SendPacket(&data); - } - } + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); + SendPacket(&data); } } - else + // we should update all queues? .. i'm not sure if this code is correct + for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { - // we should update all queues? .. i'm not sure if this code is correct - for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) - { - BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); - if(!bgQueueTypeId) - continue; - BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); - uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId); - uint8 isRated = 0; - BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; - BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); - if(itrPlayerStatus == qpMap.end()) - continue; - if(itrPlayerStatus->second.GroupInfo) - { - arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; - isRated = itrPlayerStatus->second.GroupInfo->IsRated; - } - if(bg) - { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, 0, 0, arenatype); - SendPacket(&data); - } - } + BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); + if(!bgQueueTypeId || i == queueSlot) //queueslot check in case we already send it in the above code + continue; + BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); + uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId); + BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + if(!bg) + continue; + BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; + BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); + if(itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo) + continue; + arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; + uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(itrPlayerStatus->second.GroupInfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTime()-itrPlayerStatus->second.GroupInfo->JoinTime, arenatype); + SendPacket(&data); } } @@ -762,9 +718,10 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) arenaRating = avg_pers_rating; } + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId); + uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); if(asGroup) { - GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId); sLog.outDebug("Battleground: arena join as group start"); if(isRated) sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype); @@ -780,7 +737,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); @@ -788,7 +745,6 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } sLog.outDebug("Battleground: arena join as group end"); - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating); if(isRated) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } @@ -801,13 +757,12 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); SendPacket(&data); - GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating); sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating); } void WorldSession::HandleBattleGroundReportAFK( WorldPacket & recv_data ) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 81185c38c..1d5088673 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -52,6 +52,16 @@ INSTANTIATE_SINGLETON_1( BattleGroundMgr ); BattleGroundQueue::BattleGroundQueue() { + for(uint32 i = 0; i < BG_TEAMS_COUNT; i++) + { + for(uint32 j = 0; j < MAX_BATTLEGROUND_QUEUES; j++) + { + m_SumOfWaitTimes[i][j] = 0; + m_WaitTimeLastPlayer[i][j] = 0; + for(uint32 k = 0; k < COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME; k++) + m_WaitTimes[i][j][k] = 0; + } + } } BattleGroundQueue::~BattleGroundQueue() @@ -149,7 +159,7 @@ GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId ginfo->ArenaTeamId = arenateamid; ginfo->IsRated = isRated; ginfo->IsInvitedToBGInstanceGUID = 0; - ginfo->JoinTime = getMSTime(); + ginfo->JoinTime = sWorld.GetGameTime() * IN_MILISECONDS; ginfo->Team = leader->GetTeam(); ginfo->ArenaTeamRating = arenaRating; ginfo->OpponentsTeamRating = 0; @@ -175,8 +185,6 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) { //if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak PlayerQueueInfo& info = m_QueuedPlayers[plr->GetGUID()]; - info.InviteTime = 0; - info.LastInviteTime = 0; info.LastOnlineTime = getMSTime(); info.GroupInfo = ginfo; @@ -184,6 +192,55 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) ginfo->Players[plr->GetGUID()] = &info; } +void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id) +{ + uint32 timeInQueue = (sWorld.GetGameTime() * IN_MILISECONDS) - ginfo->JoinTime; + uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas! + if( !ginfo->ArenaType ) + { + if( ginfo->Team == HORDE ) + team_index = BG_TEAM_HORDE; + } + else + { + if( ginfo->IsRated ) + team_index = BG_TEAM_HORDE; //for rated arenas use BG_TEAM_HORDE + } + + //store pointer to arrayindex of player that was added first + uint32* lastPlayerAddedPointer = &(m_WaitTimeLastPlayer[team_index][queue_id]); + //remove his time from sum + m_SumOfWaitTimes[team_index][queue_id] -= m_WaitTimes[team_index][queue_id][(*lastPlayerAddedPointer)]; + //set average time to new + m_WaitTimes[team_index][queue_id][(*lastPlayerAddedPointer)] = timeInQueue; + //add new time to sum + m_SumOfWaitTimes[team_index][queue_id] += timeInQueue; + //set index of last player added to next one + (*lastPlayerAddedPointer)++; + (*lastPlayerAddedPointer) %= COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME; +} + +uint32 BattleGroundQueue::GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id) +{ + uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas! + if( !ginfo->ArenaType ) + { + if( ginfo->Team == HORDE ) + team_index = BG_TEAM_HORDE; + } + else + { + if( ginfo->IsRated ) + team_index = BG_TEAM_HORDE; //for rated arenas use BG_TEAM_HORDE + } + //check if there is enought values(we always add values > 0) + if(m_WaitTimes[team_index][queue_id][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME - 1] ) + return (m_SumOfWaitTimes[team_index][queue_id] / COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME); + else + //if there aren't enough values return 0 - not available + return 0; +} + //remove player from queue and from group info, if group info is empty then remove it too void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCount) { @@ -373,13 +430,10 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b // set invitation ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID(); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + BGQueueIdBasedOnLevel queue_id = bg->GetQueueId(); // loop through the players for(std::map::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr) { - // set status - itr->second->InviteTime = getMSTime(); - itr->second->LastInviteTime = getMSTime(); - // get the player Player* plr = objmgr.GetPlayer(itr->first); // if offline, skip him, this should not happen - player is removed from queue when he logs out @@ -387,6 +441,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b continue; // invite the player + PlayerInvitedToBGUpdateAverageWaitTime(ginfo, queue_id); sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), bg->GetTypeID(), ginfo->Team); WorldPacket data; diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 0ce0b02ae..bf25f3e22 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -30,12 +30,11 @@ typedef std::list BGFreeSlotQueueType; typedef UNORDERED_MAP BattleMastersMap; #define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day +#define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME 10 struct GroupQueueInfo; // type predefinition struct PlayerQueueInfo // stores information for players in queue { - uint32 InviteTime; // first invite time - uint32 LastInviteTime; // last invite time uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes GroupQueueInfo * GroupInfo; // pointer to the associated groupqueueinfo }; @@ -79,6 +78,9 @@ class BattleGroundQueue GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 ArenaTeamId = 0); void AddPlayer(Player *plr, GroupQueueInfo *ginfo); void RemovePlayer(const uint64& guid, bool decreaseInvitedCount); + void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id); + 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); @@ -120,6 +122,9 @@ class BattleGroundQueue private: bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side); + uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME]; + uint32 m_WaitTimeLastPlayer[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES]; + uint32 m_SumOfWaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES]; }; /* diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 62782da3d..0b5e9b212 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7435" + #define REVISION_NR "7436" #endif // __REVISION_NR_H__ From b6064c373e948491f52147684ce1de48bf00c353 Mon Sep 17 00:00:00 2001 From: balrok Date: Tue, 10 Mar 2009 16:51:37 +0100 Subject: [PATCH 57/60] [7437] Fixed client visible instance ids for battlegrounds. Patch provided by balrok. Thx. Signed-off-by: Triply --- src/game/BattleGround.cpp | 1 + src/game/BattleGround.h | 3 ++ src/game/BattleGroundHandler.cpp | 4 +-- src/game/BattleGroundMgr.cpp | 61 ++++++++++++++++++++++++++------ src/game/BattleGroundMgr.h | 7 ++-- src/shared/revision_nr.h | 2 +- 6 files changed, 63 insertions(+), 15 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index c790dd5bd..35ad7b262 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -128,6 +128,7 @@ BattleGround::BattleGround() m_TypeID = BattleGroundTypeId(0); m_InstanceID = 0; m_Status = STATUS_NONE; + m_ClientInstanceID = 0; m_EndTime = 0; m_LastResurrectTime = 0; m_QueueId = QUEUE_ID_MAX_LEVEL_19; diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 81f4dc78a..c55a89afc 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -298,6 +298,7 @@ class BattleGround BGQueueIdBasedOnLevel GetQueueId() const { return m_QueueId; } uint32 GetInstanceID() const { return m_InstanceID; } BattleGroundStatus GetStatus() const { return m_Status; } + uint32 GetClientInstanceID() const { return m_ClientInstanceID; } uint32 GetStartTime() const { return m_StartTime; } uint32 GetEndTime() const { return m_EndTime; } uint32 GetLastResurrectTime() const { return m_LastResurrectTime; } @@ -328,6 +329,7 @@ class BattleGround } void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; } void SetStatus(BattleGroundStatus Status) { m_Status = Status; } + void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; } void SetStartTime(uint32 Time) { m_StartTime = Time; } void SetEndTime(uint32 Time) { m_EndTime = Time; } void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; } @@ -526,6 +528,7 @@ class BattleGround BattleGroundTypeId m_TypeID; uint32 m_InstanceID; //BattleGround Instance's GUID! BattleGroundStatus m_Status; + uint32 m_ClientInstanceID; //the instance-id which is sent to the client and without any other internal use uint32 m_StartTime; uint32 m_EndTime; uint32 m_LastResurrectTime; diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index fa428e10b..6afc9a07c 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -110,9 +110,9 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) return; // get bg instance or bg template if instance not found - BattleGround * bg = 0; + BattleGround * bg = NULL; if(instanceId) - BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId, bgTypeId); + BattleGround *bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 1d5088673..2dd619802 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -1148,6 +1148,8 @@ void BattleGroundMgr::DeleteAllBattleGrounds() { BattleGround * bg = itr->second; m_BattleGrounds[i].erase(itr++); + if(!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty()) + m_ClientBattleGroundIds[i][bg->GetQueueId()].erase(bg->GetClientInstanceID()); delete bg; } } @@ -1182,6 +1184,8 @@ void BattleGroundMgr::Update(uint32 diff) { BattleGround * bg = itr->second; m_BattleGrounds[i].erase(itr); + if(!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty()) + m_ClientBattleGroundIds[i][bg->GetQueueId()].erase(bg->GetClientInstanceID()); delete bg; } } @@ -1237,7 +1241,7 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro *data << uint32(QueueSlot); // queue id (0...2) - player can be in 3 queues in time // uint64 in client *data << uint64( uint64(arenatype ? arenatype : bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); - *data << uint32(0); // unknown + *data << uint32(bg->GetClientInstanceID()); // alliance/horde for BG and skirmish/rated for Arenas // following displays the minimap-icon 0 = faction icon 1 = arenaicon *data << uint8(bg->isArena()); @@ -1495,6 +1499,25 @@ void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, BattleGro 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 + //SMSG_BATTLEFIELD_LIST we need to find the battleground with this clientinstance-id + BattleGround* bg = GetBattleGroundTemplate(bgTypeId); + if( !bg ) + return NULL; + + if(bg->isArena()) + return GetBattleGround(instanceId, bgTypeId); + + for(BattleGroundSet::iterator itr = m_BattleGrounds[bgTypeId].begin(); itr != m_BattleGrounds[bgTypeId].end(); ++itr) + { + if(itr->second->GetClientInstanceID() == instanceId) + return itr->second; + } + return NULL; +} + BattleGround * BattleGroundMgr::GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId) { //search if needed @@ -1519,6 +1542,28 @@ BattleGround * BattleGroundMgr::GetBattleGroundTemplate(BattleGroundTypeId bgTyp return m_BattleGrounds[bgTypeId].empty() ? NULL : m_BattleGrounds[bgTypeId].begin()->second; } +uint32 BattleGroundMgr::CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id) +{ + if( IsArenaType(bgTypeId) ) + return 0; //arenas don't have client-instanceids + + // we create here an instanceid, which is just for + // displaying this to the client and without any other use.. + // the client-instanceIds are unique for each battleground-type + // the instance-id just needs to be as low as possible, beginning with 1 + // the following works, because std::set is default ordered with "<" + // the optimalization would be to use as bitmask std::vector - but that would only make code unreadable + uint32 lastId = 0; + for(std::set::iterator itr = m_ClientBattleGroundIds[bgTypeId][queue_id].begin(); itr != m_ClientBattleGroundIds[bgTypeId][queue_id].end();) + { + if( (++lastId) != *itr) //if there is a gap between the ids, we will break.. + break; + lastId = *itr; + } + m_ClientBattleGroundIds[bgTypeId][queue_id].insert(lastId + 1); + return lastId + 1; +} + // create a new battleground that will really be used to play BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated) { @@ -1588,6 +1633,7 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI // generate a new instance id bg->SetInstanceID(MapManager::Instance().GenerateInstanceId()); // set instance id + bg->SetClientInstanceID(CreateClientVisibleInstanceId(bgTypeId, queue_id)); // reset the new bg (set status to status_wait_queue from status_none) bg->Reset(); @@ -1862,16 +1908,11 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint6 uint32 count = 0; *data << uint32(0x00); // number of bg instances - for(BattleGroundSet::iterator itr = m_BattleGrounds[bgTypeId].begin(); itr != m_BattleGrounds[bgTypeId].end(); ++itr) + uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(bgTypeId); + for(std::set::iterator itr = m_ClientBattleGroundIds[bgTypeId][queue_id].begin(); itr != m_ClientBattleGroundIds[bgTypeId][queue_id].end();++itr) { - // skip sending battleground template - if( itr == m_BattleGrounds[bgTypeId].begin() ) - continue; - if( PlayerLevel >= itr->second->GetMinLevel() && PlayerLevel <= itr->second->GetMaxLevel() ) - { - *data << uint32(itr->second->GetInstanceID()); - ++count; - } + *data << uint32(*itr); + ++count; } data->put( count_pos , count); } diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index bf25f3e22..6e6dd3141 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -193,15 +193,17 @@ class BattleGroundMgr 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 - BattleGround * GetBattleGroundTemplate(BattleGroundTypeId bgTypeId); - BattleGround * CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated); + BattleGround* GetBattleGroundTemplate(BattleGroundTypeId bgTypeId); + BattleGround* CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated); uint32 CreateBattleGround(BattleGroundTypeId bgTypeId, bool IsArena, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO); void AddBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId, BattleGround* BG) { m_BattleGrounds[bgTypeId][InstanceID] = BG; }; void RemoveBattleGround(uint32 instanceID, BattleGroundTypeId bgTypeId) { m_BattleGrounds[bgTypeId].erase(instanceID); } + uint32 CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id); void CreateInitialBattleGrounds(); void DeleteAllBattleGrounds(); @@ -245,6 +247,7 @@ class BattleGroundMgr /* Battlegrounds */ BattleGroundSet m_BattleGrounds[MAX_BATTLEGROUND_TYPE_ID]; + std::set m_ClientBattleGroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_QUEUES]; //the instanceids just visible for the client uint32 m_NextRatingDiscardUpdate; uint64 m_NextAutoDistributionTime; uint32 m_AutoDistributionTimeChecker; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0b5e9b212..c95ed0d39 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7436" + #define REVISION_NR "7437" #endif // __REVISION_NR_H__ From a2bb5aa9edb18edb638eb11d8a6d8801d20abc3a Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 10 Mar 2009 19:05:49 +0300 Subject: [PATCH 58/60] [7438] My typos in ObjectMgr::LoadAreaTriggerTeleports --- src/game/ObjectMgr.cpp | 4 ++-- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 9e296453e..89b38c220 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -4952,7 +4952,7 @@ void ObjectMgr::LoadAreaTriggerTeleports() if(at.requiredQuest) { QuestMap::iterator qReqItr = mQuestTemplates.find(at.requiredQuest); - if(qReqItr != mQuestTemplates.end()) + if(qReqItr == mQuestTemplates.end()) { sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",at.requiredQuest,Trigger_ID); at.requiredQuest = 0; @@ -4962,7 +4962,7 @@ void ObjectMgr::LoadAreaTriggerTeleports() if(at.requiredQuestHeroic) { QuestMap::iterator qReqItr = mQuestTemplates.find(at.requiredQuestHeroic); - if(qReqItr != mQuestTemplates.end()) + if(qReqItr == mQuestTemplates.end()) { sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",at.requiredQuestHeroic,Trigger_ID); at.requiredQuestHeroic = 0; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c95ed0d39..838a591c8 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7437" + #define REVISION_NR "7438" #endif // __REVISION_NR_H__ From 071a0317f0d3d261237fccc726ab430b2ffa42f0 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Wed, 11 Mar 2009 00:04:19 +0300 Subject: [PATCH 59/60] [7439] Fix wrong liquid level in some places. Need reectract maps. Remove some log on extract maps. Add liquid status log to .gps command Signed-off-by: DiSlord --- contrib/extractor/System.cpp | 9 +++++---- contrib/extractor/ad.exe | Bin 163328 -> 162816 bytes contrib/extractor/loadlib/loadlib.cpp | 5 +++-- contrib/extractor/loadlib/loadlib.h | 2 +- sql/mangos.sql | 3 ++- sql/updates/7439_01_mangos_mangos_string.sql | 5 +++++ sql/updates/Makefile.am | 2 ++ src/game/Language.h | 3 ++- src/game/Level1.cpp | 6 ++++++ src/game/Map.h | 2 +- src/shared/revision_nr.h | 2 +- 11 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 sql/updates/7439_01_mangos_mangos_string.sql diff --git a/contrib/extractor/System.cpp b/contrib/extractor/System.cpp index 49190f65b..843fe616e 100644 --- a/contrib/extractor/System.cpp +++ b/contrib/extractor/System.cpp @@ -207,7 +207,7 @@ void ReadLiquidTypeTableDBC() // Map file format data #define MAP_MAGIC 'SPAM' -#define MAP_VERSION_MAGIC '0.1v' +#define MAP_VERSION_MAGIC '0.1w' #define MAP_AREA_MAGIC 'AERA' #define MAP_HEIGTH_MAGIC 'TGHM' #define MAP_LIQUID_MAGIC 'QILM' @@ -304,7 +304,6 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x) memset(liquid_show, 0, sizeof(liquid_show)); memset(liquid_type, 0, sizeof(liquid_type)); - memset(liquid_height, 0, sizeof(liquid_height)); // Prepare map header map_fileheader map; @@ -709,6 +708,8 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x) if (maxHeight < h) maxHeight = h; if (minHeight > h) minHeight = h; } + else + liquid_height[y][x] = CONF_use_minHeight; } } map.liquidMapOffset = map.heightMapOffset + map.heightMapSize; @@ -812,11 +813,11 @@ void ExtractMapsFromMpq() printf("Convert map files\n"); for(uint32 z = 0; z < map_count; ++z) { - printf("Extract %s (%d/%d) \n", map_ids[z].name, z, map_count); + printf("Extract %s (%d/%d) \n", map_ids[z].name, z+1, map_count); // Loadup map grid data sprintf(mpq_map_name, "World\\Maps\\%s\\%s.wdt", map_ids[z].name, map_ids[z].name); WDT_file wdt; - if (!wdt.loadFile(mpq_map_name)) + if (!wdt.loadFile(mpq_map_name, false)) { // printf("Error loading %s map wdt data\n", map_ids[z].name); continue; diff --git a/contrib/extractor/ad.exe b/contrib/extractor/ad.exe index f3a475c4e64228da2fdf9ad1093753020454ef13..8300b697cef7de057e2967b637a9ed0e0c1156e0 100755 GIT binary patch delta 30024 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 P;M-KJpn6Uoe~A4*veRqi delta 30216 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, zone_x, zone_y, ground_z, floor_z, have_map, have_vmap ); + LiquidData liquid_status; + ZLiquidStatus res = map->getLiquidStatus(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), MAP_ALL_LIQUIDS, &liquid_status); + if (res) + { + PSendSysMessage(LANG_LIQUID_STATUS, liquid_status.level, liquid_status.depth_level, liquid_status.type, res); + } return true; } diff --git a/src/game/Map.h b/src/game/Map.h index 8019534ed..7aada6e31 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -72,7 +72,7 @@ typedef MaNGOS::SingleThreaded::Lock NullGuard; // Map file format defines //****************************************** #define MAP_MAGIC 'SPAM' -#define MAP_VERSION_MAGIC '0.1v' +#define MAP_VERSION_MAGIC '0.1w' #define MAP_AREA_MAGIC 'AERA' #define MAP_HEIGTH_MAGIC 'TGHM' #define MAP_LIQUID_MAGIC 'QILM' diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 838a591c8..b4cca7098 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7438" + #define REVISION_NR "7439" #endif // __REVISION_NR_H__ From 329fb3f9d10090613a28726810df8ae8c789671b Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 11 Mar 2009 08:48:52 +0300 Subject: [PATCH 60/60] [7440] Use server-side only zone info. Optimize related calles in case zone and subzone use. This in some cases make some zones not explorable if it not have server side data in current maps but not allow cheating with zone set from client. --- src/game/GameObject.cpp | 10 ++++---- src/game/Level1.cpp | 4 ++-- src/game/Level3.cpp | 11 +++++---- src/game/Map.cpp | 13 ++++++++--- src/game/Map.h | 14 ++++++++---- src/game/MapManager.h | 14 ++++++++++-- src/game/MiscHandler.cpp | 8 +++---- src/game/NPCHandler.cpp | 11 +++++---- src/game/Object.cpp | 5 ++++ src/game/Object.h | 1 + src/game/Player.cpp | 49 ++++++++++++++++++++++++---------------- src/game/Player.h | 4 ++-- src/game/Spell.cpp | 5 +++- src/game/SpellAuras.cpp | 8 +++---- src/shared/revision_nr.h | 2 +- 15 files changed, 103 insertions(+), 56 deletions(-) diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 0aaa575ad..11ea2b8da 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -491,14 +491,15 @@ void GameObject::getFishLoot(Loot *fishloot, Player* loot_owner) { fishloot->clear(); - uint32 subzone = GetAreaId(); + uint32 zone, subzone; + GetZoneAndAreaId(zone,subzone); // if subzone loot exist use it if(LootTemplates_Fishing.HaveLootFor(subzone)) fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner,true); // else use zone loot else - fishloot->FillLoot(GetZoneId(), LootTemplates_Fishing, loot_owner,true); + fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner,true); } void GameObject::SaveToDB() @@ -1019,11 +1020,12 @@ void GameObject::Use(Unit* user) // 2) if skill == base_zone_skill => 5% chance // 3) chance is linear dependence from (base_zone_skill-skill) - uint32 subzone = GetAreaId(); + uint32 zone, subzone; + GetZoneAndAreaId(zone,subzone); int32 zone_skill = objmgr.GetFishingBaseSkillLevel( subzone ); if(!zone_skill) - zone_skill = objmgr.GetFishingBaseSkillLevel( GetZoneId() ); + zone_skill = objmgr.GetFishingBaseSkillLevel( zone ); //provide error, no fishable zone or area should be 0 if(!zone_skill) diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 85eb69920..fd97a033a 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -284,8 +284,8 @@ bool ChatHandler::HandleGPSCommand(const char* args) CellPair cell_val = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); Cell cell(cell_val); - uint32 zone_id = obj->GetZoneId(); - uint32 area_id = obj->GetAreaId(); + uint32 zone_id, area_id; + obj->GetZoneAndAreaId(zone_id,area_id); MapEntry const* mapEntry = sMapStore.LookupEntry(obj->GetMapId()); AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zone_id); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index eaaebeb49..68cdb1717 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3520,7 +3520,7 @@ bool ChatHandler::HandleLinkGraveCommand(const char* args) return false; } - if(objmgr.AddGraveYardLink(g_id,player->GetZoneId(),g_team)) + if(objmgr.AddGraveYardLink(g_id,zoneId,g_team)) PSendSysMessage(LANG_COMMAND_GRAVEYARDLINKED, g_id,zoneId); else PSendSysMessage(LANG_COMMAND_GRAVEYARDALRLINKED, g_id,zoneId); @@ -3544,6 +3544,7 @@ bool ChatHandler::HandleNearGraveCommand(const char* args) return false; Player* player = m_session->GetPlayer(); + uint32 zone_id = player->GetZoneId(); WorldSafeLocsEntry const* graveyard = objmgr.GetClosestGraveYard( player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(),player->GetMapId(),g_team); @@ -3552,7 +3553,7 @@ bool ChatHandler::HandleNearGraveCommand(const char* args) { uint32 g_id = graveyard->ID; - GraveYardData const* data = objmgr.FindGraveYardData(g_id,player->GetZoneId()); + GraveYardData const* data = objmgr.FindGraveYardData(g_id,zone_id); if (!data) { PSendSysMessage(LANG_COMMAND_GRAVEYARDERROR,g_id); @@ -3571,7 +3572,7 @@ bool ChatHandler::HandleNearGraveCommand(const char* args) else if(g_team == ALLIANCE) team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE); - PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id,team_name.c_str(),player->GetZoneId()); + PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id,team_name.c_str(),zone_id); } else { @@ -3585,9 +3586,9 @@ bool ChatHandler::HandleNearGraveCommand(const char* args) team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE); if(g_team == ~uint32(0)) - PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, player->GetZoneId()); + PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, zone_id); else - PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, player->GetZoneId(),team_name.c_str()); + PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, zone_id,team_name.c_str()); } return true; diff --git a/src/game/Map.cpp b/src/game/Map.cpp index da32317e5..f78871d8b 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1674,7 +1674,7 @@ float Map::GetWaterLevel(float x, float y ) const return 0; } -uint32 Map::GetAreaId(uint16 areaflag,uint32 map_id) +uint32 Map::GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id) { AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id); @@ -1684,7 +1684,7 @@ uint32 Map::GetAreaId(uint16 areaflag,uint32 map_id) return 0; } -uint32 Map::GetZoneId(uint16 areaflag,uint32 map_id) +uint32 Map::GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id) { AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id); @@ -1694,6 +1694,14 @@ uint32 Map::GetZoneId(uint16 areaflag,uint32 map_id) return 0; } +void Map::GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id) +{ + AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id); + + areaid = entry ? entry->ID : 0; + zoneid = entry ? (( entry->zone != 0 ) ? entry->zone : entry->ID) : 0; +} + bool Map::IsInWater(float x, float y, float pZ) const { // Check surface in x, y point for liquid @@ -2205,7 +2213,6 @@ bool InstanceMap::Add(Player *player) // first player enters (no players yet) SetResetSchedule(false); - player->SendInitWorldStates(); sLog.outDetail("MAP: Player '%s' entered the instance '%u' of map '%s'", player->GetName(), GetInstanceId(), GetMapName()); // initialize unload state m_unloadTimer = 0; diff --git a/src/game/Map.h b/src/game/Map.h index 7aada6e31..b40a46a4a 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -318,17 +318,23 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj float GetWaterLevel(float x, float y ) const; bool IsUnderWater(float x, float y, float z) const; - static uint32 GetAreaId(uint16 areaflag,uint32 map_id); - static uint32 GetZoneId(uint16 areaflag,uint32 map_id); + static uint32 GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id); + static uint32 GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id); + static void GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id); uint32 GetAreaId(float x, float y, float z) const { - return GetAreaId(GetAreaFlag(x,y,z),i_id); + return GetAreaIdByAreaFlag(GetAreaFlag(x,y,z),i_id); } uint32 GetZoneId(float x, float y, float z) const { - return GetZoneId(GetAreaFlag(x,y,z),i_id); + return GetZoneIdByAreaFlag(GetAreaFlag(x,y,z),i_id); + } + + void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const + { + GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(x,y,z),i_id); } virtual void MoveAllCreaturesInMoveList(); diff --git a/src/game/MapManager.h b/src/game/MapManager.h index 677c26120..24fb222c4 100644 --- a/src/game/MapManager.h +++ b/src/game/MapManager.h @@ -50,8 +50,18 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::SingletonGetAreaFlag(x, y, z); } - uint32 GetAreaId(uint32 mapid, float x, float y, float z) const { return Map::GetAreaId(GetAreaFlag(mapid, x, y, z),mapid); } - uint32 GetZoneId(uint32 mapid, float x, float y, float z) const { return Map::GetZoneId(GetAreaFlag(mapid, x, y, z),mapid); } + uint32 GetAreaId(uint32 mapid, float x, float y, float z) const + { + return Map::GetAreaIdByAreaFlag(GetAreaFlag(mapid, x, y, z),mapid); + } + uint32 GetZoneId(uint32 mapid, float x, float y, float z) const + { + return Map::GetZoneIdByAreaFlag(GetAreaFlag(mapid, x, y, z),mapid); + } + void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) + { + Map::GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(mapid, x, y, z),mapid); + } void Initialize(void); void Update(uint32); diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 6b7582cbc..60fa21d83 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -384,10 +384,10 @@ void WorldSession::HandleZoneUpdateOpcode( WorldPacket & recv_data ) sLog.outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone); - if(newZone != _player->GetZoneId()) - GetPlayer()->SendInitWorldStates(); // only if really enters to new zone, not just area change, works strange... - - GetPlayer()->UpdateZone(newZone); + // use server size data + uint32 newzone, newarea; + GetPlayer()->GetZoneAndAreaId(newzone,newarea); + GetPlayer()->UpdateZone(newzone,newarea); } void WorldSession::HandleSetTargetOpcode( WorldPacket & recv_data ) diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 78308b08c..65163b924 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -433,11 +433,12 @@ void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data ) void WorldSession::SendBindPoint(Creature *npc) { uint32 bindspell = 3286; + uint32 zone_id = _player->GetZoneId(); // update sql homebind - CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", _player->GetMapId(), _player->GetZoneId(), _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow()); + CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", _player->GetMapId(), zone_id, _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow()); _player->m_homebindMapId = _player->GetMapId(); - _player->m_homebindZoneId = _player->GetZoneId(); + _player->m_homebindZoneId = zone_id; _player->m_homebindX = _player->GetPositionX(); _player->m_homebindY = _player->GetPositionY(); _player->m_homebindZ = _player->GetPositionZ(); @@ -456,19 +457,19 @@ void WorldSession::SendBindPoint(Creature *npc) data << float(_player->GetPositionY()); data << float(_player->GetPositionZ()); data << uint32(_player->GetMapId()); - data << uint32(_player->GetZoneId()); + data << uint32(zone_id); SendPacket( &data ); DEBUG_LOG("New Home Position X is %f",_player->GetPositionX()); DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY()); DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ()); DEBUG_LOG("New Home MapId is %u",_player->GetMapId()); - DEBUG_LOG("New Home ZoneId is %u",_player->GetZoneId()); + DEBUG_LOG("New Home ZoneId is %u",zone_id); // zone update data.Initialize( SMSG_PLAYERBOUND, 8+4 ); data << uint64(_player->GetGUID()); - data << uint32(_player->GetZoneId()); + data << uint32(zone_id); SendPacket( &data ); _player->PlayerTalkClass->CloseGossip(); diff --git a/src/game/Object.cpp b/src/game/Object.cpp index c4c8cea87..486d5b214 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1048,6 +1048,11 @@ uint32 WorldObject::GetAreaId() const return MapManager::Instance().GetBaseMap(m_mapId)->GetAreaId(m_positionX,m_positionY,m_positionZ); } +void WorldObject::GetZoneAndAreaId(uint32& zoneid, uint32& areaid) const +{ + MapManager::Instance().GetBaseMap(m_mapId)->GetZoneAndAreaId(zoneid,areaid,m_positionX,m_positionY,m_positionZ); +} + InstanceData* WorldObject::GetInstanceData() { Map *map = GetMap(); diff --git a/src/game/Object.h b/src/game/Object.h index 8786ba611..03e329b0d 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -414,6 +414,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object uint32 GetZoneId() const; uint32 GetAreaId() const; + void GetZoneAndAreaId(uint32& zoneid, uint32& areaid) const; InstanceData* GetInstanceData(); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index af71a306d..65a3cf2b2 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1242,14 +1242,15 @@ void Player::Update( uint32 p_time ) { if(p_time >= m_zoneUpdateTimer) { - uint32 newzone = GetZoneId(); + uint32 newzone, newarea; + GetZoneAndAreaId(newzone,newarea); + if( m_zoneUpdateId != newzone ) - UpdateZone(newzone); // also update area + UpdateZone(newzone,newarea); // also update area else { // use area updates as well // needed for free far all arenas for example - uint32 newarea = GetAreaId(); if( m_areaUpdateId != newarea ) UpdateArea(newarea); @@ -1653,16 +1654,19 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati } } + uint32 newzone, newarea; + GetZoneAndAreaId(newzone,newarea); + if(!GetSession()->PlayerLogout()) { // don't reset teleport semaphore while logging out, otherwise m_teleport_dest won't be used in Player::SaveToDB SetSemaphoreTeleport(false); - UpdateZone(GetZoneId()); + UpdateZone(newzone,newarea); } // new zone - if(old_zone != GetZoneId()) + if(old_zone != newzone) { // honorless target if(pvpInfo.inHostileArea) @@ -3941,7 +3945,9 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) } // trigger update zone for alive state zone updates - UpdateZone(GetZoneId()); + uint32 newzone, newarea; + GetZoneAndAreaId(newzone,newarea); + UpdateZone(newzone,newarea); // update visibility ObjectAccessor::UpdateVisibilityForPlayer(this); @@ -6378,13 +6384,16 @@ void Player::UpdateArea(uint32 newArea) UpdateAreaDependentAuras(newArea); } -void Player::UpdateZone(uint32 newZone) +void Player::UpdateZone(uint32 newZone, uint32 newArea) { + if(m_zoneUpdateId != newZone) + SendInitWorldStates(newZone, newArea); // only if really enters to new zone, not just area change, works strange... + m_zoneUpdateId = newZone; m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL; // zone changed, so area changed as well, update it - UpdateArea(GetAreaId()); + UpdateArea(newArea); AreaTableEntry const* zone = GetAreaEntryByAreaID(newZone); if(!zone) @@ -7742,15 +7751,15 @@ void Player::SendUpdateWorldState(uint32 Field, uint32 Value) GetSession()->SendPacket(&data); } -void Player::SendInitWorldStates() +void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) { // data depends on zoneid/mapid... BattleGround* bg = GetBattleGround(); uint16 NumberOfFields = 0; uint32 mapid = GetMapId(); - uint32 zoneid = GetZoneId(); - uint32 areaid = GetAreaId(); + sLog.outDebug("Sending SMSG_INIT_WORLD_STATES to Map:%u, Zone: %u", mapid, zoneid); + // may be exist better way to do this... switch(zoneid) { @@ -12736,8 +12745,8 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver ) SpellAreaForQuestMapBounds saBounds = spellmgr.GetSpellAreaForQuestMapBounds(quest_id,true); if(saBounds.first != saBounds.second) { - uint32 zone = GetZoneId(); - uint32 area = GetAreaId(); + uint32 zone, area; + GetZoneAndAreaId(zone,area); for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) if(itr->second->autocast && itr->second->IsFitToRequirements(this,zone,area)) @@ -12951,8 +12960,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver SpellAreaForQuestMapBounds saEndBounds = spellmgr.GetSpellAreaForQuestEndMapBounds(quest_id); if(saEndBounds.first != saEndBounds.second) { - uint32 zone = GetZoneId(); - uint32 area = GetAreaId(); + GetZoneAndAreaId(zone,area); for(SpellAreaForAreaMap::const_iterator itr = saEndBounds.first; itr != saEndBounds.second; ++itr) if(!itr->second->IsFitToRequirements(this,zone,area)) @@ -12963,8 +12971,8 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver SpellAreaForQuestMapBounds saBounds = spellmgr.GetSpellAreaForQuestMapBounds(quest_id,false); if(saBounds.first != saBounds.second) { - if(!zone) zone = GetZoneId(); - if(!area) area = GetAreaId(); + if(!zone || !area) + GetZoneAndAreaId(zone,area); for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) if(itr->second->autocast && itr->second->IsFitToRequirements(this,zone,area)) @@ -18343,8 +18351,11 @@ void Player::SendInitialPacketsBeforeAddToMap() SendInitialActionButtons(); SendInitialReputations(); m_achievementMgr.SendAllAchievementData(); - UpdateZone(GetZoneId()); - SendInitWorldStates(); + + // update zone + uint32 newzone, newarea; + GetZoneAndAreaId(newzone,newarea); + UpdateZone(newzone,newarea); // also call SendInitWorldStates(); // SMSG_SET_AURA_SINGLE diff --git a/src/game/Player.h b/src/game/Player.h index 63681ada0..d224c5bd6 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1536,7 +1536,7 @@ class MANGOS_DLL_SPEC Player : public Unit PvPInfo pvpInfo; void UpdatePvP(bool state, bool ovrride=false); - void UpdateZone(uint32 newZone); + void UpdateZone(uint32 newZone,uint32 newArea); void UpdateArea(uint32 newArea); void UpdateZoneDependentAuras( uint32 zone_id ); // zones @@ -1856,7 +1856,7 @@ class MANGOS_DLL_SPEC Player : public Unit void CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType); void CastItemUseSpell(Item *item,SpellCastTargets const& targets,uint8 cast_count, uint32 glyphIndex); - void SendInitWorldStates(); + void SendInitWorldStates(uint32 zone, uint32 area); void SendUpdateWorldState(uint32 Field, uint32 Value); void SendDirectMessage(WorldPacket *data); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 0e99e9190..71ee209f5 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3756,7 +3756,10 @@ uint8 Spell::CanCast(bool strict) return SPELL_FAILED_NOT_IN_ARENA; // zone check - if (uint8 res= spellmgr.GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),m_caster->GetZoneId(),m_caster->GetAreaId(), + uint32 zone, area; + m_caster->GetZoneAndAreaId(zone,area); + + if (uint8 res= spellmgr.GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),zone,area, m_caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)m_caster) : NULL)) return res; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 0f6cae650..8e4c19084 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2389,8 +2389,8 @@ void Aura::HandleAuraDummy(bool apply, bool Real) SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); if(saBounds.first != saBounds.second) { - uint32 zone = m_target->GetZoneId(); - uint32 area = m_target->GetAreaId(); + uint32 zone, area; + m_target->GetZoneAndAreaId(zone,area); for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) { @@ -6678,8 +6678,8 @@ void Aura::HandlePhase(bool apply, bool Real) SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); if(saBounds.first != saBounds.second) { - uint32 zone = m_target->GetZoneId(); - uint32 area = m_target->GetAreaId(); + uint32 zone, area; + m_target->GetZoneAndAreaId(zone,area); for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b4cca7098..96986cb2e 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7439" + #define REVISION_NR "7440" #endif // __REVISION_NR_H__