From bf74b3e66b3f76a98e1d8222a8a907ebf84ebd28 Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Fri, 5 Apr 2024 14:37:05 -0300 Subject: [PATCH 1/6] Check and changes if you are logged with support/team outfit (in client 13.32 when open customize character window or login with GM, CM ou CS outfit, this crashes, because starts with mount). --- .../scripts/creaturescripts/others/login.lua | 8 +++++ src/creatures/creature.hpp | 4 +++ src/creatures/players/player.cpp | 4 +++ src/server/network/protocol/protocolgame.cpp | 34 +++++++++++++------ 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/data-otservbr-global/scripts/creaturescripts/others/login.lua b/data-otservbr-global/scripts/creaturescripts/others/login.lua index 8457209e90a..2747496e9ae 100644 --- a/data-otservbr-global/scripts/creaturescripts/others/login.lua +++ b/data-otservbr-global/scripts/creaturescripts/others/login.lua @@ -37,6 +37,14 @@ function playerLogin.onLogin(player) player:openChannel(0x00) -- guild end end + + local playerOutfit = player:getOutfit() + if table.contains({ 75, 266, 302 }, playerOutfit.lookType) then + playerOutfit.lookType = 136 + playerOutfit.lookAddons = 0 + player:setOutfit(playerOutfit) + end + return true end diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp index 4acbacb570a..37a1ccc8d18 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 isSupportOutfit() 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 618ffea1081..4f6b5d29294 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -5783,6 +5783,10 @@ bool Player::toggleMount(bool mount) { return false; } + if (isSupportOutfit()) { + return false; + } + if (mount) { if (isMounted()) { return false; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 0d0d8e79f17..6a15d5f81f4 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -3157,7 +3157,13 @@ void ProtocolGame::sendCreatureOutfit(std::shared_ptr creature, const msg.addByte(0x8E); msg.add(creature->getID()); AddOutfit(msg, outfit); - if (!oldProtocol && outfit.lookMount != 0) { + + auto isSupportOutfit = player->isSupportOutfit(); + if (isSupportOutfit) { + player->setCurrentMount(0); + } + + if (!oldProtocol && outfit.lookMount != 0 && !isSupportOutfit) { msg.addByte(outfit.lookMountHead); msg.addByte(outfit.lookMountBody); msg.addByte(outfit.lookMountLegs); @@ -6656,18 +6662,24 @@ void ProtocolGame::sendOutfitWindow() { bool mounted = false; Outfit_t currentOutfit = player->getDefaultOutfit(); + + auto isSupportOutfit = player->isSupportOutfit(); const auto currentMount = g_game().mounts.getMountByID(player->getLastMount()); - if (currentMount) { - mounted = (currentOutfit.lookMount == currentMount->clientId); - currentOutfit.lookMount = currentMount->clientId; + if (!isSupportOutfit) { + if (currentMount) { + mounted = (currentOutfit.lookMount == currentMount->clientId); + currentOutfit.lookMount = currentMount->clientId; + } + } else { + currentOutfit.lookMount = 0; } - AddOutfit(msg, currentOutfit); + AddOutfit(msg, currentOutfit, !isSupportOutfit); - 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(); @@ -6796,7 +6808,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); } @@ -7207,7 +7219,7 @@ void ProtocolGame::AddCreature(NetworkMessage &msg, std::shared_ptr cr } } else { static Outfit_t outfit; - AddOutfit(msg, outfit); + AddOutfit(msg, outfit, false); } LightInfo lightInfo = creature->getCreatureLight(); From 15861aa179a6cfea1c0bfcaf83454cf49a797449 Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Mon, 8 Apr 2024 11:20:19 -0300 Subject: [PATCH 2/6] resolving crash. --- src/server/network/protocol/protocolgame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 6a15d5f81f4..6dbb9d3019e 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -7219,7 +7219,7 @@ void ProtocolGame::AddCreature(NetworkMessage &msg, std::shared_ptr cr } } else { static Outfit_t outfit; - AddOutfit(msg, outfit, false); + AddOutfit(msg, outfit); } LightInfo lightInfo = creature->getCreatureLight(); From d30710c317ba01ffd4b40c6372a965f5cd46a613 Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Tue, 23 Apr 2024 10:40:47 -0300 Subject: [PATCH 3/6] Moved function to check support outfit to data path. --- .../scripts/creaturescripts/others/login.lua | 8 -------- data/scripts/creaturescripts/player/login.lua | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/data-otservbr-global/scripts/creaturescripts/others/login.lua b/data-otservbr-global/scripts/creaturescripts/others/login.lua index 2747496e9ae..8457209e90a 100644 --- a/data-otservbr-global/scripts/creaturescripts/others/login.lua +++ b/data-otservbr-global/scripts/creaturescripts/others/login.lua @@ -37,14 +37,6 @@ function playerLogin.onLogin(player) player:openChannel(0x00) -- guild end end - - local playerOutfit = player:getOutfit() - if table.contains({ 75, 266, 302 }, playerOutfit.lookType) then - playerOutfit.lookType = 136 - playerOutfit.lookAddons = 0 - player:setOutfit(playerOutfit) - end - return true end diff --git a/data/scripts/creaturescripts/player/login.lua b/data/scripts/creaturescripts/player/login.lua index 34d139a047d..c3ad6fa30d4 100644 --- a/data/scripts/creaturescripts/player/login.lua +++ b/data/scripts/creaturescripts/player/login.lua @@ -153,6 +153,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") From ea1b73996b5c1882d034640ce048ea0032a9bc8f Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Tue, 23 Apr 2024 11:56:45 -0300 Subject: [PATCH 4/6] Created config to disable support outfit selector on customize character and Adjusted another checks. --- config.lua.dist | 2 ++ src/config/config_enums.hpp | 1 + src/config/configmanager.cpp | 1 + src/game/game.cpp | 7 +++++- src/server/network/protocol/protocolgame.cpp | 25 ++++++++++---------- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/config.lua.dist b/config.lua.dist index 0507b652e29..30b87f2adbc 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -242,6 +242,7 @@ 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 depotChest = 4 autoLoot = false @@ -261,6 +262,7 @@ enablePlayerPutItemInAmmoSlot = false startStreakLevel = 0 showLootsInBestiary = false minTownIdToBankTransfer = 3 +enableSupportOutfit = true -- Teleport summon -- Set to true will never remove the summon diff --git a/src/config/config_enums.hpp b/src/config/config_enums.hpp index 4abf29c04cb..f14e5c33ff8 100644 --- a/src/config/config_enums.hpp +++ b/src/config/config_enums.hpp @@ -59,6 +59,7 @@ 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, diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index 8d4ba7a77da..df31fb1d3fa 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -97,6 +97,7 @@ 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); diff --git a/src/game/game.cpp b/src/game/game.cpp index 0dfba6f6724..cb85d63904d 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -4081,7 +4081,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->isSupportOutfit()) { outfit.lookMount = 0; } @@ -5762,6 +5762,11 @@ void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit, uint8_t isMoun return; } + if (player->isSupportOutfit()) { + 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 6dbb9d3019e..db7c6ec48a0 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -3153,21 +3153,22 @@ void ProtocolGame::sendCreatureOutfit(std::shared_ptr creature, const return; } + Outfit_t newOutfit = outfit; + if (player->isSupportOutfit()) { + player->setCurrentMount(0); + newOutfit.lookMount = 0; + } + NetworkMessage msg; msg.addByte(0x8E); msg.add(creature->getID()); - AddOutfit(msg, outfit); - - auto isSupportOutfit = player->isSupportOutfit(); - if (isSupportOutfit) { - player->setCurrentMount(0); - } + AddOutfit(msg, newOutfit); - if (!oldProtocol && outfit.lookMount != 0 && !isSupportOutfit) { - msg.addByte(outfit.lookMountHead); - msg.addByte(outfit.lookMountBody); - msg.addByte(outfit.lookMountLegs); - msg.addByte(outfit.lookMountFeet); + if (!oldProtocol && newOutfit.lookMount != 0) { + msg.addByte(newOutfit.lookMountHead); + msg.addByte(newOutfit.lookMountBody); + msg.addByte(newOutfit.lookMountLegs); + msg.addByte(newOutfit.lookMountFeet); } writeToOutputBuffer(msg); } @@ -6688,7 +6689,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); From 2509fa9f54e81abdc877565a7f97277a8b9d0a56 Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Tue, 23 Apr 2024 13:22:02 -0300 Subject: [PATCH 5/6] Improved checks and removed redundant code. --- src/server/network/protocol/protocolgame.cpp | 30 +++++++------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index db7c6ec48a0..2255a7d2f20 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -6612,15 +6612,23 @@ void ProtocolGame::sendOutfitWindow() { NetworkMessage msg; msg.addByte(0xC8); - if (oldProtocol) { - Outfit_t currentOutfit = player->getDefaultOutfit(); + Outfit_t currentOutfit = player->getDefaultOutfit(); + auto isSupportOutfit = player->isSupportOutfit(); + 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()); @@ -6661,22 +6669,6 @@ void ProtocolGame::sendOutfitWindow() { return; } - bool mounted = false; - Outfit_t currentOutfit = player->getDefaultOutfit(); - - auto isSupportOutfit = player->isSupportOutfit(); - const auto currentMount = g_game().mounts.getMountByID(player->getLastMount()); - if (!isSupportOutfit) { - if (currentMount) { - mounted = (currentOutfit.lookMount == currentMount->clientId); - currentOutfit.lookMount = currentMount->clientId; - } - } else { - currentOutfit.lookMount = 0; - } - - AddOutfit(msg, currentOutfit, !isSupportOutfit); - msg.addByte(isSupportOutfit ? 0 : currentOutfit.lookMountHead); msg.addByte(isSupportOutfit ? 0 : currentOutfit.lookMountBody); msg.addByte(isSupportOutfit ? 0 : currentOutfit.lookMountLegs); From a545808bb439d842276835d47df45733440c81e5 Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Tue, 2 Jul 2024 16:01:09 -0300 Subject: [PATCH 6/6] improved function name. --- src/creatures/creature.hpp | 2 +- src/creatures/players/player.cpp | 2 +- src/game/game.cpp | 4 ++-- src/server/network/protocol/protocolgame.cpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp index bcc8db1637f..edf2fa55b74 100644 --- a/src/creatures/creature.hpp +++ b/src/creatures/creature.hpp @@ -281,7 +281,7 @@ class Creature : virtual public Thing, public SharedObject { const Outfit_t getDefaultOutfit() const { return defaultOutfit; } - bool isSupportOutfit() const { + bool isWearingSupportOutfit() const { auto outfit = currentOutfit.lookType; return outfit == 75 || outfit == 266 || outfit == 302; } diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 45b4cab88d1..0bcb21187b4 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -5830,7 +5830,7 @@ bool Player::toggleMount(bool mount) { return false; } - if (isSupportOutfit()) { + if (isWearingSupportOutfit()) { return false; } diff --git a/src/game/game.cpp b/src/game/game.cpp index 43f95a4b09e..da9875a1e87 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -4223,7 +4223,7 @@ void Game::playerSetShowOffSocket(uint32_t playerId, Outfit_t &outfit, const Pos } const auto mount = mounts.getMountByClientID(outfit.lookMount); - if (!mount || !player->hasMount(mount) || player->isSupportOutfit()) { + if (!mount || !player->hasMount(mount) || player->isWearingSupportOutfit()) { outfit.lookMount = 0; } @@ -5920,7 +5920,7 @@ void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit, uint8_t isMoun return; } - if (player->isSupportOutfit()) { + if (player->isWearingSupportOutfit()) { outfit.lookMount = 0; isMountRandomized = 0; } diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 3adee60e19c..379f1cd3ac6 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -3203,7 +3203,7 @@ void ProtocolGame::sendCreatureOutfit(std::shared_ptr creature, const } Outfit_t newOutfit = outfit; - if (player->isSupportOutfit()) { + if (player->isWearingSupportOutfit()) { player->setCurrentMount(0); newOutfit.lookMount = 0; } @@ -6872,7 +6872,7 @@ void ProtocolGame::sendOutfitWindow() { msg.addByte(0xC8); Outfit_t currentOutfit = player->getDefaultOutfit(); - auto isSupportOutfit = player->isSupportOutfit(); + auto isSupportOutfit = player->isWearingSupportOutfit(); bool mounted = false; if (!isSupportOutfit) {