diff --git a/sql/characters.sql b/sql/characters.sql index 6f461f6c3..2cc046598 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -21,7 +21,7 @@ DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_12138_01_characters_characters` bit(1) default NULL + `required_12141_01_characters_character_currencies` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- @@ -419,6 +419,30 @@ LOCK TABLES `character_battleground_data` WRITE; /*!40000 ALTER TABLE `character_battleground_data` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `character_currencies` +-- + +DROP TABLE IF EXISTS `character_currencies`; +CREATE TABLE `character_currencies` ( + `guid` int(11) unsigned NOT NULL DEFAULT '0', + `id` smallint(5) unsigned NOT NULL DEFAULT '0', + `totalCount` int(11) unsigned NOT NULL DEFAULT '0', + `weekCount` int(11) unsigned NOT NULL DEFAULT '0', + `seasonCount` int(11) unsigned NOT NULL DEFAULT '0', + `flags` tinyint(2) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`guid`,`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_currencies` +-- + +LOCK TABLES `character_currencies` WRITE; +/*!40000 ALTER TABLE `character_currencies` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_currencies` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `character_declinedname` -- diff --git a/sql/mangos.sql b/sql/mangos.sql index 513ad76ed..0cb690581 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_12138_01_mangos_command` bit(1) default NULL + `required_12141_02_mangos_mangos_command` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -649,6 +649,7 @@ INSERT INTO `command` VALUES ('lookup achievement',2,'Syntax: .lookup $name\r\nLooks up a achievement by $namepart, and returns all matches with their quest ID\'s. Achievement shift-links generated with information about achievment state for selected player. Also for completed achievments in list show complete date.'), ('lookup area',1,'Syntax: .lookup area $namepart\r\n\r\nLooks up an area by $namepart, and returns all matches with their area ID\'s.'), ('lookup creature',3,'Syntax: .lookup creature $namepart\r\n\r\nLooks up a creature by $namepart, and returns all matches with their creature ID\'s.'), +('lookup currency',3,'Syntax: .lookup currency $namepart\r\n\r\nLooks up a currency by $namepart, and returns all matches.'), ('lookup event',2,'Syntax: .lookup event $name\r\nAttempts to find the ID of the event with the provided $name.'), ('lookup faction',3,'Syntax: .lookup faction $name\r\nAttempts to find the ID of the faction with the provided $name.'), ('lookup item',3,'Syntax: .lookup item $itemname\r\n\r\nLooks up an item by $itemname, and returns all matches with their Item ID\'s.'), @@ -666,15 +667,14 @@ INSERT INTO `command` VALUES ('lookup title',2,'Syntax: .lookup title $$namepart\r\n\r\nLooks up a title by $namepart, and returns all matches with their title ID\'s and index\'s.'), ('mailbox',3,'Syntax: .mailbox\r\n\r\nShow your mailbox content.'), ('maxskill',3,'Syntax: .maxskill\r\nSets all skills of the targeted player to their maximum VALUESfor its current level.'), -('modify arena',1,'Syntax: .modify arena #value\r\nAdd $amount arena points to the selected player.'), ('modify aspeed',1,'Syntax: .modify aspeed #rate\r\n\r\nModify all speeds -run,swim,run back,swim back- of the selected player to \"normalbase speed for this move type\"*rate. If no player is selected, modify your speed.\r\n\r\n #rate may range from 0.1 to 10.'), ('modify bwalk',1,'Syntax: .modify bwalk #rate\r\n\r\nModify the speed of the selected player while running backwards to \"normal walk back speed\"*rate. If no player is selected, modify your speed.\r\n\r\n #rate may range from 0.1 to 10.'), +('modify currency',2,'Syntax: .modify currency $id $amount\r\n\r\nAdd $amount points of currency $id to the selected player.'), ('modify drunk',1,'Syntax: .modify drunk #value\r\n Set drunk level to #value (0..100). Value 0 remove drunk state, 100 is max drunked state.'), ('modify energy',1,'Syntax: .modify energy #energy\r\n\r\nModify the energy of the selected player. If no player is selected, modify your energy.'), ('modify faction',1,'Syntax: .modify faction #factionid #flagid #npcflagid #dynamicflagid\r\n\r\nModify the faction and flags of the selected creature. Without arguments, display the faction and flags of the selected creature.'), ('modify fly', 1, 'Syntax: .modify fly #rate\r\n.fly #rate\r\n\r\nModify the flying speed of the selected player to \"normal base fly speed\"*rate. If no player is selected, modify your fly.\r\n\r\n #rate may range from 0.1 to 10.'), ('modify gender',2,'Syntax: .modify gender male/female\r\n\r\nChange gender of selected player.'), -('modify honor',1,'Syntax: .modify honor $amount\r\n\r\nAdd $amount honor points to the selected player.'), ('modify hp',1,'Syntax: .modify hp #newhp\r\n\r\nModify the hp of the selected player. If no player is selected, modify your hp.'), ('modify mana',1,'Syntax: .modify mana #newmana\r\n\r\nModify the mana of the selected player. If no player is selected, modify your mana.'), ('modify money',1,'Syntax: .modify money #money\r\n.money #money\r\n\r\nAdd or remove money to the selected player. If no player is selected, modify your money.\r\n\r\n #gold can be negative to remove money.'), @@ -3506,14 +3506,14 @@ INSERT INTO `mangos_string` VALUES (296,'Ticket deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (297,'Spawn distance changed to: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (298,'Spawn time changed to: %i',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(299,'The honor of %s was set to %u!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(299,'The currency id %u of %s was set to %u!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (300,'Your chat has been disabled for %u minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (301,'You have disabled %s\'s chat for %u minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (302,'Player\'s chat is already enabled.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (303,'Your chat has been enabled.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (304,'You have enabled %s\'s chat.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (305,'Faction %s (%u) reputation of %s was set to %5d!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(306,'The arena points of %s was set to %u!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(306,'Amount',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (307,'No faction found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (308,'Faction %i unknown!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (309,'Invalid parameter %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), @@ -3660,6 +3660,7 @@ INSERT INTO `mangos_string` VALUES (450,'Graveyard #%u already linked to zone #%u (current).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (451,'Graveyard #%u linked to zone #%u (current).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (452,'Graveyard #%u can\'t be linked to subzone or not existed zone #%u (internal error).',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(453,'No currencies found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (454,'No faction in Graveyard with id= #%u , fix your DB',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (455,'invalid team, please fix database',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (456,'any',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), diff --git a/sql/updates/12141_01_characters_character_currencies.sql b/sql/updates/12141_01_characters_character_currencies.sql new file mode 100644 index 000000000..83ae3d6a3 --- /dev/null +++ b/sql/updates/12141_01_characters_character_currencies.sql @@ -0,0 +1,12 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_12138_01_characters_characters required_12141_01_characters_character_currencies bit; + +DROP TABLE IF EXISTS `character_currencies`; +CREATE TABLE `character_currencies` ( + `guid` int(11) unsigned NOT NULL DEFAULT '0', + `id` smallint(5) unsigned NOT NULL DEFAULT '0', + `totalCount` int(11) unsigned NOT NULL DEFAULT '0', + `weekCount` int(11) unsigned NOT NULL DEFAULT '0', + `seasonCount` int(11) unsigned NOT NULL DEFAULT '0', + `flags` tinyint(2) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`guid`,`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/sql/updates/12141_01_mangos_command.sql b/sql/updates/12141_01_mangos_command.sql new file mode 100644 index 000000000..c9fbeea05 --- /dev/null +++ b/sql/updates/12141_01_mangos_command.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_12138_01_mangos_command required_12141_01_mangos_command bit; + +DELETE FROM `command` WHERE `name` IN ('modify honor', 'modify arena', 'modify currency', 'lookup currency'); +INSERT INTO `command` VALUES +('modify currency',2,'Syntax: .modify currency $id $amount\r\n\r\nAdd $amount points of currency $id to the selected player.'), +('lookup currency',3,'Syntax: .lookup currency $namepart\r\n\r\nLooks up a currency by $namepart, and returns all matches.'); \ No newline at end of file diff --git a/sql/updates/12141_02_mangos_mangos_string.sql b/sql/updates/12141_02_mangos_mangos_string.sql new file mode 100644 index 000000000..3a55fe0c1 --- /dev/null +++ b/sql/updates/12141_02_mangos_mangos_string.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_12141_01_mangos_command required_12141_02_mangos_mangos_command bit; + +DELETE FROM `mangos_string` WHERE `entry` IN (299, 306, 453); +INSERT INTO `mangos_string` VALUE +(299,'The currency id %u of %s was set to %u!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(306,'Amount',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(453,'No currencies found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 18c2c6a8e..e31c192c3 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -1042,6 +1042,15 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui progressType = PROGRESS_HIGHEST; break; } + case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY_EARNED: + { + if (!miscvalue1 || !miscvalue2 || miscvalue1 != achievementCriteria->currencyEarned.currencyId) + return; + + change = miscvalue2; + progressType = PROGRESS_ACCUMULATE; + break; + } case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if (!miscvalue1) @@ -1737,6 +1746,9 @@ uint32 AchievementMgr::GetCriteriaProgressMaxCounter(AchievementCriteriaEntry co case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE: resultValue = achievementCriteria->complete_quests_in_zone.questCount; break; + case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY_EARNED: + resultValue = achievementCriteria->currencyEarned.count; + break; case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE: case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE: resultValue = achievementCriteria->healing_done.count; diff --git a/src/game/BattleGround/BattleGroundMgr.cpp b/src/game/BattleGround/BattleGroundMgr.cpp index 83a403743..0b5e80d59 100644 --- a/src/game/BattleGround/BattleGroundMgr.cpp +++ b/src/game/BattleGround/BattleGroundMgr.cpp @@ -1764,8 +1764,8 @@ void BattleGroundMgr::DistributeArenaPoints() // update to database CharacterDatabase.PExecute("UPDATE characters SET arenaPoints = arenaPoints + '%u' WHERE guid = '%u'", plr_itr->second, plr_itr->first); // add points if player is online - if (Player* pl = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, plr_itr->first))) - pl->ModifyArenaPoints(plr_itr->second); + //if (Player* pl = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, plr_itr->first))) + // pl->ModifyArenaPoints(plr_itr->second); } PlayerPoints.clear(); diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 75e468914..5def23fb3 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -1398,3 +1398,21 @@ void WorldSession::HandleReorderCharactersOpcode(WorldPacket& recv_data) slots[i], guids[i].GetCounter(), GetAccountId()); CharacterDatabase.CommitTransaction(); } + +void WorldSession::HandleSetCurrencyFlagsOpcode(WorldPacket& recv_data) +{ + uint32 currencyId, flags; + recv_data >> flags >> currencyId; + + DEBUG_LOG("CMSG_SET_CURRENCY_FLAGS: currency: %u, flags: %u", currencyId, flags); + + if (flags & ~PLAYERCURRENCY_MASK_USED_BY_CLIENT) + { + DEBUG_LOG("CMSG_SET_CURRENCY_FLAGS: received unknown currency flags 0x%X from player %s account %u for currency %u", + flags & ~PLAYERCURRENCY_MASK_USED_BY_CLIENT, GetPlayer()->GetGuidStr().c_str(), GetAccountId(), currencyId); + } + + flags &= PLAYERCURRENCY_MASK_USED_BY_CLIENT; + GetPlayer()->SetCurrencyFlags(currencyId, uint8(flags)); +} + diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 121f6b82e..e6de5507f 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -381,6 +381,7 @@ ChatCommand* ChatHandler::getCommandTable() { "achievement", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupAchievementCommand, "", NULL }, { "area", SEC_MODERATOR, true, &ChatHandler::HandleLookupAreaCommand, "", NULL }, { "creature", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupCreatureCommand, "", NULL }, + { "currency", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupCurrencyCommand, "", NULL }, { "event", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupEventCommand, "", NULL }, { "faction", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupFactionCommand, "", NULL }, { "item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupItemCommand, "", NULL }, @@ -410,6 +411,7 @@ ChatCommand* ChatHandler::getCommandTable() static ChatCommand modifyCommandTable[] = { + { "currency", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyCurrencyCommand, "", NULL }, { "hp", SEC_MODERATOR, false, &ChatHandler::HandleModifyHPCommand, "", NULL }, { "mana", SEC_MODERATOR, false, &ChatHandler::HandleModifyManaCommand, "", NULL }, { "rage", SEC_MODERATOR, false, &ChatHandler::HandleModifyRageCommand, "", NULL }, @@ -425,9 +427,7 @@ ChatCommand* ChatHandler::getCommandTable() { "faction", SEC_MODERATOR, false, &ChatHandler::HandleModifyFactionCommand, "", NULL }, { "tp", SEC_MODERATOR, false, &ChatHandler::HandleModifyTalentCommand, "", NULL }, { "mount", SEC_MODERATOR, false, &ChatHandler::HandleModifyMountCommand, "", NULL }, - { "honor", SEC_MODERATOR, false, &ChatHandler::HandleModifyHonorCommand, "", NULL }, { "rep", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyRepCommand, "", NULL }, - { "arena", SEC_MODERATOR, false, &ChatHandler::HandleModifyArenaCommand, "", NULL }, { "drunk", SEC_MODERATOR, false, &ChatHandler::HandleModifyDrunkCommand, "", NULL }, { "standstate", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyStandStateCommand, "", NULL }, { "morph", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyMorphCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 75d866d00..ff8737efb 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -298,6 +298,7 @@ class MANGOS_DLL_SPEC ChatHandler bool HandleLookupAchievementCommand(char* args); bool HandleLookupAreaCommand(char* args); bool HandleLookupCreatureCommand(char* args); + bool HandleLookupCurrencyCommand(char* args); bool HandleLookupEventCommand(char* args); bool HandleLookupFactionCommand(char* args); bool HandleLookupItemCommand(char* args); @@ -329,9 +330,8 @@ class MANGOS_DLL_SPEC ChatHandler bool HandleModifyMountCommand(char* args); bool HandleModifyFactionCommand(char* args); bool HandleModifyTalentCommand(char* args); - bool HandleModifyHonorCommand(char* args); bool HandleModifyRepCommand(char* args); - bool HandleModifyArenaCommand(char* args); + bool HandleModifyCurrencyCommand(char* args); bool HandleModifyPhaseCommand(char* args); bool HandleModifyGenderCommand(char* args); @@ -660,6 +660,7 @@ class MANGOS_DLL_SPEC ChatHandler void ShowItemListHelper(uint32 itemId, int loc_idx, Player* target = NULL); void ShowQuestListHelper(uint32 questId, int32 loc_idx, Player* target = NULL); bool ShowPlayerListHelper(QueryResult* result, uint32* limit = NULL, bool title = true, bool error = true); + void ShowCurrencyListHelper(Player* target, CurrencyTypesEntry const* currency, LocaleConstant loc); void ShowSpellListHelper(Player* target, SpellEntry const* spellInfo, LocaleConstant loc); void ShowPoolListHelper(uint16 pool_id); void ShowTicket(GMTicket const* ticket); diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 6e94c274f..72086356f 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -133,6 +133,13 @@ struct AchievementCriteriaEntry uint32 questCount; // 4 } complete_quests_in_zone; + // ACHIEVEMENT_CRITERIA_TYPE_CURRENCY_EARNED = 12 + struct + { + uint32 currencyId; // 3 + uint32 count; // 4 + } currencyEarned; + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14 struct { diff --git a/src/game/Language.h b/src/game/Language.h index fe78a11bd..f1121d44e 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -287,7 +287,7 @@ enum MangosStrings LANG_COMMAND_TICKETDEL = 296, LANG_COMMAND_SPAWNDIST = 297, LANG_COMMAND_SPAWNTIME = 298, - LANG_COMMAND_MODIFY_HONOR = 299, + LANG_COMMAND_MODIFY_CURRENCY = 299, LANG_YOUR_CHAT_DISABLED = 300, LANG_YOU_DISABLE_CHAT = 301, @@ -296,7 +296,7 @@ enum MangosStrings LANG_YOU_ENABLE_CHAT = 304, LANG_COMMAND_MODIFY_REP = 305, - LANG_COMMAND_MODIFY_ARENA = 306, + LANG_CURRENCY_AMOUNT = 306, LANG_COMMAND_FACTION_NOTFOUND = 307, LANG_COMMAND_FACTION_UNKNOWN = 308, LANG_COMMAND_FACTION_INVPARAM = 309, @@ -452,7 +452,7 @@ enum MangosStrings LANG_COMMAND_GRAVEYARDALRLINKED = 450, LANG_COMMAND_GRAVEYARDLINKED = 451, LANG_COMMAND_GRAVEYARDWRONGZONE = 452, - // = 453, + LANG_COMMAND_NOCURRENCYFOUND = 453, LANG_COMMAND_GRAVEYARDERROR = 454, LANG_COMMAND_GRAVEYARD_NOTEAM = 455, LANG_COMMAND_GRAVEYARD_ANY = 456, diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 1d4e580ac..6e852f868 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -1562,32 +1562,6 @@ bool ChatHandler::HandleModifyMoneyCommand(char* args) return true; } -bool ChatHandler::HandleModifyHonorCommand(char* args) -{ - if (!*args) - return false; - - Player* target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target)) - return false; - - int32 amount = (int32)atoi(args); - - target->ModifyHonorPoints(amount); - - PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, GetNameLink(target).c_str(), target->GetHonorPoints()); - - return true; -} - bool ChatHandler::HandleTeleCommand(char* args) { if (!*args) diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index afa11572e..a25f78d8d 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3308,6 +3308,32 @@ bool ChatHandler::HandleLookupSkillCommand(char* args) return true; } +void ChatHandler::ShowCurrencyListHelper(Player* target, CurrencyTypesEntry const* currency, LocaleConstant loc) +{ + uint32 id = currency->ID; + + uint32 count = target ? target->GetCurrencyCount(id) : 0; + + uint32 talentCost = GetTalentSpellCost(id); + + // send spell in "id - [name] (Amount: x)" format + std::ostringstream ss; + if (m_session) + ss << id << " - |cff00aa00|Hcurrency:" << id << "|h[" << currency->name[loc]; + else + ss << id << " - " << currency->name[loc]; + + if (m_session) + ss << " " << localeNames[loc] << "]|h|r"; + else + ss << " " << localeNames[loc]; + + if (target) + ss << " (" << GetMangosString(LANG_CURRENCY_AMOUNT) << ": " << count << ")"; + + SendSysMessage(ss.str().c_str()); +} + void ChatHandler::ShowSpellListHelper(Player* target, SpellEntry const* spellInfo, LocaleConstant loc) { uint32 id = spellInfo->Id; @@ -3356,6 +3382,65 @@ void ChatHandler::ShowSpellListHelper(Player* target, SpellEntry const* spellInf SendSysMessage(ss.str().c_str()); } +bool ChatHandler::HandleLookupCurrencyCommand(char* args) +{ + if (!*args) + return false; + + // can be NULL at console call + Player* target = getSelectedPlayer(); + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart, wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + uint32 counter = 0; // Counter for figure out that we found smth. + + // Search in CurrencyTypes.dbc + for (uint32 id = 0; id < sCurrencyTypesStore.GetNumRows(); ++id) + { + CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(id); + if (currency) + { + int loc = GetSessionDbcLocale(); + std::string name = currency->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = currency->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + ShowCurrencyListHelper(target, currency, LocaleConstant(loc)); + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + SendSysMessage(LANG_COMMAND_NOCURRENCYFOUND); + return true; +} + bool ChatHandler::HandleLookupSpellCommand(char* args) { if (!*args) @@ -3952,11 +4037,23 @@ bool ChatHandler::HandleDamageCommand(char* args) return true; } -bool ChatHandler::HandleModifyArenaCommand(char* args) +bool ChatHandler::HandleModifyCurrencyCommand(char* args) { if (!*args) return false; + uint32 currencyId; + if (!ExtractUint32KeyFromLink(&args, "Hcurrency", currencyId)) + return false; + + CurrencyTypesEntry const * entry = sCurrencyTypesStore.LookupEntry(currencyId); + if (!entry) + return false; + + int32 amount; + if (!ExtractInt32(&args, amount)) + return false; + Player* target = getSelectedPlayer(); if (!target) { @@ -3965,11 +4062,9 @@ bool ChatHandler::HandleModifyArenaCommand(char* args) return false; } - int32 amount = (int32)atoi(args); + target->ModifyCurrencyCount(currencyId, amount, false, false); - target->ModifyArenaPoints(amount); - - PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, GetNameLink(target).c_str(), target->GetArenaPoints()); + PSendSysMessage(LANG_COMMAND_MODIFY_CURRENCY, currencyId, GetNameLink(target).c_str(), target->GetCurrencyCount(currencyId)); return true; } @@ -4972,11 +5067,9 @@ bool ChatHandler::HandleResetHonorCommand(char* args) if (!ExtractPlayerTarget(&args, &target)) return false; - target->SetHonorPoints(0); + target->SetCurrencyCount(CURRENCY_HONOR_POINTS, 0); target->SetUInt32Value(PLAYER_FIELD_KILLS, 0); target->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0); - //target->SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); - //target->SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL); return true; diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 42328736b..57c407c01 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1144,7 +1144,7 @@ void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) WorldPacket data(MSG_INSPECT_HONOR_STATS, 8 + 1 + 4 * 4); data << player->GetObjectGuid(); - data << uint8(player->GetHonorPoints()); + data << uint8(player->GetCurrencyCount(CURRENCY_HONOR_POINTS)); data << uint32(player->GetUInt32Value(PLAYER_FIELD_KILLS)); //data << uint32(player->GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); //data << uint32(player->GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION)); diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 73c6a2119..48815d8a3 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -1373,4 +1373,9 @@ void InitializeOpcodes() //OPCODE(SMSG_COMPRESSED_UNKNOWN_1310, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_PLAYER_MOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(CMSG_REORDER_CHARACTERS, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleReorderCharactersOpcode ); + OPCODE(SMSG_SET_CURRENCY_WEEK_LIMIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_SET_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_SEND_CURRENCIES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(CMSG_SET_CURRENCY_FLAGS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetCurrencyFlagsOpcode ); + OPCODE(SMSG_WEEKLY_RESET_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); }; diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 39ae1248e..ffa524b36 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1391,6 +1391,11 @@ enum Opcodes SMSG_SPLINE_MOVE_SET_TURN_RATE = 0x78B5, // 4.3.4 15595 SMSG_SPLINE_MOVE_SET_WALK_SPEED = 0x34A5, // 4.3.4 15595 CMSG_REORDER_CHARACTERS = 0x0593, // 4.3.4 15595 + SMSG_SET_CURRENCY_WEEK_LIMIT = 0x70A7, // 4.3.4 15595 + SMSG_SET_CURRENCY = 0x59B0, // 4.3.4 15595 + SMSG_SEND_CURRENCIES = 0x15A5, // 4.3.4 15595 + CMSG_SET_CURRENCY_FLAGS = 0x7306, // 4.3.4 15595 + SMSG_WEEKLY_RESET_CURRENCY = 0x3CA1, // 4.3.4 15595 }; #define MAX_OPCODE_TABLE_SIZE 0xFFFF diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 9296cdf34..88e188930 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -551,10 +551,6 @@ Player::Player(WorldSession* session): Unit(), m_mover(this), m_camera(this), m_ m_armorPenetrationPct = 0.0f; m_spellPenetrationItemMod = 0; - // Honor System - m_honorPoints = 0; - m_arenaPoints = 0; - // Player summoning m_summon_expire = 0; m_summon_mapid = 0; @@ -724,8 +720,8 @@ bool Player::Create(uint32 guidlow, const std::string& name, uint8 race, uint8 c InitRunes(); SetUInt32Value(PLAYER_FIELD_COINAGE, sWorld.getConfig(CONFIG_UINT32_START_PLAYER_MONEY)); - SetHonorPoints(sWorld.getConfig(CONFIG_UINT32_START_HONOR_POINTS)); - SetArenaPoints(sWorld.getConfig(CONFIG_UINT32_START_ARENA_POINTS)); + SetCurrencyCount(CURRENCY_HONOR_POINTS,sWorld.getConfig(CONFIG_UINT32_START_HONOR_POINTS)); + SetCurrencyCount(CURRENCY_CONQUEST_POINTS, sWorld.getConfig(CONFIG_UINT32_START_CONQUEST_POINTS)); // Played time m_Last_tick = time(NULL); @@ -4378,6 +4374,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe CharacterDatabase.PExecute("DELETE FROM character_equipmentsets WHERE guid = '%u'", lowguid); CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE PlayerGuid1 = '%u' OR PlayerGuid2 = '%u'", lowguid, lowguid); CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE PlayerGuid = '%u'", lowguid); + CharacterDatabase.PExecute("DELETE FROM character_currencies WHERE guid = '%u'", lowguid); CharacterDatabase.CommitTransaction(); break; } @@ -6635,52 +6632,11 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, float honor) GetSession()->SendPacket(&data); // add honor points - ModifyHonorPoints(int32(honor)); + ModifyCurrencyCount(CURRENCY_HONOR_POINTS, int32(honor)); - // FIXME 4x ApplyModUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, uint32(honor), true); return true; } -void Player::SetHonorPoints(uint32 value) -{ - if (value > sWorld.getConfig(CONFIG_UINT32_MAX_HONOR_POINTS)) - value = sWorld.getConfig(CONFIG_UINT32_MAX_HONOR_POINTS); - - // FIXME 4x SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, value); - // must be recalculated to new honor points items and removed - m_honorPoints = value; -} - -void Player::SetArenaPoints(uint32 value) -{ - if (value > sWorld.getConfig(CONFIG_UINT32_MAX_ARENA_POINTS)) - value = sWorld.getConfig(CONFIG_UINT32_MAX_ARENA_POINTS); - - // FIXME 4x SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, value); - // must be recalculated to new honor points items and removed - m_arenaPoints = value; -} - -void Player::ModifyHonorPoints(int32 value) -{ - int32 newValue = (int32)GetHonorPoints() + value; - - if (newValue < 0) - newValue = 0; - - SetHonorPoints(newValue); -} - -void Player::ModifyArenaPoints(int32 value) -{ - int32 newValue = (int32)GetArenaPoints() + value; - - if (newValue < 0) - newValue = 0; - - SetArenaPoints(newValue); -} - uint32 Player::GetGuildIdFromDB(ObjectGuid guid) { uint32 lowguid = guid.GetCounter(); @@ -15667,6 +15623,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) m_deathState = DEAD; + _LoadCurrencies(holder->GetResult(PLAYER_LOGIN_QUERY_LOADCURRENCIES)); _LoadSpells(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSPELLS)); // after spell load, learn rewarded spell if need also @@ -17237,6 +17194,7 @@ void Player::SaveToDB() _SaveSkills(); m_achievementMgr.SaveToDB(); m_reputationMgr.SaveToDB(); + _SaveCurrencies(); _SaveEquipmentSets(); GetSession()->SaveTutorialsData(); // changed only while character in game _SaveGlyphs(); @@ -19008,10 +18966,10 @@ void Player::TakeExtendedCost(uint32 extendedCostId, uint32 count) { ItemExtendedCostEntry const* extendedCost = sItemExtendedCostStore.LookupEntry(extendedCostId); - if (extendedCost->reqhonorpoints) - ModifyHonorPoints(-int32(extendedCost->reqhonorpoints * count)); - if (extendedCost->reqarenapoints) - ModifyArenaPoints(-int32(extendedCost->reqarenapoints * count)); + //if (extendedCost->reqhonorpoints) + // ModifyHonorPoints(-int32(extendedCost->reqhonorpoints * count)); + //if (extendedCost->reqarenapoints) + // ModifyArenaPoints(-int32(extendedCost->reqarenapoints * count)); for (uint8 i = 0; i < MAX_EXTENDED_COST_ITEMS; ++i) { @@ -19113,18 +19071,18 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorGuid, uint32 vendorslot, uin } // honor points price - if (GetHonorPoints() < (iece->reqhonorpoints * count)) - { - SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL); - return false; - } + //if (GetHonorPoints() < (iece->reqhonorpoints * count)) + //{ + // SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL); + // return false; + //} // arena points price - if (GetArenaPoints() < (iece->reqarenapoints * count)) - { - SendEquipError(EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS, NULL, NULL); - return false; - } + //if (GetArenaPoints() < (iece->reqarenapoints * count)) + //{ + // SendEquipError(EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS, NULL, NULL); + // return false; + //} // item base price for (uint8 i = 0; i < MAX_EXTENDED_COST_ITEMS; ++i) @@ -19282,18 +19240,18 @@ bool Player::BuyCurrencyFromVendorSlot(ObjectGuid vendorGuid, uint32 vendorslot, } // honor points price - if (GetHonorPoints() < (iece->reqhonorpoints * count)) - { - SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL); - return false; - } + //if (GetHonorPoints() < (iece->reqhonorpoints * count)) + //{ + // SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL); + // return false; + //} // arena points price - if (GetArenaPoints() < (iece->reqarenapoints * count)) - { - SendEquipError(EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS, NULL, NULL); - return false; - } + //if (GetArenaPoints() < (iece->reqarenapoints * count)) + //{ + // SendEquipError(EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS, NULL, NULL); + // return false; + //} // item base price for (uint8 i = 0; i < MAX_EXTENDED_COST_ITEMS; ++i) @@ -19313,13 +19271,39 @@ bool Player::BuyCurrencyFromVendorSlot(ObjectGuid vendorGuid, uint32 vendorslot, return false; } } + else + { + SendBuyError(BUY_ERR_ITEM_SOLD_OUT, 0, 0, 0); + return false; + } - // TODO: check if player already has maximum currency + if (uint32 totalCap = GetCurrencyTotalCap(pCurrency)) + { + if (GetCurrencyCount(currencyId) >= totalCap) + { - // TODO: modify currency + SendBuyError(BUY_ERR_CANT_CARRY_MORE, 0, 0, 0); + return false; + } + } - DEBUG_LOG("WORLD: BuyCurrencyFromVendorSlot - %s: Player %s buys currency %u amount %u.", - vendorGuid.GetString().c_str(), GetGuidStr().c_str(), currencyId, count); + if (uint32 weekCap = GetCurrencyWeekCap(pCurrency)) + { + if (GetCurrencyWeekCount(currencyId) >= weekCap) + { + SendBuyError(BUY_ERR_CANT_CARRY_MORE, 0, 0, 0); + return false; + } + } + + if (crItem->ExtendedCost) + TakeExtendedCost(crItem->ExtendedCost, count); + + ModifyCurrencyCount(currencyId, crItem->maxcount, true, false); + + + DEBUG_LOG("WORLD: BuyCurrencyFromVendorSlot - %s: Player %s buys currency %u amount %u count %u.", + vendorGuid.GetString().c_str(), GetGuidStr().c_str(), currencyId, crItem->maxcount, count); return true; } @@ -20129,6 +20113,8 @@ void Player::SendInitialPacketsBeforeAddToMap() if (IsFreeFlying() || IsTaxiFlying()) m_movementInfo.AddMovementFlag(MOVEFLAG_FLYING); + SendCurrencies(); + SetMover(this); } @@ -23137,3 +23123,276 @@ void Player::_fillGearScoreData(Item* item, GearScoreVec* gearScore, uint32& two break; } } + +void Player::SendCurrencies() const +{ + WorldPacket data(SMSG_SEND_CURRENCIES, m_currencies.size() * 4); + data.WriteBits(m_currencies.size(), 23); + + for (PlayerCurrenciesMap::const_iterator itr = m_currencies.begin(); itr != m_currencies.end(); ++itr) + { + uint32 weekCap = GetCurrencyWeekCap(itr->second.currencyEntry); + data.WriteBit(weekCap && itr->second.weekCount); + data.WriteBits(itr->second.flags, 4); + data.WriteBit(weekCap); + data.WriteBit(itr->second.currencyEntry->HasSeasonCount()); + } + + for (PlayerCurrenciesMap::const_iterator itr = m_currencies.begin(); itr != m_currencies.end(); ++itr) + { + data << uint32(floor(itr->second.totalCount / itr->second.currencyEntry->GetPrecision())); + + uint32 weekCap = GetCurrencyWeekCap(itr->second.currencyEntry); + if (weekCap) + data << uint32(floor(weekCap / itr->second.currencyEntry->GetPrecision())); + if (itr->second.currencyEntry->HasSeasonCount()) + data << uint32(floor(itr->second.seasonCount / itr->second.currencyEntry->GetPrecision())); + data << uint32(itr->first); + if (weekCap && itr->second.weekCount) + data << uint32(floor(itr->second.weekCount / itr->second.currencyEntry->GetPrecision())); + } + + GetSession()->SendPacket(&data); +} + +uint32 Player::GetCurrencyWeekCap(CurrencyTypesEntry const * currency) const +{ + uint32 cap = currency->WeekCap; + switch (currency->ID) + { + case CURRENCY_CONQUEST_POINTS: + cap = sWorld.getConfig(CONFIG_UINT32_CONQUEST_POINTS_DEFAULT_WEEK_CAP); + break; + } + + return cap; +} + +void Player::SendCurrencyWeekCap(uint32 id) const +{ + if (!IsInWorld() || GetSession()->PlayerLoading()) + return; + + CurrencyTypesEntry const * currency = sCurrencyTypesStore.LookupEntry(id); + if (!currency) + return; + + uint32 cap = GetCurrencyTotalCap(currency); + if (!cap) + return; + + WorldPacket packet(SMSG_SET_CURRENCY_WEEK_LIMIT, 8); + packet << uint32(floor(cap / currency->GetPrecision())); + packet << uint32(currency->ID); + GetSession()->SendPacket(&packet); +} + +uint32 Player::GetCurrencyTotalCap(CurrencyTypesEntry const* currency) const +{ + uint32 cap = currency->TotalCap; + + return cap; +} + +uint32 Player::GetCurrencyCount(uint32 id) const +{ + PlayerCurrenciesMap::const_iterator itr = m_currencies.find(id); + return itr != m_currencies.end() ? itr->second.totalCount : 0; +} + +uint32 Player::GetCurrencySeasonCount(uint32 id) const +{ + PlayerCurrenciesMap::const_iterator itr = m_currencies.find(id); + return itr != m_currencies.end() ? itr->second.seasonCount : 0; +} + +uint32 Player::GetCurrencyWeekCount(uint32 id) const +{ + PlayerCurrenciesMap::const_iterator itr = m_currencies.find(id); + return itr != m_currencies.end() ? itr->second.weekCount : 0; +} + +void Player::ModifyCurrencyCount(uint32 id, int32 count, bool modifyWeek, bool modifySeason) +{ + if (!count) + return; + + CurrencyTypesEntry const * currency = NULL; + + int32 oldTotalCount = 0; + int32 oldWeekCount = 0; + PlayerCurrenciesMap::iterator itr = m_currencies.find(id); + + if (itr == m_currencies.end()) + { + currency = sCurrencyTypesStore.LookupEntry(id); + MANGOS_ASSERT(currency); + + PlayerCurrency cur; + cur.state = PLAYERCURRENCY_NEW; + cur.totalCount = 0; + cur.weekCount = 0; + cur.seasonCount = 0; + cur.flags = 0; + cur.currencyEntry = currency; + m_currencies[id] = cur; + itr = m_currencies.find(id); + } + else + { + oldTotalCount = itr->second.totalCount; + oldWeekCount = itr->second.weekCount; + currency = itr->second.currencyEntry; + } + + int32 newTotalCount = oldTotalCount + count; + if (newTotalCount < 0) + newTotalCount = 0; + + int32 newWeekCount = oldWeekCount + (modifyWeek && count > 0 ? count : 0); + if (newWeekCount < 0) + newWeekCount = 0; + + int32 totalCap = GetCurrencyTotalCap(currency); + if (totalCap && int32(totalCap) < newTotalCount) + { + int32 delta = newTotalCount - totalCap; + newTotalCount = totalCap; + newWeekCount -= delta; + } + + int32 weekCap = GetCurrencyWeekCap(currency); + if (modifyWeek && weekCap && newWeekCount > weekCap) + { + int32 delta = newWeekCount - weekCap; + newWeekCount = weekCap; + newTotalCount -= delta; + } + + if (newTotalCount != oldTotalCount) + { + if (itr->second.state != PLAYERCURRENCY_NEW) + itr->second.state = PLAYERCURRENCY_CHANGED; + + itr->second.totalCount = newTotalCount; + itr->second.weekCount = newWeekCount; + + int32 diff = newTotalCount - oldTotalCount; + if (diff > 0 && modifySeason) + itr->second.seasonCount += diff; + + // probably excessive checks + if (IsInWorld() && !GetSession()->PlayerLoading()) + { + if (diff > 0) + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CURRENCY_EARNED, id, newTotalCount); + + WorldPacket packet(SMSG_SET_CURRENCY, 13); + bool bit0 = modifyWeek && weekCap && diff > 0; + bool bit1 = currency->HasSeasonCount(); + bool bit2 = currency->ID == CURRENCY_CONQUEST_ARENA_META || currency->ID == CURRENCY_CONQUEST_BG_META; // hides message in client when set + packet.WriteBit(bit0); + packet.WriteBit(bit1); + packet.WriteBit(bit2); + + if (bit1) + packet << uint32(floor(itr->second.seasonCount / currency->GetPrecision())); + packet << uint32(floor(newTotalCount / currency->GetPrecision())); + packet << uint32(id); + if (bit0) + packet << uint32(floor(newWeekCount / currency->GetPrecision())); + GetSession()->SendPacket(&packet); + } + + if (itr->first == CURRENCY_CONQUEST_ARENA_META || itr->first == CURRENCY_CONQUEST_BG_META) + ModifyCurrencyCount(CURRENCY_CONQUEST_POINTS, diff, modifyWeek); + } +} + +void Player::SetCurrencyCount(uint32 id, uint32 count) +{ + ModifyCurrencyCount(id, int32(count) - GetCurrencyCount(id)); +} + +void Player::_LoadCurrencies(QueryResult* result) +{ + // 0 1 2 4 5 + // "SELECT id, totalCount, weekCount, seasonCount, flags FROM character_currencies WHERE guid = '%u'" + + if (result) + { + do + { + Field* fields = result->Fetch(); + + uint32 currency_id = fields[0].GetUInt16(); + uint32 totalCount = fields[1].GetUInt32(); + uint32 weekCount = fields[2].GetUInt32(); + uint32 seasonCount = fields[3].GetUInt32(); + uint8 flags = fields[4].GetUInt8(); + + CurrencyTypesEntry const * entry = sCurrencyTypesStore.LookupEntry(currency_id); + if (!entry) + { + sLog.outError("Player::_LoadCurrencies: %s has not existing currency id %u, removing.", GetGuidStr().c_str(), currency_id); + CharacterDatabase.PExecute("DELETE FROM character_currencies WHERE id = '%u'", currency_id); + continue; + } + + uint32 weekCap = GetCurrencyWeekCap(entry); + uint32 totalCap = GetCurrencyTotalCap(entry); + + PlayerCurrency cur; + + cur.state = PLAYERCURRENCY_UNCHANGED; + + if (totalCap && totalCount > totalCap) + cur.totalCount = totalCap; + else + cur.totalCount = totalCount; + + if (weekCap && weekCount > weekCap) + cur.weekCount = weekCap; + else + cur.weekCount = weekCount; + + cur.seasonCount = seasonCount; + + cur.flags = flags & PLAYERCURRENCY_MASK_USED_BY_CLIENT; + cur.currencyEntry = entry; + + m_currencies[currency_id] = cur; + } + while (result->NextRow()); + } +} + +void Player::_SaveCurrencies() +{ + for (PlayerCurrenciesMap::iterator itr = m_currencies.begin(); itr != m_currencies.end();) + { + if (itr->second.state == PLAYERCURRENCY_CHANGED) + CharacterDatabase.PExecute("UPDATE `character_currencies` SET `totalCount` = '%u', `weekCount` = '%u', `seasonCount` = '%u', `flags` = '%u' WHERE `guid` = '%u' AND `id` = '%u'", itr->second.totalCount, itr->second.weekCount, itr->second.seasonCount, itr->second.flags, GetGUIDLow(), itr->first); + else if (itr->second.state == PLAYERCURRENCY_NEW) + CharacterDatabase.PExecute("INSERT INTO `character_currencies` (`guid`, `id`, `totalCount`, `weekCount`, `seasonCount`, `flags`) VALUES ('%u', '%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), itr->first, itr->second.totalCount, itr->second.weekCount, itr->second.seasonCount, itr->second.flags); + + if (itr->second.state == PLAYERCURRENCY_REMOVED) + m_currencies.erase(itr++); + else + { + itr->second.state = PLAYERCURRENCY_UNCHANGED; + ++itr; + } + } +} + +void Player::SetCurrencyFlags(uint32 currencyId, uint8 flags) +{ + PlayerCurrenciesMap::iterator itr = m_currencies.find(currencyId); + if (itr == m_currencies.end()) + return; + + itr->second.flags = flags; + itr->second.state = PLAYERCURRENCY_CHANGED; +} + diff --git a/src/game/Player.h b/src/game/Player.h index 925953d53..a53a9fdda 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -87,6 +87,37 @@ enum BuyBankSlotResult ERR_BANKSLOT_OK = 3 }; +enum PlayerCurrencyFlag +{ + PLAYERCURRENCY_FLAG_NONE = 0x0, + PLAYERCURRENCY_FLAG_UNK1 = 0x1, // unused? + PLAYERCURRENCY_FLAG_UNK2 = 0x2, // unused? + PLAYERCURRENCY_FLAG_SHOW_IN_BACKPACK = 0x4, + PLAYERCURRENCY_FLAG_UNUSED = 0x8, + + PLAYERCURRENCY_MASK_USED_BY_CLIENT = + PLAYERCURRENCY_FLAG_SHOW_IN_BACKPACK | + PLAYERCURRENCY_FLAG_UNUSED, +}; + +enum PlayerCurrencyState +{ + PLAYERCURRENCY_UNCHANGED = 0, + PLAYERCURRENCY_CHANGED = 1, + PLAYERCURRENCY_NEW = 2, + PLAYERCURRENCY_REMOVED = 3 +}; + +struct PlayerCurrency +{ + PlayerCurrencyState state; + uint32 totalCount; + uint32 weekCount; + uint32 seasonCount; + uint8 flags; + CurrencyTypesEntry const * currencyEntry; +}; + enum PlayerSpellState { PLAYERSPELL_UNCHANGED = 0, @@ -110,6 +141,7 @@ struct PlayerTalent PlayerSpellState state; }; +typedef UNORDERED_MAP PlayerCurrenciesMap; typedef UNORDERED_MAP PlayerSpellMap; typedef UNORDERED_MAP PlayerTalentMap; @@ -827,6 +859,7 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADTALENTS, PLAYER_LOGIN_QUERY_LOADWEEKLYQUESTSTATUS, PLAYER_LOGIN_QUERY_LOADMONTHLYQUESTSTATUS, + PLAYER_LOGIN_QUERY_LOADCURRENCIES, MAX_PLAYER_LOGIN_QUERY }; @@ -1938,16 +1971,24 @@ class MANGOS_DLL_SPEC Player : public Unit void UpdateSkillsToMaxSkillsForLevel(); // for .levelup void ModifySkillBonus(uint32 skillid, int32 val, bool talent); + /*********************************************************/ + /*** CURRENCY SYSTEM ***/ + /*********************************************************/ + uint32 GetCurrencyCount(uint32 id) const; + uint32 GetCurrencySeasonCount(uint32 id) const; + uint32 GetCurrencyWeekCount(uint32 id) const; + void SendCurrencies() const; + void ModifyCurrencyCount(uint32 id, int32 count, bool modifyWeek = true, bool modifySeason = true); + bool HasCurrencyCount(uint32 id, uint32 count) const { return GetCurrencyCount(id) >= count; } + bool HasCurrencySeasonCount(uint32 id, uint32 count) const { return GetCurrencySeasonCount(id) >= count; } + void SetCurrencyCount(uint32 id, uint32 count); + void SendCurrencyWeekCap(uint32 id) const; + void SetCurrencyFlags(uint32 currencyId, uint8 flags); + /*********************************************************/ /*** PVP SYSTEM ***/ /*********************************************************/ bool RewardHonor(Unit *pVictim, uint32 groupsize, float honor = -1); - uint32 GetHonorPoints() { return m_honorPoints; } - uint32 GetArenaPoints() { return m_arenaPoints; } - void SetHonorPoints(uint32 honor); - void SetArenaPoints(uint32 arena); - void ModifyHonorPoints( int32 value ); - void ModifyArenaPoints( int32 value ); uint32 GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot); @@ -2428,11 +2469,13 @@ class MANGOS_DLL_SPEC Player : public Unit int32 getMaxTimer(MirrorTimerType timer); /*********************************************************/ - /*** HONOR SYSTEM ***/ + /*** CURRENCY SYSTEM ***/ /*********************************************************/ - time_t m_lastHonorUpdateTime; - uint32 m_honorPoints; - uint32 m_arenaPoints; + PlayerCurrenciesMap m_currencies; + uint32 GetCurrencyWeekCap(CurrencyTypesEntry const * currency) const; + uint32 GetCurrencyTotalCap(CurrencyTypesEntry const * currency) const; + void _LoadCurrencies(QueryResult* result); + void _SaveCurrencies(); void outDebugStatsValues() const; ObjectGuid m_lootGuid; diff --git a/src/game/World.cpp b/src/game/World.cpp index 8209c2654..c1cf767ea 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -596,13 +596,9 @@ void World::LoadConfigSettings(bool reload) setConfigMinMax(CONFIG_UINT32_START_PLAYER_MONEY, "StartPlayerMoney", 0, 0, MAX_MONEY_AMOUNT); - setConfig(CONFIG_UINT32_MAX_HONOR_POINTS, "MaxHonorPoints", 75000); - - setConfigMinMax(CONFIG_UINT32_START_HONOR_POINTS, "StartHonorPoints", 0, 0, getConfig(CONFIG_UINT32_MAX_HONOR_POINTS)); - - setConfig(CONFIG_UINT32_MAX_ARENA_POINTS, "MaxArenaPoints", 5000); - - setConfigMinMax(CONFIG_UINT32_START_ARENA_POINTS, "StartArenaPoints", 0, 0, getConfig(CONFIG_UINT32_MAX_ARENA_POINTS)); + setConfig(CONFIG_UINT32_START_HONOR_POINTS, "StartHonorPoints", 0); + setConfig(CONFIG_UINT32_CONQUEST_POINTS_DEFAULT_WEEK_CAP, "ConquestPointsDefaultWeekCap", 1350 * 100); // with precision + setConfig(CONFIG_UINT32_START_CONQUEST_POINTS, "StartConquestPoints", 0); setConfig(CONFIG_BOOL_ALL_TAXI_PATHS, "AllFlightPaths", false); diff --git a/src/game/World.h b/src/game/World.h index e212b55de..5f7e88e11 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -108,10 +108,8 @@ enum eConfigUInt32Values CONFIG_UINT32_START_PLAYER_LEVEL, CONFIG_UINT32_START_HEROIC_PLAYER_LEVEL, CONFIG_UINT32_START_PLAYER_MONEY, - CONFIG_UINT32_MAX_HONOR_POINTS, CONFIG_UINT32_START_HONOR_POINTS, - CONFIG_UINT32_MAX_ARENA_POINTS, - CONFIG_UINT32_START_ARENA_POINTS, + CONFIG_UINT32_START_CONQUEST_POINTS, CONFIG_UINT32_INSTANCE_RESET_TIME_HOUR, CONFIG_UINT32_INSTANCE_UNLOAD_DELAY, CONFIG_UINT32_MAX_SPELL_CASTS_IN_CHAIN, @@ -189,6 +187,7 @@ enum eConfigUInt32Values CONFIG_UINT32_GUID_RESERVE_SIZE_CREATURE, CONFIG_UINT32_GUID_RESERVE_SIZE_GAMEOBJECT, CONFIG_UINT32_MIN_LEVEL_FOR_RAID, + CONFIG_UINT32_CONQUEST_POINTS_DEFAULT_WEEK_CAP, CONFIG_UINT32_VALUE_COUNT }; diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index bf42edb27..c29270e9d 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -859,6 +859,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleReadyForAccountDataTimesOpcode(WorldPacket& recv_data); void HandleQueryQuestsCompletedOpcode(WorldPacket& recv_data); void HandleQuestPOIQueryOpcode(WorldPacket& recv_data); + void HandleSetCurrencyFlagsOpcode(WorldPacket& recv_data); private: // private trade methods void moveItems(Item* myItems[], Item* hisItems[]); diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 5086a21a4..99c03d014 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -537,22 +537,18 @@ LogColors = "" # If you want to start with one silver, use for example 100 (100 copper = 1 silver) # Default: 0 # -# MaxHonorPoints -# Max honor points that player can have. -# Default: 75000 -# # StartHonorPoints # Amount of honor that new players will start with # Default: 0 # -# MaxArenaPoints -# Max arena points that player can have. -# Default: 5000 -# -# StartArenaPoints -# Amount of arena points that new players will start with +# StartConquestPoints +# Amount of conquest points that new players will start with # Default: 0 # +# ConquestPointsDefaultWeekCap +# Amount of conquest points that player can earn per week +# Default: 135000 (with precision) +# # InstantLogout # Enable or disable instant logout for security level (0..4) or high (NOT in combat/while dueling/while falling) # Default: 1 (Mods/GMs/Admins) @@ -783,10 +779,9 @@ MaxPlayerLevel = 85 StartPlayerLevel = 1 StartHeroicPlayerLevel = 55 StartPlayerMoney = 0 -MaxHonorPoints = 75000 StartHonorPoints = 0 -MaxArenaPoints = 5000 -StartArenaPoints = 0 +StartConquestPoints = 0 +ConquestPointsDefaultWeekCap = 135000 InstantLogout = 1 DisableWaterBreath = 4 AllFlightPaths = 0 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index db118ebba..4e68bcd50 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 "12140" + #define REVISION_NR "12141" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 79a602c3a..42b6ed0e8 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ - #define REVISION_DB_CHARACTERS "required_12138_01_characters_characters" - #define REVISION_DB_MANGOS "required_12138_01_mangos_command" + #define REVISION_DB_CHARACTERS "required_12140_01_characters_character_currencies" + #define REVISION_DB_MANGOS "required_12140_02_mangos_mangos_command" #define REVISION_DB_REALMD "required_12112_01_realmd_account_access" #endif // __REVISION_SQL_H__