diff --git a/config.lua.dist b/config.lua.dist index 9d1ed2fa681..89bd3e68fc3 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -239,6 +239,7 @@ onlyPremiumAccount = false -- Customs -- NOTE: stashMoving = true, stow an container inside your stash +-- NOTE: stashItemCount, the maximum items quantity in stash -- NOTE: depotChest, the non-stackable items will be moved to the selected depot chest(I - XVIII). -- NOTE: autoBank = true, the dropped coins from monsters will be automatically deposited to your bank account. -- NOTE: toggleGoldPouchAllowAnything will allow players to move items or gold to gold pouch @@ -254,7 +255,9 @@ onlyPremiumAccount = false -- NOTE: startStreakLevel will make a reward streak level for new players who never logged in -- NOTE: if showLootsInBestiary is true, will cause all loots to be shown in the bestiary even if the player has not reached the required number of kills -- NOTE: minTownIdToBankTransfer blocks towns less than defined from receiving money transfers +-- NOTE: enableSupportOutfit enable GODS and GMS to select support outfit (gamemaster, customer support or community manager) stashMoving = false +stashItemCount = 5000 depotChest = 4 autoLoot = false autoBank = false @@ -273,6 +276,7 @@ enablePlayerPutItemInAmmoSlot = false startStreakLevel = 0 showLootsInBestiary = false minTownIdToBankTransfer = 3 +enableSupportOutfit = true -- Teleport summon -- Set to true will never remove the summon @@ -502,6 +506,9 @@ rateMonsterHealth = 1.0 rateMonsterAttack = 1.0 rateMonsterDefense = 1.0 +-- Npc rates +rateNpcHealth = 1.0 + -- Boss rates rateBossHealth = 1.0 rateBossAttack = 1.0 @@ -539,6 +546,7 @@ location = "South America" -- Leave empty if you wish to disable. discordWebhookURL = "" discordSendFooter = true +discordWebhookDelayMs = 1000 -- Vip System (Get more info in: https://github.com/opentibiabr/canary/pull/1063) -- NOTE: set vipSystemEnabled to true to enable the vip system functionalities (this overrides premium checks) diff --git a/data-otservbr-global/npc/obi.lua b/data-otservbr-global/npc/obi.lua index d63995619da..8694accfa0c 100644 --- a/data-otservbr-global/npc/obi.lua +++ b/data-otservbr-global/npc/obi.lua @@ -141,7 +141,7 @@ npcConfig.shop = { { itemName = "hatchet", clientId = 3276, sell = 25 }, { itemName = "katana", clientId = 3300, sell = 35 }, { itemName = "mace", clientId = 3286, sell = 30 }, - { itemName = "machete", clientId = 3308, sell = 30 }, + { itemName = "machete", clientId = 3308, sell = 6 }, { itemName = "rapier", clientId = 3272, buy = 15, sell = 5 }, { itemName = "sabre", clientId = 3273, buy = 25, sell = 12 }, { itemName = "scythe", clientId = 3453, buy = 12, sell = 3 }, diff --git a/data-otservbr-global/npc/ramina.lua b/data-otservbr-global/npc/ramina.lua index b115ca4b6f9..78972d2a78f 100644 --- a/data-otservbr-global/npc/ramina.lua +++ b/data-otservbr-global/npc/ramina.lua @@ -65,7 +65,7 @@ npcConfig.shop = { { itemName = "orange", clientId = 3586, buy = 12 }, { itemName = "peas", clientId = 11683, buy = 5 }, { itemName = "vial of fruit juice", clientId = 2874, buy = 10, count = 14 }, - { itemName = "vial of water", clientId = 2874, buy = 2, count = 1 }, + { itemName = "vial of water", clientId = 2874, buy = 6, count = 1 }, } -- On buy npc shop message npcType.onBuyItem = function(npc, player, itemId, subType, amount, ignore, inBackpacks, totalCost) diff --git a/data-otservbr-global/npc/sessek.lua b/data-otservbr-global/npc/sessek.lua index ee7f56a2536..8a8d24ca532 100644 --- a/data-otservbr-global/npc/sessek.lua +++ b/data-otservbr-global/npc/sessek.lua @@ -55,11 +55,11 @@ npcConfig.shop = { { itemName = "peas", clientId = 11683, buy = 3 }, { itemName = "pineapple", clientId = 11459, buy = 14 }, { itemName = "roll", clientId = 3601, buy = 2 }, - { itemName = "vial of coconut milk", clientId = 2874, buy = 2, count = 15 }, + { itemName = "vial of coconut milk", clientId = 2874, buy = 6, count = 15 }, { itemName = "vial of fruit juice", clientId = 2874, buy = 6, count = 14 }, - { itemName = "vial of tea", clientId = 2874, buy = 3, count = 17 }, - { itemName = "vial of water", clientId = 2874, buy = 2, count = 1 }, - { itemName = "vial of wine", clientId = 2874, buy = 3, count = 2 }, + { itemName = "vial of tea", clientId = 2874, buy = 6, count = 17 }, + { itemName = "vial of water", clientId = 2874, buy = 6, count = 1 }, + { itemName = "vial of wine", clientId = 2874, buy = 6, count = 2 }, } -- On buy npc shop message npcType.onBuyItem = function(npc, player, itemId, subType, amount, ignore, inBackpacks, totalCost) diff --git a/data-otservbr-global/scripts/movements/quests/children_of_the_revolution/symbol.lua b/data-otservbr-global/scripts/movements/quests/children_of_the_revolution/symbol.lua index b6b0bfe6d88..ac12a11b0c1 100644 --- a/data-otservbr-global/scripts/movements/quests/children_of_the_revolution/symbol.lua +++ b/data-otservbr-global/scripts/movements/quests/children_of_the_revolution/symbol.lua @@ -16,5 +16,5 @@ function symbol.onStepIn(creature, item, position, fromPosition) end symbol:type("stepin") -symbol:position({ x = 33349, y = 31123, z = 5 }) +symbol:position({ x = 33357, y = 31123, z = 5 }) symbol:register() diff --git a/data/scripts/creaturescripts/player/login.lua b/data/scripts/creaturescripts/player/login.lua index 41676066975..5f9f0e695f4 100644 --- a/data/scripts/creaturescripts/player/login.lua +++ b/data/scripts/creaturescripts/player/login.lua @@ -169,6 +169,14 @@ function playerLoginGlobal.onLogin(player) onMovementRemoveProtection(playerId, player:getPosition(), 10) end + -- Change support outfit to a normal outfit to open customize character without crashes + local playerOutfit = player:getOutfit() + if table.contains({ 75, 266, 302 }, playerOutfit.lookType) then + playerOutfit.lookType = 136 + playerOutfit.lookAddons = 0 + player:setOutfit(playerOutfit) + end + player:initializeLoyaltySystem() player:registerEvent("PlayerDeath") player:registerEvent("DropLoot") diff --git a/src/config/config_enums.hpp b/src/config/config_enums.hpp index 0e53c97546e..bf480505014 100644 --- a/src/config/config_enums.hpp +++ b/src/config/config_enums.hpp @@ -14,7 +14,6 @@ enum ConfigKey_t : uint16_t { ACTIONS_DELAY_INTERVAL, ADVENTURERSBLESSING_LEVEL, AIMBOT_HOTKEY_ENABLED, - ALLOW_BLOCK_SPAWN, ALLOW_CHANGEOUTFIT, ALLOW_RELOAD, AUGMENT_INCREASED_DAMAGE_PERCENT, @@ -63,11 +62,11 @@ enum ConfigKey_t : uint16_t { DISCORD_WEBHOOK_URL, EMOTE_SPELLS, ENABLE_PLAYER_PUT_ITEM_IN_AMMO_SLOT, + ENABLE_SUPPORT_OUTFIT, EX_ACTIONS_DELAY_INTERVAL, EXP_FROM_PLAYERS_LEVEL_RANGE, EXPERIENCE_FROM_PLAYERS, FAMILIAR_TIME, - FORCE_MONSTERTYPE_LOAD, FORGE_AMOUNT_MULTIPLIER, FORGE_BASE_SUCCESS_RATE, FORGE_BONUS_SUCCESS_RATE, @@ -135,8 +134,6 @@ enum ConfigKey_t : uint16_t { M_CONST, MAINTAIN_MODE_MESSAGE, MAP_AUTHOR, - MAP_CUSTOM_AUTHOR, - MAP_CUSTOM_NAME, MAP_DOWNLOAD_URL, MAP_NAME, MARKET_OFFER_DURATION, @@ -221,8 +218,6 @@ enum ConfigKey_t : uint16_t { RATE_MONSTER_ATTACK, RATE_MONSTER_DEFENSE, RATE_MONSTER_HEALTH, - RATE_NPC_ATTACK, - RATE_NPC_DEFENSE, RATE_NPC_HEALTH, RATE_OFFLINE_TRAINING_SPEED, RATE_SKILL, diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index 35d2cf3b1be..6390d0699b3 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -72,8 +72,6 @@ bool ConfigManager::load() { loadStringConfig(L, IP, "ip", "127.0.0.1"); loadStringConfig(L, MAINTAIN_MODE_MESSAGE, "maintainModeMessage", ""); loadStringConfig(L, MAP_AUTHOR, "mapAuthor", "Eduardo Dantas"); - loadStringConfig(L, MAP_CUSTOM_AUTHOR, "mapCustomAuthor", "OTServBR"); - loadStringConfig(L, MAP_CUSTOM_NAME, "mapCustomName", ""); loadStringConfig(L, MAP_DOWNLOAD_URL, "mapDownloadUrl", ""); loadStringConfig(L, MAP_NAME, "mapName", "canary"); loadStringConfig(L, MYSQL_DB, "mysqlDatabase", "canary"); @@ -84,7 +82,6 @@ bool ConfigManager::load() { } loadBoolConfig(L, AIMBOT_HOTKEY_ENABLED, "hotkeyAimbotEnabled", true); - loadBoolConfig(L, ALLOW_BLOCK_SPAWN, "allowBlockSpawn", true); loadBoolConfig(L, ALLOW_CHANGEOUTFIT, "allowChangeOutfit", true); loadBoolConfig(L, ALLOW_RELOAD, "allowReload", false); loadBoolConfig(L, AUTOBANK, "autoBank", false); @@ -97,8 +94,8 @@ bool ConfigManager::load() { loadBoolConfig(L, DISCORD_SEND_FOOTER, "discordSendFooter", true); loadBoolConfig(L, EMOTE_SPELLS, "emoteSpells", false); loadBoolConfig(L, ENABLE_PLAYER_PUT_ITEM_IN_AMMO_SLOT, "enablePlayerPutItemInAmmoSlot", false); + loadBoolConfig(L, ENABLE_SUPPORT_OUTFIT, "enableSupportOutfit", true); loadBoolConfig(L, EXPERIENCE_FROM_PLAYERS, "experienceByKillingPlayers", false); - loadBoolConfig(L, FORCE_MONSTERTYPE_LOAD, "forceMonsterTypesOnLoad", true); loadBoolConfig(L, FREE_PREMIUM, "freePremium", false); loadBoolConfig(L, GLOBAL_SERVER_SAVE_CLEAN_MAP, "globalServerSaveCleanMap", false); loadBoolConfig(L, GLOBAL_SERVER_SAVE_CLOSE, "globalServerSaveClose", false); @@ -193,8 +190,6 @@ bool ConfigManager::load() { loadFloatConfig(L, RATE_MONSTER_ATTACK, "rateMonsterAttack", 1.0); loadFloatConfig(L, RATE_MONSTER_DEFENSE, "rateMonsterDefense", 1.0); loadFloatConfig(L, RATE_MONSTER_HEALTH, "rateMonsterHealth", 1.0); - loadFloatConfig(L, RATE_NPC_ATTACK, "rateNpcAttack", 1.0); - loadFloatConfig(L, RATE_NPC_DEFENSE, "rateNpcDefense", 1.0); loadFloatConfig(L, RATE_NPC_HEALTH, "rateNpcHealth", 1.0); loadFloatConfig(L, RATE_OFFLINE_TRAINING_SPEED, "rateOfflineTrainingSpeed", 1.0); loadFloatConfig(L, RATE_SOUL_REGEN_SPEED, "rateSoulRegenSpeed", 1.0); @@ -235,7 +230,7 @@ bool ConfigManager::load() { loadIntConfig(L, FAMILIAR_TIME, "familiarTime", 30); loadIntConfig(L, FORGE_BASE_SUCCESS_RATE, "forgeBaseSuccessRate", 50); loadIntConfig(L, FORGE_BONUS_SUCCESS_RATE, "forgeBonusSuccessRate", 15); - loadIntConfig(L, FORGE_CONVERGENCE_FUSION_DUST_COST, "forgeConvergenceFusionCost", 130); + loadIntConfig(L, FORGE_CONVERGENCE_FUSION_DUST_COST, "forgeConvergenceFusionDustCost", 130); loadIntConfig(L, FORGE_CONVERGENCE_TRANSFER_DUST_COST, "forgeConvergenceTransferCost", 160); loadIntConfig(L, FORGE_CORE_COST, "forgeCoreCost", 50); loadIntConfig(L, FORGE_COST_ONE_SLIVER, "forgeCostOneSliver", 20); @@ -383,11 +378,17 @@ bool ConfigManager::reload() { return result; } +void ConfigManager::missingConfigWarning(const char* identifier) { + g_logger().warn("[{}]: Missing configuration for identifier: {}", __FUNCTION__, identifier); +} + std::string ConfigManager::loadStringConfig(lua_State* L, const ConfigKey_t &key, const char* identifier, const std::string &defaultValue) { std::string value = defaultValue; lua_getglobal(L, identifier); if (lua_isstring(L, -1)) { value = lua_tostring(L, -1); + } else { + missingConfigWarning(identifier); } configs[key] = value; lua_pop(L, 1); @@ -399,6 +400,8 @@ int32_t ConfigManager::loadIntConfig(lua_State* L, const ConfigKey_t &key, const lua_getglobal(L, identifier); if (lua_isnumber(L, -1)) { value = static_cast(lua_tointeger(L, -1)); + } else { + missingConfigWarning(identifier); } configs[key] = value; lua_pop(L, 1); @@ -410,6 +413,8 @@ bool ConfigManager::loadBoolConfig(lua_State* L, const ConfigKey_t &key, const c lua_getglobal(L, identifier); if (lua_isboolean(L, -1)) { value = static_cast(lua_toboolean(L, -1)); + } else { + missingConfigWarning(identifier); } configs[key] = value; lua_pop(L, 1); @@ -421,6 +426,8 @@ float ConfigManager::loadFloatConfig(lua_State* L, const ConfigKey_t &key, const lua_getglobal(L, identifier); if (lua_isnumber(L, -1)) { value = static_cast(lua_tonumber(L, -1)); + } else { + missingConfigWarning(identifier); } configs[key] = value; lua_pop(L, 1); diff --git a/src/config/configmanager.hpp b/src/config/configmanager.hpp index 406ff69891e..2a0c0861955 100644 --- a/src/config/configmanager.hpp +++ b/src/config/configmanager.hpp @@ -26,6 +26,8 @@ class ConfigManager { bool load(); bool reload(); + void missingConfigWarning(const char* identifier); + const std::string &setConfigFileLua(const std::string &what) { configFileLua = { what }; return configFileLua; diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp index 670d5f3d688..edf2fa55b74 100644 --- a/src/creatures/creature.hpp +++ b/src/creatures/creature.hpp @@ -281,6 +281,10 @@ class Creature : virtual public Thing, public SharedObject { const Outfit_t getDefaultOutfit() const { return defaultOutfit; } + bool isWearingSupportOutfit() const { + auto outfit = currentOutfit.lookType; + return outfit == 75 || outfit == 266 || outfit == 302; + } bool isInvisible() const; ZoneType_t getZoneType() { if (getTile()) { diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 2660c039110..a6db39f587d 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -5826,6 +5826,10 @@ bool Player::toggleMount(bool mount) { return false; } + if (isWearingSupportOutfit()) { + return false; + } + if (mount) { if (isMounted()) { return false; diff --git a/src/creatures/players/wheel/player_wheel.cpp b/src/creatures/players/wheel/player_wheel.cpp index 4c7a3dc52e0..2a3e1366430 100644 --- a/src/creatures/players/wheel/player_wheel.cpp +++ b/src/creatures/players/wheel/player_wheel.cpp @@ -1031,7 +1031,7 @@ void PlayerWheel::sendOpenWheelWindow(NetworkMessage &msg, uint32_t ownerId) con // TODO: read items from inventory auto voc = m_player.getVocation(); m_player.client->sendResourceBalance(RESOURCE_BANK, m_player.getBankBalance()); - m_player.client->sendResourceBalance(RESOURCE_INVENTORY, m_player.getMoney()); + m_player.client->sendResourceBalance(RESOURCE_INVENTORY_MONEY, m_player.getMoney()); m_player.client->sendResourceBalance(RESOURCE_LESSER_GEMS, m_player.getItemTypeCount(voc->getWheelGemId(WheelGemQuality_t::Lesser))); m_player.client->sendResourceBalance(RESOURCE_REGULAR_GEMS, m_player.getItemTypeCount(voc->getWheelGemId(WheelGemQuality_t::Regular))); m_player.client->sendResourceBalance(RESOURCE_GREATER_GEMS, m_player.getItemTypeCount(voc->getWheelGemId(WheelGemQuality_t::Greater))); diff --git a/src/game/game.cpp b/src/game/game.cpp index 2348d384569..949da71c0a3 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -2362,7 +2362,7 @@ std::tuple Game::addItemBatch(const std::shared if (item->getContainer()) { containersCreated++; } - totalAdded++; + totalAdded += item->getItemCount(); } ret = returnError; @@ -4266,7 +4266,7 @@ void Game::playerSetShowOffSocket(uint32_t playerId, Outfit_t &outfit, const Pos } const auto mount = mounts.getMountByClientID(outfit.lookMount); - if (!mount || !player->hasMount(mount)) { + if (!mount || !player->hasMount(mount) || player->isWearingSupportOutfit()) { outfit.lookMount = 0; } @@ -5963,6 +5963,11 @@ void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit, uint8_t isMoun return; } + if (player->isWearingSupportOutfit()) { + outfit.lookMount = 0; + isMountRandomized = 0; + } + player->setRandomMount(isMountRandomized); if (isMountRandomized && outfit.lookMount != 0 && player->hasAnyMount()) { diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index f3a4bcef3ac..c67cee710a8 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -3203,15 +3203,22 @@ void ProtocolGame::sendCreatureOutfit(std::shared_ptr creature, const return; } + Outfit_t newOutfit = outfit; + if (player->isWearingSupportOutfit()) { + player->setCurrentMount(0); + newOutfit.lookMount = 0; + } + NetworkMessage msg; msg.addByte(0x8E); msg.add(creature->getID()); - AddOutfit(msg, outfit); - if (!oldProtocol && outfit.lookMount != 0) { - msg.addByte(outfit.lookMountHead); - msg.addByte(outfit.lookMountBody); - msg.addByte(outfit.lookMountLegs); - msg.addByte(outfit.lookMountFeet); + AddOutfit(msg, newOutfit); + + if (!oldProtocol && newOutfit.lookMount != 0) { + msg.addByte(newOutfit.lookMountHead); + msg.addByte(newOutfit.lookMountBody); + msg.addByte(newOutfit.lookMountLegs); + msg.addByte(newOutfit.lookMountFeet); } writeToOutputBuffer(msg); } @@ -4252,10 +4259,12 @@ void ProtocolGame::sendBasicData() { msg.addByte(player->getVocation()->getClientId()); // Prey window - if (player->getVocation()->getId() == 0 && player->getGroup()->id < GROUP_TYPE_GAMEMASTER) { - msg.addByte(0); - } else { - msg.addByte(1); // has reached Main (allow player to open Prey window) + if (!oldProtocol) { + if (player->getVocation()->getId() == 0 && player->getGroup()->id < GROUP_TYPE_GAMEMASTER) { + msg.addByte(0); + } else { + msg.addByte(1); // has reached Main (allow player to open Prey window) + } } // Filter only valid ids @@ -4795,7 +4804,7 @@ void ProtocolGame::sendGameNews() { void ProtocolGame::sendResourcesBalance(uint64_t money /*= 0*/, uint64_t bank /*= 0*/, uint64_t preyCards /*= 0*/, uint64_t taskHunting /*= 0*/, uint64_t forgeDust /*= 0*/, uint64_t forgeSliver /*= 0*/, uint64_t forgeCores /*= 0*/) { sendResourceBalance(RESOURCE_BANK, bank); - sendResourceBalance(RESOURCE_INVENTORY, money); + sendResourceBalance(RESOURCE_INVENTORY_MONEY, money); sendResourceBalance(RESOURCE_PREY_CARDS, preyCards); sendResourceBalance(RESOURCE_TASK_HUNTING, taskHunting); sendResourceBalance(RESOURCE_FORGE_DUST, forgeDust); @@ -4816,40 +4825,35 @@ void ProtocolGame::sendResourceBalance(Resource_t resourceType, uint64_t value) } void ProtocolGame::sendSaleItemList(const std::vector &shopVector, const std::map &inventoryMap) { - // Since we already have full inventory map we shouldn't call getMoney here - it is simply wasting cpu power - uint64_t playerMoney = 0; - auto it = inventoryMap.find(ITEM_CRYSTAL_COIN); - if (it != inventoryMap.end()) { - playerMoney += static_cast(it->second) * 10000; - } - it = inventoryMap.find(ITEM_PLATINUM_COIN); - if (it != inventoryMap.end()) { - playerMoney += static_cast(it->second) * 100; - } - it = inventoryMap.find(ITEM_GOLD_COIN); - if (it != inventoryMap.end()) { - playerMoney += static_cast(it->second); - } + sendResourceBalance(RESOURCE_BANK, player->getBankBalance()); - NetworkMessage msg; - msg.addByte(0xEE); - msg.addByte(0x00); - msg.add(player->getBankBalance()); uint16_t currency = player->getShopOwner() ? player->getShopOwner()->getCurrency() : static_cast(ITEM_GOLD_COIN); - msg.addByte(0xEE); if (currency == ITEM_GOLD_COIN) { - msg.addByte(0x01); - msg.add(playerMoney); + // Since we already have full inventory map we shouldn't call getMoney here - it is simply wasting cpu power + uint64_t playerMoney = 0; + auto it = inventoryMap.find(ITEM_CRYSTAL_COIN); + if (it != inventoryMap.end()) { + playerMoney += static_cast(it->second) * 10000; + } + it = inventoryMap.find(ITEM_PLATINUM_COIN); + if (it != inventoryMap.end()) { + playerMoney += static_cast(it->second) * 100; + } + it = inventoryMap.find(ITEM_GOLD_COIN); + if (it != inventoryMap.end()) { + playerMoney += static_cast(it->second); + } + sendResourceBalance(RESOURCE_INVENTORY_MONEY, playerMoney); } else { - msg.addByte(oldProtocol ? 0x01 : 0x02); - uint64_t newCurrency = 0; + uint64_t customCurrencyValue = 0; auto search = inventoryMap.find(currency); if (search != inventoryMap.end()) { - newCurrency += static_cast(search->second); + customCurrencyValue += static_cast(search->second); } - msg.add(newCurrency); + sendResourceBalance(oldProtocol ? RESOURCE_INVENTORY_MONEY : RESOURCE_INVENTORY_CURRENCY_CUSTOM, customCurrencyValue); } + NetworkMessage msg; msg.addByte(0x7B); if (oldProtocol) { @@ -4865,7 +4869,7 @@ void ProtocolGame::sendSaleItemList(const std::vector &shopVector, co continue; } - it = inventoryMap.find(shopBlock.itemId); + auto it = inventoryMap.find(shopBlock.itemId); if (it != inventoryMap.end()) { msg.add(shopBlock.itemId); if (oldProtocol) { @@ -6949,15 +6953,23 @@ void ProtocolGame::sendOutfitWindow() { NetworkMessage msg; msg.addByte(0xC8); - if (oldProtocol) { - Outfit_t currentOutfit = player->getDefaultOutfit(); + Outfit_t currentOutfit = player->getDefaultOutfit(); + auto isSupportOutfit = player->isWearingSupportOutfit(); + bool mounted = false; + + if (!isSupportOutfit) { const auto currentMount = g_game().mounts.getMountByID(player->getLastMount()); if (currentMount) { + mounted = (currentOutfit.lookMount == currentMount->clientId); currentOutfit.lookMount = currentMount->clientId; } + } else { + currentOutfit.lookMount = 0; + } - AddOutfit(msg, currentOutfit); + AddOutfit(msg, currentOutfit); + if (oldProtocol) { std::vector protocolOutfits; const auto outfits = Outfits::getInstance().getOutfits(player->getSex()); protocolOutfits.reserve(outfits.size()); @@ -6998,20 +7010,10 @@ void ProtocolGame::sendOutfitWindow() { return; } - bool mounted = false; - Outfit_t currentOutfit = player->getDefaultOutfit(); - const auto currentMount = g_game().mounts.getMountByID(player->getLastMount()); - if (currentMount) { - mounted = (currentOutfit.lookMount == currentMount->clientId); - currentOutfit.lookMount = currentMount->clientId; - } - - AddOutfit(msg, currentOutfit); - - msg.addByte(currentOutfit.lookMountHead); - msg.addByte(currentOutfit.lookMountBody); - msg.addByte(currentOutfit.lookMountLegs); - msg.addByte(currentOutfit.lookMountFeet); + msg.addByte(isSupportOutfit ? 0 : currentOutfit.lookMountHead); + msg.addByte(isSupportOutfit ? 0 : currentOutfit.lookMountBody); + msg.addByte(isSupportOutfit ? 0 : currentOutfit.lookMountLegs); + msg.addByte(isSupportOutfit ? 0 : currentOutfit.lookMountFeet); msg.add(currentOutfit.lookFamiliarsType); auto startOutfits = msg.getBufferPosition(); @@ -7020,7 +7022,7 @@ void ProtocolGame::sendOutfitWindow() { uint16_t outfitSize = 0; msg.skipBytes(2); - if (player->isAccessPlayer()) { + if (player->isAccessPlayer() && g_configManager().getBoolean(ENABLE_SUPPORT_OUTFIT, __FUNCTION__)) { msg.add(75); msg.addString("Gamemaster", "ProtocolGame::sendOutfitWindow - Gamemaster"); msg.addByte(0); @@ -7144,7 +7146,7 @@ void ProtocolGame::sendOutfitWindow() { msg.addByte(mounted ? 0x01 : 0x00); // Version 12.81 - Random mount 'bool' - msg.addByte(player->isRandomMounted() ? 0x01 : 0x00); + msg.addByte(isSupportOutfit ? 0x00 : (player->isRandomMounted() ? 0x01 : 0x00)); writeToOutputBuffer(msg); } diff --git a/src/server/server_definitions.hpp b/src/server/server_definitions.hpp index 1d5ed5b628e..b957292b579 100644 --- a/src/server/server_definitions.hpp +++ b/src/server/server_definitions.hpp @@ -55,7 +55,8 @@ enum SessionEndInformations : uint8_t { enum Resource_t : uint8_t { RESOURCE_BANK = 0x00, - RESOURCE_INVENTORY = 0x01, + RESOURCE_INVENTORY_MONEY = 0x01, + RESOURCE_INVENTORY_CURRENCY_CUSTOM = 0x02, RESOURCE_PREY_CARDS = 0x0A, RESOURCE_TASK_HUNTING = 0x32, RESOURCE_FORGE_DUST = 0x46,