From 9e6390d88dca78a7f3982d4e063e84ece67b8b21 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 27 Oct 2008 16:43:31 +0300 Subject: [PATCH 1/9] Load npc_options at server startup, use cached data at creature gossip menu init. Also new .reload table command added. Note: currently it will not affect creatures that have gossim memu created at command use moment. --- src/game/Chat.cpp | 1 + src/game/Chat.h | 1 + src/game/Creature.cpp | 42 +++++++++++---------------------------- src/game/Creature.h | 2 +- src/game/Level3.cpp | 9 +++++++++ src/game/ObjectMgr.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++ src/game/ObjectMgr.h | 5 +++++ src/game/World.cpp | 3 +++ 8 files changed, 77 insertions(+), 31 deletions(-) diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 86e96d5bf..d0cdfc25c 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -228,6 +228,7 @@ ChatCommand * ChatHandler::getCommandTable() { "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL }, { "mangos_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMangosStringCommand, "", NULL }, { "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL }, + { "npc_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcOptionCommand, "", NULL }, { "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL }, { "npc_vendor", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcVendorCommand, "", NULL }, { "page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPageTextsCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index c91f0b673..6006bfa76 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -183,6 +183,7 @@ class ChatHandler bool HandleReloadLootTemplatesSkinningCommand(const char* args); bool HandleReloadMangosStringCommand(const char* args); bool HandleReloadNpcGossipCommand(const char* args); + bool HandleReloadNpcOptionCommand(const char* args); bool HandleReloadNpcTrainerCommand(const char* args); bool HandleReloadNpcVendorCommand(const char* args); bool HandleReloadQuestAreaTriggersCommand(const char* args); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 34f7b1ee9..783a1a7c1 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -668,12 +668,9 @@ void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid ) // lazy loading single time at use LoadGossipOptions(); - GossipOption* gso; - GossipOption* ingso; - for( GossipOptionList::iterator i = m_goptions.begin( ); i != m_goptions.end( ); i++ ) { - gso=&*i; + GossipOption* gso=&*i; if(gso->GossipId == gossipid) { bool cantalking=true; @@ -746,11 +743,9 @@ void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid ) } } - if(!gso->Option.empty() && cantalking ) - { //note for future dev: should have database fields for BoxMessage & BoxMoney - pm->GetGossipMenu().AddMenuItem((uint8)gso->Icon,gso->Option, gossipid,gso->Action,"",0,false); - ingso=gso; - } + //note for future dev: should have database fields for BoxMessage & BoxMoney + if(!gso->OptionText.empty() && cantalking) + pm->GetGossipMenu().AddMenuItem((uint8)gso->Icon,gso->OptionText, gossipid,gso->Action,"",0,false); } } @@ -797,8 +792,8 @@ void Creature::OnGossipSelect(Player* player, uint32 option) uint32 action=gossipmenu.GetItem(option).m_gAction; uint32 zoneid=GetZoneId(); uint64 guid=GetGUID(); + GossipOption const *gossip=GetGossipOption( action ); - uint32 textid; if(!gossip) { zoneid=0; @@ -806,7 +801,8 @@ void Creature::OnGossipSelect(Player* player, uint32 option) if(!gossip) return; } - textid=GetGossipTextId( action, zoneid); + + uint32 textid=GetGossipTextId( action, zoneid); if(textid==0) textid=GetNpcTextId(); @@ -895,7 +891,7 @@ void Creature::OnPoiSelect(Player* player, GossipOption const *gossip) Map const* map=MapManager::Instance().GetBaseMap( mapid ); uint16 areaflag=map->GetAreaFlag(GetPositionX(),GetPositionY()); uint32 zoneid=Map::GetZoneId(areaflag,mapid); - std::string areaname= gossip->Option; + std::string areaname= gossip->OptionText; /* uint16 pflag; @@ -989,24 +985,10 @@ void Creature::LoadGossipOptions() uint32 npcflags=GetUInt32Value(UNIT_NPC_FLAGS); - QueryResult *result = WorldDatabase.PQuery( "SELECT id,gossip_id,npcflag,icon,action,option_text FROM npc_option WHERE (npcflag & %u)<>0", npcflags ); - - if(!result) - return; - - GossipOption go; - do - { - Field *fields = result->Fetch(); - go.Id= fields[0].GetUInt32(); - go.GossipId = fields[1].GetUInt32(); - go.NpcFlag=fields[2].GetUInt32(); - go.Icon=fields[3].GetUInt32(); - go.Action=fields[4].GetUInt32(); - go.Option=fields[5].GetCppString(); - addGossipOption(go); - }while( result->NextRow() ); - delete result; + CacheNpcOptionList const& noList = objmgr.GetNpcOptions (); + for (CacheNpcOptionList::const_iterator i = noList.begin (); i != noList.end (); ++i) + if(i->NpcFlag & npcflags) + addGossipOption(*i); m_gossipOptionLoaded = true; } diff --git a/src/game/Creature.h b/src/game/Creature.h index 5d0ff9cf7..678c6e14a 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -109,7 +109,7 @@ struct GossipOption uint32 NpcFlag; uint32 Icon; uint32 Action; - std::string Option; + std::string OptionText; }; enum CreatureFlagsExtra diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index fbf235738..71e67ecdf 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -100,6 +100,7 @@ bool ChatHandler::HandleReloadAllLootCommand(const char*) bool ChatHandler::HandleReloadAllNpcCommand(const char* /*args*/) { HandleReloadNpcGossipCommand("a"); + HandleReloadNpcOptionCommand("a"); HandleReloadNpcTrainerCommand("a"); HandleReloadNpcVendorCommand("a"); return true; @@ -345,6 +346,14 @@ bool ChatHandler::HandleReloadMangosStringCommand(const char*) return true; } +bool ChatHandler::HandleReloadNpcOptionCommand(const char*) +{ + sLog.outString( "Re-Loading `npc_option` Table!" ); + objmgr.LoadNpcOptions(); + SendGlobalSysMessage("DB table `npc_option` reloaded."); + return true; +} + bool ChatHandler::HandleReloadNpcGossipCommand(const char*) { sLog.outString( "Re-Loading `npc_gossip` Table!" ); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 9720564bf..eeee3a4a0 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -6882,6 +6882,51 @@ void ObjectMgr::LoadNpcTextId() sLog.outString( ">> Loaded %d NpcTextId ", count ); } +void ObjectMgr::LoadNpcOptions() +{ + m_mCacheNpcOptionList.clear(); // For reload case + + QueryResult *result = WorldDatabase.Query( "SELECT id,gossip_id,npcflag,icon,action,option_text FROM npc_option"); + if( !result ) + { + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `npc_option`, table is empty!"); + return; + } + + barGoLink bar( result->GetRowCount() ); + + uint32 count = 0; + + do + { + bar.step(); + + Field* fields = result->Fetch(); + + GossipOption go; + go.Id = fields[0].GetUInt32(); + go.GossipId = fields[1].GetUInt32(); + go.NpcFlag = fields[2].GetUInt32(); + go.Icon = fields[3].GetUInt32(); + go.Action = fields[4].GetUInt32(); + go.OptionText = fields[5].GetCppString(); + + m_mCacheNpcOptionList.push_back(go); + + ++count; + + } while (result->NextRow()); + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %d npc_option entries", count ); +} + void ObjectMgr::AddVendorItem( uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 extendedcost ) { VendorItemData& vList = m_mCacheVendorItemMap[entry]; diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 982b9a4a9..e7a03d3a4 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -229,6 +229,7 @@ struct PlayerCondition // NPC gossip text id typedef HM_NAMESPACE::hash_map CacheNpcTextIdMap; +typedef std::list CacheNpcOptionList; typedef HM_NAMESPACE::hash_map CacheVendorItemMap; typedef HM_NAMESPACE::hash_map CacheTrainerSpellMap; @@ -544,6 +545,7 @@ class ObjectMgr void LoadWeatherZoneChances(); void LoadGameTele(); + void LoadNpcOptions(); void LoadNpcTextId(); void LoadVendors(); void LoadTrainerSpell(); @@ -712,6 +714,8 @@ class ObjectMgr bool AddGameTele(GameTele& data); bool DeleteGameTele(std::string name); + CacheNpcOptionList const& GetNpcOptions() const { return m_mCacheNpcOptionList; } + uint32 GetNpcGossip(uint32 entry) const { CacheNpcTextIdMap::const_iterator iter = m_mCacheNpcTextIdMap.find(entry); @@ -850,6 +854,7 @@ class ObjectMgr typedef std::vector ConditionStore; ConditionStore mConditions; + CacheNpcOptionList m_mCacheNpcOptionList; CacheNpcTextIdMap m_mCacheNpcTextIdMap; CacheVendorItemMap m_mCacheVendorItemMap; CacheTrainerSpellMap m_mCacheTrainerSpellMap; diff --git a/src/game/World.cpp b/src/game/World.cpp index 1496e7be3..135493f7d 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1111,6 +1111,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Npc Text Id..." ); objmgr.LoadNpcTextId(); // must be after load Creature and NpcText + sLog.outString( "Loading Npc Options..." ); + objmgr.LoadNpcOptions(); + sLog.outString( "Loading vendors..." ); objmgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate From 74ddd38af391bdf99549e66d6562e03b102dc855 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 27 Oct 2008 18:47:13 +0300 Subject: [PATCH 2/9] Prevent crash at access to deleted social data for player. Remove social data at logout instead ~Player that called also for temporary Player object for Player::MinimalLoadFromDB call. --- src/game/Player.cpp | 6 ++---- src/game/SpellEffects.cpp | 2 +- src/game/WorldSession.cpp | 1 + 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index ab3e98e59..ed23d9c33 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -426,10 +426,8 @@ Player::~Player () { CleanupsBeforeDelete(); - if(m_uint32Values) // only for fully created Object - { - sSocialMgr.RemovePlayerSocial(GetGUIDLow()); - } + // it must be unloaded already in PlayerLogout and accessed only for loggined player + //m_social = NULL; // Note: buy back item already deleted from DB when player was saved for(int i = 0; i < PLAYER_SLOTS_COUNT; ++i) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 6525efecf..e71114367 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4945,7 +4945,7 @@ void Spell::EffectDuel(uint32 i) Player *target = (Player*)unitTarget; // caster or target already have requested duel - if( caster->duel || target->duel || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) ) + if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) ) return; // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities) diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 60c060567..261d613bf 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -380,6 +380,7 @@ void WorldSession::LogoutPlayer(bool Save) ///- Delete the player object _player->CleanupsBeforeDelete(); // do some cleanup before deleting to prevent crash at crossreferences to already deleted data + sSocialMgr.RemovePlayerSocial (_player->GetGUIDLow ()); delete _player; _player = NULL; From 94e29ce6a89b3629a793dc504b86a698ddaa8d17 Mon Sep 17 00:00:00 2001 From: GriffonHeart Date: Mon, 27 Oct 2008 22:12:45 +0300 Subject: [PATCH 3/9] [2008_10_27_01_npc_option.sql,2008_10_27_02_locales_npc_option.sql] Implement npc_option localization support, also store in DB BoxText/BoxMoney/Coded. Signed-off-by: VladimirMangos --- sql/mangos.sql | 45 +++++++++- sql/updates/2008_10_27_01_npc_option.sql | 7 ++ .../2008_10_27_02_locales_npc_option.sql | 22 +++++ sql/updates/Makefile.am | 4 + src/game/Creature.cpp | 20 ++++- src/game/Creature.h | 13 ++- src/game/NPCHandler.cpp | 16 ++-- src/game/ObjectMgr.cpp | 89 +++++++++++++++++-- src/game/ObjectMgr.h | 9 ++ src/game/QuestHandler.cpp | 4 +- src/game/World.cpp | 1 + 11 files changed, 206 insertions(+), 24 deletions(-) create mode 100644 sql/updates/2008_10_27_01_npc_option.sql create mode 100644 sql/updates/2008_10_27_02_locales_npc_option.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index c320c9169..47c30e301 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -1803,6 +1803,42 @@ LOCK TABLES `locales_item` WRITE; /*!40000 ALTER TABLE `locales_item` ENABLE KEYS */; UNLOCK TABLES; + +-- +-- Table structure for table `locales_npc_option` +-- + +DROP TABLE IF EXISTS `locales_npc_option`; +CREATE TABLE `locales_npc_option` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `option_text_loc1` text, + `option_text_loc2` text, + `option_text_loc3` text, + `option_text_loc4` text, + `option_text_loc5` text, + `option_text_loc6` text, + `option_text_loc7` text, + `option_text_loc8` text, + `box_text_loc1` text, + `box_text_loc2` text, + `box_text_loc3` text, + `box_text_loc4` text, + `box_text_loc5` text, + `box_text_loc6` text, + `box_text_loc7` text, + `box_text_loc8` text, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `locales_npc_option` +-- + +LOCK TABLES `locales_npc_option` WRITE; +/*!40000 ALTER TABLE `locales_npc_option` DISABLE KEYS */; +/*!40000 ALTER TABLE `locales_npc_option` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `locales_npc_text` -- @@ -2707,12 +2743,15 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `npc_option`; CREATE TABLE `npc_option` ( - `id` tinyint(3) unsigned NOT NULL default '0', - `gossip_id` tinyint(3) unsigned NOT NULL default '0', + `id` mediumint(8) unsigned NOT NULL default '0', + `gossip_id` mediumint(8) unsigned NOT NULL default '0', `npcflag` int(10) unsigned NOT NULL default '0', `icon` tinyint(3) unsigned NOT NULL default '0', - `action` tinyint(3) unsigned NOT NULL default '0', + `action` mediumint(8) unsigned NOT NULL default '0', + `box_money` int(10) unsigned NOT NULL default '0', + `coded` tinyint(3) unsigned NOT NULL default '0', `option_text` text, + `box_text` text, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/2008_10_27_01_npc_option.sql b/sql/updates/2008_10_27_01_npc_option.sql new file mode 100644 index 000000000..983a6c9e6 --- /dev/null +++ b/sql/updates/2008_10_27_01_npc_option.sql @@ -0,0 +1,7 @@ +ALTER TABLE `npc_option` + CHANGE COLUMN `id` `id` mediumint(8) unsigned NOT NULL default '0', + CHANGE COLUMN `gossip_id` `gossip_id` mediumint(8) unsigned NOT NULL default '0', + CHANGE COLUMN `action` `action` mediumint(8) unsigned NOT NULL default '0', + ADD COLUMN `box_money` int(10) unsigned NOT NULL default '0' AFTER `action`, + ADD COLUMN `coded` tinyint(3) unsigned NOT NULL default '0' AFTER `box_money`, + ADD COLUMN `box_text` text AFTER `option_text`; diff --git a/sql/updates/2008_10_27_02_locales_npc_option.sql b/sql/updates/2008_10_27_02_locales_npc_option.sql new file mode 100644 index 000000000..172e35a24 --- /dev/null +++ b/sql/updates/2008_10_27_02_locales_npc_option.sql @@ -0,0 +1,22 @@ +CREATE TABLE `locales_npc_option` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `option_text_loc1` text, + `option_text_loc2` text, + `option_text_loc3` text, + `option_text_loc4` text, + `option_text_loc5` text, + `option_text_loc6` text, + `option_text_loc7` text, + `option_text_loc8` text, + `box_text_loc1` text, + `box_text_loc2` text, + `box_text_loc3` text, + `box_text_loc4` text, + `box_text_loc5` text, + `box_text_loc6` text, + `box_text_loc7` text, + `box_text_loc8` text, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index da45d285a..5acb7d68d 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -107,6 +107,8 @@ pkgdata_DATA = \ 2008_10_23_04_mangos_command.sql \ 2008_10_23_05_mangos_command.sql \ 2008_10_26_01_mangos_mangos_string.sql \ + 2008_10_27_01_npc_option.sql \ + 2008_10_27_02_locales_npc_option.sql \ README ## Additional files to include when running 'make dist' @@ -195,4 +197,6 @@ EXTRA_DIST = \ 2008_10_23_04_mangos_command.sql \ 2008_10_23_05_mangos_command.sql \ 2008_10_26_01_mangos_mangos_string.sql \ + 2008_10_27_01_npc_option.sql \ + 2008_10_27_02_locales_npc_option.sql \ README diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 783a1a7c1..070007792 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -738,14 +738,30 @@ void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid ) case GOSSIP_OPTION_AUCTIONEER: break; // no checks default: - sLog.outErrorDb("Creature %u (entry: %u) have unknown gossip option %u",GetGUIDLow(),GetEntry(),gso->Action); + sLog.outErrorDb("Creature %u (entry: %u) have unknown gossip option %u",GetDBTableGUIDLow(),GetEntry(),gso->Action); break; } } //note for future dev: should have database fields for BoxMessage & BoxMoney if(!gso->OptionText.empty() && cantalking) - pm->GetGossipMenu().AddMenuItem((uint8)gso->Icon,gso->OptionText, gossipid,gso->Action,"",0,false); + { + std::string OptionText = gso->OptionText; + std::string BoxText = gso->BoxText; + int loc_idx = pPlayer->GetSession()->GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + NpcOptionLocale const *no = objmgr.GetNpcOptionLocale(gso->Id); + if (no) + { + if (no->OptionText.size() > loc_idx && !no->OptionText[loc_idx].empty()) + OptionText=no->OptionText[loc_idx]; + if (no->BoxText.size() > loc_idx && !no->BoxText[loc_idx].empty()) + BoxText=no->BoxText[loc_idx]; + } + } + pm->GetGossipMenu().AddMenuItem((uint8)gso->Icon,OptionText, gossipid,gso->Action,BoxText,gso->BoxMoney,gso->Coded); + } } } diff --git a/src/game/Creature.h b/src/game/Creature.h index 678c6e14a..3e01aec3e 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -109,7 +109,10 @@ struct GossipOption uint32 NpcFlag; uint32 Icon; uint32 Action; + uint32 BoxMoney; + bool Coded; std::string OptionText; + std::string BoxText; }; enum CreatureFlagsExtra @@ -207,6 +210,12 @@ struct CreatureLocale std::vector SubName; }; +struct NpcOptionLocale +{ + std::vector OptionText; + std::vector BoxText; +}; + struct EquipmentInfo { uint32 entry; @@ -467,8 +476,8 @@ class MANGOS_DLL_SPEC Creature : public Unit CreatureDataAddon const* GetCreatureAddon() const; char const* GetScriptName() const; - void prepareGossipMenu( Player *pPlayer,uint32 gossipid ); - void sendPreparedGossip( Player* player); + void prepareGossipMenu( Player *pPlayer, uint32 gossipid = 0 ); + void sendPreparedGossip( Player* player ); void OnGossipSelect(Player* player, uint32 option); void OnPoiSelect(Player* player, GossipOption const *gossip); diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 2fd973610..076ec192a 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -295,8 +295,8 @@ void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data ) if(!Script->GossipHello( _player, unit )) { _player->TalkedToCreature(unit->GetEntry(),unit->GetGUID()); - unit->prepareGossipMenu(_player,0); - unit->sendPreparedGossip( _player ); + unit->prepareGossipMenu(_player); + unit->sendPreparedGossip(_player); } } @@ -335,14 +335,14 @@ void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data ) if(!code.empty()) { - - if(!Script->GossipSelectWithCode( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str()) ) - unit->OnGossipSelect( _player, option ); + if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str())) + unit->OnGossipSelect (_player, option); } else - - if(!Script->GossipSelect( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option )) ) - unit->OnGossipSelect( _player, option ); + { + if (!Script->GossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option))) + unit->OnGossipSelect (_player, option); + } } void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data ) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index eeee3a4a0..49c4f93c7 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -563,6 +563,74 @@ void ObjectMgr::LoadCreatureLocales() sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() ); } +void ObjectMgr::LoadNpcOptionLocales() +{ + mNpcOptionLocaleMap.clear(); // need for reload case + + QueryResult *result = WorldDatabase.Query("SELECT entry," + "option_text_loc1,box_text_loc1,option_text_loc2,box_text_loc2," + "option_text_loc3,box_text_loc3,option_text_loc4,box_text_loc4," + "option_text_loc5,box_text_loc5,option_text_loc6,box_text_loc6," + "option_text_loc7,box_text_loc7,option_text_loc8,box_text_loc8 " + "FROM locales_npc_option"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outString(">> Loaded 0 npc_option locale strings. DB table `locales_npc_option` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + NpcOptionLocale& data = mNpcOptionLocaleMap[entry]; + + for(int i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[1+2*(i-1)].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.OptionText.size() <= idx) + data.OptionText.resize(idx+1); + + data.OptionText[idx] = str; + } + } + str = fields[1+2*(i-1)+1].GetCppString(); + if(!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.BoxText.size() <= idx) + data.BoxText.resize(idx+1); + + data.BoxText[idx] = str; + } + } + } + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u npc_option locale strings", mNpcOptionLocaleMap.size() ); +} + void ObjectMgr::LoadCreatureTemplates() { sCreatureStorage.Load(); @@ -6886,7 +6954,11 @@ void ObjectMgr::LoadNpcOptions() { m_mCacheNpcOptionList.clear(); // For reload case - QueryResult *result = WorldDatabase.Query( "SELECT id,gossip_id,npcflag,icon,action,option_text FROM npc_option"); + QueryResult *result = WorldDatabase.Query( + // 0 1 2 3 4 5 6 7 8 + "SELECT id,gossip_id,npcflag,icon,action,box_money,coded,option_text,box_text " + "FROM npc_option"); + if( !result ) { barGoLink bar( 1 ); @@ -6909,12 +6981,15 @@ void ObjectMgr::LoadNpcOptions() Field* fields = result->Fetch(); GossipOption go; - go.Id = fields[0].GetUInt32(); - go.GossipId = fields[1].GetUInt32(); - go.NpcFlag = fields[2].GetUInt32(); - go.Icon = fields[3].GetUInt32(); - go.Action = fields[4].GetUInt32(); - go.OptionText = fields[5].GetCppString(); + go.Id = fields[0].GetUInt32(); + go.GossipId = fields[1].GetUInt32(); + go.NpcFlag = fields[2].GetUInt32(); + go.Icon = fields[3].GetUInt32(); + go.Action = fields[4].GetUInt32(); + go.BoxMoney = fields[5].GetUInt32(); + go.Coded = fields[6].GetUInt8()!=0; + go.OptionText = fields[7].GetCppString(); + go.BoxText = fields[8].GetCppString(); m_mCacheNpcOptionList.push_back(go); diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index e7a03d3a4..c9b4e9bdf 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -139,6 +139,7 @@ typedef HM_NAMESPACE::hash_map QuestLocaleMap; typedef HM_NAMESPACE::hash_map NpcTextLocaleMap; typedef HM_NAMESPACE::hash_map PageTextLocaleMap; typedef HM_NAMESPACE::hash_map MangosStringLocaleMap; +typedef HM_NAMESPACE::hash_map NpcOptionLocaleMap; typedef std::multimap QuestRelations; @@ -515,6 +516,7 @@ class ObjectMgr void LoadQuestLocales(); void LoadNpcTextLocales(); void LoadPageTextLocales(); + void LoadNpcOptionLocales(); void LoadInstanceTemplate(); void LoadGossipText(); @@ -639,6 +641,12 @@ class ObjectMgr if(itr==mPageTextLocaleMap.end()) return NULL; return &itr->second; } + NpcOptionLocale const* GetNpcOptionLocale(uint32 entry) const + { + NpcOptionLocaleMap::const_iterator itr = mNpcOptionLocaleMap.find(entry); + if(itr==mNpcOptionLocaleMap.end()) return NULL; + return &itr->second; + } GameObjectData const* GetGOData(uint32 guid) const { @@ -844,6 +852,7 @@ class ObjectMgr NpcTextLocaleMap mNpcTextLocaleMap; PageTextLocaleMap mPageTextLocaleMap; MangosStringLocaleMap mMangosStringLocaleMap; + NpcOptionLocaleMap mNpcOptionLocaleMap; RespawnTimes mCreatureRespawnTimes; RespawnTimes mGORespawnTimes; diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 42eea5082..0334332a9 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -103,8 +103,8 @@ void WorldSession::HandleQuestgiverHelloOpcode( WorldPacket & recv_data ) if(Script->GossipHello( _player, pCreature ) ) return; - pCreature->prepareGossipMenu(_player,0); - pCreature->sendPreparedGossip( _player ); + pCreature->prepareGossipMenu(_player); + pCreature->sendPreparedGossip(_player); } void WorldSession::HandleQuestgiverAcceptQuestOpcode( WorldPacket & recv_data ) diff --git a/src/game/World.cpp b/src/game/World.cpp index 135493f7d..c32c29759 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -945,6 +945,7 @@ void World::SetInitialWorldSettings() objmgr.LoadQuestLocales(); objmgr.LoadNpcTextLocales(); objmgr.LoadPageTextLocales(); + objmgr.LoadNpcOptionLocales(); objmgr.SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts) sLog.outString( "Loading Page Texts..." ); From 58bc947ef9c7fa699f10c8b50835cf8cc835b00c Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 28 Oct 2008 10:14:05 +0300 Subject: [PATCH 4/9] Fixed subcommands list output at console. --- src/game/Chat.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index d0cdfc25c..625788f8a 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -787,7 +787,13 @@ bool ChatHandler::ShowHelpForSubCommands(ChatCommand *table, char const* cmd, ch if( *subcmd && !hasStringAbbr(table[i].Name, subcmd)) continue; - (list += "\n ") += table[i].Name; + if(m_session) + list += "\n "; + else + list += "\n\r "; + + list += table[i].Name; + if(table[i].ChildCommands) list += " ..."; } From 6169f57ab95cb0e38c5d1339da4a99ff0a398df9 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 28 Oct 2008 13:27:40 +0300 Subject: [PATCH 5/9] Simplify check requirement report command results to target and output command user name. * Provided ChatHandler::GetName for player name/"console command" output dependent from chat/console command call. * New function for check when command work result send to command target. * Remove unrequired complexy in mangos string usage in some commands. --- sql/mangos.sql | 2 +- .../2008_10_28_01_mangos_mangos_string.sql | 5 + src/game/Chat.cpp | 22 ++++ src/game/Chat.h | 4 + src/game/Language.h | 5 +- src/game/Level1.cpp | 109 +++++++----------- src/game/Level3.cpp | 10 +- 7 files changed, 84 insertions(+), 73 deletions(-) create mode 100644 sql/updates/2008_10_28_01_mangos_mangos_string.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 47c30e301..ece5eccee 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -2266,7 +2266,7 @@ INSERT INTO `mangos_string` VALUES (168,'Locations found are:\n %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (169,'Mail sent to %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (170,'You try to hear sound %u but it doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(171,'You are being teleported by server console command.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(172,'server console command',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (200,'No selection.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (201,'Object GUID is: lowpart %u highpart %X',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (202,'The name was too long by %i characters.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), diff --git a/sql/updates/2008_10_28_01_mangos_mangos_string.sql b/sql/updates/2008_10_28_01_mangos_mangos_string.sql new file mode 100644 index 000000000..fa325bb94 --- /dev/null +++ b/sql/updates/2008_10_28_01_mangos_mangos_string.sql @@ -0,0 +1,5 @@ +DELETE FROM mangos_string WHERE entry IN (171,172); + +INSERT INTO mangos_string VALUES +(172,'server console command',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 625788f8a..72f060399 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -1194,6 +1194,17 @@ GameTele const* ChatHandler::extractGameTeleFromLink(char* text) return objmgr.GetGameTele(cId); } +const char *ChatHandler::GetName() const +{ + return m_session->GetPlayer()->GetName(); +} + +bool ChatHandler::needReportToTarget(Player* chr) const +{ + Player* pl = m_session->GetPlayer(); + return pl != chr && pl->IsVisibleGloballyFor(chr); +} + const char *CliHandler::GetMangosString(int32 entry) const { return objmgr.GetMangosStringForDBCLocale(entry); @@ -1210,3 +1221,14 @@ void CliHandler::SendSysMessage(const char *str) m_print(str); m_print("\r\n"); } + +const char *CliHandler::GetName() const +{ + return GetMangosString(LANG_CONSOLE_COMMAND); +} + +bool CliHandler::needReportToTarget(Player* /*chr*/) const +{ + return true; +} + diff --git a/src/game/Chat.h b/src/game/Chat.h index 6006bfa76..dbdd4b5c5 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -69,12 +69,14 @@ class ChatHandler int ParseCommands(const char* text); + virtual char const* GetName() const; protected: explicit ChatHandler() : m_session(NULL) {} // for CLI subclass bool hasStringAbbr(const char* name, const char* part); virtual bool isAvailable(ChatCommand const& cmd) const; + virtual bool needReportToTarget(Player* chr) const; void SendGlobalSysMessage(const char *str); @@ -455,6 +457,8 @@ class CliHandler : public ChatHandler const char *GetMangosString(int32 entry) const; bool isAvailable(ChatCommand const& cmd) const; void SendSysMessage(const char *str); + char const* GetName() const; + bool needReportToTarget(Player* chr) const; private: Print* m_print; diff --git a/src/game/Language.h b/src/game/Language.h index e512d297b..4815a6e8d 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -166,8 +166,9 @@ enum MangosStrings LANG_MAIL_SENT = 169, LANG_SOUND_NOT_EXIST = 170, - LANG_TELEPORTED_TO_BY_CONSOLE = 171, - // Room for more level 1 172-199 not used + // 171, // not used + LANG_CONSOLE_COMMAND = 172, + // Room for more level 1 173-199 not used // level 2 chat LANG_NO_SELECTION = 200, diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 243e39340..56e805f5b 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -309,9 +309,10 @@ bool ChatHandler::HandleGPSCommand(const char* args) zone_x, zone_y, ground_z, floor_z, have_map, have_vmap ); sLog.outDebug("Player %s GPS call for %s '%s' (%s: %u):", - m_session->GetPlayer()->GetName(), + GetName(), (obj->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), obj->GetName(), (obj->GetTypeId() == TYPEID_PLAYER ? "GUID" : "Entry"), (obj->GetTypeId() == TYPEID_PLAYER ? obj->GetGUIDLow(): obj->GetEntry()) ); + sLog.outDebug(GetMangosString(LANG_MAP_POSITION), obj->GetMapId(), (mapEntry ? mapEntry->name[sWorld.GetDefaultDbcLocale()] : "" ), zone_id, (zoneEntry ? zoneEntry->area_name[sWorld.GetDefaultDbcLocale()] : "" ), @@ -374,9 +375,8 @@ bool ChatHandler::HandleNamegoCommand(const char* args) } PSendSysMessage(LANG_SUMMONING, chr->GetName(),""); - - if (m_session->GetPlayer()->IsVisibleGloballyFor(chr)) - ChatHandler(chr).PSendSysMessage(LANG_SUMMONED_BY, m_session->GetPlayer()->GetName()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_SUMMONED_BY, GetName()); // stop flight if need if(chr->isInFlight()) @@ -655,7 +655,8 @@ bool ChatHandler::HandleModifyHPCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_HP, chr->GetName(), hp, hpm); - ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, m_session->GetPlayer()->GetName(), hp, hpm); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, GetName(), hp, hpm); chr->SetMaxHealth( hpm ); chr->SetHealth( hp ); @@ -698,7 +699,8 @@ bool ChatHandler::HandleModifyManaCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_MANA, chr->GetName(), mana, manam); - ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, m_session->GetPlayer()->GetName(), mana, manam); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, GetName(), mana, manam); chr->SetMaxPower(POWER_MANA,manam ); chr->SetPower(POWER_MANA, mana ); @@ -742,7 +744,8 @@ bool ChatHandler::HandleModifyEnergyCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_ENERGY, chr->GetName(), energy/10, energym/10); - ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, m_session->GetPlayer()->GetName(), energy/10, energym/10); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, GetName(), energy/10, energym/10); chr->SetMaxPower(POWER_ENERGY,energym ); chr->SetPower(POWER_ENERGY, energy ); @@ -788,8 +791,8 @@ bool ChatHandler::HandleModifyRageCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_RAGE, chr->GetName(), rage/10, ragem/10); - // Special case: I use GetMangosString here to get local of destination char ;) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_RAGE_CHANGED), m_session->GetPlayer()->GetName(), rage/10, ragem/10); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, GetName(), rage/10, ragem/10); chr->SetMaxPower(POWER_RAGE,ragem ); chr->SetPower(POWER_RAGE, rage ); @@ -867,11 +870,6 @@ bool ChatHandler::HandleModifyFactionCommand(const char* args) PSendSysMessage(LANG_YOU_CHANGE_FACTION, chr->GetGUIDLow(),factionid,flag,npcflag,dyflag); - //sprintf((char*)buf,"%s changed your Faction to %i.", m_session->GetPlayer()->GetName(), factionid); - //FillSystemMessageData(&data, m_session, buf); - - //chr->GetSession()->SendPacket(&data); - chr->setFaction(factionid); chr->SetUInt32Value(UNIT_FIELD_FLAGS,flag); chr->SetUInt32Value(UNIT_NPC_FLAGS,npcflag); @@ -917,8 +915,8 @@ bool ChatHandler::HandleModifySpellCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_SPELLFLATID, spellflatid, val, mark, chr->GetName()); - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, m_session->GetPlayer()->GetName(), spellflatid, val, mark); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, GetName(), spellflatid, val, mark); WorldPacket data(SMSG_SET_FLAT_SPELL_MODIFIER, (1+1+2+2)); data << uint8(spellflatid); @@ -974,10 +972,8 @@ bool ChatHandler::HandleTaxiCheatCommand(const char* args) { chr->SetTaxiCheater(true); PSendSysMessage(LANG_YOU_GIVE_TAXIS, chr->GetName()); - - if(chr != m_session->GetPlayer()) - // to send localized data to target - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_TAXIS_ADDED), m_session->GetPlayer()->GetName()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, GetName()); return true; } @@ -985,9 +981,8 @@ bool ChatHandler::HandleTaxiCheatCommand(const char* args) { chr->SetTaxiCheater(false); PSendSysMessage(LANG_YOU_REMOVE_TAXIS, chr->GetName()); - - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_TAXIS_REMOVED), m_session->GetPlayer()->GetName()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, GetName()); return true; } @@ -1028,9 +1023,8 @@ bool ChatHandler::HandleModifyASpeedCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_ASPEED, ASpeed, chr->GetName()); - - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_ASPEED_CHANGED), m_session->GetPlayer()->GetName(), ASpeed); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, GetName(), ASpeed); chr->SetSpeed(MOVE_WALK, ASpeed,true); chr->SetSpeed(MOVE_RUN, ASpeed,true); @@ -1071,9 +1065,8 @@ bool ChatHandler::HandleModifySpeedCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_SPEED, Speed, chr->GetName()); - - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_SPEED_CHANGED), m_session->GetPlayer()->GetName(), Speed); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, GetName(), Speed); chr->SetSpeed(MOVE_RUN,Speed,true); @@ -1111,9 +1104,8 @@ bool ChatHandler::HandleModifySwimCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, Swim, chr->GetName()); - - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_SWIM_SPEED_CHANGED), m_session->GetPlayer()->GetName(), Swim); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, GetName(), Swim); chr->SetSpeed(MOVE_SWIM,Swim,true); @@ -1151,9 +1143,8 @@ bool ChatHandler::HandleModifyBWalkCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, BSpeed, chr->GetName()); - - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_BACK_SPEED_CHANGED), m_session->GetPlayer()->GetName(), BSpeed); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetName(), BSpeed); chr->SetSpeed(MOVE_WALKBACK,BSpeed,true); @@ -1184,9 +1175,8 @@ bool ChatHandler::HandleModifyFlyCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, FSpeed, chr->GetName()); - - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_FLY_SPEED_CHANGED), m_session->GetPlayer()->GetName(), FSpeed); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetName(), FSpeed); chr->SetSpeed(MOVE_FLY,FSpeed,true); @@ -1216,9 +1206,8 @@ bool ChatHandler::HandleModifyScaleCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, chr->GetName()); - - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_SIZE_CHANGED), m_session->GetPlayer()->GetName(), Scale); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, GetName(), Scale); chr->SetFloatValue(OBJECT_FIELD_SCALE_X, Scale); @@ -1460,9 +1449,8 @@ bool ChatHandler::HandleModifyMountCommand(const char* args) } PSendSysMessage(LANG_YOU_GIVE_MOUNT, chr->GetName()); - - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_MOUNT_GIVED), m_session->GetPlayer()->GetName()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_MOUNT_GIVED, GetName()); chr->SetUInt32Value( UNIT_FIELD_FLAGS , 0x001000 ); chr->Mount(mId); @@ -1509,25 +1497,24 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args) if(newmoney <= 0 ) { PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, chr->GetName()); - - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_ALL_MONEY_GONE), m_session->GetPlayer()->GetName()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, GetName()); chr->SetMoney(0); } else { PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), chr->GetName()); - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_MONEY_TAKEN), m_session->GetPlayer()->GetName(), abs(addmoney)); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetName(), abs(addmoney)); chr->SetMoney( newmoney ); } } else { PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, chr->GetName()); - if(chr != m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetMangosString(LANG_YOURS_MONEY_GIVEN), m_session->GetPlayer()->GetName(), addmoney); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetName(), addmoney); chr->ModifyMoney( addmoney ); } @@ -2020,14 +2007,8 @@ bool ChatHandler::HandleNameTeleCommand(const char * args) } PSendSysMessage(LANG_TELEPORTING_TO, chr->GetName(),"", tele->name.c_str()); - - if (m_session) - { - if(m_session->GetPlayer()->IsVisibleGloballyFor(chr)) - ChatHandler(chr).PSendSysMessage(LANG_TELEPORTED_TO_BY, m_session->GetPlayer()->GetName()); - } - else - ChatHandler(chr).SendSysMessage(LANG_TELEPORTED_TO_BY_CONSOLE); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetName()); // stop flight if need if(chr->isInFlight()) @@ -2097,9 +2078,8 @@ bool ChatHandler::HandleGroupTeleCommand(const char * args) } PSendSysMessage(LANG_TELEPORTING_TO, pl->GetName(),"", tele->name.c_str()); - - if (m_session->GetPlayer() != pl && m_session->GetPlayer()->IsVisibleGloballyFor(pl)) - ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, m_session->GetPlayer()->GetName()); + if (needReportToTarget(pl)) + ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetName()); // stop flight if need if(pl->isInFlight()) @@ -2191,9 +2171,8 @@ bool ChatHandler::HandleGroupgoCommand(const char* args) } PSendSysMessage(LANG_SUMMONING, pl->GetName(),""); - - if (m_session->GetPlayer()->IsVisibleGloballyFor(pl)) - ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, m_session->GetPlayer()->GetName()); + if (needReportToTarget(pl)) + ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, GetName()); // stop flight if need if(pl->isInFlight()) diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 71e67ecdf..cdd22d478 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -741,7 +741,7 @@ bool ChatHandler::HandleAccountSetGmLevelCommand(const char* args) if(targetPlayer) { - ChatHandler(targetPlayer).PSendSysMessage(LANG_YOURS_SECURITY_CHANGED,m_session->GetPlayer()->GetName(), gm); + ChatHandler(targetPlayer).PSendSysMessage(LANG_YOURS_SECURITY_CHANGED,GetName(), gm); targetPlayer->GetSession()->SetSecurity(gm); } @@ -3680,14 +3680,14 @@ bool ChatHandler::HandleExploreCheatCommand(const char* args) if (flag != 0) { PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, chr->GetName()); - if(chr!=m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,m_session->GetPlayer()->GetName()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,GetName()); } else { PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, chr->GetName()); - if(chr!=m_session->GetPlayer()) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,m_session->GetPlayer()->GetName()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,GetName()); } for (uint8 i=0; i<128; i++) From e98a123027a5d4ec536a001a921ca8ecc07008d0 Mon Sep 17 00:00:00 2001 From: dythzer Date: Sun, 26 Oct 2008 18:11:12 +0100 Subject: [PATCH 6/9] Added new command: .repairitems - repairs all items of selected player Signed-off-by: VladimirMangos --- sql/mangos.sql | 3 +++ .../2008_10_28_02_mangos_mangos_string.sql | 5 +++++ sql/updates/2008_10_28_03_mangos_command.sql | 4 ++++ sql/updates/Makefile.am | 6 ++++++ src/game/Chat.cpp | 1 + src/game/Chat.h | 1 + src/game/Language.h | 4 +++- src/game/Level2.cpp | 20 +++++++++++++++++++ 8 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 sql/updates/2008_10_28_02_mangos_mangos_string.sql create mode 100644 sql/updates/2008_10_28_03_mangos_command.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index ece5eccee..be9dc8be9 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -358,6 +358,7 @@ INSERT INTO `command` VALUES ('reload all_spell',3,'Syntax: .reload all_spell\r\n\r\nReload all `spell_*` tables with reload support added and that can be _safe_ reloaded.'), ('reload all_locales',3,'Syntax: .reload all_locales\r\n\r\nReload all `locales_*` tables with reload support added and that can be _safe_ reloaded.'), ('reload config',3,'Syntax: .reload config\r\n\r\nReload config settings (by default stored in mangosd.conf). Not all settings can be change at reload: some new setting values will be ignored until restart, some values will applied with delay or only to new objects/maps, some values will explicitly rejected to change at reload.'), +('repairitems',2,'Syntax: .repairitems\r\n\r\nRepair all selected player''s items.'), ('reset all',3,'Syntax: .reset all spells\r\n\r\nSyntax: .reset all talents\r\n\r\nRequest reset spells or talents at next login each existed character.'), ('reset honor',3,'Syntax:\r\n.reset honor [Playername]\r\n Reset all honor data for targeted character.'), ('reset level',3,'Syntax:\r\n.reset level [Playername]\r\n Reset level to 1 including reset stats and talents. Equipped items with greater level requirement can be lost.'), @@ -2403,6 +2404,8 @@ INSERT INTO `mangos_string` VALUES (333,'GM mode is OFF',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (334,'GM Chat Badge is ON',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (335,'GM Chat Badge is OFF',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(336,'You repair all %s''s items.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(337,'All your items repaired by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (401,'You change security level of account %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (402,'%s changed your security level to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), diff --git a/sql/updates/2008_10_28_02_mangos_mangos_string.sql b/sql/updates/2008_10_28_02_mangos_mangos_string.sql new file mode 100644 index 000000000..16f340532 --- /dev/null +++ b/sql/updates/2008_10_28_02_mangos_mangos_string.sql @@ -0,0 +1,5 @@ +DELETE FROM mangos_string WHERE entry IN (336,337); + +INSERT INTO mangos_string VALUES +(336,'You repair all %s''s items.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(337,'All your items repaired by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/2008_10_28_03_mangos_command.sql b/sql/updates/2008_10_28_03_mangos_command.sql new file mode 100644 index 000000000..438f6e746 --- /dev/null +++ b/sql/updates/2008_10_28_03_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM command WHERE name IN ('repairitems'); + +INSERT INTO command VALUES +('repairitems',2,'Syntax: .repairitems\r\n\r\nRepair all selected player''s items.'); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 5acb7d68d..1703688e8 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -109,6 +109,9 @@ pkgdata_DATA = \ 2008_10_26_01_mangos_mangos_string.sql \ 2008_10_27_01_npc_option.sql \ 2008_10_27_02_locales_npc_option.sql \ + 2008_10_28_01_mangos_mangos_string.sql \ + 2008_10_28_02_mangos_mangos_string.sql \ + 2008_10_28_03_mangos_command.sql \ README ## Additional files to include when running 'make dist' @@ -199,4 +202,7 @@ EXTRA_DIST = \ 2008_10_26_01_mangos_mangos_string.sql \ 2008_10_27_01_npc_option.sql \ 2008_10_27_02_locales_npc_option.sql \ + 2008_10_28_01_mangos_mangos_string.sql \ + 2008_10_28_02_mangos_mangos_string.sql \ + 2008_10_28_03_mangos_command.sql \ README diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 72f060399..ad7b396af 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -527,6 +527,7 @@ ChatCommand * ChatHandler::getCommandTable() { "combatstop", SEC_GAMEMASTER, false, &ChatHandler::HandleCombatStopCommand, "", NULL }, { "chardelete", SEC_CONSOLE, true, &ChatHandler::HandleCombatStopCommand, "", NULL }, { "sendmessage", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMessageCommand, "", NULL }, + { "repairitems", SEC_GAMEMASTER, false, &ChatHandler::HandleRepairitemsCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; diff --git a/src/game/Chat.h b/src/game/Chat.h index dbdd4b5c5..402284399 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -406,6 +406,7 @@ class ChatHandler bool HandleComeToMeCommand(const char *args); bool HandleCombatStopCommand(const char *args); bool HandleSendMessageCommand(const char * args); + bool HandleRepairitemsCommand(const char* args); //! Development Commands bool HandleSetValue(const char* args); diff --git a/src/game/Language.h b/src/game/Language.h index 4815a6e8d..21a93cc15 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -317,7 +317,9 @@ enum MangosStrings LANG_GM_OFF = 333, LANG_GM_CHAT_ON = 334, LANG_GM_CHAT_OFF = 335, - // Room for more level 2 336-399 not used + LANG_YOU_REPAIR_ITEMS = 336, + LANG_YOUR_ITEMS_REPAIRED = 337, + // Room for more level 2 338-399 not used // level 3 chat LANG_SCRIPTS_RELOADED = 400, diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 81ac177d8..8a3d434f7 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -4047,3 +4047,23 @@ bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/) CorpsesErase(); return true; } + +bool ChatHandler::HandleRepairitemsCommand(const char* args) +{ + Player *target = getSelectedPlayer(); + + if(!target) + { + PSendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // Repair items + target->DurabilityRepairAll(false, 0, false); + + PSendSysMessage(LANG_YOU_REPAIR_ITEMS, target->GetName()); + if(needReportToTarget(target)) + ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetName()); + return true; +} From 4db0c0018182135122792dda084e4145a4258ba5 Mon Sep 17 00:00:00 2001 From: Seline Date: Tue, 28 Oct 2008 01:42:26 +0100 Subject: [PATCH 7/9] Use .respawn only for selected creature (if any) If no creature is selected, old behavior is used (respawn everything). Thanks Seline for the diff. Signed-off-by: freghar (cherry picked from commit 6bbdffac9acb9c02a74be632b35a90f0bda3ccb0) Signed-off-by: VladimirMangos Some changes in creature targeting and work in case alive target. Help data updated. Signed-off-by: VladimirMangos --- sql/mangos.sql | 2 +- sql/updates/2008_10_28_04_mangos_command.sql | 4 ++++ sql/updates/Makefile.am | 2 ++ src/game/Level3.cpp | 16 ++++++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 sql/updates/2008_10_28_04_mangos_command.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index be9dc8be9..8e3e149a3 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -365,7 +365,7 @@ INSERT INTO `command` VALUES ('reset spells',3,'Syntax:\r\n.reset spells [Playername]\r\n Removes all non-original spells from spellbook.\r\n. Playername can be name of offline character.'), ('reset stats',3,'Syntax:\r\n.reset stats [Playername]\r\n Resets(recalculate) all stats of the targeted player to their original VALUESat current level.'), ('reset talents',3,'Syntax:\r\n.reset talents [Playername]\r\n Removes all talents of the targeted player. Playername can be name of offline character.'), -('respawn',3,'Syntax: .respawn\r\n\r\nRespawn all nearest creatures and GO without waiting respawn time expiration.'), +('respawn',3,'Syntax: .respawn\r\n\r\nRespawn selected creature or respawn all nearest creatures (if none selected) and GO without waiting respawn time expiration.'), ('revive',3,'Syntax: .revive\r\n\r\nRevive the selected player. If no player is selected, it will revive you.'), ('save',0,'Syntax: .save\r\n\r\nSaves your character.'), ('saveall',1,'Syntax: .saveall\r\n\r\nSave all characters in game.'), diff --git a/sql/updates/2008_10_28_04_mangos_command.sql b/sql/updates/2008_10_28_04_mangos_command.sql new file mode 100644 index 000000000..c1758fc58 --- /dev/null +++ b/sql/updates/2008_10_28_04_mangos_command.sql @@ -0,0 +1,4 @@ +DELETE FROM command WHERE name IN ('respawn'); + +INSERT INTO command VALUES +('respawn',3,'Syntax: .respawn\r\n\r\nRespawn selected creature or respawn all nearest creatures (if none selected) and GO without waiting respawn time expiration.'); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 1703688e8..1829616e2 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -112,6 +112,7 @@ pkgdata_DATA = \ 2008_10_28_01_mangos_mangos_string.sql \ 2008_10_28_02_mangos_mangos_string.sql \ 2008_10_28_03_mangos_command.sql \ + 2008_10_28_04_mangos_command.sql \ README ## Additional files to include when running 'make dist' @@ -205,4 +206,5 @@ EXTRA_DIST = \ 2008_10_28_01_mangos_mangos_string.sql \ 2008_10_28_02_mangos_mangos_string.sql \ 2008_10_28_03_mangos_command.sql \ + 2008_10_28_04_mangos_command.sql \ README diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index cdd22d478..2129c41b1 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -5315,6 +5315,22 @@ bool ChatHandler::HandleBanListIPCommand(const char* args) bool ChatHandler::HandleRespawnCommand(const char* /*args*/) { + Unit* target = getSelectedUnit(); + + if(target) + { + if(target->GetTypeId()!=TYPEID_UNIT) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if(target->isDead()) + ((Creature*)target)->Respawn(); + return true; + } + Player* pl = m_session->GetPlayer(); CellPair p(MaNGOS::ComputeCellPair(pl->GetPositionX(), pl->GetPositionY())); From 454ff6e667147d75dbaf7ce08548bfa25a6bc9c0 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 28 Oct 2008 17:41:15 +0300 Subject: [PATCH 8/9] Add *.user to all Visual Stidio versions .gitignore --- win/VC71/.gitignore | 1 + win/VC80/.gitignore | 1 + win/VC90/.gitignore | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/win/VC71/.gitignore b/win/VC71/.gitignore index c0bac5034..5c035e465 100644 --- a/win/VC71/.gitignore +++ b/win/VC71/.gitignore @@ -14,3 +14,4 @@ *__x64_Debug* *__Win32_Release* *__x64_Release* +*.user diff --git a/win/VC80/.gitignore b/win/VC80/.gitignore index c0bac5034..5c035e465 100644 --- a/win/VC80/.gitignore +++ b/win/VC80/.gitignore @@ -14,3 +14,4 @@ *__x64_Debug* *__Win32_Release* *__x64_Release* +*.user diff --git a/win/VC90/.gitignore b/win/VC90/.gitignore index 9123b0a96..5c035e465 100644 --- a/win/VC90/.gitignore +++ b/win/VC90/.gitignore @@ -14,4 +14,4 @@ *__x64_Debug* *__Win32_Release* *__x64_Release* -*.user \ No newline at end of file +*.user From 61b2b3d2341456a8423ffc8a97466a33299232de Mon Sep 17 00:00:00 2001 From: ApoC Date: Sat, 25 Oct 2008 20:51:40 +0200 Subject: [PATCH 9/9] Prevent adding more than 5 people into RAID subgroup. Optimized free subgroup in raid finding. Optimized method calls, now using const uint64& instead of value passing. Signed-off-by: ApoC --- src/game/Group.cpp | 79 +++++++++++++++++++++++++++++---------- src/game/Group.h | 60 ++++++++++++++++++++++------- src/game/GroupHandler.cpp | 3 ++ 3 files changed, 109 insertions(+), 33 deletions(-) diff --git a/src/game/Group.cpp b/src/game/Group.cpp index eade6412d..d850fcfee 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -42,6 +42,7 @@ Group::Group() m_lootMethod = (LootMethod)0; m_looterGuid = 0; m_lootThreshold = ITEM_QUALITY_UNCOMMON; + m_subGroupsCounts = NULL; for(int i=0; isecond.save->RemoveGroup(this); + + // Sub group counters clean up + if (m_subGroupsCounts) + delete[] m_subGroupsCounts; } bool Group::Create(const uint64 &guid, const char * name) @@ -79,6 +84,10 @@ bool Group::Create(const uint64 &guid, const char * name) m_leaderName = name; m_groupType = isBGGroup() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL; + + if (m_groupType == GROUPTYPE_RAID) + _initRaidSubGroupsCounter(); + m_lootMethod = GROUP_LOOT; m_lootThreshold = ITEM_QUALITY_UNCOMMON; m_looterGuid = guid; @@ -134,6 +143,10 @@ bool Group::LoadGroupFromDB(const uint64 &leaderGuid, QueryResult *result, bool } m_groupType = (*result)[13].GetBool() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL; + + if (m_groupType == GROUPTYPE_RAID) + _initRaidSubGroupsCounter(); + m_difficulty = (*result)[14].GetUInt8(); m_mainTank = (*result)[0].GetUInt64(); m_mainAssistant = (*result)[1].GetUInt64(); @@ -176,6 +189,9 @@ bool Group::LoadMemberFromDB(uint32 guidLow, uint8 subgroup, bool assistant) member.group = subgroup; member.assistant = assistant; m_memberSlots.push_back(member); + + SubGroupCounterIncrease(subgroup); + return true; } @@ -384,7 +400,7 @@ void Group::SendLootStartRoll(uint32 CountDown, const Roll &r) } } -void Group::SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) +void Group::SendLootRoll(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) { WorldPacket data(SMSG_LOOT_ROLL, (8+4+8+4+4+4+1+1)); data << uint64(SourceGuid); // guid of the item rolled @@ -408,7 +424,7 @@ void Group::SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, } } -void Group::SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) +void Group::SendLootRollWon(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) { WorldPacket data(SMSG_LOOT_ROLL_WON, (8+4+4+4+4+8+1+1)); data << uint64(SourceGuid); // guid of the item rolled @@ -451,7 +467,7 @@ void Group::SendLootAllPassed(uint32 NumberOfPlayers, const Roll &r) } } -void Group::GroupLoot(uint64 playerGUID, Loot *loot, Creature *creature) +void Group::GroupLoot(const uint64& playerGUID, Loot *loot, Creature *creature) { std::vector::iterator i; ItemPrototype const *item; @@ -507,7 +523,7 @@ void Group::GroupLoot(uint64 playerGUID, Loot *loot, Creature *creature) } } -void Group::NeedBeforeGreed(uint64 playerGUID, Loot *loot, Creature *creature) +void Group::NeedBeforeGreed(const uint64& playerGUID, Loot *loot, Creature *creature) { ItemPrototype const *item; Player *player = objmgr.GetPlayer(playerGUID); @@ -561,7 +577,7 @@ void Group::NeedBeforeGreed(uint64 playerGUID, Loot *loot, Creature *creature) } } -void Group::MasterLoot(uint64 playerGUID, Loot* /*loot*/, Creature *creature) +void Group::MasterLoot(const uint64& playerGUID, Loot* /*loot*/, Creature *creature) { Player *player = objmgr.GetPlayer(playerGUID); if(!player) @@ -597,7 +613,7 @@ void Group::MasterLoot(uint64 playerGUID, Loot* /*loot*/, Creature *creature) } } -void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise) +void Group::CountRollVote(const uint64& playerGUID, const uint64& Guid, uint32 NumberOfPlayers, uint8 Choise) { Rolls::iterator rollI = GetRoll(Guid); if (rollI == RollId.end()) @@ -929,13 +945,20 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant) { // get first not-full group uint8 groupid = 0; - std::vector temp(MAXRAIDSIZE/MAXGROUPSIZE); - for(member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr) + if (m_subGroupsCounts) { - if (itr->group >= temp.size()) continue; - ++temp[itr->group]; - if(temp[groupid] >= MAXGROUPSIZE) - ++groupid; + bool groupFound = false; + for (; groupid < MAXRAIDSIZE/MAXGROUPSIZE; ++groupid) + { + if (m_subGroupsCounts[groupid] < MAXGROUPSIZE) + { + groupFound = true; + break; + } + } + // We are raid group and no one slot is free + if (!groupFound) + return false; } return _addMember(guid, name, isAssistant, groupid); @@ -958,6 +981,8 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant, u member.assistant = isAssistant; m_memberSlots.push_back(member); + SubGroupCounterIncrease(group); + if(player) { player->SetGroupInvite(NULL); @@ -995,7 +1020,11 @@ bool Group::_removeMember(const uint64 &guid) member_witerator slot = _getMemberWSlot(guid); if (slot != m_memberSlots.end()) + { + SubGroupCounterDecrease(slot->group); + m_memberSlots.erase(slot); + } if(!isBGGroup()) CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid='%u'", GUID_LOPART(guid)); @@ -1088,13 +1117,6 @@ void Group::_removeRolls(const uint64 &guid) } } -void Group::_convertToRaid() -{ - m_groupType = GROUPTYPE_RAID; - - if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid)); -} - bool Group::_setMembersGroup(const uint64 &guid, const uint8 &group) { member_witerator slot = _getMemberWSlot(guid); @@ -1102,7 +1124,11 @@ bool Group::_setMembersGroup(const uint64 &guid, const uint8 &group) return false; slot->group = group; + + SubGroupCounterIncrease(group); + if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE group_member SET subgroup='%u' WHERE memberGuid='%u'", group, GUID_LOPART(guid)); + return true; } @@ -1156,12 +1182,20 @@ void Group::ChangeMembersGroup(const uint64 &guid, const uint8 &group) if(!isRaidGroup()) return; Player *player = objmgr.GetPlayer(guid); + if (!player) { + uint8 prevSubGroup; + prevSubGroup = GetMemberGroup(guid); + + SubGroupCounterDecrease(prevSubGroup); + if(_setMembersGroup(guid, group)) SendUpdate(); } - else ChangeMembersGroup(player, group); + else + // This methods handles itself groupcounter decrease + ChangeMembersGroup(player, group); } // only for online members @@ -1171,6 +1205,11 @@ void Group::ChangeMembersGroup(Player *player, const uint8 &group) return; if(_setMembersGroup(player->GetGUID(), group)) { + uint8 prevSubGroup; + prevSubGroup = player->GetSubGroup(); + + SubGroupCounterDecrease(prevSubGroup); + player->GetGroupRef().setSubGroup(group); SendUpdate(); } diff --git a/src/game/Group.h b/src/game/Group.h index 0dc7135e7..c3e7585a0 100644 --- a/src/game/Group.h +++ b/src/game/Group.h @@ -181,8 +181,8 @@ class MANGOS_DLL_SPEC Group ItemQualities GetLootThreshold() const { return m_lootThreshold; } // member manipulation methods - bool IsMember(uint64 guid) const { return _getMemberCSlot(guid) != m_memberSlots.end(); } - bool IsLeader(uint64 guid) const { return (GetLeaderGUID() == guid); } + bool IsMember(const uint64& guid) const { return _getMemberCSlot(guid) != m_memberSlots.end(); } + bool IsLeader(const uint64& guid) const { return (GetLeaderGUID() == guid); } bool IsAssistant(uint64 guid) const { member_citerator mslot = _getMemberCSlot(guid); @@ -192,7 +192,7 @@ class MANGOS_DLL_SPEC Group return mslot->assistant; } - bool SameSubGroup(uint64 guid1, uint64 guid2) const + bool SameSubGroup(uint64 guid1,const uint64& guid2) const { member_citerator mslot2 = _getMemberCSlot(guid2); if(mslot2==m_memberSlots.end()) @@ -210,6 +210,11 @@ class MANGOS_DLL_SPEC Group return (mslot1->group==slot2->group); } + bool HasFreeSlotSubGroup(uint8 subgroup) const + { + return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAXGROUPSIZE); + } + bool SameSubGroup(Player const* member1, Player const* member2) const; MemberSlotList const& GetMemberSlots() const { return m_memberSlots; } @@ -228,7 +233,11 @@ class MANGOS_DLL_SPEC Group // some additional raid methods void ConvertToRaid() { - _convertToRaid(); + m_groupType = GROUPTYPE_RAID; + + _initRaidSubGroupsCounter(); + + if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid)); SendUpdate(); } void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; } @@ -236,14 +245,14 @@ class MANGOS_DLL_SPEC Group void ChangeMembersGroup(const uint64 &guid, const uint8 &group); void ChangeMembersGroup(Player *player, const uint8 &group); - void SetAssistant(const uint64 &guid, const bool &state) + void SetAssistant(uint64 guid, const bool &state) { if(!isRaidGroup()) return; if(_setAssistantFlag(guid, state)) SendUpdate(); } - void SetMainTank(const uint64 &guid) + void SetMainTank(uint64 guid) { if(!isRaidGroup()) return; @@ -251,7 +260,7 @@ class MANGOS_DLL_SPEC Group if(_setMainTank(guid)) SendUpdate(); } - void SetMainAssistant(const uint64 &guid) + void SetMainAssistant(uint64 guid) { if(!isRaidGroup()) return; @@ -282,12 +291,12 @@ class MANGOS_DLL_SPEC Group /*********************************************************/ void SendLootStartRoll(uint32 CountDown, const Roll &r); - void SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); - void SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); + void SendLootRoll(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); + void SendLootRollWon(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); void SendLootAllPassed(uint32 NumberOfPlayers, const Roll &r); - void GroupLoot(uint64 playerGUID, Loot *loot, Creature *creature); - void NeedBeforeGreed(uint64 playerGUID, Loot *loot, Creature *creature); - void MasterLoot(uint64 playerGUID, Loot *loot, Creature *creature); + void GroupLoot(const uint64& playerGUID, Loot *loot, Creature *creature); + void NeedBeforeGreed(const uint64& playerGUID, Loot *loot, Creature *creature); + void MasterLoot(const uint64& playerGUID, Loot *loot, Creature *creature); Rolls::iterator GetRoll(uint64 Guid) { Rolls::iterator iter; @@ -301,7 +310,7 @@ class MANGOS_DLL_SPEC Group return RollId.end(); } void CountTheRoll(Rolls::iterator roll, uint32 NumberOfPlayers); - void CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise); + void CountRollVote(const uint64& playerGUID, const uint64& Guid, uint32 NumberOfPlayers, uint8 Choise); void EndRoll(); void LinkMember(GroupReference *pRef) { m_memberMgr.insertFirst(pRef); } @@ -328,6 +337,18 @@ class MANGOS_DLL_SPEC Group void _homebindIfInstance(Player *player); + void _initRaidSubGroupsCounter() + { + // Sub group counters initialization + if (!m_subGroupsCounts) + m_subGroupsCounts = new uint8[MAXRAIDSIZE / MAXGROUPSIZE]; + + memset((void*)m_subGroupsCounts, 0, (MAXRAIDSIZE / MAXGROUPSIZE)*sizeof(uint8)); + + for (member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr) + ++m_subGroupsCounts[itr->group]; + } + member_citerator _getMemberCSlot(uint64 Guid) const { for(member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr) @@ -348,6 +369,18 @@ class MANGOS_DLL_SPEC Group return m_memberSlots.end(); } + void SubGroupCounterIncrease(uint8 subgroup) + { + if (m_subGroupsCounts) + ++m_subGroupsCounts[subgroup]; + } + + void SubGroupCounterDecrease(uint8 subgroup) + { + if (m_subGroupsCounts) + --m_subGroupsCounts[subgroup]; + } + MemberSlotList m_memberSlots; GroupRefManager m_memberMgr; InvitesList m_invitees; @@ -364,5 +397,6 @@ class MANGOS_DLL_SPEC Group uint64 m_looterGuid; Rolls RollId; BoundInstancesMap m_boundInstances[TOTAL_DIFFICULTIES]; + uint8* m_subGroupsCounts; }; #endif diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index 5695f1290..780198c02 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -543,6 +543,9 @@ void WorldSession::HandleGroupChangeSubGroupOpcode( WorldPacket & recv_data ) /** error handling **/ if(!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) return; + + if (!group->HasFreeSlotSubGroup(groupNr)) + return; /********************/ // everything's fine, do it