From 4c54d85d63d361b64f5a5bf8b618a9644e3b6f24 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:04:41 -0300 Subject: [PATCH 01/29] 1/6 feature: Creature : AttachedEffect, Shader attachEffectById detachEffectById getShader setShader --- config.lua.dist | 8 +++ src/creatures/creature.cpp | 17 ++++++ src/creatures/creature.hpp | 13 ++++ src/creatures/players/player.cpp | 35 +++++++++++ src/creatures/players/player.hpp | 4 ++ src/game/game.cpp | 28 +++++++++ src/game/game.hpp | 3 + .../creatures/creature_functions.cpp | 59 +++++++++++++++++++ .../creatures/creature_functions.hpp | 8 +++ src/server/network/protocol/protocolgame.cpp | 42 +++++++++++++ src/server/network/protocol/protocolgame.hpp | 3 + 11 files changed, 220 insertions(+) diff --git a/config.lua.dist b/config.lua.dist index 7d0360d9360..3cb315c9ff0 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -588,3 +588,11 @@ metricsPrometheusAddress = "0.0.0.0:9464" --- OStream metricsEnableOstream = false metricsOstreamInterval = 1000 +OTCRFeatures = { -- posible* + ["enable"] = { + 102, -- GameCreatureAttachedEffect + 103 -- GameCreatureShader + }, + ["disable"] = { -- for example in 13.10 g_game.enableFeature(GameSequencedPackets) + } +} diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp index baf93fb651a..01f2665edf6 100644 --- a/src/creatures/creature.cpp +++ b/src/creatures/creature.cpp @@ -2002,3 +2002,20 @@ void Creature::sendAsyncTasks() { }, TaskGroup::WalkParallel); } + +void Creature::attachEffectById(uint16_t id) { + auto it = std::find(attachedEffectList.begin(), attachedEffectList.end(), id); + if (it != attachedEffectList.end()) { + return; + } + attachedEffectList.push_back(id); + g_game().sendAttachedEffect(static_self_cast(), id); +} +void Creature::detachEffectById(uint16_t id) { + auto it = std::find(attachedEffectList.begin(), attachedEffectList.end(), id); + if (it == attachedEffectList.end()) { + return; + } + attachedEffectList.erase(it); + g_game().sendDetachEffect(static_self_cast(), id); +} diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp index 46f628188e5..569547c4309 100644 --- a/src/creatures/creature.hpp +++ b/src/creatures/creature.hpp @@ -692,6 +692,17 @@ class Creature : virtual public Thing, public SharedObject { void setCharmChanceModifier(int8_t value) { charmChanceModifier = value; } + std::string getShader() const { + return shader; + } + void setShader(const std::string &shaderName) { + shader = shaderName; + } + void attachEffectById(uint16_t id); + void detachEffectById(uint16_t id); + const std::vector getAttachedEffectList() const { + return attachedEffectList; + } protected: enum FlagAsyncClass_t : uint8_t { @@ -881,4 +892,6 @@ class Creature : virtual public Thing, public SharedObject { } uint8_t m_flagAsyncTask = 0; + std::vector attachedEffectList; + std::string shader; }; diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index dfdf467aa97..fc652105ef3 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -9572,6 +9572,41 @@ void Player::sendLootContainers() const { } } +// OTCR Features + +void Player::sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId) const { + if (!client || !creature) { + return; + } + if (creature->getPlayer()) { + if (client) { + client->sendAttachedEffect(creature, effectId); + } + } +} + +void Player::sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId) const { + if (!client || !creature) { + return; + } + if (creature->getPlayer()) { + if (client) { + client->sendDetachEffect(creature, effectId); + } + } +} + +void Player::sendShader(const std::shared_ptr &creature, const std::string &shaderName) const { + if (!client || !creature) { + return; + } + if (creature->getPlayer()) { + if (client) { + client->sendShader(creature, shaderName); + } + } +} + void Player::sendSingleSoundEffect(const Position &pos, SoundEffect_t id, SourceEffect_t source) const { if (client) { client->sendSingleSoundEffect(pos, id, source); diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 03f248cfa2f..10e2213e0ed 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -1262,6 +1262,10 @@ class Player final : public Creature, public Cylinder, public Bankable { uint16_t getPlayerVocationEnum() const; + void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId) const; + void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId) const; + void sendShader(const std::shared_ptr &creature, const std::string &shaderName) const; + private: friend class PlayerLock; std::mutex mutex; diff --git a/src/game/game.cpp b/src/game/game.cpp index 49f8bf21d98..a44166fbe2d 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -10852,3 +10852,31 @@ void Game::updatePlayersOnline() const { g_logger().error("[Game::updatePlayersOnline] Failed to update players online."); } } + +void Game::sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId) { + auto spectators = Spectators().find(creature->getPosition(), true); + for (const auto &spectator : spectators) { + auto player = spectator->getPlayer(); + if (player) { // Solo procede si player no es nullptr + player->sendAttachedEffect(creature, effectId); + } + } +} +void Game::sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId) { + auto spectators = Spectators().find(creature->getPosition(), true); + for (const auto &spectator : spectators) { + auto player = spectator->getPlayer(); + if (player) { // Solo procede si player no es nullptr + player->sendDetachEffect(creature, effectId); + } + } +} +void Game::updateCreatureShader(const std::shared_ptr &creature) { + auto spectators = Spectators().find(creature->getPosition(), true); + for (const auto &spectator : spectators) { + auto player = spectator->getPlayer(); + if (player) { // Solo procede si player no es nullptr + player->sendShader(creature, creature->getShader()); + } + } +} diff --git a/src/game/game.hpp b/src/game/game.hpp index b1afd810100..edbb91a2441 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -712,6 +712,9 @@ class Game { const std::map &getBlessingNames(); const std::unordered_map &getHirelingSkills(); const std::unordered_map &getHirelingOutfits(); + void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId); + void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId); + void updateCreatureShader(const std::shared_ptr &creature); private: std::map m_achievements; diff --git a/src/lua/functions/creatures/creature_functions.cpp b/src/lua/functions/creatures/creature_functions.cpp index 0da3b6cc07a..11b76c5e7c4 100644 --- a/src/lua/functions/creatures/creature_functions.cpp +++ b/src/lua/functions/creatures/creature_functions.cpp @@ -1107,3 +1107,62 @@ int CreatureFunctions::luaCreatureClearIcons(lua_State* L) { pushBoolean(L, true); return 1; } + +int CreatureFunctions::luaCreatureAttachEffectById(lua_State* L) { + // creature:attachEffectById(effectId, [temporary]) + const auto &creature = getUserdataShared(L, 1); + if (!creature) { + reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + pushBoolean(L, false); + return 1; + } + uint16_t id = getNumber(L, 2); + bool temp = getBoolean(L, 3, false); + if (temp) { + g_game().sendAttachedEffect(creature, id); + } else { + creature->attachEffectById(id); + } + return 1; +} + +int CreatureFunctions::luaCreatureDetachEffectById(lua_State* L) { + // creature:detachEffectById(effectId) + const auto &creature = getUserdataShared(L, 1); + if (!creature) { + reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + pushBoolean(L, false); + return 1; + } + uint16_t id = getNumber(L, 2); + creature->detachEffectById(id); + return 1; +} + +int CreatureFunctions::luaCreatureGetShader(lua_State* L) { + // creature:getShader() + const auto &creature = getUserdataShared(L, 1); + if (!creature) { + reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + pushBoolean(L, false); + return 1; + } + + pushString(L, creature->getShader()); + + return 1; +} + +int CreatureFunctions::luaCreatureSetShader(lua_State* L) { + // creature:setShader(shaderName) + const auto &creature = getUserdataShared(L, 1); + if (!creature) { + reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + pushBoolean(L, false); + return 1; + } + creature->setShader(getString(L, 2)); + g_game().updateCreatureShader(creature); + pushBoolean(L, true); + return 1; +} diff --git a/src/lua/functions/creatures/creature_functions.hpp b/src/lua/functions/creatures/creature_functions.hpp index f0f1d12bb77..5dcf3eaac07 100644 --- a/src/lua/functions/creatures/creature_functions.hpp +++ b/src/lua/functions/creatures/creature_functions.hpp @@ -93,6 +93,10 @@ class CreatureFunctions final : LuaScriptInterface { registerMethod(L, "Creature", "getIcons", CreatureFunctions::luaCreatureGetIcons); registerMethod(L, "Creature", "removeIcon", CreatureFunctions::luaCreatureRemoveIcon); registerMethod(L, "Creature", "clearIcons", CreatureFunctions::luaCreatureClearIcons); + registerMethod(L, "Creature", "attachEffectById", CreatureFunctions::luaCreatureAttachEffectById); + registerMethod(L, "Creature", "detachEffectById", CreatureFunctions::luaCreatureDetachEffectById); + registerMethod(L, "Creature", "getShader", CreatureFunctions::luaCreatureGetShader); + registerMethod(L, "Creature", "setShader", CreatureFunctions::luaCreatureSetShader); CombatFunctions::init(L); MonsterFunctions::init(L); @@ -196,4 +200,8 @@ class CreatureFunctions final : LuaScriptInterface { static int luaCreatureGetIcon(lua_State* L); static int luaCreatureRemoveIcon(lua_State* L); static int luaCreatureClearIcons(lua_State* L); + static int luaCreatureAttachEffectById(lua_State* L); + static int luaCreatureDetachEffectById(lua_State* L); + static int luaCreatureGetShader(lua_State* L); + static int luaCreatureSetShader(lua_State* L); }; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 99c8a960677..35e05c9dbbc 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -7746,6 +7746,13 @@ void ProtocolGame::AddCreature(NetworkMessage &msg, const std::shared_ptrcanWalkthroughEx(creature) ? 0x00 : 0x01); + if (isOTC && otclientV8 == 0) { + msg.addString(creature->getShader()); + msg.addByte(static_cast(creature->getAttachedEffectList().size())); + for (const uint16_t id : creature->getAttachedEffectList()) { + msg.add(id); + } + } } void ProtocolGame::AddPlayerStats(NetworkMessage &msg) { @@ -9267,3 +9274,38 @@ void ProtocolGame::sendTakeScreenshot(Screenshot_t screenshotType) { msg.addByte(screenshotType); writeToOutputBuffer(msg); } + +void ProtocolGame::sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId) { + if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { + return; + } + + NetworkMessage msg; + msg.addByte(0x34); + msg.add(creature->getID()); + msg.add(effectId); + writeToOutputBuffer(msg); +} + +void ProtocolGame::sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId) { + if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { + return; + } + + NetworkMessage msg; + msg.addByte(0x35); + msg.add(creature->getID()); + msg.add(effectId); + writeToOutputBuffer(msg); +} + +void ProtocolGame::sendShader(const std::shared_ptr &creature, const std::string &shaderName) { + if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { + return; + } + NetworkMessage msg; + msg.addByte(0x36); + msg.add(creature->getID()); + msg.addString(shaderName); + writeToOutputBuffer(msg); +} diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index 27fa6c8716c..59b939ace38 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -542,6 +542,9 @@ class ProtocolGame final : public Protocol { void sendHotkeyPreset(); void sendTakeScreenshot(Screenshot_t screenshotType); void sendDisableLoginMusic(); + void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId); + void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId); + void sendShader(const std::shared_ptr &creature, const std::string &shaderName); uint8_t m_playerDeathTime = 0; From 745b7b807c233574ac732503c8d6ce93863cbc80 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:58:36 -0300 Subject: [PATCH 02/29] 2/7 feature: Map Shader player:setMapShader("Map - Party") --- src/creatures/players/player.cpp | 6 ++++ src/creatures/players/player.hpp | 8 ++++++ .../creatures/player/player_functions.cpp | 28 +++++++++++++++++++ .../creatures/player/player_functions.hpp | 7 +++++ src/server/network/protocol/protocolgame.cpp | 10 +++++++ src/server/network/protocol/protocolgame.hpp | 1 + 6 files changed, 60 insertions(+) diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index fc652105ef3..a4e125ec7af 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -9607,6 +9607,12 @@ void Player::sendShader(const std::shared_ptr &creature, const std::st } } +void Player::sendMapShader(const std::string &shaderName) const { + if (client) { + client->sendMapShader(shaderName); + } +} + void Player::sendSingleSoundEffect(const Position &pos, SoundEffect_t id, SourceEffect_t source) const { if (client) { client->sendSingleSoundEffect(pos, id, source); diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 10e2213e0ed..17e9f73bc70 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -1265,6 +1265,13 @@ class Player final : public Creature, public Cylinder, public Bankable { void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId) const; void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId) const; void sendShader(const std::shared_ptr &creature, const std::string &shaderName) const; + void sendMapShader(const std::string &shaderName) const; + const std::string &getMapShader() const { + return mapShader; + } + void setMapShader(const std::string &shaderName) { + this->mapShader = shaderName; + } private: friend class PlayerLock; @@ -1375,6 +1382,7 @@ class Player final : public Creature, public Cylinder, public Bankable { std::string name; std::string guildNick; std::string loyaltyTitle; + std::string mapShader; Skill skills[SKILL_LAST + 1]; LightInfo itemsLight; diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index c4c2faa8cee..2dc4da24616 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -4462,3 +4462,31 @@ int PlayerFunctions::luaPlayerSendCreatureAppear(lua_State* L) { pushBoolean(L, true); return 1; } + +int PlayerFunctions::luaPlayerGetMapShader(lua_State* L) { + // player:getMapShader() + const auto &player = getUserdataShared(L, 1); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + pushBoolean(L, false); + return 0; + } + + pushString(L, player->getMapShader()); + return 1; +} + + +int PlayerFunctions::luaPlayerSetMapShader(lua_State* L) { + // player:setMapShader(shaderName, [temporary]) + const auto &player = getUserdataShared(L, 1); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + pushBoolean(L, false); + return 0; + } + const auto shaderName = getString(L, 2); + player->sendMapShader(shaderName); + pushBoolean(L, true); + return 1; +} diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp index 090e4371abe..3457836132e 100644 --- a/src/lua/functions/creatures/player/player_functions.hpp +++ b/src/lua/functions/creatures/player/player_functions.hpp @@ -388,6 +388,10 @@ class PlayerFunctions final : LuaScriptInterface { registerMethod(L, "Player", "removeIconBakragore", PlayerFunctions::luaPlayerRemoveIconBakragore); registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear); + // OTCR Features + registerMethod(L, "Player", "getMapShader", PlayerFunctions::luaPlayerGetMapShader); + registerMethod(L, "Player", "setMapShader", PlayerFunctions::luaPlayerSetMapShader); + GroupFunctions::init(L); GuildFunctions::init(L); MountFunctions::init(L); @@ -755,6 +759,9 @@ class PlayerFunctions final : LuaScriptInterface { static int luaPlayerRemoveIconBakragore(lua_State* L); static int luaPlayerSendCreatureAppear(lua_State* L); + + static int luaPlayerGetMapShader(lua_State* L); + static int luaPlayerSetMapShader(lua_State* L); friend class CreatureFunctions; }; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 35e05c9dbbc..aeea3c32a6b 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -9309,3 +9309,13 @@ void ProtocolGame::sendShader(const std::shared_ptr &creature, const s msg.addString(shaderName); writeToOutputBuffer(msg); } + +void ProtocolGame::sendMapShader(const std::string &shaderName) { + if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { + return; + } + NetworkMessage msg; + msg.addByte(0x37); + msg.addString(shaderName); + writeToOutputBuffer(msg); +} diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index 59b939ace38..f2bbb41d8e9 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -545,6 +545,7 @@ class ProtocolGame final : public Protocol { void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId); void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId); void sendShader(const std::shared_ptr &creature, const std::string &shaderName); + void sendMapShader( const std::string &shaderName); uint8_t m_playerDeathTime = 0; From ee26730227c121bfd07bebfcc610fa12ae23ff8e Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Mon, 4 Nov 2024 21:39:09 -0300 Subject: [PATCH 03/29] 3/7 feature: TypingIcon --- src/creatures/players/player.cpp | 6 ++++++ src/creatures/players/player.hpp | 1 + src/game/game.cpp | 22 +++++++++++++++++--- src/game/game.hpp | 2 ++ src/server/network/protocol/protocolgame.cpp | 19 +++++++++++++++++ src/server/network/protocol/protocolgame.hpp | 11 ++++++---- 6 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index a4e125ec7af..d65d5ad9349 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -9613,6 +9613,12 @@ void Player::sendMapShader(const std::string &shaderName) const { } } +void Player::sendPlayerTyping(const std::shared_ptr &creature, uint8_t typing) const { + if (client) { + client->sendPlayerTyping(creature, typing); + } +} + void Player::sendSingleSoundEffect(const Position &pos, SoundEffect_t id, SourceEffect_t source) const { if (client) { client->sendSingleSoundEffect(pos, id, source); diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 17e9f73bc70..8745bc48e00 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -1272,6 +1272,7 @@ class Player final : public Creature, public Cylinder, public Bankable { void setMapShader(const std::string &shaderName) { this->mapShader = shaderName; } + void sendPlayerTyping(const std::shared_ptr &creature, uint8_t typing) const; private: friend class PlayerLock; diff --git a/src/game/game.cpp b/src/game/game.cpp index a44166fbe2d..c4d4f6860b1 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -10857,7 +10857,7 @@ void Game::sendAttachedEffect(const std::shared_ptr &creature, uint16_ auto spectators = Spectators().find(creature->getPosition(), true); for (const auto &spectator : spectators) { auto player = spectator->getPlayer(); - if (player) { // Solo procede si player no es nullptr + if (player) { player->sendAttachedEffect(creature, effectId); } } @@ -10866,7 +10866,7 @@ void Game::sendDetachEffect(const std::shared_ptr &creature, uint16_t auto spectators = Spectators().find(creature->getPosition(), true); for (const auto &spectator : spectators) { auto player = spectator->getPlayer(); - if (player) { // Solo procede si player no es nullptr + if (player) { player->sendDetachEffect(creature, effectId); } } @@ -10875,8 +10875,24 @@ void Game::updateCreatureShader(const std::shared_ptr &creature) { auto spectators = Spectators().find(creature->getPosition(), true); for (const auto &spectator : spectators) { auto player = spectator->getPlayer(); - if (player) { // Solo procede si player no es nullptr + if (player) { player->sendShader(creature, creature->getShader()); } } } + +void Game::playerSetTyping(uint32_t playerId, uint8_t typing) { + const auto &player = getPlayerByID(playerId); + if (!player) { + return; + } + auto spectators = Spectators().find(player->getPosition(), true); + auto playersSpectators = spectators.filter(); + for (const auto &spectator : spectators) { + if (const auto &tmpPlayer = spectator->getPlayer()) { + tmpPlayer->sendPlayerTyping(player, typing); + } + } +} + + diff --git a/src/game/game.hpp b/src/game/game.hpp index edbb91a2441..13a001665a3 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -715,6 +715,8 @@ class Game { void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId); void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId); void updateCreatureShader(const std::shared_ptr &creature); + void playerSetTyping(uint32_t playerId, uint8_t typing); + private: std::map m_achievements; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index aeea3c32a6b..153fa8e2c59 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -1032,6 +1032,9 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage &msg, uint8_t recvby case 0x32: parseExtendedOpcode(msg); break; // otclient extended opcode + case 0x38: + parsePlayerTyping(msg); // player are typing or not + break; case 0x60: parseInventoryImbuements(msg); break; @@ -2512,6 +2515,11 @@ void ProtocolGame::parseCyclopediaMonsterTracker(NetworkMessage &msg) { } } +void ProtocolGame::parsePlayerTyping(NetworkMessage &msg) { + uint8_t typing = msg.getByte(); + g_dispatcher().addEvent([self = getThis(), playerID = player->getID(), typing] { g_game().playerSetTyping(playerID, typing); }, __FUNCTION__); +} + void ProtocolGame::sendTeamFinderList() { if (!player || oldProtocol) { return; @@ -9319,3 +9327,14 @@ void ProtocolGame::sendMapShader(const std::string &shaderName) { msg.addString(shaderName); writeToOutputBuffer(msg); } + +void ProtocolGame::sendPlayerTyping(const std::shared_ptr &creature, uint8_t typing) { + if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { + return; + } + NetworkMessage msg; + msg.addByte(0x38); + msg.add(creature->getID()); + msg.addByte(typing); + writeToOutputBuffer(msg); +} diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index f2bbb41d8e9..2f318bb128f 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -489,6 +489,13 @@ class ProtocolGame final : public Protocol { // OTCv8 void sendFeatures(); + // OTCR + void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId); + void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId); + void sendShader(const std::shared_ptr &creature, const std::string &shaderName); + void sendMapShader(const std::string &shaderName); + void sendPlayerTyping(const std::shared_ptr &creature, uint8_t typing); + void parsePlayerTyping(NetworkMessage &msg); void parseInventoryImbuements(NetworkMessage &msg); void sendInventoryImbuements(const std::map> &items); @@ -542,10 +549,6 @@ class ProtocolGame final : public Protocol { void sendHotkeyPreset(); void sendTakeScreenshot(Screenshot_t screenshotType); void sendDisableLoginMusic(); - void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId); - void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId); - void sendShader(const std::shared_ptr &creature, const std::string &shaderName); - void sendMapShader( const std::string &shaderName); uint8_t m_playerDeathTime = 0; From 23e166a147c90060f49bbec8d7b573ffd8848793 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Mon, 4 Nov 2024 22:46:28 -0300 Subject: [PATCH 04/29] review: mehah --- src/game/game.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index c4d4f6860b1..f21bd69a537 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -10854,7 +10854,7 @@ void Game::updatePlayersOnline() const { } void Game::sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId) { - auto spectators = Spectators().find(creature->getPosition(), true); + auto spectators = Spectators().find(creature->getPosition(), true); for (const auto &spectator : spectators) { auto player = spectator->getPlayer(); if (player) { @@ -10863,7 +10863,7 @@ void Game::sendAttachedEffect(const std::shared_ptr &creature, uint16_ } } void Game::sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId) { - auto spectators = Spectators().find(creature->getPosition(), true); + auto spectators = Spectators().find(creature->getPosition(), true); for (const auto &spectator : spectators) { auto player = spectator->getPlayer(); if (player) { @@ -10872,7 +10872,7 @@ void Game::sendDetachEffect(const std::shared_ptr &creature, uint16_t } } void Game::updateCreatureShader(const std::shared_ptr &creature) { - auto spectators = Spectators().find(creature->getPosition(), true); + auto spectators = Spectators().find(creature->getPosition(), true); for (const auto &spectator : spectators) { auto player = spectator->getPlayer(); if (player) { @@ -10886,9 +10886,8 @@ void Game::playerSetTyping(uint32_t playerId, uint8_t typing) { if (!player) { return; } - auto spectators = Spectators().find(player->getPosition(), true); - auto playersSpectators = spectators.filter(); - for (const auto &spectator : spectators) { + + for (const auto &spectator : Spectators().find(player->getPosition(), true)) { if (const auto &tmpPlayer = spectator->getPlayer()) { tmpPlayer->sendPlayerTyping(player, typing); } From eae411286740475f49e2769f817e18b468654092 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Mon, 4 Nov 2024 23:59:16 -0300 Subject: [PATCH 05/29] 4/7 feature: Item Shader --- config.lua.dist | 10 +++-- src/game/game.cpp | 35 +++++++++++++++++- src/game/game.hpp | 2 +- src/items/item.hpp | 18 +++++++++ src/lua/functions/items/item_functions.cpp | 39 ++++++++++++++++++++ src/lua/functions/items/item_functions.hpp | 7 ++++ src/server/network/protocol/protocolgame.cpp | 10 +++++ 7 files changed, 115 insertions(+), 6 deletions(-) diff --git a/config.lua.dist b/config.lua.dist index 3cb315c9ff0..9691169b731 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -588,11 +588,13 @@ metricsPrometheusAddress = "0.0.0.0:9464" --- OStream metricsEnableOstream = false metricsOstreamInterval = 1000 -OTCRFeatures = { -- posible* + +--- OTC +OTCRFeatures = { -- possible* ["enable"] = { - 102, -- GameCreatureAttachedEffect - 103 -- GameCreatureShader + 102, -- g_game.enableFeature(GameCreatureAttachedEffect) + 103 -- g_game.enableFeature(GameCreatureShader) }, - ["disable"] = { -- for example in 13.10 g_game.enableFeature(GameSequencedPackets) + ["disable"] = { -- utility ,for example in 13.10 g_game.disableFeature(GameSequencedPackets) } } diff --git a/src/game/game.cpp b/src/game/game.cpp index f21bd69a537..ad9d213b6b6 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -10894,4 +10894,37 @@ void Game::playerSetTyping(uint32_t playerId, uint8_t typing) { } } - +void Game::refreshItem(const std::shared_ptr &item) { + if (!item || !item->getParent()) { + return; + } + const auto &parent = item->getParent(); + if (const auto &creature = parent->getCreature()) { + if (const auto &player = creature->getPlayer()) { + int32_t index = player->getThingIndex(item); + if (index > -1) { + player->sendInventoryItem(static_cast(index), item); + } + } + return; + } + if (const auto &container = parent->getContainer()) { + int32_t index = container->getThingIndex(item); + if (index > -1 && index <= std::numeric_limits::max()) { + const auto spectators = Spectators().find(container->getPosition(), false, 2, 2, 2, 2); + // send to client + for (const auto &spectator : spectators) { + spectator->getPlayer()->sendUpdateContainerItem(container, static_cast(index), item); + } + } + return; + } + if (const auto &tile = parent->getTile()) { + const auto spectators = Spectators().find(tile->getPosition(), true); + // send to client + for (const auto &spectator : spectators) { + spectator->getPlayer()->sendUpdateTileItem(tile, tile->getPosition(), item); + } + return; + } +} diff --git a/src/game/game.hpp b/src/game/game.hpp index 13a001665a3..7f421780efc 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -716,7 +716,7 @@ class Game { void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId); void updateCreatureShader(const std::shared_ptr &creature); void playerSetTyping(uint32_t playerId, uint8_t typing); - + void refreshItem(const std::shared_ptr &item); private: std::map m_achievements; diff --git a/src/items/item.hpp b/src/items/item.hpp index d199fab15cf..a334b71ef4c 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -141,6 +141,24 @@ class ItemProperties { return getCorpseOwner() == static_cast(std::numeric_limits::max()); } + void setShader(const std::string &shaderName) { + if (shaderName.empty()) { + removeCustomAttribute("shader"); + return; + } + + setCustomAttribute("shader", shaderName); + } + + bool hasShader() const { + return getCustomAttribute("shader") != nullptr; + } + + std::string getShader() const { + const CustomAttribute* shader = getCustomAttribute("shader"); + return shader ? shader->getString() : ""; + } + protected: std::unique_ptr &initAttributePtr() { if (!attributePtr) { diff --git a/src/lua/functions/items/item_functions.cpp b/src/lua/functions/items/item_functions.cpp index c54d43bc94b..4c37670d7e4 100644 --- a/src/lua/functions/items/item_functions.cpp +++ b/src/lua/functions/items/item_functions.cpp @@ -1040,3 +1040,42 @@ int ItemFunctions::luaItemHasOwner(lua_State* L) { pushBoolean(L, item->hasOwner()); return 1; } + +int ItemFunctions::luaItemHasShader(lua_State* L) { + // item:hasShader() + const auto &item = getUserdataShared(L, 1); + if (!item) { + reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + return 1; + } + + pushBoolean(L, item->hasShader()); + return 1; +} + +int ItemFunctions::luaItemGetShader(lua_State* L) { + // item:getShader() + const auto &item = getUserdataShared(L, 1); + if (!item) { + reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + pushBoolean(L, false); + return 1; + } + + pushString(L, item->getShader()); + return 1; +} + +int ItemFunctions::luaItemSetShader(lua_State* L) { + // item:setShader(shaderName) + const auto &item = getUserdataShared(L, 1); + if (!item) { + reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + pushBoolean(L, false); + return 1; + } + + item->setShader(getString(L, 2)); + pushBoolean(L, true); + return 1; +} diff --git a/src/lua/functions/items/item_functions.hpp b/src/lua/functions/items/item_functions.hpp index 1cf3764eac8..0f5a2fcad5c 100644 --- a/src/lua/functions/items/item_functions.hpp +++ b/src/lua/functions/items/item_functions.hpp @@ -97,6 +97,9 @@ class ItemFunctions final : LuaScriptInterface { registerMethod(L, "Item", "canReceiveAutoCarpet", ItemFunctions::luaItemCanReceiveAutoCarpet); + registerMethod(L, "Item", "setShader", ItemFunctions::luaItemSetShader); + registerMethod(L, "Item", "getShader", ItemFunctions::luaItemGetShader); + registerMethod(L, "Item", "hasShader", ItemFunctions::luaItemHasShader); ContainerFunctions::init(L); ImbuementFunctions::init(L); ItemTypeFunctions::init(L); @@ -175,4 +178,8 @@ class ItemFunctions final : LuaScriptInterface { static int luaItemIsOwner(lua_State* L); static int luaItemGetOwnerName(lua_State* L); static int luaItemHasOwner(lua_State* L); + + static int luaItemSetShader(lua_State* L); + static int luaItemGetShader(lua_State* L); + static int luaItemHasShader(lua_State* L); }; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 153fa8e2c59..0b1756b48cb 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -318,6 +318,11 @@ void ProtocolGame::AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint if (it.isWrapKit && !oldProtocol) { msg.add(0x00); } + + // OTCR Features + if (isOTC && otclientV8 == 0) { + msg.addString(""); + } } void ProtocolGame::AddItem(NetworkMessage &msg, const std::shared_ptr &item) { @@ -462,6 +467,11 @@ void ProtocolGame::AddItem(NetworkMessage &msg, const std::shared_ptr &ite msg.add(0x00); } } + + // OTCR Features + if (isOTC && otclientV8 == 0) { + msg.addString(item->getShader()); + } } void ProtocolGame::release() { From 74ea55f7d1cd035b57d1ca97f330fbb158f1837a Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Tue, 5 Nov 2024 01:11:39 -0300 Subject: [PATCH 06/29] 5/7 send disableFeature / enableFeature const auto &enabledFeatures = g_configManager().getEnabledOTCFeatures(); const auto &disabledFeatures = g_configManager().getDisabledOTCFeatures(); for (int32_t feature : enabledFeatures) { g_logger().info("Feature enabled: {}", feature); } for (int32_t feature : disabledFeatures) { g_logger().info("Feature disabled: {}", feature); } Update configmanager.hpp --- config.lua.dist | 11 +++-- src/config/configmanager.cpp | 42 ++++++++++++++++++++ src/config/configmanager.hpp | 6 +++ src/server/network/protocol/protocolgame.cpp | 22 ++++++++++ src/server/network/protocol/protocolgame.hpp | 1 + 5 files changed, 78 insertions(+), 4 deletions(-) diff --git a/config.lua.dist b/config.lua.dist index 9691169b731..f6d4494879a 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -589,12 +589,15 @@ metricsPrometheusAddress = "0.0.0.0:9464" metricsEnableOstream = false metricsOstreamInterval = 1000 ---- OTC -OTCRFeatures = { -- possible* - ["enable"] = { +-- OTC Features +-- NOTE: Features added in this list will be forced to be used on the client +-- These features can be found in "modules/gamelib/const.lua" +OTCRFeatures = { + enable = { + 101, -- g_game.enableFeature(GameItemShader) 102, -- g_game.enableFeature(GameCreatureAttachedEffect) 103 -- g_game.enableFeature(GameCreatureShader) }, - ["disable"] = { -- utility ,for example in 13.10 g_game.disableFeature(GameSequencedPackets) + disable = { -- utility: for example in 13.10 g_game.disableFeature(GameSequencedPackets) } } diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index 1c00df76c2f..56510007d6a 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -363,6 +363,8 @@ bool ConfigManager::load() { loadStringConfig(L, WORLD_TYPE, "worldType", "pvp"); loadStringConfig(L, LOGLEVEL, "logLevel", "info"); + loadLuaOTCFeatures(L); + loaded = true; lua_close(L); return true; @@ -464,3 +466,43 @@ float ConfigManager::getFloat(const ConfigKey_t &key, const std::source_location g_logger().warn("[{}] accessing invalid or wrong type index: {}[{}]. Called line: {}:{}, in {}", __FUNCTION__, magic_enum::enum_name(key), fmt::underlying(key), location.line(), location.column(), location.function_name()); return 0.0f; } + +void ConfigManager::loadLuaOTCFeatures(lua_State* L) { + lua_getglobal(L, "OTCRFeatures"); + if (!lua_istable(L, -1)) { + return; + } + + lua_pushstring(L, "enable"); + lua_gettable(L, -2); + if (lua_istable(L, -1)) { + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + const auto feature = static_cast(lua_tointeger(L, -1)); + enabledOTCFeatures.push_back(feature); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + lua_pushstring(L, "disable"); + lua_gettable(L, -2); + if (lua_istable(L, -1)) { + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + const auto feature = static_cast(lua_tointeger(L, -1)); + disabledOTCFeatures.push_back(feature); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + lua_pop(L, 1); +} +OTCFeatures ConfigManager::getEnabledOTCFeatures() const { + return enabledOTCFeatures; +} + +OTCFeatures ConfigManager::getDisabledOTCFeatures() const { + return disabledOTCFeatures; +} diff --git a/src/config/configmanager.hpp b/src/config/configmanager.hpp index ddc15e45ed3..17a8028a52b 100644 --- a/src/config/configmanager.hpp +++ b/src/config/configmanager.hpp @@ -12,6 +12,7 @@ #include "config_enums.hpp" using ConfigValue = std::variant; +using OTCFeatures = std::vector; class ConfigManager { public: @@ -40,6 +41,8 @@ class ConfigManager { [[nodiscard]] int32_t getNumber(const ConfigKey_t &key, const std::source_location &location = std::source_location::current()) const; [[nodiscard]] bool getBoolean(const ConfigKey_t &key, const std::source_location &location = std::source_location::current()) const; [[nodiscard]] float getFloat(const ConfigKey_t &key, const std::source_location &location = std::source_location::current()) const; + OTCFeatures getEnabledOTCFeatures() const; + OTCFeatures getDisabledOTCFeatures() const; private: phmap::flat_hash_map configs; @@ -50,6 +53,9 @@ class ConfigManager { std::string configFileLua = { "config.lua" }; bool loaded = false; + OTCFeatures enabledOTCFeatures = {}; + OTCFeatures disabledOTCFeatures = {}; + void loadLuaOTCFeatures(lua_State* L); }; constexpr auto g_configManager = ConfigManager::getInstance; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 0b1756b48cb..dc27820e2e6 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -494,6 +494,9 @@ void ProtocolGame::login(const std::string &name, uint32_t accountId, OperatingS // Extended opcodes if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) { isOTC = true; + if (isOTC && otclientV8 == 0) { + //sendOTCRFeatures(); // need pr in redemption + } NetworkMessage opcodeMessage; opcodeMessage.addByte(0x32); opcodeMessage.addByte(0x00); @@ -8393,6 +8396,25 @@ void ProtocolGame::sendFeatures() { writeToOutputBuffer(msg); } +// OTCR +void ProtocolGame::sendOTCRFeatures() { + const auto &enabledFeatures = g_configManager().getEnabledOTCFeatures(); + const auto &disabledFeatures = g_configManager().getDisabledOTCFeatures(); + NetworkMessage msg; + msg.addByte(0x43); + uint16_t totalFeatures = static_cast(enabledFeatures.size() + disabledFeatures.size()); + msg.add(totalFeatures); + for (int32_t feature : enabledFeatures) { + msg.addByte(static_cast(feature)); + msg.addByte(0x01); + } + for (int32_t feature : disabledFeatures) { + msg.addByte(static_cast(feature)); + msg.addByte(0x00); + } + writeToOutputBuffer(msg); +} + void ProtocolGame::parseInventoryImbuements(NetworkMessage &msg) { if (oldProtocol) { return; diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index 2f318bb128f..d74d282d8fc 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -490,6 +490,7 @@ class ProtocolGame final : public Protocol { // OTCv8 void sendFeatures(); // OTCR + void sendOTCRFeatures(); void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId); void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId); void sendShader(const std::shared_ptr &creature, const std::string &shaderName); From b09547e7340bfe6c247c9448b357de28db0c1ac7 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Tue, 5 Nov 2024 02:17:55 -0300 Subject: [PATCH 07/29] review: dudantas --- src/creatures/creature.cpp | 4 +-- src/creatures/creature.hpp | 2 +- src/creatures/players/player.cpp | 27 +++++++++---------- src/creatures/players/player.hpp | 10 +++---- src/game/game.cpp | 9 ++++--- src/items/item.hpp | 6 ++--- .../creatures/player/player_functions.cpp | 2 +- src/lua/functions/items/item_functions.cpp | 3 ++- src/server/network/protocol/protocolgame.cpp | 12 ++++----- src/server/network/protocol/protocolgame.hpp | 4 +-- 10 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp index 01f2665edf6..4f9cff5bff4 100644 --- a/src/creatures/creature.cpp +++ b/src/creatures/creature.cpp @@ -2004,7 +2004,7 @@ void Creature::sendAsyncTasks() { } void Creature::attachEffectById(uint16_t id) { - auto it = std::find(attachedEffectList.begin(), attachedEffectList.end(), id); + auto it = std::ranges::find(attachedEffectList, id); if (it != attachedEffectList.end()) { return; } @@ -2012,7 +2012,7 @@ void Creature::attachEffectById(uint16_t id) { g_game().sendAttachedEffect(static_self_cast(), id); } void Creature::detachEffectById(uint16_t id) { - auto it = std::find(attachedEffectList.begin(), attachedEffectList.end(), id); + auto it = std::ranges::find(attachedEffectList, id); if (it == attachedEffectList.end()) { return; } diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp index 569547c4309..9a20f410b9f 100644 --- a/src/creatures/creature.hpp +++ b/src/creatures/creature.hpp @@ -695,7 +695,7 @@ class Creature : virtual public Thing, public SharedObject { std::string getShader() const { return shader; } - void setShader(const std::string &shaderName) { + void setShader(const std::string_view &shaderName) { shader = shaderName; } void attachEffectById(uint16_t id); diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index d65d5ad9349..ccdab30964e 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -9578,10 +9578,9 @@ void Player::sendAttachedEffect(const std::shared_ptr &creature, uint1 if (!client || !creature) { return; } + if (creature->getPlayer()) { - if (client) { - client->sendAttachedEffect(creature, effectId); - } + client->sendAttachedEffect(creature, effectId); } } @@ -9590,33 +9589,33 @@ void Player::sendDetachEffect(const std::shared_ptr &creature, uint16_ return; } if (creature->getPlayer()) { - if (client) { - client->sendDetachEffect(creature, effectId); - } + client->sendDetachEffect(creature, effectId); } } -void Player::sendShader(const std::shared_ptr &creature, const std::string &shaderName) const { +void Player::sendShader(const std::shared_ptr &creature, const std::string_view &shaderName) const { if (!client || !creature) { return; } if (creature->getPlayer()) { - if (client) { client->sendShader(creature, shaderName); - } } } -void Player::sendMapShader(const std::string &shaderName) const { - if (client) { - client->sendMapShader(shaderName); +void Player::sendMapShader(const std::string_view &shaderName) const { + if (!client) { + return; } + + client->sendMapShader(shaderName); } void Player::sendPlayerTyping(const std::shared_ptr &creature, uint8_t typing) const { - if (client) { - client->sendPlayerTyping(creature, typing); + if (!client) { + return; } + + client->sendPlayerTyping(creature, typing); } void Player::sendSingleSoundEffect(const Position &pos, SoundEffect_t id, SourceEffect_t source) const { diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 8745bc48e00..4159da9a327 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -1264,12 +1264,12 @@ class Player final : public Creature, public Cylinder, public Bankable { void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId) const; void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId) const; - void sendShader(const std::shared_ptr &creature, const std::string &shaderName) const; - void sendMapShader(const std::string &shaderName) const; - const std::string &getMapShader() const { + void sendShader(const std::shared_ptr &creature, const std::string_view &shaderName) const; + void sendMapShader(const std::string_view &shaderName) const; + const std::string_view &getMapShader() const { return mapShader; } - void setMapShader(const std::string &shaderName) { + void setMapShader(const std::string_view &shaderName) { this->mapShader = shaderName; } void sendPlayerTyping(const std::shared_ptr &creature, uint8_t typing) const; @@ -1383,7 +1383,7 @@ class Player final : public Creature, public Cylinder, public Bankable { std::string name; std::string guildNick; std::string loyaltyTitle; - std::string mapShader; + std::string_view mapShader; Skill skills[SKILL_LAST + 1]; LightInfo itemsLight; diff --git a/src/game/game.cpp b/src/game/game.cpp index ad9d213b6b6..b4a8702a572 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -10856,25 +10856,27 @@ void Game::updatePlayersOnline() const { void Game::sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId) { auto spectators = Spectators().find(creature->getPosition(), true); for (const auto &spectator : spectators) { - auto player = spectator->getPlayer(); + const auto &player = spectator->getPlayer(); if (player) { player->sendAttachedEffect(creature, effectId); } } } + void Game::sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId) { auto spectators = Spectators().find(creature->getPosition(), true); for (const auto &spectator : spectators) { - auto player = spectator->getPlayer(); + const auto &player = spectator->getPlayer(); if (player) { player->sendDetachEffect(creature, effectId); } } } + void Game::updateCreatureShader(const std::shared_ptr &creature) { auto spectators = Spectators().find(creature->getPosition(), true); for (const auto &spectator : spectators) { - auto player = spectator->getPlayer(); + const auto &player = spectator->getPlayer(); if (player) { player->sendShader(creature, creature->getShader()); } @@ -10886,7 +10888,6 @@ void Game::playerSetTyping(uint32_t playerId, uint8_t typing) { if (!player) { return; } - for (const auto &spectator : Spectators().find(player->getPosition(), true)) { if (const auto &tmpPlayer = spectator->getPlayer()) { tmpPlayer->sendPlayerTyping(player, typing); diff --git a/src/items/item.hpp b/src/items/item.hpp index a334b71ef4c..dad0e691619 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -141,20 +141,20 @@ class ItemProperties { return getCorpseOwner() == static_cast(std::numeric_limits::max()); } - void setShader(const std::string &shaderName) { + void setShader(const std::string_view &shaderName) { if (shaderName.empty()) { removeCustomAttribute("shader"); return; } - setCustomAttribute("shader", shaderName); + setCustomAttribute("shader", std::string(shaderName)); // temp } bool hasShader() const { return getCustomAttribute("shader") != nullptr; } - std::string getShader() const { + std::string_view getShader() const { const CustomAttribute* shader = getCustomAttribute("shader"); return shader ? shader->getString() : ""; } diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index 2dc4da24616..1ec62b01240 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -4472,7 +4472,7 @@ int PlayerFunctions::luaPlayerGetMapShader(lua_State* L) { return 0; } - pushString(L, player->getMapShader()); + pushString(L, std::string(player->getMapShader())); // temp return 1; } diff --git a/src/lua/functions/items/item_functions.cpp b/src/lua/functions/items/item_functions.cpp index 4c37670d7e4..44423ea5ab3 100644 --- a/src/lua/functions/items/item_functions.cpp +++ b/src/lua/functions/items/item_functions.cpp @@ -1062,7 +1062,7 @@ int ItemFunctions::luaItemGetShader(lua_State* L) { return 1; } - pushString(L, item->getShader()); + pushString(L, std::string(item->getShader())); // temp return 1; } @@ -1076,6 +1076,7 @@ int ItemFunctions::luaItemSetShader(lua_State* L) { } item->setShader(getString(L, 2)); + g_game().refreshItem(item); pushBoolean(L, true); return 1; } diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index dc27820e2e6..a70b6659166 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -470,7 +470,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, const std::shared_ptr &ite // OTCR Features if (isOTC && otclientV8 == 0) { - msg.addString(item->getShader()); + msg.addString(std::string(item->getShader())); // temp } } @@ -9320,7 +9320,7 @@ void ProtocolGame::sendAttachedEffect(const std::shared_ptr &creature, return; } - NetworkMessage msg; + NetworkMessage msg; msg.addByte(0x34); msg.add(creature->getID()); msg.add(effectId); @@ -9339,24 +9339,24 @@ void ProtocolGame::sendDetachEffect(const std::shared_ptr &creature, u writeToOutputBuffer(msg); } -void ProtocolGame::sendShader(const std::shared_ptr &creature, const std::string &shaderName) { +void ProtocolGame::sendShader(const std::shared_ptr &creature, const std::string_view &shaderName) { if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { return; } NetworkMessage msg; msg.addByte(0x36); msg.add(creature->getID()); - msg.addString(shaderName); + msg.addString(std::string(shaderName)); // temp writeToOutputBuffer(msg); } -void ProtocolGame::sendMapShader(const std::string &shaderName) { +void ProtocolGame::sendMapShader(const std::string_view &shaderName) { if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { return; } NetworkMessage msg; msg.addByte(0x37); - msg.addString(shaderName); + msg.addString(std::string(shaderName)); // temp writeToOutputBuffer(msg); } diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index d74d282d8fc..20b39e45b94 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -493,8 +493,8 @@ class ProtocolGame final : public Protocol { void sendOTCRFeatures(); void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId); void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId); - void sendShader(const std::shared_ptr &creature, const std::string &shaderName); - void sendMapShader(const std::string &shaderName); + void sendShader(const std::shared_ptr &creature, const std::string_view &shaderName); + void sendMapShader(const std::string_view &shaderName); void sendPlayerTyping(const std::shared_ptr &creature, uint8_t typing); void parsePlayerTyping(NetworkMessage &msg); From 9484492ab847ce40b01b900d6b7bbaf190615a2d Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Tue, 5 Nov 2024 02:46:01 -0300 Subject: [PATCH 08/29] fix sonarcloud bot --- src/creatures/creature.hpp | 2 +- src/server/network/protocol/protocolgame.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp index 9a20f410b9f..77b0b91429b 100644 --- a/src/creatures/creature.hpp +++ b/src/creatures/creature.hpp @@ -700,7 +700,7 @@ class Creature : virtual public Thing, public SharedObject { } void attachEffectById(uint16_t id); void detachEffectById(uint16_t id); - const std::vector getAttachedEffectList() const { + std::vector getAttachedEffectList() const { return attachedEffectList; } diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index a70b6659166..97d7b34e94e 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -495,7 +495,7 @@ void ProtocolGame::login(const std::string &name, uint32_t accountId, OperatingS if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) { isOTC = true; if (isOTC && otclientV8 == 0) { - //sendOTCRFeatures(); // need pr in redemption + //sendOTCRFeatures(); first I need to make pr in redemption } NetworkMessage opcodeMessage; opcodeMessage.addByte(0x32); @@ -8402,7 +8402,7 @@ void ProtocolGame::sendOTCRFeatures() { const auto &disabledFeatures = g_configManager().getDisabledOTCFeatures(); NetworkMessage msg; msg.addByte(0x43); - uint16_t totalFeatures = static_cast(enabledFeatures.size() + disabledFeatures.size()); + auto totalFeatures = static_cast(enabledFeatures.size() + disabledFeatures.size()); msg.add(totalFeatures); for (int32_t feature : enabledFeatures) { msg.addByte(static_cast(feature)); From f490ce45e99c5d1d2d3125729589fe8003c7443d Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Tue, 5 Nov 2024 02:47:02 -0300 Subject: [PATCH 09/29] fix sonarcloud bot 2 --- src/server/network/protocol/protocolgame.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 97d7b34e94e..07a4b85da28 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -8404,11 +8404,11 @@ void ProtocolGame::sendOTCRFeatures() { msg.addByte(0x43); auto totalFeatures = static_cast(enabledFeatures.size() + disabledFeatures.size()); msg.add(totalFeatures); - for (int32_t feature : enabledFeatures) { + for (auto feature : enabledFeatures) { msg.addByte(static_cast(feature)); msg.addByte(0x01); } - for (int32_t feature : disabledFeatures) { + for (auto feature : disabledFeatures) { msg.addByte(static_cast(feature)); msg.addByte(0x00); } From 1437b7eff2fa52acfd5ae9892bd8899d0d349535 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Tue, 5 Nov 2024 03:10:22 -0300 Subject: [PATCH 10/29] fix: wrong review --- src/creatures/creature.hpp | 2 +- src/creatures/players/player.cpp | 4 ++-- src/creatures/players/player.hpp | 10 +++++----- src/items/item.cpp | 18 ++++++++++++++++++ src/items/item.hpp | 19 +++---------------- .../creatures/player/player_functions.cpp | 2 +- src/lua/functions/items/item_functions.cpp | 2 +- src/server/network/protocol/protocolgame.cpp | 10 +++++----- src/server/network/protocol/protocolgame.hpp | 4 ++-- 9 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp index 77b0b91429b..87f4cae3a09 100644 --- a/src/creatures/creature.hpp +++ b/src/creatures/creature.hpp @@ -695,7 +695,7 @@ class Creature : virtual public Thing, public SharedObject { std::string getShader() const { return shader; } - void setShader(const std::string_view &shaderName) { + void setShader(const std::string_view shaderName) { shader = shaderName; } void attachEffectById(uint16_t id); diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index ccdab30964e..ce59755a3c0 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -9593,7 +9593,7 @@ void Player::sendDetachEffect(const std::shared_ptr &creature, uint16_ } } -void Player::sendShader(const std::shared_ptr &creature, const std::string_view &shaderName) const { +void Player::sendShader(const std::shared_ptr &creature, const std::string &shaderName) const { if (!client || !creature) { return; } @@ -9602,7 +9602,7 @@ void Player::sendShader(const std::shared_ptr &creature, const std::st } } -void Player::sendMapShader(const std::string_view &shaderName) const { +void Player::sendMapShader(const std::string &shaderName) const { if (!client) { return; } diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 4159da9a327..f7b60983cf7 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -1264,12 +1264,12 @@ class Player final : public Creature, public Cylinder, public Bankable { void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId) const; void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId) const; - void sendShader(const std::shared_ptr &creature, const std::string_view &shaderName) const; - void sendMapShader(const std::string_view &shaderName) const; - const std::string_view &getMapShader() const { + void sendShader(const std::shared_ptr &creature, const std::string &shaderName) const; + void sendMapShader(const std::string &shaderName) const; + const std::string &getMapShader() const { return mapShader; } - void setMapShader(const std::string_view &shaderName) { + void setMapShader(const std::string_view shaderName) { this->mapShader = shaderName; } void sendPlayerTyping(const std::shared_ptr &creature, uint8_t typing) const; @@ -1383,7 +1383,7 @@ class Player final : public Creature, public Cylinder, public Bankable { std::string name; std::string guildNick; std::string loyaltyTitle; - std::string_view mapShader; + std::string mapShader; Skill skills[SKILL_LAST + 1]; LightInfo itemsLight; diff --git a/src/items/item.cpp b/src/items/item.cpp index 14af2cfb47f..a9195a05468 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -3465,3 +3465,21 @@ int32_t ItemProperties::getDuration() const { return getAttribute(ItemAttribute_t::DURATION); } } + +void ItemProperties::setShader(const std::string &shaderName) { + if (shaderName.empty()) { + removeCustomAttribute("shader"); + return; + } + + setCustomAttribute("shader", shaderName); // temp +} + +bool ItemProperties::hasShader() const { + return getCustomAttribute("shader") != nullptr; +} + +std::string ItemProperties::getShader() const { + const CustomAttribute* shader = getCustomAttribute("shader"); + return shader ? shader->getString() : ""; +} diff --git a/src/items/item.hpp b/src/items/item.hpp index dad0e691619..14b08ab80dc 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -141,24 +141,11 @@ class ItemProperties { return getCorpseOwner() == static_cast(std::numeric_limits::max()); } - void setShader(const std::string_view &shaderName) { - if (shaderName.empty()) { - removeCustomAttribute("shader"); - return; - } - - setCustomAttribute("shader", std::string(shaderName)); // temp - } + void setShader(const std::string &shaderName); - bool hasShader() const { - return getCustomAttribute("shader") != nullptr; - } - - std::string_view getShader() const { - const CustomAttribute* shader = getCustomAttribute("shader"); - return shader ? shader->getString() : ""; - } + bool hasShader() const; + std::string getShader() const; protected: std::unique_ptr &initAttributePtr() { if (!attributePtr) { diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index 1ec62b01240..2dc4da24616 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -4472,7 +4472,7 @@ int PlayerFunctions::luaPlayerGetMapShader(lua_State* L) { return 0; } - pushString(L, std::string(player->getMapShader())); // temp + pushString(L, player->getMapShader()); return 1; } diff --git a/src/lua/functions/items/item_functions.cpp b/src/lua/functions/items/item_functions.cpp index 44423ea5ab3..50fa3d81d45 100644 --- a/src/lua/functions/items/item_functions.cpp +++ b/src/lua/functions/items/item_functions.cpp @@ -1062,7 +1062,7 @@ int ItemFunctions::luaItemGetShader(lua_State* L) { return 1; } - pushString(L, std::string(item->getShader())); // temp + pushString(L, item->getShader()); return 1; } diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 07a4b85da28..29ead201d70 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -470,7 +470,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, const std::shared_ptr &ite // OTCR Features if (isOTC && otclientV8 == 0) { - msg.addString(std::string(item->getShader())); // temp + msg.addString(item->getShader()); } } @@ -9339,24 +9339,24 @@ void ProtocolGame::sendDetachEffect(const std::shared_ptr &creature, u writeToOutputBuffer(msg); } -void ProtocolGame::sendShader(const std::shared_ptr &creature, const std::string_view &shaderName) { +void ProtocolGame::sendShader(const std::shared_ptr &creature, const std::string &shaderName) { if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { return; } NetworkMessage msg; msg.addByte(0x36); msg.add(creature->getID()); - msg.addString(std::string(shaderName)); // temp + msg.addString(shaderName); writeToOutputBuffer(msg); } -void ProtocolGame::sendMapShader(const std::string_view &shaderName) { +void ProtocolGame::sendMapShader(const std::string &shaderName) { if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { return; } NetworkMessage msg; msg.addByte(0x37); - msg.addString(std::string(shaderName)); // temp + msg.addString(shaderName); writeToOutputBuffer(msg); } diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index 20b39e45b94..d74d282d8fc 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -493,8 +493,8 @@ class ProtocolGame final : public Protocol { void sendOTCRFeatures(); void sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId); void sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId); - void sendShader(const std::shared_ptr &creature, const std::string_view &shaderName); - void sendMapShader(const std::string_view &shaderName); + void sendShader(const std::shared_ptr &creature, const std::string &shaderName); + void sendMapShader(const std::string &shaderName); void sendPlayerTyping(const std::shared_ptr &creature, uint8_t typing); void parsePlayerTyping(NetworkMessage &msg); From 67777a93fb8fc6df8aa5dfaa31df8b7a3374c879 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 5 Nov 2024 06:14:04 +0000 Subject: [PATCH 11/29] Code format - (Clang-format) --- src/creatures/players/player.cpp | 2 +- src/game/game.cpp | 2 +- src/items/item.hpp | 1 + src/lua/functions/creatures/creature_functions.cpp | 2 +- src/lua/functions/creatures/player/player_functions.cpp | 1 - src/lua/functions/creatures/player/player_functions.hpp | 2 +- src/server/network/protocol/protocolgame.cpp | 4 ++-- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index ce59755a3c0..11b21070bbc 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -9598,7 +9598,7 @@ void Player::sendShader(const std::shared_ptr &creature, const std::st return; } if (creature->getPlayer()) { - client->sendShader(creature, shaderName); + client->sendShader(creature, shaderName); } } diff --git a/src/game/game.cpp b/src/game/game.cpp index b4a8702a572..93a04fd42b8 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -10867,7 +10867,7 @@ void Game::sendDetachEffect(const std::shared_ptr &creature, uint16_t auto spectators = Spectators().find(creature->getPosition(), true); for (const auto &spectator : spectators) { const auto &player = spectator->getPlayer(); - if (player) { + if (player) { player->sendDetachEffect(creature, effectId); } } diff --git a/src/items/item.hpp b/src/items/item.hpp index 14b08ab80dc..de7222875ef 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -146,6 +146,7 @@ class ItemProperties { bool hasShader() const; std::string getShader() const; + protected: std::unique_ptr &initAttributePtr() { if (!attributePtr) { diff --git a/src/lua/functions/creatures/creature_functions.cpp b/src/lua/functions/creatures/creature_functions.cpp index 11b76c5e7c4..c8da254c4d5 100644 --- a/src/lua/functions/creatures/creature_functions.cpp +++ b/src/lua/functions/creatures/creature_functions.cpp @@ -1110,7 +1110,7 @@ int CreatureFunctions::luaCreatureClearIcons(lua_State* L) { int CreatureFunctions::luaCreatureAttachEffectById(lua_State* L) { // creature:attachEffectById(effectId, [temporary]) - const auto &creature = getUserdataShared(L, 1); + const auto &creature = getUserdataShared(L, 1); if (!creature) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index 2dc4da24616..a5cb113971b 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -4476,7 +4476,6 @@ int PlayerFunctions::luaPlayerGetMapShader(lua_State* L) { return 1; } - int PlayerFunctions::luaPlayerSetMapShader(lua_State* L) { // player:setMapShader(shaderName, [temporary]) const auto &player = getUserdataShared(L, 1); diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp index 3457836132e..4fdb04ac259 100644 --- a/src/lua/functions/creatures/player/player_functions.hpp +++ b/src/lua/functions/creatures/player/player_functions.hpp @@ -759,7 +759,7 @@ class PlayerFunctions final : LuaScriptInterface { static int luaPlayerRemoveIconBakragore(lua_State* L); static int luaPlayerSendCreatureAppear(lua_State* L); - + static int luaPlayerGetMapShader(lua_State* L); static int luaPlayerSetMapShader(lua_State* L); diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 29ead201d70..60e1fa9ded8 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -495,7 +495,7 @@ void ProtocolGame::login(const std::string &name, uint32_t accountId, OperatingS if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) { isOTC = true; if (isOTC && otclientV8 == 0) { - //sendOTCRFeatures(); first I need to make pr in redemption + // sendOTCRFeatures(); first I need to make pr in redemption } NetworkMessage opcodeMessage; opcodeMessage.addByte(0x32); @@ -1047,7 +1047,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage &msg, uint8_t recvby break; // otclient extended opcode case 0x38: parsePlayerTyping(msg); // player are typing or not - break; + break; case 0x60: parseInventoryImbuements(msg); break; From 6766389acfbf7c29ea7b86476af16eaee43b511a Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Tue, 5 Nov 2024 04:12:08 -0300 Subject: [PATCH 12/29] fix: itemShader old protocol otcr --- src/server/network/protocol/protocolgame.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 60e1fa9ded8..39aeaacb457 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -285,6 +285,10 @@ void ProtocolGame::AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint msg.addByte(0xFF); } + // OTCR Features + if (isOTC && otclientV8 == 0) { + msg.addString(""); + } return; } @@ -353,6 +357,10 @@ void ProtocolGame::AddItem(NetworkMessage &msg, const std::shared_ptr &ite msg.addByte(0xFF); } + // OTCR Features + if (isOTC && otclientV8 == 0) { + msg.addString(item->getShader()); + } return; } From 7c45b97747f7ba59c30d75bf30830866caad5699 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:26:17 -0300 Subject: [PATCH 13/29] clean variable --- src/creatures/creature.cpp | 1 + src/server/network/protocol/protocolgame.cpp | 22 +++++++++++--------- src/server/network/protocol/protocolgame.hpp | 3 ++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp index 4f9cff5bff4..c912e541f5b 100644 --- a/src/creatures/creature.cpp +++ b/src/creatures/creature.cpp @@ -2011,6 +2011,7 @@ void Creature::attachEffectById(uint16_t id) { attachedEffectList.push_back(id); g_game().sendAttachedEffect(static_self_cast(), id); } + void Creature::detachEffectById(uint16_t id) { auto it = std::ranges::find(attachedEffectList, id); if (it == attachedEffectList.end()) { diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 39aeaacb457..f69a478ee9c 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -286,7 +286,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint } // OTCR Features - if (isOTC && otclientV8 == 0) { + if (isOTCR) { msg.addString(""); } return; @@ -324,7 +324,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint } // OTCR Features - if (isOTC && otclientV8 == 0) { + if (isOTCR) { msg.addString(""); } } @@ -358,7 +358,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, const std::shared_ptr &ite } // OTCR Features - if (isOTC && otclientV8 == 0) { + if (isOTCR) { msg.addString(item->getShader()); } return; @@ -477,7 +477,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, const std::shared_ptr &ite } // OTCR Features - if (isOTC && otclientV8 == 0) { + if (isOTCR) { msg.addString(item->getShader()); } } @@ -7775,7 +7775,8 @@ void ProtocolGame::AddCreature(NetworkMessage &msg, const std::shared_ptrcanWalkthroughEx(creature) ? 0x00 : 0x01); - if (isOTC && otclientV8 == 0) { + + if (isOTCR) { msg.addString(creature->getShader()); msg.addByte(static_cast(creature->getAttachedEffectList().size())); for (const uint16_t id : creature->getAttachedEffectList()) { @@ -8406,6 +8407,7 @@ void ProtocolGame::sendFeatures() { // OTCR void ProtocolGame::sendOTCRFeatures() { + isOTCR = true; const auto &enabledFeatures = g_configManager().getEnabledOTCFeatures(); const auto &disabledFeatures = g_configManager().getDisabledOTCFeatures(); NetworkMessage msg; @@ -9324,7 +9326,7 @@ void ProtocolGame::sendTakeScreenshot(Screenshot_t screenshotType) { } void ProtocolGame::sendAttachedEffect(const std::shared_ptr &creature, uint16_t effectId) { - if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { + if (!isOTCR) { return; } @@ -9336,7 +9338,7 @@ void ProtocolGame::sendAttachedEffect(const std::shared_ptr &creature, } void ProtocolGame::sendDetachEffect(const std::shared_ptr &creature, uint16_t effectId) { - if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { + if (!isOTCR) { return; } @@ -9348,7 +9350,7 @@ void ProtocolGame::sendDetachEffect(const std::shared_ptr &creature, u } void ProtocolGame::sendShader(const std::shared_ptr &creature, const std::string &shaderName) { - if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { + if (!isOTCR) { return; } NetworkMessage msg; @@ -9359,7 +9361,7 @@ void ProtocolGame::sendShader(const std::shared_ptr &creature, const s } void ProtocolGame::sendMapShader(const std::string &shaderName) { - if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { + if (!isOTCR) { return; } NetworkMessage msg; @@ -9369,7 +9371,7 @@ void ProtocolGame::sendMapShader(const std::string &shaderName) { } void ProtocolGame::sendPlayerTyping(const std::shared_ptr &creature, uint8_t typing) { - if (!isOTC || player->getOperatingSystem() >= CLIENTOS_OTCLIENTV8_LINUX) { + if (!isOTCR) { return; } NetworkMessage msg; diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index d74d282d8fc..d9f1196cc72 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -533,9 +533,10 @@ class ProtocolGame final : public Protocol { bool shouldAddExivaRestrictions = false; bool oldProtocol = false; + bool isOTC = false; + bool isOTCR = false; uint16_t otclientV8 = 0; - bool isOTC = false; void sendOpenStash(); void parseStashWithdraw(NetworkMessage &msg); From bd1854cccdcf8d83a35438a2b04ccccd1d8a6a6a Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:26:31 -0300 Subject: [PATCH 14/29] fix return get shader --- src/lua/functions/creatures/player/player_functions.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index a5cb113971b..c59b0432c51 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -4485,6 +4485,7 @@ int PlayerFunctions::luaPlayerSetMapShader(lua_State* L) { return 0; } const auto shaderName = getString(L, 2); + player->setMapShader(shaderName); player->sendMapShader(shaderName); pushBoolean(L, true); return 1; From 0ff915ef4387d2efb214b7e09ed5ab14c86c6181 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:26:50 -0300 Subject: [PATCH 15/29] missing content player:getAttachedEffects --- .../functions/creatures/creature_functions.cpp | 18 ++++++++++++++++++ .../functions/creatures/creature_functions.hpp | 2 ++ 2 files changed, 20 insertions(+) diff --git a/src/lua/functions/creatures/creature_functions.cpp b/src/lua/functions/creatures/creature_functions.cpp index c8da254c4d5..e24b6d636b9 100644 --- a/src/lua/functions/creatures/creature_functions.cpp +++ b/src/lua/functions/creatures/creature_functions.cpp @@ -1139,6 +1139,24 @@ int CreatureFunctions::luaCreatureDetachEffectById(lua_State* L) { return 1; } +int CreatureFunctions::luaCreatureGetAttachedEffects(lua_State* L) { + // creature:getAttachedEffects() + const auto &creature = getUserdataShared(L, 1); + if (!creature) { + reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + lua_pushnil(L); + return 1; + } + + const auto &effects = creature->getAttachedEffectList(); + lua_createtable(L, effects.size(), 0); + for (size_t i = 0; i < effects.size(); ++i) { + lua_pushnumber(L, effects[i]); + lua_rawseti(L, -2, i + 1); + } + return 1; +} + int CreatureFunctions::luaCreatureGetShader(lua_State* L) { // creature:getShader() const auto &creature = getUserdataShared(L, 1); diff --git a/src/lua/functions/creatures/creature_functions.hpp b/src/lua/functions/creatures/creature_functions.hpp index 5dcf3eaac07..c7ef6601654 100644 --- a/src/lua/functions/creatures/creature_functions.hpp +++ b/src/lua/functions/creatures/creature_functions.hpp @@ -95,6 +95,7 @@ class CreatureFunctions final : LuaScriptInterface { registerMethod(L, "Creature", "clearIcons", CreatureFunctions::luaCreatureClearIcons); registerMethod(L, "Creature", "attachEffectById", CreatureFunctions::luaCreatureAttachEffectById); registerMethod(L, "Creature", "detachEffectById", CreatureFunctions::luaCreatureDetachEffectById); + registerMethod(L, "Creature", "getAttachedEffects", CreatureFunctions::luaCreatureGetAttachedEffects); registerMethod(L, "Creature", "getShader", CreatureFunctions::luaCreatureGetShader); registerMethod(L, "Creature", "setShader", CreatureFunctions::luaCreatureSetShader); @@ -202,6 +203,7 @@ class CreatureFunctions final : LuaScriptInterface { static int luaCreatureClearIcons(lua_State* L); static int luaCreatureAttachEffectById(lua_State* L); static int luaCreatureDetachEffectById(lua_State* L); + static int luaCreatureGetAttachedEffects(lua_State* L); static int luaCreatureGetShader(lua_State* L); static int luaCreatureSetShader(lua_State* L); }; From f538950ba5bb8f836f37b85c77933a5a502ee8d7 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:27:24 -0300 Subject: [PATCH 16/29] simple test Talkations. delete when finished --- .../talkactions/gm/delete_test_otcr.lua | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 data/scripts/talkactions/gm/delete_test_otcr.lua diff --git a/data/scripts/talkactions/gm/delete_test_otcr.lua b/data/scripts/talkactions/gm/delete_test_otcr.lua new file mode 100644 index 00000000000..b50cbdec7dd --- /dev/null +++ b/data/scripts/talkactions/gm/delete_test_otcr.lua @@ -0,0 +1,103 @@ +local talkAction = TalkAction("!testOTCR") + +local options = { + ["Creature"] = {{ + name = "set attach Effect 7", + action = function(player) + player:attachEffectById(7) + end + }, { + name = "get all attach Effect", + action = function(player) + local effects = player:getAttachedEffects() + if #effects > 0 then + local effectsString = "your AE are: " .. table.concat(effects, ", ") + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, effectsString) + else + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "you do not have any AE.") + end + + end + }, { + name = "detach Effect 7", + action = function(player) + player:detachEffectById(7) + end + }, { + name = "set Shader player", + action = function(player) + player:setShader("Outfit - Rainbow") + end + }, { + name = "no shader player", + action = function(player) + player:setShader("") + end + }, { + name = "get Shader player", + action = function(player) + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, player:getShader()) + end + }}, + ["Map"] = {{ + name = "set Shader Map", + action = function(player) + player:setMapShader("Map - Party") + end + }, { + name = "no shader Map", + action = function(player) + player:setMapShader("") + end + }, { + name = "get Shader Map", + action = function(player) + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, player:getMapShader()) + end + }}, + ["Item"] = {{ + name = "Shader", + action = function(player) + local item = player:addItem(ITEM_BAG, 1, false, CONST_SLOT_BACKPACK) + item:setShader("Map - Party") + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "item have shader : ".. item:getShader()) + end + }} +} + +function talkAction.onSay(player, words, param, type) + local modalWindow = ModalWindow({ + title = "Fast Test", + message = "Choose one of the following options:" + }) + + for category, subOptions in pairs(options) do + modalWindow:addChoice(category, function(player, button, choice) + local subModalWindow = ModalWindow({ + title = "Select a Sub-Option", + message = "Choose one of the following sub-options for " .. category .. ":" + }) + + for _, subOption in ipairs(subOptions) do + subModalWindow:addChoice(subOption.name, function(player, button, choice) + if button.name == "OK" then + subOption.action(player) + end + end) + end + + subModalWindow:addButton("OK") + subModalWindow:addButton("Cancel") + subModalWindow:sendToPlayer(player) + end) + end + + modalWindow:addButton("OK") + modalWindow:addButton("Cancel") + modalWindow:sendToPlayer(player) + return false +end + +talkAction:groupType("gamemaster") +talkAction:separator(" ") +talkAction:register() From 0217e803e3d798ec5173451f5316352fe32804c2 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 6 Nov 2024 02:28:21 +0000 Subject: [PATCH 17/29] Lua code format - (Stylua) --- .../talkactions/gm/delete_test_otcr.lua | 186 +++++++++--------- 1 file changed, 98 insertions(+), 88 deletions(-) diff --git a/data/scripts/talkactions/gm/delete_test_otcr.lua b/data/scripts/talkactions/gm/delete_test_otcr.lua index b50cbdec7dd..6b764a43963 100644 --- a/data/scripts/talkactions/gm/delete_test_otcr.lua +++ b/data/scripts/talkactions/gm/delete_test_otcr.lua @@ -1,101 +1,111 @@ local talkAction = TalkAction("!testOTCR") local options = { - ["Creature"] = {{ - name = "set attach Effect 7", - action = function(player) - player:attachEffectById(7) - end - }, { - name = "get all attach Effect", - action = function(player) - local effects = player:getAttachedEffects() - if #effects > 0 then - local effectsString = "your AE are: " .. table.concat(effects, ", ") - player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, effectsString) - else - player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "you do not have any AE.") - end - - end - }, { - name = "detach Effect 7", - action = function(player) - player:detachEffectById(7) - end - }, { - name = "set Shader player", - action = function(player) - player:setShader("Outfit - Rainbow") - end - }, { - name = "no shader player", - action = function(player) - player:setShader("") - end - }, { - name = "get Shader player", - action = function(player) - player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, player:getShader()) - end - }}, - ["Map"] = {{ - name = "set Shader Map", - action = function(player) - player:setMapShader("Map - Party") - end - }, { - name = "no shader Map", - action = function(player) - player:setMapShader("") - end - }, { - name = "get Shader Map", - action = function(player) - player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, player:getMapShader()) - end - }}, - ["Item"] = {{ - name = "Shader", - action = function(player) - local item = player:addItem(ITEM_BAG, 1, false, CONST_SLOT_BACKPACK) - item:setShader("Map - Party") - player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "item have shader : ".. item:getShader()) - end - }} + ["Creature"] = { + { + name = "set attach Effect 7", + action = function(player) + player:attachEffectById(7) + end, + }, + { + name = "get all attach Effect", + action = function(player) + local effects = player:getAttachedEffects() + if #effects > 0 then + local effectsString = "your AE are: " .. table.concat(effects, ", ") + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, effectsString) + else + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "you do not have any AE.") + end + end, + }, + { + name = "detach Effect 7", + action = function(player) + player:detachEffectById(7) + end, + }, + { + name = "set Shader player", + action = function(player) + player:setShader("Outfit - Rainbow") + end, + }, + { + name = "no shader player", + action = function(player) + player:setShader("") + end, + }, + { + name = "get Shader player", + action = function(player) + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, player:getShader()) + end, + }, + }, + ["Map"] = { + { + name = "set Shader Map", + action = function(player) + player:setMapShader("Map - Party") + end, + }, + { + name = "no shader Map", + action = function(player) + player:setMapShader("") + end, + }, + { + name = "get Shader Map", + action = function(player) + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, player:getMapShader()) + end, + }, + }, + ["Item"] = { { + name = "Shader", + action = function(player) + local item = player:addItem(ITEM_BAG, 1, false, CONST_SLOT_BACKPACK) + item:setShader("Map - Party") + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "item have shader : " .. item:getShader()) + end, + } }, } function talkAction.onSay(player, words, param, type) - local modalWindow = ModalWindow({ - title = "Fast Test", - message = "Choose one of the following options:" - }) + local modalWindow = ModalWindow({ + title = "Fast Test", + message = "Choose one of the following options:", + }) - for category, subOptions in pairs(options) do - modalWindow:addChoice(category, function(player, button, choice) - local subModalWindow = ModalWindow({ - title = "Select a Sub-Option", - message = "Choose one of the following sub-options for " .. category .. ":" - }) + for category, subOptions in pairs(options) do + modalWindow:addChoice(category, function(player, button, choice) + local subModalWindow = ModalWindow({ + title = "Select a Sub-Option", + message = "Choose one of the following sub-options for " .. category .. ":", + }) - for _, subOption in ipairs(subOptions) do - subModalWindow:addChoice(subOption.name, function(player, button, choice) - if button.name == "OK" then - subOption.action(player) - end - end) - end + for _, subOption in ipairs(subOptions) do + subModalWindow:addChoice(subOption.name, function(player, button, choice) + if button.name == "OK" then + subOption.action(player) + end + end) + end - subModalWindow:addButton("OK") - subModalWindow:addButton("Cancel") - subModalWindow:sendToPlayer(player) - end) - end + subModalWindow:addButton("OK") + subModalWindow:addButton("Cancel") + subModalWindow:sendToPlayer(player) + end) + end - modalWindow:addButton("OK") - modalWindow:addButton("Cancel") - modalWindow:sendToPlayer(player) - return false + modalWindow:addButton("OK") + modalWindow:addButton("Cancel") + modalWindow:sendToPlayer(player) + return false end talkAction:groupType("gamemaster") From 9fe26c50bdb6b1deb0a3fd9b56de64877a94d5c9 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Wed, 6 Nov 2024 00:43:41 -0300 Subject: [PATCH 18/29] format --- src/items/item.cpp | 2 +- src/server/network/protocol/protocolgame.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/items/item.cpp b/src/items/item.cpp index a9195a05468..f22b5709576 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -3472,7 +3472,7 @@ void ItemProperties::setShader(const std::string &shaderName) { return; } - setCustomAttribute("shader", shaderName); // temp + setCustomAttribute("shader", shaderName); } bool ItemProperties::hasShader() const { diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index f69a478ee9c..4d9873e44ca 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -9353,6 +9353,7 @@ void ProtocolGame::sendShader(const std::shared_ptr &creature, const s if (!isOTCR) { return; } + NetworkMessage msg; msg.addByte(0x36); msg.add(creature->getID()); @@ -9364,6 +9365,7 @@ void ProtocolGame::sendMapShader(const std::string &shaderName) { if (!isOTCR) { return; } + NetworkMessage msg; msg.addByte(0x37); msg.addString(shaderName); @@ -9374,6 +9376,7 @@ void ProtocolGame::sendPlayerTyping(const std::shared_ptr &creature, u if (!isOTCR) { return; } + NetworkMessage msg; msg.addByte(0x38); msg.add(creature->getID()); From 8d6961da5d36bafe12a07462bcc70836fbe91a32 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Wed, 6 Nov 2024 10:13:32 -0300 Subject: [PATCH 19/29] improve: variable name --- config.lua.dist | 4 ++-- src/config/configmanager.cpp | 16 ++++++++-------- src/config/configmanager.hpp | 8 ++++---- src/server/network/protocol/protocolgame.cpp | 18 +++++++++--------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/config.lua.dist b/config.lua.dist index f6d4494879a..409e5dcc551 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -593,11 +593,11 @@ metricsOstreamInterval = 1000 -- NOTE: Features added in this list will be forced to be used on the client -- These features can be found in "modules/gamelib/const.lua" OTCRFeatures = { - enable = { + enableFeature = { 101, -- g_game.enableFeature(GameItemShader) 102, -- g_game.enableFeature(GameCreatureAttachedEffect) 103 -- g_game.enableFeature(GameCreatureShader) }, - disable = { -- utility: for example in 13.10 g_game.disableFeature(GameSequencedPackets) + disableFeature = { } } diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index 56510007d6a..6c5be5e6ad1 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -473,25 +473,25 @@ void ConfigManager::loadLuaOTCFeatures(lua_State* L) { return; } - lua_pushstring(L, "enable"); + lua_pushstring(L, "enableFeature"); lua_gettable(L, -2); if (lua_istable(L, -1)) { lua_pushnil(L); while (lua_next(L, -2) != 0) { const auto feature = static_cast(lua_tointeger(L, -1)); - enabledOTCFeatures.push_back(feature); + enabledFeaturesOTC.push_back(feature); lua_pop(L, 1); } } lua_pop(L, 1); - lua_pushstring(L, "disable"); + lua_pushstring(L, "disableFeature"); lua_gettable(L, -2); if (lua_istable(L, -1)) { lua_pushnil(L); while (lua_next(L, -2) != 0) { const auto feature = static_cast(lua_tointeger(L, -1)); - disabledOTCFeatures.push_back(feature); + disabledFeaturesOTC.push_back(feature); lua_pop(L, 1); } } @@ -499,10 +499,10 @@ void ConfigManager::loadLuaOTCFeatures(lua_State* L) { lua_pop(L, 1); } -OTCFeatures ConfigManager::getEnabledOTCFeatures() const { - return enabledOTCFeatures; +OTCFeatures ConfigManager::getEnabledFeaturesOTC() const { + return enabledFeaturesOTC; } -OTCFeatures ConfigManager::getDisabledOTCFeatures() const { - return disabledOTCFeatures; +OTCFeatures ConfigManager::getDisabledFeaturesOTC() const { + return disabledFeaturesOTC; } diff --git a/src/config/configmanager.hpp b/src/config/configmanager.hpp index 17a8028a52b..0a0473d44c1 100644 --- a/src/config/configmanager.hpp +++ b/src/config/configmanager.hpp @@ -41,8 +41,8 @@ class ConfigManager { [[nodiscard]] int32_t getNumber(const ConfigKey_t &key, const std::source_location &location = std::source_location::current()) const; [[nodiscard]] bool getBoolean(const ConfigKey_t &key, const std::source_location &location = std::source_location::current()) const; [[nodiscard]] float getFloat(const ConfigKey_t &key, const std::source_location &location = std::source_location::current()) const; - OTCFeatures getEnabledOTCFeatures() const; - OTCFeatures getDisabledOTCFeatures() const; + OTCFeatures getEnabledFeaturesOTC() const; + OTCFeatures getDisabledFeaturesOTC() const; private: phmap::flat_hash_map configs; @@ -53,8 +53,8 @@ class ConfigManager { std::string configFileLua = { "config.lua" }; bool loaded = false; - OTCFeatures enabledOTCFeatures = {}; - OTCFeatures disabledOTCFeatures = {}; + OTCFeatures enabledFeaturesOTC = {}; + OTCFeatures disabledFeaturesOTC = {}; void loadLuaOTCFeatures(lua_State* L); }; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index c62e5a583ed..29d2d5b4d0a 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -287,7 +287,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint // OTCR Features if (isOTCR) { - msg.addString(""); + msg.addString(""); // g_game.enableFeature(GameItemShader) } return; } @@ -325,7 +325,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint // OTCR Features if (isOTCR) { - msg.addString(""); + msg.addString(""); // g_game.enableFeature(GameItemShader) } } @@ -359,7 +359,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, const std::shared_ptr &ite // OTCR Features if (isOTCR) { - msg.addString(item->getShader()); + msg.addString(item->getShader()); // g_game.enableFeature(GameItemShader) } return; } @@ -478,7 +478,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, const std::shared_ptr &ite // OTCR Features if (isOTCR) { - msg.addString(item->getShader()); + msg.addString(item->getShader()); // g_game.enableFeature(GameItemShader) } } @@ -7777,10 +7777,10 @@ void ProtocolGame::AddCreature(NetworkMessage &msg, const std::shared_ptrcanWalkthroughEx(creature) ? 0x00 : 0x01); if (isOTCR) { - msg.addString(creature->getShader()); - msg.addByte(static_cast(creature->getAttachedEffectList().size())); + msg.addString(creature->getShader()); // g_game.enableFeature(GameCreatureShader) + msg.addByte(static_cast(creature->getAttachedEffectList().size())); // g_game.enableFeature(GameCreatureAttachedEffect) for (const uint16_t id : creature->getAttachedEffectList()) { - msg.add(id); + msg.add(id); // g_game.enableFeature(GameCreatureAttachedEffect) } } } @@ -8408,8 +8408,8 @@ void ProtocolGame::sendFeatures() { // OTCR void ProtocolGame::sendOTCRFeatures() { isOTCR = true; - const auto &enabledFeatures = g_configManager().getEnabledOTCFeatures(); - const auto &disabledFeatures = g_configManager().getDisabledOTCFeatures(); + const auto &enabledFeatures = g_configManager().getEnabledFeaturesOTC(); + const auto &disabledFeatures = g_configManager().getDisabledFeaturesOTC(); NetworkMessage msg; msg.addByte(0x43); auto totalFeatures = static_cast(enabledFeatures.size() + disabledFeatures.size()); From 3744f16c28367be9df2c25e2a3e7d1bb93c3f71b Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Wed, 6 Nov 2024 13:08:29 -0300 Subject: [PATCH 20/29] game_outfit functional version, not cleaned or optimized reload required ? iOLoginData load, save? need clean Player.cpp --- config.lua.dist | 3 +- data/XML/attachedeffects.xml | 15 + .../talkactions/gm/delete_test_otcr.lua | 100 ++- src/creatures/CMakeLists.txt | 1 + .../attachedeffects/attachedeffects.cpp | 122 +++ .../attachedeffects/attachedeffects.hpp | 73 ++ src/creatures/creature.hpp | 4 + src/creatures/creatures_definitions.hpp | 4 + src/creatures/players/player.cpp | 762 ++++++++++++++++++ src/creatures/players/player.hpp | 85 ++ src/game/game.cpp | 79 ++ src/game/game.hpp | 2 + .../functions/core/game/game_functions.cpp | 58 ++ .../functions/core/game/game_functions.hpp | 3 + .../creatures/combat/condition_functions.cpp | 4 + .../creatures/player/player_functions.cpp | 44 + .../creatures/player/player_functions.hpp | 5 + src/lua/functions/lua_functions_loader.cpp | 13 +- src/server/network/protocol/protocolgame.cpp | 122 ++- src/server/network/protocol/protocolgame.hpp | 2 + src/utils/const.hpp | 16 + vcproj/canary.vcxproj | 2 + 22 files changed, 1508 insertions(+), 11 deletions(-) create mode 100644 data/XML/attachedeffects.xml create mode 100644 src/creatures/appearance/attachedeffects/attachedeffects.cpp create mode 100644 src/creatures/appearance/attachedeffects/attachedeffects.hpp diff --git a/config.lua.dist b/config.lua.dist index 409e5dcc551..e770bbb5664 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -596,7 +596,8 @@ OTCRFeatures = { enableFeature = { 101, -- g_game.enableFeature(GameItemShader) 102, -- g_game.enableFeature(GameCreatureAttachedEffect) - 103 -- g_game.enableFeature(GameCreatureShader) + 103, -- g_game.enableFeature(GameCreatureShader) + 118 -- g_game.enableFeature(GameWingsAurasEffectsShader) }, disableFeature = { } diff --git a/data/XML/attachedeffects.xml b/data/XML/attachedeffects.xml new file mode 100644 index 00000000000..c84fb9567a5 --- /dev/null +++ b/data/XML/attachedeffects.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/data/scripts/talkactions/gm/delete_test_otcr.lua b/data/scripts/talkactions/gm/delete_test_otcr.lua index 6b764a43963..168fe228f51 100644 --- a/data/scripts/talkactions/gm/delete_test_otcr.lua +++ b/data/scripts/talkactions/gm/delete_test_otcr.lua @@ -1,7 +1,7 @@ local talkAction = TalkAction("!testOTCR") local options = { - ["Creature"] = { + Creature = { { name = "set attach Effect 7", action = function(player) @@ -45,7 +45,7 @@ local options = { end, }, }, - ["Map"] = { + Map = { { name = "set Shader Map", action = function(player) @@ -65,7 +65,7 @@ local options = { end, }, }, - ["Item"] = { { + Items = { { name = "Shader", action = function(player) local item = player:addItem(ITEM_BAG, 1, false, CONST_SLOT_BACKPACK) @@ -73,6 +73,73 @@ local options = { player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "item have shader : " .. item:getShader()) end, } }, + game_outfit = { + { + name = "pdump auras", + action = function(player) + local effects = Game.getAllAttachedeffects("aura") + if #effects > 0 then + local ids = {} + for _, effect in ipairs(effects) do + table.insert(ids, effect.id) + end + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "aura registered on the server: ".. table.concat(ids, ", ")) + else + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "the server did not charge aura check .xml") + + end + end, + }, + { + name = "pdump wing", + action = function(player) + local effects = Game.getAllAttachedeffects("wing") + if #effects > 0 then + local ids = {} + for _, effect in ipairs(effects) do + table.insert(ids, effect.id) + end + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "wing registered on the server: "..table.concat(ids, ", ")) + else + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "the server did not charge wing check .xml") + end + end, + }, + { + name = "pdump effect", + action = function(player) + + local effects = Game.getAllAttachedeffects("effect") + if #effects > 0 then + local ids = {} + for _, effect in ipairs(effects) do + table.insert(ids, effect.id) + end + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "effect registered on the server: "..table.concat(ids, ", ")) + else + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "the server did not charge effect check .xml") + end + + end, + }, + { + name = "pdump shader", + action = function(player) + + local effects = Game.getAllAttachedeffects("shader") + if #effects > 0 then + local ids = {} + for _, effect in ipairs(effects) do + table.insert(ids, effect.name) + end + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "shader registered on the server: "..table.concat(ids, ", ")) + else + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "the server did not charge shader check .xml") + end + + end, + }, + }, } function talkAction.onSay(player, words, param, type) @@ -89,21 +156,25 @@ function talkAction.onSay(player, words, param, type) }) for _, subOption in ipairs(subOptions) do - subModalWindow:addChoice(subOption.name, function(player, button, choice) + subModalWindow:addChoice(subOption.name, function(plyr, btn, ch) if button.name == "OK" then - subOption.action(player) + subOption.action(plyr) end end) end subModalWindow:addButton("OK") - subModalWindow:addButton("Cancel") + subModalWindow:addButton("Cancel", function(plyr) + subModalWindow:clear() + end) subModalWindow:sendToPlayer(player) end) end modalWindow:addButton("OK") - modalWindow:addButton("Cancel") + modalWindow:addButton("Cancel", function(player) + modalWindow:clear() + end) modalWindow:sendToPlayer(player) return false end @@ -111,3 +182,18 @@ end talkAction:groupType("gamemaster") talkAction:separator(" ") talkAction:register() + + +local playerLoginTestOTCR = CreatureEvent("simpletest") + +function playerLoginTestOTCR.onLogin(player) + if not player then + return false + end + if player:getClient().os >= 10 and player:getClient().os < 20 then + player:say("say !testOTCR", TALKTYPE_SAY) + end +return true +end + +playerLoginTestOTCR:register() diff --git a/src/creatures/CMakeLists.txt b/src/creatures/CMakeLists.txt index c87a45a0aa0..7ed509fc8e3 100644 --- a/src/creatures/CMakeLists.txt +++ b/src/creatures/CMakeLists.txt @@ -1,6 +1,7 @@ target_sources(${PROJECT_NAME}_lib PRIVATE appearance/mounts/mounts.cpp appearance/outfit/outfit.cpp + appearance/attachedeffects/attachedeffects.cpp combat/combat.cpp combat/condition.cpp combat/spells.cpp diff --git a/src/creatures/appearance/attachedeffects/attachedeffects.cpp b/src/creatures/appearance/attachedeffects/attachedeffects.cpp new file mode 100644 index 00000000000..f9d2e30e9d7 --- /dev/null +++ b/src/creatures/appearance/attachedeffects/attachedeffects.cpp @@ -0,0 +1,122 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2024 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ +#include "creatures/Appearance/attachedeffects/attachedeffects.hpp" + +#include "config/configmanager.hpp" +#include "game/game.hpp" +#include "utils/pugicast.hpp" +#include "utils/tools.hpp" + +bool Attachedeffects::reload() { + auras.clear(); + shaders.clear(); + effects.clear(); + wings.clear(); + return loadFromXml(); +} + +bool Attachedeffects::loadFromXml() { + pugi::xml_document doc; + auto folder = g_configManager().getString(CORE_DIRECTORY) + "/XML/attachedeffects.xml"; + pugi::xml_parse_result result = doc.load_file(folder.c_str()); + if (!result) { + printXMLError(__FUNCTION__, folder, result); + return false; + } + + for (auto auraNode : doc.child("attachedeffects").children("aura")) { + auras.emplace(std::make_shared( + pugi::cast(auraNode.attribute("id").value()), + auraNode.attribute("name").as_string() + )); + } + + for (auto shaderNode : doc.child("attachedeffects").children("shader")) { + shaders.emplace(std::make_shared( + pugi::cast(shaderNode.attribute("id").value()), + shaderNode.attribute("name").as_string() + )); + } + + for (auto effectNode : doc.child("attachedeffects").children("effect")) { + effects.emplace(std::make_shared( + pugi::cast(effectNode.attribute("id").value()), + effectNode.attribute("name").as_string() + )); + } + + for (auto wingNode : doc.child("attachedeffects").children("wing")) { + wings.emplace(std::make_shared( + pugi::cast(wingNode.attribute("id").value()), + wingNode.attribute("name").as_string() + )); + } + + return true; +} + +std::shared_ptr Attachedeffects::getAuraByID(uint8_t id) { + auto it = std::find_if(auras.begin(), auras.end(), [id](const std::shared_ptr &aura) { + return aura->id == id; + }); + return it != auras.end() ? *it : nullptr; +} + +std::shared_ptr Attachedeffects::getEffectByID(uint8_t id) { + auto it = std::find_if(effects.begin(), effects.end(), [id](const std::shared_ptr &effect) { + return effect->id == id; + }); + return it != effects.end() ? *it : nullptr; +} + +std::shared_ptr Attachedeffects::getWingByID(uint8_t id) { + auto it = std::find_if(wings.begin(), wings.end(), [id](const std::shared_ptr &wing) { + return wing->id == id; + }); + return it != wings.end() ? *it : nullptr; +} + +std::shared_ptr Attachedeffects::getShaderByID(uint8_t id) { + auto it = std::find_if(shaders.begin(), shaders.end(), [id](const std::shared_ptr &shader) { + return shader->id == id; + }); + return it != shaders.end() ? *it : nullptr; +} + +std::shared_ptr Attachedeffects::getAuraByName(const std::string &name) { + auto auraName = name.c_str(); + auto it = std::find_if(auras.begin(), auras.end(), [auraName](const std::shared_ptr &aura) { + return strcasecmp(auraName, aura->name.c_str()) == 0; + }); + return it != auras.end() ? *it : nullptr; +} + +std::shared_ptr Attachedeffects::getShaderByName(const std::string &name) { + auto shaderName = name.c_str(); + auto it = std::find_if(shaders.begin(), shaders.end(), [shaderName](const std::shared_ptr &shader) { + return strcasecmp(shaderName, shader->name.c_str()) == 0; + }); + return it != shaders.end() ? *it : nullptr; +} + +std::shared_ptr Attachedeffects::getEffectByName(const std::string &name) { + auto effectName = name.c_str(); + auto it = std::find_if(effects.begin(), effects.end(), [effectName](const std::shared_ptr &effect) { + return strcasecmp(effectName, effect->name.c_str()) == 0; + }); + return it != effects.end() ? *it : nullptr; +} + +std::shared_ptr Attachedeffects::getWingByName(const std::string &name) { + auto wingName = name.c_str(); + auto it = std::find_if(wings.begin(), wings.end(), [wingName](const std::shared_ptr &wing) { + return strcasecmp(wingName, wing->name.c_str()) == 0; + }); + return it != wings.end() ? *it : nullptr; +} diff --git a/src/creatures/appearance/attachedeffects/attachedeffects.hpp b/src/creatures/appearance/attachedeffects/attachedeffects.hpp new file mode 100644 index 00000000000..494ddb979ac --- /dev/null +++ b/src/creatures/appearance/attachedeffects/attachedeffects.hpp @@ -0,0 +1,73 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2024 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#pragma once + +struct Aura { + Aura(uint16_t initId, const std::string &name) : + id(initId), name(name) { } + uint8_t id; + std::string name; +}; + +struct Shader { + Shader(uint8_t initId, const std::string &name) : + id(initId), name(name) { } + uint8_t id; + std::string name; +}; + +struct Effect { + Effect(uint16_t initId, const std::string &name) : + id(initId), name(name) { } + uint8_t id; + std::string name; +}; + +struct Wing { + Wing(uint16_t initId, const std::string &name) : + id(initId), name(name) { } + uint8_t id; + std::string name; +}; + +class Attachedeffects { +public: + bool reload(); + bool loadFromXml(); + + std::shared_ptr getAuraByID(uint8_t id); + std::shared_ptr getEffectByID(uint8_t id); + std::shared_ptr getWingByID(uint8_t id); + std::shared_ptr getShaderByID(uint8_t id); + + std::shared_ptr getAuraByName(const std::string &name); + std::shared_ptr getShaderByName(const std::string &name); + std::shared_ptr getEffectByName(const std::string &name); + std::shared_ptr getWingByName(const std::string &name); + + [[nodiscard]] const phmap::parallel_flat_hash_set> &getAuras() const { + return auras; + } + [[nodiscard]] const phmap::parallel_flat_hash_set> &getShaders() const { + return shaders; + } + [[nodiscard]] const phmap::parallel_flat_hash_set> &getEffects() const { + return effects; + } + [[nodiscard]] const phmap::parallel_flat_hash_set> &getWings() const { + return wings; + } + +private: + phmap::parallel_flat_hash_set> auras; + phmap::parallel_flat_hash_set> shaders; + phmap::parallel_flat_hash_set> effects; + phmap::parallel_flat_hash_set> wings; +}; diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp index 87f4cae3a09..0b3a70013a5 100644 --- a/src/creatures/creature.hpp +++ b/src/creatures/creature.hpp @@ -778,6 +778,10 @@ class Creature : virtual public Thing, public SharedObject { Outfit_t currentOutfit; Outfit_t defaultOutfit; + uint16_t currentWing; + uint16_t currentAura; + uint16_t currentEffect; + uint16_t currentShader; Position lastPosition; LightInfo internalLight; diff --git a/src/creatures/creatures_definitions.hpp b/src/creatures/creatures_definitions.hpp index f7ba1e203b1..28f86213cad 100644 --- a/src/creatures/creatures_definitions.hpp +++ b/src/creatures/creatures_definitions.hpp @@ -1665,6 +1665,10 @@ struct Outfit_t { uint8_t lookMountLegs = 0; uint8_t lookMountFeet = 0; uint16_t lookFamiliarsType = 0; + uint16_t lookWing = 0; + uint16_t lookAura = 0; + uint16_t lookEffect = 0; + uint16_t lookShader = 0; }; struct voiceBlock_t { diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 11b21070bbc..34a608c85ca 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -12,6 +12,7 @@ #include "config/configmanager.hpp" #include "core.hpp" #include "creatures/appearance/mounts/mounts.hpp" +#include "creatures/appearance/attachedeffects/attachedeffects.hpp" #include "creatures/combat/combat.hpp" #include "creatures/combat/condition.hpp" #include "creatures/interactions/chat.hpp" @@ -1052,6 +1053,14 @@ void Player::addStorageValue(const uint32_t key, const int32_t value, const bool } if (IS_IN_KEYRANGE(key, MOUNTS_RANGE)) { // do nothing + } else if (IS_IN_KEYRANGE(key, WING_RANGE)) { + // do nothing + } else if (IS_IN_KEYRANGE(key, EFFECT_RANGE)) { + // do nothing + } else if (IS_IN_KEYRANGE(key, AURA_RANGE)) { + // do nothing + } else if (IS_IN_KEYRANGE(key, SHADER_RANGE)) { + // do nothing } else if (IS_IN_KEYRANGE(key, FAMILIARS_RANGE)) { familiars.emplace_back( value >> 16 @@ -7004,6 +7013,759 @@ void Player::dismount() { defaultOutfit.lookMount = 0; } +// Wings + +uint8_t Player::getLastWing() const { + const int32_t value = getStorageValue(PSTRG_WING_CURRENTWING); + if (value > 0) { + return value; + } + return static_cast(kv()->get("last-wing")->get()); +} + +uint8_t Player::getCurrentWing() const { + const int32_t value = getStorageValue(PSTRG_WING_CURRENTWING); + if (value > 0) { + return value; + } + return 0; +} + +void Player::setCurrentWing(uint8_t wing) { + addStorageValue(PSTRG_WING_CURRENTWING, wing); +} + +bool Player::hasAnyWing() const { + const auto &wings = g_game().attachedeffects->getWings(); + return std::ranges::any_of(wings, [&](const auto &wing) { + return hasWing(wing); + }); +} + +uint8_t Player::getRandomWingId() const { + std::vector playerWings; + const auto wings = g_game().attachedeffects->getWings(); + for (const auto &wing : wings) { + if (hasWing(wing)) { + playerWings.emplace_back(wing->id); + } + } + + const auto playerWingsSize = static_cast(playerWings.size() - 1); + const auto randomIndex = uniform_random(0, std::max(0, playerWingsSize)); + return playerWings.at(randomIndex); +} + +bool Player::toggleWing(bool wing) { + if ((OTSYS_TIME() - lastToggleWing) < 3000 && !wasWinged) { + sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED); + return false; + } + + if (wing) { + if (isWinged()) { + return false; + } + + const auto &playerOutfit = Outfits::getInstance().getOutfitByLookType(getPlayer(), defaultOutfit.lookType); + if (!playerOutfit) { + return false; + } + + uint8_t currentWingId = getLastWing(); + if (currentWingId == 0) { + sendOutfitWindow(); + return false; + } + + if (isRandomMounted()) { + currentWingId = getRandomWingId(); + } + + const auto ¤tWing = g_game().attachedeffects->getWingByID(currentWingId); + if (!currentWing) { + return false; + } + + if (!hasWing(currentWing)) { + setCurrentWing(0); + kv()->set("last-wing", 0); + sendOutfitWindow(); + return false; + } + + if (hasCondition(CONDITION_OUTFIT)) { + sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); + return false; + } + + defaultOutfit.lookWing = currentWing->id; + setCurrentWing(currentWing->id); + kv()->set("last-wing", currentWing->id); + + } else { + if (!isWinged()) { + return false; + } + + diswing(); + } + + g_game().internalCreatureChangeOutfit(static_self_cast(), defaultOutfit); + lastToggleWing = OTSYS_TIME(); + return true; +} + +bool Player::tameWing(uint8_t wingId) { + if (!g_game().attachedeffects->getWingByID(wingId)) { + return false; + } + + const uint8_t tmpWingId = wingId - 1; + const uint32_t key = PSTRG_WING_RANGE_START + (tmpWingId / 31); + + int32_t value = getStorageValue(key); + if (value != -1) { + value |= (1 << (tmpWingId % 31)); + } else { + value = (1 << (tmpWingId % 31)); + } + + addStorageValue(key, value); + return true; +} + +bool Player::untameWing(uint8_t wingId) { + if (!g_game().attachedeffects->getWingByID(wingId)) { + return false; + } + + const uint8_t tmpWingId = wingId - 1; + const uint32_t key = PSTRG_WING_RANGE_START + (tmpWingId / 31); + + int32_t value = getStorageValue(key); + if (value == -1) { + return true; + } + + value &= ~(1 << (tmpWingId % 31)); + addStorageValue(key, value); + + if (getCurrentWing() == wingId) { + if (isWinged()) { + diswing(); + g_game().internalCreatureChangeOutfit(static_self_cast(), defaultOutfit); + } + + setCurrentWing(0); + kv()->set("last-wing", 0); + } + + return true; +} + +bool Player::hasWing(const std::shared_ptr &wing) const { + if (isAccessPlayer()) { + return true; + } + + const uint8_t tmpWingId = wing->id - 1; + + const int32_t value = getStorageValue(PSTRG_WING_RANGE_START + (tmpWingId / 31)); + if (value == -1) { + return false; + } + + return ((1 << (tmpWingId % 31)) & value) != 0; +} + +void Player::diswing() { + const auto &wing = g_game().attachedeffects->getWingByID(getCurrentWing()); + defaultOutfit.lookWing = 0; +} + + + +// Auras + +uint8_t Player::getLastAura() const { + const int32_t value = getStorageValue(PSTRG_AURA_CURRENTAURA); + if (value > 0) { + return value; + } + return static_cast(kv()->get("last-aura")->get()); +} + +uint8_t Player::getCurrentAura() const { + const int32_t value = getStorageValue(PSTRG_AURA_CURRENTAURA); + if (value > 0) { + return value; + } + return 0; +} + +void Player::setCurrentAura(uint8_t aura) { + addStorageValue(PSTRG_AURA_CURRENTAURA, aura); +} + +bool Player::hasAnyAura() const { + const auto &auras = g_game().attachedeffects->getAuras(); + return std::ranges::any_of(auras, [&](const auto &aura) { + return hasAura(aura); + }); +} + +uint8_t Player::getRandomAuraId() const { + std::vector playerAuras; + const auto auras = g_game().attachedeffects->getAuras(); + for (const auto &aura : auras) { + if (hasAura(aura)) { + playerAuras.emplace_back(aura->id); + } + } + + const auto playerAurasSize = static_cast(playerAuras.size() - 1); + const auto randomIndex = uniform_random(0, std::max(0, playerAurasSize)); + return playerAuras.at(randomIndex); +} + +bool Player::toggleAura(bool aura) { + if ((OTSYS_TIME() - lastToggleAura) < 3000 && !wasAuraed) { + sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED); + return false; + } + + if (aura) { + if (isAuraed()) { + return false; + } + + const auto &playerOutfit = Outfits::getInstance().getOutfitByLookType(getPlayer(), defaultOutfit.lookType); + if (!playerOutfit) { + return false; + } + + uint8_t currentAuraId = getLastAura(); + if (currentAuraId == 0) { + sendOutfitWindow(); + return false; + } + + if (isRandomMounted()) { + currentAuraId = getRandomAuraId(); + } + + const auto ¤tAura = g_game().attachedeffects->getAuraByID(currentAuraId); + if (!currentAura) { + return false; + } + + if (!hasAura(currentAura)) { + setCurrentAura(0); + kv()->set("last-aura", 0); + sendOutfitWindow(); + return false; + } + + if (hasCondition(CONDITION_OUTFIT)) { + sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); + return false; + } + + defaultOutfit.lookAura = currentAura->id; + setCurrentAura(currentAura->id); + kv()->set("last-aura", currentAura->id); + + } else { + if (!isAuraed()) { + return false; + } + + disaura(); + } + + g_game().internalCreatureChangeOutfit(static_self_cast(), defaultOutfit); + lastToggleAura = OTSYS_TIME(); + return true; +} + +bool Player::tameAura(uint8_t auraId) { + if (!g_game().attachedeffects->getAuraByID(auraId)) { + return false; + } + + const uint8_t tmpAuraId = auraId - 1; + const uint32_t key = PSTRG_AURA_RANGE_START + (tmpAuraId / 31); + + int32_t value = getStorageValue(key); + if (value != -1) { + value |= (1 << (tmpAuraId % 31)); + } else { + value = (1 << (tmpAuraId % 31)); + } + + addStorageValue(key, value); + return true; +} + +bool Player::untameAura(uint8_t auraId) { + if (!g_game().attachedeffects->getAuraByID(auraId)) { + return false; + } + + const uint8_t tmpAuraId = auraId - 1; + const uint32_t key = PSTRG_AURA_RANGE_START + (tmpAuraId / 31); + + int32_t value = getStorageValue(key); + if (value == -1) { + return true; + } + + value &= ~(1 << (tmpAuraId % 31)); + addStorageValue(key, value); + + if (getCurrentAura() == auraId) { + if (isAuraed()) { + disaura(); + g_game().internalCreatureChangeOutfit(static_self_cast(), defaultOutfit); + } + + setCurrentAura(0); + kv()->set("last-aura", 0); + } + + return true; +} + +bool Player::hasAura(const std::shared_ptr &aura) const { + if (isAccessPlayer()) { + return true; + } + const uint8_t tmpAuraId = aura->id - 1; + + const int32_t value = getStorageValue(PSTRG_AURA_RANGE_START + (tmpAuraId / 31)); + if (value == -1) { + return false; + } + + return ((1 << (tmpAuraId % 31)) & value) != 0; +} + +void Player::disaura() { + const auto &aura = g_game().attachedeffects->getAuraByID(getCurrentAura()); + defaultOutfit.lookAura = 0; +} + + +// Effects + +uint8_t Player::getLastEffect() const { + const int32_t value = getStorageValue(PSTRG_EFFECT_CURRENTEFFECT); + if (value > 0) { + return value; + } + return static_cast(kv()->get("last-effect")->get()); +} + +uint8_t Player::getCurrentEffect() const { + const int32_t value = getStorageValue(PSTRG_EFFECT_CURRENTEFFECT); + if (value > 0) { + return value; + } + return 0; +} + +void Player::setCurrentEffect(uint8_t effect) { + addStorageValue(PSTRG_EFFECT_CURRENTEFFECT, effect); +} + +bool Player::hasAnyEffect() const { + const auto &effects = g_game().attachedeffects->getEffects(); + return std::ranges::any_of(effects, [&](const auto &effect) { + return hasEffect(effect); + }); +} + +uint8_t Player::getRandomEffectId() const { + std::vector playerEffects; + const auto effects = g_game().attachedeffects->getEffects(); + for (const auto &effect : effects) { + if (hasEffect(effect)) { + playerEffects.emplace_back(effect->id); + } + } + + const auto playerEffectsSize = static_cast(playerEffects.size() - 1); + const auto randomIndex = uniform_random(0, std::max(0, playerEffectsSize)); + return playerEffects.at(randomIndex); +} + +bool Player::toggleEffect(bool effect) { + if ((OTSYS_TIME() - lastToggleEffect) < 3000 && !wasEffected) { + sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED); + return false; + } + + if (effect) { + if (isEffected()) { + return false; + } + + + const auto &playerOutfit = Outfits::getInstance().getOutfitByLookType(getPlayer(), defaultOutfit.lookType); + if (!playerOutfit) { + return false; + } + + uint8_t currentEffectId = getLastEffect(); + if (currentEffectId == 0) { + sendOutfitWindow(); + return false; + } + + if (isRandomMounted()) { + currentEffectId = getRandomEffectId(); + } + + const auto ¤tEffect = g_game().attachedeffects->getEffectByID(currentEffectId); + if (!currentEffect) { + return false; + } + + if (!hasEffect(currentEffect)) { + setCurrentEffect(0); + kv()->set("last-effect", 0); + sendOutfitWindow(); + return false; + } + + if (hasCondition(CONDITION_OUTFIT)) { + sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); + return false; + } + + defaultOutfit.lookEffect = currentEffect->id; + setCurrentEffect(currentEffect->id); + kv()->set("last-effect", currentEffect->id); + + } else { + if (!isEffected()) { + return false; + } + + diseffect(); + } + + g_game().internalCreatureChangeOutfit(static_self_cast(), defaultOutfit); + lastToggleEffect = OTSYS_TIME(); + return true; +} + +bool Player::tameEffect(uint8_t effectId) { + if (!g_game().attachedeffects->getEffectByID(effectId)) { + return false; + } + + const uint8_t tmpEffectId = effectId - 1; + const uint32_t key = PSTRG_EFFECT_RANGE_START + (tmpEffectId / 31); + + int32_t value = getStorageValue(key); + if (value != -1) { + value |= (1 << (tmpEffectId % 31)); + } else { + value = (1 << (tmpEffectId % 31)); + } + + addStorageValue(key, value); + return true; +} + +bool Player::untameEffect(uint8_t effectId) { + if (!g_game().attachedeffects->getEffectByID(effectId)) { + return false; + } + + const uint8_t tmpEffectId = effectId - 1; + const uint32_t key = PSTRG_EFFECT_RANGE_START + (tmpEffectId / 31); + + int32_t value = getStorageValue(key); + if (value == -1) { + return true; + } + + value &= ~(1 << (tmpEffectId % 31)); + addStorageValue(key, value); + + if (getCurrentEffect() == effectId) { + if (isEffected()) { + diseffect(); + g_game().internalCreatureChangeOutfit(static_self_cast(), defaultOutfit); + } + + setCurrentEffect(0); + kv()->set("last-effect", 0); + } + + return true; +} + +bool Player::hasEffect(const std::shared_ptr &effect) const { + if (isAccessPlayer()) { + return true; + } + + const uint8_t tmpEffectId = effect->id - 1; + + const int32_t value = getStorageValue(PSTRG_EFFECT_RANGE_START + (tmpEffectId / 31)); + if (value == -1) { + return false; + } + + return ((1 << (tmpEffectId % 31)) & value) != 0; +} + +void Player::diseffect() { + const auto &effect = g_game().attachedeffects->getEffectByID(getCurrentEffect()); + defaultOutfit.lookEffect = 0; +} + +// Shaders +uint16_t Player::getRandomShader() const { + std::vector shadersId; + for (const auto &shader : g_game().attachedeffects->getShaders()) { + if (hasShader(shader.get())) { + shadersId.push_back(shader->id); + } + } + + if (shadersId.empty()) { + return 0; + } + + return shadersId[uniform_random(0, shadersId.size() - 1)]; +} + +uint16_t Player::getCurrentShader() const { + return currentShader; +} + +void Player::setCurrentShader(uint16_t shaderId) { + currentShader = shaderId; +} + +bool Player::toggleShader(bool shader) { + if ((OTSYS_TIME() - lastToggleShader) < 3000 && !wasShadered) { + sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED); + return false; + } + + if (shader) { + if (isShadered()) { + return false; + } + + const auto &playerOutfit = Outfits::getInstance().getOutfitByLookType(getPlayer(), defaultOutfit.lookType); + if (!playerOutfit) { + return false; + } + + uint16_t currentShaderId = getCurrentShader(); + if (currentShaderId == 0) { + sendOutfitWindow(); + return false; + } + + auto currentShaderPtr = g_game().attachedeffects->getShaderByID(currentShaderId); + if (!currentShaderPtr) { + return false; + } + + Shader* currentShader = currentShaderPtr.get(); + + if (!hasShader(currentShader)) { + setCurrentShader(0); + sendOutfitWindow(); + return false; + } + + if (hasCondition(CONDITION_OUTFIT)) { + sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); + return false; + } + + defaultOutfit.lookShader = currentShader->id; + + } else { + if (!isShadered()) { + return false; + } + + disshader(); + } + + g_game().internalCreatureChangeOutfit(static_self_cast(), defaultOutfit); + lastToggleShader = OTSYS_TIME(); + return true; +} + +bool Player::tameShader(uint16_t shaderId) { + auto shaderPtr = g_game().attachedeffects->getShaderByID(shaderId); + if (!shaderPtr) { + return false; + } + + if (hasShader(shaderPtr.get())) { + return false; + } + + shaders.insert(shaderId); + return true; +} + +bool Player::untameShader(uint16_t shaderId) { + auto shaderPtr = g_game().attachedeffects->getShaderByID(shaderId); + if (!shaderPtr) { + return false; + } + + if (!hasShader(shaderPtr.get())) { + return false; + } + + shaders.erase(shaderId); + + if (getCurrentShader() == shaderId) { + if (isShadered()) { + disshader(); + g_game().internalCreatureChangeOutfit(static_self_cast(), defaultOutfit); + } + + setCurrentShader(0); + } + + return true; +} + +bool Player::hasShader(const Shader* shader) const { + if (isAccessPlayer()) { + return true; + } + + return shaders.find(shader->id) != shaders.end(); +} + +bool Player::hasShaders() const { + for (const auto &shader : g_game().attachedeffects->getShaders()) { + if (hasShader(shader.get())) { + return true; + } + } + return false; +} + +void Player::disshader() { + defaultOutfit.lookShader = 0; +} + +std::string Player::getCurrentShader_NAME() const { + uint16_t currentShaderId = getCurrentShader(); + const auto ¤tShader = g_game().attachedeffects->getShaderByID(static_cast(currentShaderId)); + + if (currentShader != nullptr) { + return currentShader->name; + } else { + return "Outfit - Default"; + } +} + +bool Player::addCustomOutfit(const std::string &type, const std::variant &idOrName) { + uint16_t elementId; + + // Get element ID based on variant type + if (std::holds_alternative(idOrName)) { + elementId = std::get(idOrName); + } else { + const std::string &name = std::get(idOrName); + + if (type == "wings") { + auto element = g_game().attachedeffects->getWingByName(name); + if (!element) { + return false; + } + elementId = element->id; + } else if (type == "aura") { + auto element = g_game().attachedeffects->getAuraByName(name); + if (!element) { + return false; + } + elementId = element->id; + } else if (type == "shader") { + auto element = g_game().attachedeffects->getShaderByName(name); + if (!element) { + return false; + } + elementId = element->id; + } else { + return false; + } + } + + // Add element based on type + if (type == "wings") { + return tameWing(elementId); + } else if (type == "aura") { + return tameAura(elementId); + } else if (type == "shader") { + return tameShader(elementId); + } + + return false; +} + +bool Player::removeCustomOutfit(const std::string &type, const std::variant &idOrName) { + uint16_t elementId; + + // Get element ID based on variant type + if (std::holds_alternative(idOrName)) { + elementId = std::get(idOrName); + } else { + const std::string &name = std::get(idOrName); + + if (type == "wings") { + auto element = g_game().attachedeffects->getWingByName(name); + if (!element) { + return false; + } + elementId = element->id; + } else if (type == "aura") { + auto element = g_game().attachedeffects->getAuraByName(name); + if (!element) { + return false; + } + elementId = element->id; + } else if (type == "shader") { + auto element = g_game().attachedeffects->getShaderByName(name); + if (!element) { + return false; + } + elementId = element->id; + } else { + return false; + } + } + + // Remove element based on type + if (type == "wings") { + return untameWing(elementId); + } else if (type == "aura") { + return untameAura(elementId); + } else if (type == "shader") { + return untameShader(elementId); + } + + return false; +} + bool Player::addOfflineTrainingTries(skills_t skill, uint64_t tries) { if (tries == 0 || skill == SKILL_LEVEL) { return false; diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index f7b60983cf7..a056af6432a 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -48,11 +48,16 @@ class Container; class KV; class BedItem; class Npc; +class Attachedeffects; struct ModalWindow; struct Achievement; struct VIPGroup; struct Mount; +struct Wing; +struct Effect; +struct Shader; +struct Aura; struct OutfitEntry; struct Outfit; struct FamiliarEntry; @@ -192,6 +197,70 @@ class Player final : public Creature, public Cylinder, public Bankable { bool hasAnyMount() const; uint8_t getRandomMountId() const; void dismount(); + + // -- @ wings + uint8_t getLastWing() const; + uint8_t getCurrentWing() const; + void setCurrentWing(uint8_t wingId); + bool isWinged() const { + return defaultOutfit.lookWing != 0; + } + bool toggleWing(bool wing); + bool tameWing(uint8_t wingId); + bool untameWing(uint8_t wingId); + bool hasWing(const std::shared_ptr &wing) const; + bool hasAnyWing() const; + uint8_t getRandomWingId() const; + void diswing(); + + // -- @ + // -- @ Auras + uint8_t getLastAura() const; + uint8_t getCurrentAura() const; + void setCurrentAura(uint8_t auraId); + bool isAuraed() const { + return defaultOutfit.lookAura != 0; + } + bool toggleAura(bool aura); + bool tameAura(uint8_t auraId); + bool untameAura(uint8_t auraId); + bool hasAura(const std::shared_ptr &aura) const; + bool hasAnyAura() const; + uint8_t getRandomAuraId() const; + void disaura(); + // -- @ + // -- @ Effect + uint8_t getLastEffect() const; + uint8_t getCurrentEffect() const; + void setCurrentEffect(uint8_t effectId); + bool isEffected() const { + return defaultOutfit.lookEffect != 0; + } + bool toggleEffect(bool effect); + bool tameEffect(uint8_t effectId); + bool untameEffect(uint8_t effectId); + bool hasEffect(const std::shared_ptr &effect) const; + bool hasAnyEffect() const; + uint8_t getRandomEffectId() const; + void diseffect(); + // -- @ + // -- @ Shader + uint16_t getRandomShader() const; + uint16_t getCurrentShader() const; + void setCurrentShader(uint16_t shaderId); + bool isShadered() const { + return defaultOutfit.lookShader != 0; + } + bool toggleShader(bool shader); + bool tameShader(uint16_t shaderId); + bool untameShader(uint16_t shaderId); + bool hasShader(const Shader* shader) const; + bool hasShaders() const; + void disshader(); + std::string getCurrentShader_NAME() const; + bool addCustomOutfit(const std::string &type, const std::variant &idOrName); + bool removeCustomOutfit(const std::string &type, const std::variant &idOrName); + uint16_t getDodgeChance() const; uint8_t isRandomMounted() const; @@ -1364,6 +1433,10 @@ class Player final : public Creature, public Cylinder, public Bankable { std::vector quickLootListItemIds; std::vector outfits; + std::unordered_set wings; + std::unordered_set auras; + std::unordered_set effects; + std::unordered_set shaders; std::vector familiars; std::vector> preys; @@ -1416,6 +1489,10 @@ class Player final : public Creature, public Cylinder, public Bankable { int64_t lastPing; int64_t lastPong; int64_t nextAction = 0; + int64_t lastToggleWing = 0; + int64_t lastToggleEffect = 0; + int64_t lastToggleAura = 0; + int64_t lastToggleShader = 0; int64_t nextPotionAction = 0; int64_t lastQuickLootNotification = 0; int64_t lastWalking = 0; @@ -1558,6 +1635,14 @@ class Player final : public Creature, public Cylinder, public Bankable { bool moved = false; bool m_isDead = false; bool imbuementTrackerWindowOpen = false; + bool wasWinged = false; + bool wasAuraed = false; + bool wasEffected = false; + bool wasShadered = false; + bool randomizeWing = false; + bool randomizeAura = false; + bool randomizeEffect = false; + bool randomizeShader = false; // Hazard system int64_t lastHazardSystemCriticalHit = 0; diff --git a/src/game/game.cpp b/src/game/game.cpp index 93a04fd42b8..065484d07a2 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -11,6 +11,7 @@ #include "config/configmanager.hpp" #include "creatures/appearance/mounts/mounts.hpp" +#include "creatures/appearance/attachedeffects/attachedeffects.hpp" #include "creatures/combat/condition.hpp" #include "creatures/combat/spells.hpp" #include "creatures/creature.hpp" @@ -217,6 +218,7 @@ Game::Game() { wildcardTree = std::make_shared(false); mounts = std::make_unique(); + attachedeffects = std::make_unique(); using enum CyclopediaBadge_t; using enum CyclopediaTitle_t; @@ -623,6 +625,7 @@ void Game::setGameState(GameState_t newState) { raids.startup(); mounts->loadFromXml(); + attachedeffects->loadFromXml(); loadMotdNum(); loadPlayersRecord(); @@ -6128,6 +6131,82 @@ void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit, uint8_t isMoun internalCreatureChangeOutfit(player, outfit); } + + // @ wings + if (outfit.lookWing != 0) { + const auto wing = attachedeffects->getWingByID(outfit.lookWing); + if (!wing) { + return; + } + + player->detachEffectById(player->getCurrentWing()); + player->setCurrentWing(wing->id); + player->attachEffectById(wing->id); + } else { + if (player->isWinged()) { + player->diswing(); + } + player->detachEffectById(player->getCurrentWing()); + player->wasWinged = false; + } + // @ + // @ Effect + if (outfit.lookEffect != 0) { + const auto effect = attachedeffects->getEffectByID(outfit.lookEffect); + if (!effect) { + return; + } + + player->detachEffectById(player->getCurrentEffect()); + player->setCurrentEffect(effect->id); + player->attachEffectById(effect->id); + } else { + if (player->isEffected()) { + player->diseffect(); + } + player->detachEffectById(player->getCurrentEffect()); + player->wasEffected = false; + } + // @ + // @ Aura + if (outfit.lookAura != 0) { + const auto aura = attachedeffects->getAuraByID(outfit.lookAura); + if (!aura) { + return; + } + player->detachEffectById(player->getCurrentAura()); + player->setCurrentAura(aura->id); + player->attachEffectById(aura->id); + } else { + if (player->isAuraed()) { + player->disaura(); + } + player->detachEffectById(player->getCurrentAura()); + player->wasAuraed = false; + } + // @ + /// shaders + if (outfit.lookShader != 0) { + const auto shaderPtr = attachedeffects->getShaderByID(outfit.lookShader); + if (!shaderPtr) { + return; + } + Shader* shader = shaderPtr.get(); + + if (!player->hasShader(shader)) { + return; + } + + player->setCurrentShader(shader->id); + player->sendShader(player, shader->name); + + } else { + if (player->isShadered()) { + player->disshader(); + } + player->sendShader(player, "Outfit - Default"); + player->wasShadered = false; + } } void Game::playerShowQuestLog(uint32_t playerId) { diff --git a/src/game/game.hpp b/src/game/game.hpp index 7f421780efc..16b7a3467c2 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -38,6 +38,7 @@ class IOWheel; class ItemClassification; class Guild; class Mounts; +class Attachedeffects; class Spectators; class Player; class Account; @@ -560,6 +561,7 @@ class Game { Map map; std::unique_ptr mounts; [[no_unique_address]] Outfits outfits; + std::unique_ptr attachedeffects; Raids raids; std::unique_ptr m_appearancesPtr; diff --git a/src/lua/functions/core/game/game_functions.cpp b/src/lua/functions/core/game/game_functions.cpp index 16133833bbc..2490f0c71df 100644 --- a/src/lua/functions/core/game/game_functions.cpp +++ b/src/lua/functions/core/game/game_functions.cpp @@ -9,6 +9,7 @@ #include "lua/functions/core/game/game_functions.hpp" +#include "creatures/Appearance/attachedeffects/attachedeffects.hpp" // delete before push #include "core.hpp" #include "creatures/monsters/monster.hpp" #include "creatures/monsters/monsters.hpp" @@ -916,3 +917,60 @@ int GameFunctions::luaGameGetAchievements(lua_State* L) { } return 1; } + +int GameFunctions::getAllAttachedeffects(lua_State* L) { // delete before push + // Game.getAllAttachedeffects(type) + const std::string type = luaL_checkstring(L, 1); + + lua_newtable(L); + + if (type == "aura") { + const auto &auras = g_game().attachedeffects->getAuras(); + int index = 1; + for (const auto &aura : auras) { + lua_newtable(L); + lua_pushinteger(L, aura->id); + lua_setfield(L, -2, "id"); + lua_pushstring(L, aura->name.c_str()); + lua_setfield(L, -2, "name"); + lua_rawseti(L, -2, index++); + } + } else if (type == "wing") { + const auto &wings = g_game().attachedeffects->getWings(); + int index = 1; + for (const auto &wing : wings) { + lua_newtable(L); + lua_pushinteger(L, wing->id); + lua_setfield(L, -2, "id"); + lua_pushstring(L, wing->name.c_str()); + lua_setfield(L, -2, "name"); + lua_rawseti(L, -2, index++); + } + } else if (type == "effect") { + const auto &wings = g_game().attachedeffects->getEffects(); + int index = 1; + for (const auto &wing : wings) { + lua_newtable(L); + lua_pushinteger(L, wing->id); + lua_setfield(L, -2, "id"); + lua_pushstring(L, wing->name.c_str()); + lua_setfield(L, -2, "name"); + lua_rawseti(L, -2, index++); + } + } else if (type == "shader") { + const auto &shaders = g_game().attachedeffects->getShaders(); + int index = 1; + for (const auto &shader : shaders) { + lua_newtable(L); + lua_pushinteger(L, shader->id); + lua_setfield(L, -2, "id"); + lua_pushstring(L, shader->name.c_str()); + lua_setfield(L, -2, "name"); + lua_rawseti(L, -2, index++); + } + } else { + lua_pushnil(L); + } + + return 1; +} diff --git a/src/lua/functions/core/game/game_functions.hpp b/src/lua/functions/core/game/game_functions.hpp index 3c668c54fb4..f94494871b3 100644 --- a/src/lua/functions/core/game/game_functions.hpp +++ b/src/lua/functions/core/game/game_functions.hpp @@ -95,6 +95,8 @@ class GameFunctions final : LuaScriptInterface { registerMethod(L, "Game", "getSecretAchievements", GameFunctions::luaGameGetSecretAchievements); registerMethod(L, "Game", "getPublicAchievements", GameFunctions::luaGameGetPublicAchievements); registerMethod(L, "Game", "getAchievements", GameFunctions::luaGameGetAchievements); + + registerMethod(L, "Game", "getAllAttachedeffects", GameFunctions::getAllAttachedeffects); // delete before push } private: @@ -172,4 +174,5 @@ class GameFunctions final : LuaScriptInterface { static int luaGameGetSecretAchievements(lua_State* L); static int luaGameGetPublicAchievements(lua_State* L); static int luaGameGetAchievements(lua_State* L); + static int getAllAttachedeffects(lua_State* L); // delete before push }; diff --git a/src/lua/functions/creatures/combat/condition_functions.cpp b/src/lua/functions/creatures/combat/condition_functions.cpp index 1362f0f1f31..b4b880c79a8 100644 --- a/src/lua/functions/creatures/combat/condition_functions.cpp +++ b/src/lua/functions/creatures/combat/condition_functions.cpp @@ -198,6 +198,10 @@ int ConditionFunctions::luaConditionSetOutfit(lua_State* L) { outfit.lookHead = getNumber(L, 4); outfit.lookType = getNumber(L, 3); outfit.lookTypeEx = getNumber(L, 2); + outfit.lookWing = getNumber(L, 15); + outfit.lookAura = getNumber(L, 16); + outfit.lookEffect = getNumber(L, 17); + outfit.lookShader = getNumber(L, 18); } const std::shared_ptr &condition = getUserdataShared(L, 1)->dynamic_self_cast(); diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index c59b0432c51..e899649f98b 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -4490,3 +4490,47 @@ int PlayerFunctions::luaPlayerSetMapShader(lua_State* L) { pushBoolean(L, true); return 1; } + +int PlayerFunctions::luaPlayerAddCustomOutfit(lua_State* L) { + // player:addCustomOutfit(type, id or name) + const auto &player = getUserdataShared(L, 1); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + pushBoolean(L, false); + return 0; + } + + std::string type = getString(L, 2); + std::variant idOrName; + + if (isNumber(L, 3)) { + idOrName = getNumber(L, 3); + } else { + idOrName = getString(L, 3); + } + + pushBoolean(L, player->addCustomOutfit(type, idOrName)); + return 1; +} + +int PlayerFunctions::luaPlayerRemoveCustomOutfit(lua_State* L) { + // player:removeCustomOutfit(type, id or name) + const auto &player = getUserdataShared(L, 1); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + pushBoolean(L, false); + return 0; + } + + std::string type = getString(L, 2); + std::variant idOrName; + + if (isNumber(L, 3)) { + idOrName = getNumber(L, 3); + } else { + idOrName = getString(L, 3); + } + + pushBoolean(L, player->removeCustomOutfit(type, idOrName)); + return 1; +} diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp index 4fdb04ac259..97b10ed591c 100644 --- a/src/lua/functions/creatures/player/player_functions.hpp +++ b/src/lua/functions/creatures/player/player_functions.hpp @@ -391,6 +391,8 @@ class PlayerFunctions final : LuaScriptInterface { // OTCR Features registerMethod(L, "Player", "getMapShader", PlayerFunctions::luaPlayerGetMapShader); registerMethod(L, "Player", "setMapShader", PlayerFunctions::luaPlayerSetMapShader); + registerMethod(L, "Player", "removeCustomOutfit", PlayerFunctions::luaPlayerRemoveCustomOutfit); + registerMethod(L, "Player", "addCustomOutfit", PlayerFunctions::luaPlayerAddCustomOutfit); GroupFunctions::init(L); GuildFunctions::init(L); @@ -763,5 +765,8 @@ class PlayerFunctions final : LuaScriptInterface { static int luaPlayerGetMapShader(lua_State* L); static int luaPlayerSetMapShader(lua_State* L); + static int luaPlayerAddCustomOutfit(lua_State* L); + static int luaPlayerRemoveCustomOutfit(lua_State* L); + friend class CreatureFunctions; }; diff --git a/src/lua/functions/lua_functions_loader.cpp b/src/lua/functions/lua_functions_loader.cpp index 894cf252c80..545e2c0ff2f 100644 --- a/src/lua/functions/lua_functions_loader.cpp +++ b/src/lua/functions/lua_functions_loader.cpp @@ -441,7 +441,12 @@ Outfit_t LuaFunctionsLoader::getOutfit(lua_State* L, int32_t arg) { outfit.lookTypeEx = getField(L, arg, "lookTypeEx"); outfit.lookType = getField(L, arg, "lookType"); - lua_pop(L, 13); + outfit.lookWing = getField(L, arg, "lookShader"); + outfit.lookAura = getField(L, arg, "lookAura"); + outfit.lookEffect = getField(L, arg, "lookEffect"); + outfit.lookShader = getField(L, arg, "lookShader"); + + lua_pop(L, 17); return outfit; } @@ -623,7 +628,7 @@ void LuaFunctionsLoader::pushOutfit(lua_State* L, const Outfit_t &outfit) { return; } - lua_createtable(L, 0, 13); + lua_createtable(L, 0, 17); setField(L, "lookType", outfit.lookType); setField(L, "lookTypeEx", outfit.lookTypeEx); setField(L, "lookHead", outfit.lookHead); @@ -637,6 +642,10 @@ void LuaFunctionsLoader::pushOutfit(lua_State* L, const Outfit_t &outfit) { setField(L, "lookMountLegs", outfit.lookMountLegs); setField(L, "lookMountFeet", outfit.lookMountFeet); setField(L, "lookFamiliarsType", outfit.lookFamiliarsType); + setField(L, "lookWing ", outfit.lookWing); + setField(L, "lookAura", outfit.lookAura); + setField(L, "lookEffect ", outfit.lookEffect); + setField(L, "lookShader ", outfit.lookShader); } void LuaFunctionsLoader::registerClass(lua_State* L, const std::string &className, const std::string &baseClass, lua_CFunction newFunction /* = nullptr*/) { diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 29d2d5b4d0a..7d3f56359d6 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -12,6 +12,7 @@ #include "config/configmanager.hpp" #include "core.hpp" #include "creatures/appearance/mounts/mounts.hpp" +#include "creatures/appearance/attachedeffects/attachedeffects.hpp" #include "creatures/combat/condition.hpp" #include "creatures/combat/spells.hpp" #include "creatures/interactions/chat.hpp" @@ -503,7 +504,7 @@ void ProtocolGame::login(const std::string &name, uint32_t accountId, OperatingS if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) { isOTC = true; if (isOTC && otclientV8 == 0) { - // sendOTCRFeatures(); first I need to make pr in redemption + sendOTCRFeatures(); } NetworkMessage opcodeMessage; opcodeMessage.addByte(0x32); @@ -1719,6 +1720,14 @@ void ProtocolGame::parseSetOutfit(NetworkMessage &msg) { } uint8_t isMountRandomized = msg.getByte(); + newOutfit.lookWing = isOTCR ? msg.get() : 0; + newOutfit.lookAura = isOTCR ? msg.get() : 0; + newOutfit.lookEffect = isOTCR ? msg.get() : 0; + std::string shaderName = isOTCR ? msg.getString() : ""; + if (!shaderName.empty()) { + const auto &shader = g_game().attachedeffects->getShaderByName(shaderName); + newOutfit.lookShader = shader ? shader->id : 0; + } g_game().playerChangeOutfit(player->getID(), newOutfit, isMountRandomized); } else if (outfitType == 1) { // This value probably has something to do with try outfit variable inside outfit window dialog @@ -7096,6 +7105,24 @@ void ProtocolGame::sendOutfitWindow() { currentOutfit.lookMount = 0; } + const auto ¤tWing = g_game().attachedeffects->getWingByID(player->getCurrentWing()); + if (currentWing) { + currentOutfit.lookWing = currentWing->id; + } + // @ -- auras + const auto ¤tAura = g_game().attachedeffects->getAuraByID(player->getCurrentAura()); + if (currentAura) { + currentOutfit.lookAura = currentAura->id; + } + // @ -- effects + const auto ¤tEffect = g_game().attachedeffects->getEffectByID(player->getCurrentEffect()); + if (currentEffect) { + currentOutfit.lookEffect = currentEffect->id; + } + const auto ¤tShader = g_game().attachedeffects->getShaderByID(player->getCurrentShader()); + if (currentShader) { + currentOutfit.lookShader = currentShader->id; + } AddOutfit(msg, currentOutfit); if (oldProtocol) { @@ -7135,6 +7162,9 @@ void ProtocolGame::sendOutfitWindow() { msg.addString(mount->name); } + if (isOTCR) { + sendOutfitWindowCustomOTCR(msg); + } writeToOutputBuffer(msg); return; } @@ -7277,6 +7307,9 @@ void ProtocolGame::sendOutfitWindow() { // Version 12.81 - Random mount 'bool' msg.addByte(isSupportOutfit ? 0x00 : (player->isRandomMounted() ? 0x01 : 0x00)); + if (isOTCR) { + sendOutfitWindowCustomOTCR(msg); + } writeToOutputBuffer(msg); } @@ -7909,6 +7942,9 @@ void ProtocolGame::AddOutfit(NetworkMessage &msg, const Outfit_t &outfit, bool a if (addMount) { msg.add(outfit.lookMount); } + if (isOTCR) { + AddOutfitCustomOTCR(msg, outfit); + } } void ProtocolGame::addImbuementInfo(NetworkMessage &msg, uint16_t imbuementId) const { @@ -9383,3 +9419,87 @@ void ProtocolGame::sendPlayerTyping(const std::shared_ptr &creature, u msg.addByte(typing); writeToOutputBuffer(msg); } + +void ProtocolGame::AddOutfitCustomOTCR(NetworkMessage &msg, const Outfit_t &outfit) { + if (!isOTCR) { + return; + } + + msg.add(outfit.lookWing); + msg.add(outfit.lookAura); + msg.add(outfit.lookEffect); + const auto &shader = g_game().attachedeffects->getShaderByID(outfit.lookShader); + msg.addString(shader ? shader->name : ""); +} + +void ProtocolGame::sendOutfitWindowCustomOTCR(NetworkMessage &msg) { + if (!isOTCR) { + return; + } + // wings + auto startWings = msg.getBufferPosition(); + uint16_t limitWings = std::numeric_limits::max(); + uint16_t wingSize = 0; + msg.skipBytes(1); + const auto wings = g_game().attachedeffects->getWings(); + for (const auto &wing : wings) { + if (player->hasWing(wing)) { + msg.add(wing->id); + msg.addString(wing->name); + ++wingSize; + } + if (wingSize == limitWings) { + break; + } + } + auto endWings = msg.getBufferPosition(); + msg.setBufferPosition(startWings); + msg.add(wingSize); + msg.setBufferPosition(endWings); + // auras + auto startAuras = msg.getBufferPosition(); + uint16_t limitAuras = std::numeric_limits::max(); + uint16_t auraSize = 0; + msg.skipBytes(1); + const auto auras = g_game().attachedeffects->getAuras(); + for (const auto &aura : auras) { + if (player->hasAura(aura)) { + msg.add(aura->id); + msg.addString(aura->name); + ++auraSize; + } + } + auto endAuras = msg.getBufferPosition(); + msg.setBufferPosition(startAuras); + msg.add(auraSize); + msg.setBufferPosition(endAuras); + // effects + auto startEffects = msg.getBufferPosition(); + uint16_t limitEffects = std::numeric_limits::max(); + uint16_t effectSize = 0; + msg.skipBytes(1); + const auto effects = g_game().attachedeffects->getEffects(); + for (const auto &effect : effects) { + if (player->hasEffect(effect)) { + msg.add(effect->id); + msg.addString(effect->name); + ++effectSize; + } + } + auto endEffects = msg.getBufferPosition(); + msg.setBufferPosition(startEffects); + msg.add(effectSize); + msg.setBufferPosition(endEffects); + // shader + std::vector shaders; + for (const auto &shader : g_game().attachedeffects->getShaders()) { + if (player->hasShader(shader.get())) { + shaders.push_back(shader.get()); + } + } + msg.addByte(static_cast(shaders.size())); + for (const Shader* shader : shaders) { + msg.add(shader->id); + msg.addString(shader->name); + } +} diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index d9f1196cc72..de8f0781499 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -497,6 +497,8 @@ class ProtocolGame final : public Protocol { void sendMapShader(const std::string &shaderName); void sendPlayerTyping(const std::shared_ptr &creature, uint8_t typing); void parsePlayerTyping(NetworkMessage &msg); + void AddOutfitCustomOTCR(NetworkMessage &msg, const Outfit_t &outfit); + void sendOutfitWindowCustomOTCR(NetworkMessage &msg); void parseInventoryImbuements(NetworkMessage &msg); void sendInventoryImbuements(const std::map> &items); diff --git a/src/utils/const.hpp b/src/utils/const.hpp index 4cc296e4a7e..0e828a6f2b9 100644 --- a/src/utils/const.hpp +++ b/src/utils/const.hpp @@ -48,6 +48,22 @@ static constexpr int32_t PSTRG_OUTFITS_RANGE_SIZE = 500; static constexpr int32_t PSTRG_MOUNTS_RANGE_START = (PSTRG_RESERVED_RANGE_START + 2001); static constexpr int32_t PSTRG_MOUNTS_RANGE_SIZE = 10; static constexpr int32_t PSTRG_MOUNTS_CURRENTMOUNT = (PSTRG_MOUNTS_RANGE_START + 10); +//[2012 - 2022]; +static constexpr int32_t PSTRG_WING_RANGE_START = (PSTRG_RESERVED_RANGE_START + 2012); +static constexpr int32_t PSTRG_WING_RANGE_SIZE = 10; +static constexpr int32_t PSTRG_WING_CURRENTWING = (PSTRG_WING_RANGE_START + 10); +//[2023 - 2033]; +static constexpr int32_t PSTRG_EFFECT_RANGE_START = (PSTRG_RESERVED_RANGE_START + 2023); +static constexpr int32_t PSTRG_EFFECT_RANGE_SIZE = 10; +static constexpr int32_t PSTRG_EFFECT_CURRENTEFFECT = (PSTRG_EFFECT_RANGE_START + 10); +//[2034 - 2044]; +static constexpr int32_t PSTRG_AURA_RANGE_START = (PSTRG_RESERVED_RANGE_START + 2034); +static constexpr int32_t PSTRG_AURA_RANGE_SIZE = 10; +static constexpr int32_t PSTRG_AURA_CURRENTAURA = (PSTRG_AURA_RANGE_START + 10); +//[2045 - 2055]; +static constexpr int32_t PSTRG_SHADER_RANGE_START = (PSTRG_RESERVED_RANGE_START + 2045); +static constexpr int32_t PSTRG_SHADER_RANGE_SIZE = 10; +static constexpr int32_t PSTRG_SHADER_CURRENTSHADER = (PSTRG_SHADER_RANGE_START + 10); // [3000 - 3500]; static constexpr int32_t PSTRG_FAMILIARS_RANGE_START = (PSTRG_RESERVED_RANGE_START + 3000); static constexpr int32_t PSTRG_FAMILIARS_RANGE_SIZE = 500; diff --git a/vcproj/canary.vcxproj b/vcproj/canary.vcxproj index 7cbdd118ccc..de155191590 100644 --- a/vcproj/canary.vcxproj +++ b/vcproj/canary.vcxproj @@ -20,6 +20,7 @@ + @@ -237,6 +238,7 @@ + From 789354a79c372a440dcba370fa105de91b229efd Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Thu, 7 Nov 2024 15:28:42 -0300 Subject: [PATCH 21/29] this requires review canary team .no break v8 and cipsoft --- src/server/network/protocol/protocolgame.cpp | 30 +++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 7d3f56359d6..86ce4f32729 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -1719,7 +1719,7 @@ void ProtocolGame::parseSetOutfit(NetworkMessage &msg) { g_logger().debug("Bool isMounted: {}", isMounted); } - uint8_t isMountRandomized = msg.getByte(); + uint8_t isMountRandomized = !oldProtocol ? msg.getByte() : 0; newOutfit.lookWing = isOTCR ? msg.get() : 0; newOutfit.lookAura = isOTCR ? msg.get() : 0; newOutfit.lookEffect = isOTCR ? msg.get() : 0; @@ -3290,12 +3290,6 @@ void ProtocolGame::sendCreatureOutfit(const std::shared_ptr &creature, msg.add(creature->getID()); 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); } @@ -7169,10 +7163,12 @@ void ProtocolGame::sendOutfitWindow() { return; } - msg.addByte(isSupportOutfit ? 0 : currentOutfit.lookMountHead); - msg.addByte(isSupportOutfit ? 0 : currentOutfit.lookMountBody); - msg.addByte(isSupportOutfit ? 0 : currentOutfit.lookMountLegs); - msg.addByte(isSupportOutfit ? 0 : currentOutfit.lookMountFeet); + if (currentOutfit.lookMount == 0) { + 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(); @@ -7738,12 +7734,6 @@ void ProtocolGame::AddCreature(NetworkMessage &msg, const std::shared_ptrisInGhostMode() && !creature->isInvisible()) { const Outfit_t &outfit = creature->getCurrentOutfit(); AddOutfit(msg, outfit); - if (!oldProtocol && outfit.lookMount != 0) { - msg.addByte(outfit.lookMountHead); - msg.addByte(outfit.lookMountBody); - msg.addByte(outfit.lookMountLegs); - msg.addByte(outfit.lookMountFeet); - } } else { static Outfit_t outfit; AddOutfit(msg, outfit); @@ -7941,6 +7931,12 @@ void ProtocolGame::AddOutfit(NetworkMessage &msg, const Outfit_t &outfit, bool a if (addMount) { msg.add(outfit.lookMount); + if (!oldProtocol && outfit.lookMount != 0) { + msg.addByte(outfit.lookMountHead); + msg.addByte(outfit.lookMountBody); + msg.addByte(outfit.lookMountLegs); + msg.addByte(outfit.lookMountFeet); + } } if (isOTCR) { AddOutfitCustomOTCR(msg, outfit); From 6a23e40adc0301943b07553ec5ac5e1c6df6e73c Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 7 Nov 2024 18:34:24 +0000 Subject: [PATCH 22/29] Lua code format - (Stylua) --- data/scripts/talkactions/gm/delete_test_otcr.lua | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/data/scripts/talkactions/gm/delete_test_otcr.lua b/data/scripts/talkactions/gm/delete_test_otcr.lua index 168fe228f51..a46f7026810 100644 --- a/data/scripts/talkactions/gm/delete_test_otcr.lua +++ b/data/scripts/talkactions/gm/delete_test_otcr.lua @@ -83,10 +83,9 @@ local options = { for _, effect in ipairs(effects) do table.insert(ids, effect.id) end - player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "aura registered on the server: ".. table.concat(ids, ", ")) + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "aura registered on the server: " .. table.concat(ids, ", ")) else player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "the server did not charge aura check .xml") - end end, }, @@ -99,7 +98,7 @@ local options = { for _, effect in ipairs(effects) do table.insert(ids, effect.id) end - player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "wing registered on the server: "..table.concat(ids, ", ")) + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "wing registered on the server: " .. table.concat(ids, ", ")) else player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "the server did not charge wing check .xml") end @@ -108,35 +107,31 @@ local options = { { name = "pdump effect", action = function(player) - local effects = Game.getAllAttachedeffects("effect") if #effects > 0 then local ids = {} for _, effect in ipairs(effects) do table.insert(ids, effect.id) end - player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "effect registered on the server: "..table.concat(ids, ", ")) + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "effect registered on the server: " .. table.concat(ids, ", ")) else player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "the server did not charge effect check .xml") end - end, }, { name = "pdump shader", action = function(player) - local effects = Game.getAllAttachedeffects("shader") if #effects > 0 then local ids = {} for _, effect in ipairs(effects) do table.insert(ids, effect.name) end - player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "shader registered on the server: "..table.concat(ids, ", ")) + player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "shader registered on the server: " .. table.concat(ids, ", ")) else player:sendTextMessage(MESSAGE_GAMEMASTER_CONSOLE, "the server did not charge shader check .xml") end - end, }, }, @@ -183,7 +178,6 @@ talkAction:groupType("gamemaster") talkAction:separator(" ") talkAction:register() - local playerLoginTestOTCR = CreatureEvent("simpletest") function playerLoginTestOTCR.onLogin(player) @@ -193,7 +187,7 @@ function playerLoginTestOTCR.onLogin(player) if player:getClient().os >= 10 and player:getClient().os < 20 then player:say("say !testOTCR", TALKTYPE_SAY) end -return true + return true end playerLoginTestOTCR:register() From 36da43e17a347343dbb4cdc95ee294a7ca4386ec Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:40:26 -0300 Subject: [PATCH 23/29] fix: review sonarcloud ? --- .../attachedeffects/attachedeffects.cpp | 17 +++++++++-------- src/creatures/players/player.cpp | 10 +++++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/creatures/appearance/attachedeffects/attachedeffects.cpp b/src/creatures/appearance/attachedeffects/attachedeffects.cpp index f9d2e30e9d7..6e71f3bd3e4 100644 --- a/src/creatures/appearance/attachedeffects/attachedeffects.cpp +++ b/src/creatures/appearance/attachedeffects/attachedeffects.cpp @@ -6,6 +6,7 @@ * Contributors: https://github.com/opentibiabr/canary/graphs/contributors * Website: https://docs.opentibiabr.com/ */ + #include "creatures/Appearance/attachedeffects/attachedeffects.hpp" #include "config/configmanager.hpp" @@ -62,28 +63,28 @@ bool Attachedeffects::loadFromXml() { } std::shared_ptr Attachedeffects::getAuraByID(uint8_t id) { - auto it = std::find_if(auras.begin(), auras.end(), [id](const std::shared_ptr &aura) { + auto it = std::ranges::find_if(auras.begin(), auras.end(), [id](const std::shared_ptr &aura) { return aura->id == id; }); return it != auras.end() ? *it : nullptr; } std::shared_ptr Attachedeffects::getEffectByID(uint8_t id) { - auto it = std::find_if(effects.begin(), effects.end(), [id](const std::shared_ptr &effect) { + auto it = std::ranges::find_if(effects.begin(), effects.end(), [id](const std::shared_ptr &effect) { return effect->id == id; }); return it != effects.end() ? *it : nullptr; } std::shared_ptr Attachedeffects::getWingByID(uint8_t id) { - auto it = std::find_if(wings.begin(), wings.end(), [id](const std::shared_ptr &wing) { + auto it = std::ranges::find_if(wings.begin(), wings.end(), [id](const std::shared_ptr &wing) { return wing->id == id; }); return it != wings.end() ? *it : nullptr; } std::shared_ptr Attachedeffects::getShaderByID(uint8_t id) { - auto it = std::find_if(shaders.begin(), shaders.end(), [id](const std::shared_ptr &shader) { + auto it = std::ranges::find_if(shaders.begin(), shaders.end(), [id](const std::shared_ptr &shader) { return shader->id == id; }); return it != shaders.end() ? *it : nullptr; @@ -91,7 +92,7 @@ std::shared_ptr Attachedeffects::getShaderByID(uint8_t id) { std::shared_ptr Attachedeffects::getAuraByName(const std::string &name) { auto auraName = name.c_str(); - auto it = std::find_if(auras.begin(), auras.end(), [auraName](const std::shared_ptr &aura) { + auto it = std::ranges::find_if(auras.begin(), auras.end(), [auraName](const std::shared_ptr &aura) { return strcasecmp(auraName, aura->name.c_str()) == 0; }); return it != auras.end() ? *it : nullptr; @@ -99,7 +100,7 @@ std::shared_ptr Attachedeffects::getAuraByName(const std::string &name) { std::shared_ptr Attachedeffects::getShaderByName(const std::string &name) { auto shaderName = name.c_str(); - auto it = std::find_if(shaders.begin(), shaders.end(), [shaderName](const std::shared_ptr &shader) { + auto it = std::ranges::find_if(shaders.begin(), shaders.end(), [shaderName](const std::shared_ptr &shader) { return strcasecmp(shaderName, shader->name.c_str()) == 0; }); return it != shaders.end() ? *it : nullptr; @@ -107,7 +108,7 @@ std::shared_ptr Attachedeffects::getShaderByName(const std::string &name std::shared_ptr Attachedeffects::getEffectByName(const std::string &name) { auto effectName = name.c_str(); - auto it = std::find_if(effects.begin(), effects.end(), [effectName](const std::shared_ptr &effect) { + auto it = std::ranges::find_if(effects.begin(), effects.end(), [effectName](const std::shared_ptr &effect) { return strcasecmp(effectName, effect->name.c_str()) == 0; }); return it != effects.end() ? *it : nullptr; @@ -115,7 +116,7 @@ std::shared_ptr Attachedeffects::getEffectByName(const std::string &name std::shared_ptr Attachedeffects::getWingByName(const std::string &name) { auto wingName = name.c_str(); - auto it = std::find_if(wings.begin(), wings.end(), [wingName](const std::shared_ptr &wing) { + auto it = std::ranges::find_if(wings.begin(), wings.end(), [wingName](const std::shared_ptr &wing) { return strcasecmp(wingName, wing->name.c_str()) == 0; }); return it != wings.end() ? *it : nullptr; diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 34a608c85ca..b4c0e6ed129 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -7043,17 +7043,17 @@ bool Player::hasAnyWing() const { } uint8_t Player::getRandomWingId() const { - std::vector playerWings; + std::vector availableWings; const auto wings = g_game().attachedeffects->getWings(); for (const auto &wing : wings) { if (hasWing(wing)) { - playerWings.emplace_back(wing->id); + availableWings.emplace_back(wing->id); } } - const auto playerWingsSize = static_cast(playerWings.size() - 1); - const auto randomIndex = uniform_random(0, std::max(0, playerWingsSize)); - return playerWings.at(randomIndex); + const auto availableWingsSize = static_cast(availableWings.size() - 1); + const auto randomIndex = uniform_random(0, std::max(0, availableWingsSize)); + return availableWings.at(randomIndex); } bool Player::toggleWing(bool wing) { From 8e939e5f21620ec3d5fba1a703b08b7b141440b1 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 7 Nov 2024 19:41:06 +0000 Subject: [PATCH 24/29] Code format - (Clang-format) --- src/creatures/players/player.cpp | 4 --- src/game/game.cpp | 2 +- .../functions/core/game/game_functions.cpp | 34 +++++++++---------- src/server/network/protocol/protocolgame.cpp | 4 +-- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index b4c0e6ed129..f79ecc75b80 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -7184,8 +7184,6 @@ void Player::diswing() { defaultOutfit.lookWing = 0; } - - // Auras uint8_t Player::getLastAura() const { @@ -7356,7 +7354,6 @@ void Player::disaura() { defaultOutfit.lookAura = 0; } - // Effects uint8_t Player::getLastEffect() const { @@ -7411,7 +7408,6 @@ bool Player::toggleEffect(bool effect) { return false; } - const auto &playerOutfit = Outfits::getInstance().getOutfitByLookType(getPlayer(), defaultOutfit.lookType); if (!playerOutfit) { return false; diff --git a/src/game/game.cpp b/src/game/game.cpp index 065484d07a2..3ada9bb4245 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -6132,7 +6132,7 @@ void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit, uint8_t isMoun internalCreatureChangeOutfit(player, outfit); } - // @ wings + // @ wings if (outfit.lookWing != 0) { const auto wing = attachedeffects->getWingByID(outfit.lookWing); if (!wing) { diff --git a/src/lua/functions/core/game/game_functions.cpp b/src/lua/functions/core/game/game_functions.cpp index 2490f0c71df..87920d0f5f2 100644 --- a/src/lua/functions/core/game/game_functions.cpp +++ b/src/lua/functions/core/game/game_functions.cpp @@ -920,57 +920,57 @@ int GameFunctions::luaGameGetAchievements(lua_State* L) { int GameFunctions::getAllAttachedeffects(lua_State* L) { // delete before push // Game.getAllAttachedeffects(type) - const std::string type = luaL_checkstring(L, 1); + const std::string type = luaL_checkstring(L, 1); - lua_newtable(L); + lua_newtable(L); if (type == "aura") { const auto &auras = g_game().attachedeffects->getAuras(); int index = 1; for (const auto &aura : auras) { - lua_newtable(L); + lua_newtable(L); lua_pushinteger(L, aura->id); lua_setfield(L, -2, "id"); - lua_pushstring(L, aura->name.c_str()); + lua_pushstring(L, aura->name.c_str()); lua_setfield(L, -2, "name"); - lua_rawseti(L, -2, index++); + lua_rawseti(L, -2, index++); } } else if (type == "wing") { const auto &wings = g_game().attachedeffects->getWings(); int index = 1; for (const auto &wing : wings) { - lua_newtable(L); + lua_newtable(L); lua_pushinteger(L, wing->id); lua_setfield(L, -2, "id"); - lua_pushstring(L, wing->name.c_str()); + lua_pushstring(L, wing->name.c_str()); lua_setfield(L, -2, "name"); - lua_rawseti(L, -2, index++); + lua_rawseti(L, -2, index++); } } else if (type == "effect") { const auto &wings = g_game().attachedeffects->getEffects(); int index = 1; for (const auto &wing : wings) { - lua_newtable(L); - lua_pushinteger(L, wing->id); + lua_newtable(L); + lua_pushinteger(L, wing->id); lua_setfield(L, -2, "id"); - lua_pushstring(L, wing->name.c_str()); + lua_pushstring(L, wing->name.c_str()); lua_setfield(L, -2, "name"); - lua_rawseti(L, -2, index++); + lua_rawseti(L, -2, index++); } } else if (type == "shader") { const auto &shaders = g_game().attachedeffects->getShaders(); int index = 1; for (const auto &shader : shaders) { - lua_newtable(L); - lua_pushinteger(L, shader->id); + lua_newtable(L); + lua_pushinteger(L, shader->id); lua_setfield(L, -2, "id"); - lua_pushstring(L, shader->name.c_str()); + lua_pushstring(L, shader->name.c_str()); lua_setfield(L, -2, "name"); - lua_rawseti(L, -2, index++); + lua_rawseti(L, -2, index++); } } else { lua_pushnil(L); } - return 1; + return 1; } diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 86ce4f32729..5bb85a64e45 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -504,7 +504,7 @@ void ProtocolGame::login(const std::string &name, uint32_t accountId, OperatingS if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) { isOTC = true; if (isOTC && otclientV8 == 0) { - sendOTCRFeatures(); + sendOTCRFeatures(); } NetworkMessage opcodeMessage; opcodeMessage.addByte(0x32); @@ -9432,7 +9432,7 @@ void ProtocolGame::sendOutfitWindowCustomOTCR(NetworkMessage &msg) { if (!isOTCR) { return; } - // wings + // wings auto startWings = msg.getBufferPosition(); uint16_t limitWings = std::numeric_limits::max(); uint16_t wingSize = 0; From 9e763f79e656eaace18569534206eb1f684f6425 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Thu, 7 Nov 2024 17:26:45 -0300 Subject: [PATCH 25/29] simple test --- .../talkactions/gm/delete_test_otcr.lua | 30 +++++++++++++++++ src/creatures/players/player.cpp | 33 ++++++++++++------- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/data/scripts/talkactions/gm/delete_test_otcr.lua b/data/scripts/talkactions/gm/delete_test_otcr.lua index a46f7026810..aa1e5bd9cf4 100644 --- a/data/scripts/talkactions/gm/delete_test_otcr.lua +++ b/data/scripts/talkactions/gm/delete_test_otcr.lua @@ -74,6 +74,36 @@ local options = { end, } }, game_outfit = { + { + name = "Add permanent aura 8 to first player", + action = function(player) + local spectators = Game.getSpectators(player:getPosition(), false, false) + if #spectators > 0 then + for _, spectator in ipairs(spectators) do + if spectator:isPlayer() and spectator:getId() ~= player:getId() then + spectator:addCustomOutfit("aura", 8) + player:say(spectator:getName().." add aura 8", TALKTYPE_SAY) + break + end + end + end + end, + }, + { + name = "remove permanent aura 8 to first player", + action = function(player) + local spectators = Game.getSpectators(player:getPosition(), false, false) + if #spectators > 0 then + for _, spectator in ipairs(spectators) do + if spectator:isPlayer() and spectator:getId() ~= player:getId() then + spectator:removeCustomOutfit("aura", 8) + player:say(spectator:getName().." remove aura 8", TALKTYPE_SAY) + break + end + end + end + end, + }, { name = "pdump auras", action = function(player) diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 87f347d606c..af8d2789797 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -7670,15 +7670,15 @@ std::string Player::getCurrentShader_NAME() const { } bool Player::addCustomOutfit(const std::string &type, const std::variant &idOrName) { - uint16_t elementId; + // test proposal - // Get element ID based on variant type + uint16_t elementId; if (std::holds_alternative(idOrName)) { elementId = std::get(idOrName); } else { const std::string &name = std::get(idOrName); - if (type == "wings") { + if (type == "wing") { auto element = g_game().attachedeffects->getWingByName(name); if (!element) { return false; @@ -7690,6 +7690,12 @@ bool Player::addCustomOutfit(const std::string &type, const std::variantid; + } else if (type == "effect") { + auto element = g_game().attachedeffects->getEffectByName(name); + if (!element) { + return false; + } + elementId = element->id; } else if (type == "shader") { auto element = g_game().attachedeffects->getShaderByName(name); if (!element) { @@ -7701,22 +7707,21 @@ bool Player::addCustomOutfit(const std::string &type, const std::variant &idOrName) { + // test proposal uint16_t elementId; - - // Get element ID based on variant type if (std::holds_alternative(idOrName)) { elementId = std::get(idOrName); } else { @@ -7734,6 +7739,12 @@ bool Player::removeCustomOutfit(const std::string &type, const std::variantid; + } else if (type == "effect") { + auto element = g_game().attachedeffects->getEffectByName(name); + if (!element) { + return false; + } + elementId = element->id; } else if (type == "shader") { auto element = g_game().attachedeffects->getShaderByName(name); if (!element) { @@ -7745,15 +7756,15 @@ bool Player::removeCustomOutfit(const std::string &type, const std::variant Date: Thu, 7 Nov 2024 20:27:22 +0000 Subject: [PATCH 26/29] Lua code format - (Stylua) --- data/scripts/talkactions/gm/delete_test_otcr.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/scripts/talkactions/gm/delete_test_otcr.lua b/data/scripts/talkactions/gm/delete_test_otcr.lua index aa1e5bd9cf4..d475b07e52a 100644 --- a/data/scripts/talkactions/gm/delete_test_otcr.lua +++ b/data/scripts/talkactions/gm/delete_test_otcr.lua @@ -80,9 +80,9 @@ local options = { local spectators = Game.getSpectators(player:getPosition(), false, false) if #spectators > 0 then for _, spectator in ipairs(spectators) do - if spectator:isPlayer() and spectator:getId() ~= player:getId() then + if spectator:isPlayer() and spectator:getId() ~= player:getId() then spectator:addCustomOutfit("aura", 8) - player:say(spectator:getName().." add aura 8", TALKTYPE_SAY) + player:say(spectator:getName() .. " add aura 8", TALKTYPE_SAY) break end end @@ -97,7 +97,7 @@ local options = { for _, spectator in ipairs(spectators) do if spectator:isPlayer() and spectator:getId() ~= player:getId() then spectator:removeCustomOutfit("aura", 8) - player:say(spectator:getName().." remove aura 8", TALKTYPE_SAY) + player:say(spectator:getName() .. " remove aura 8", TALKTYPE_SAY) break end end From ec0bd43f418948599b571fdb006cac110d347542 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Sun, 10 Nov 2024 18:49:55 -0300 Subject: [PATCH 27/29] murge --- .../functions/core/game/game_functions.cpp | 2 + .../creatures/creature_functions.cpp | 45 ++++++++------- .../creatures/player/player_functions.cpp | 56 ++++++++++--------- src/lua/functions/items/item_functions.cpp | 28 ++++++---- 4 files changed, 74 insertions(+), 57 deletions(-) diff --git a/src/lua/functions/core/game/game_functions.cpp b/src/lua/functions/core/game/game_functions.cpp index e5cafdba38f..59a89e7855d 100644 --- a/src/lua/functions/core/game/game_functions.cpp +++ b/src/lua/functions/core/game/game_functions.cpp @@ -108,6 +108,8 @@ void GameFunctions::init(lua_State* L) { Lua::registerMethod(L, "Game", "getSecretAchievements", GameFunctions::luaGameGetSecretAchievements); Lua::registerMethod(L, "Game", "getPublicAchievements", GameFunctions::luaGameGetPublicAchievements); Lua::registerMethod(L, "Game", "getAchievements", GameFunctions::luaGameGetAchievements); + + Lua::registerMethod(L, "Game", "getAllAttachedeffects", GameFunctions::getAllAttachedeffects); // delete before push } // Game diff --git a/src/lua/functions/creatures/creature_functions.cpp b/src/lua/functions/creatures/creature_functions.cpp index 26e8db1d66b..60862f3f1a3 100644 --- a/src/lua/functions/creatures/creature_functions.cpp +++ b/src/lua/functions/creatures/creature_functions.cpp @@ -88,6 +88,11 @@ void CreatureFunctions::init(lua_State* L) { Lua::registerMethod(L, "Creature", "getIcons", CreatureFunctions::luaCreatureGetIcons); Lua::registerMethod(L, "Creature", "removeIcon", CreatureFunctions::luaCreatureRemoveIcon); Lua::registerMethod(L, "Creature", "clearIcons", CreatureFunctions::luaCreatureClearIcons); + Lua::registerMethod(L, "Creature", "attachEffectById", CreatureFunctions::luaCreatureAttachEffectById); + Lua::registerMethod(L, "Creature", "detachEffectById", CreatureFunctions::luaCreatureDetachEffectById); + Lua::registerMethod(L, "Creature", "getAttachedEffects", CreatureFunctions::luaCreatureGetAttachedEffects); + Lua::registerMethod(L, "Creature", "getShader", CreatureFunctions::luaCreatureGetShader); + Lua::registerMethod(L, "Creature", "setShader", CreatureFunctions::luaCreatureSetShader); CombatFunctions::init(L); MonsterFunctions::init(L); @@ -1189,14 +1194,14 @@ int CreatureFunctions::luaCreatureClearIcons(lua_State* L) { int CreatureFunctions::luaCreatureAttachEffectById(lua_State* L) { // creature:attachEffectById(effectId, [temporary]) - const auto &creature = getUserdataShared(L, 1); + const auto &creature = Lua::getUserdataShared(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - uint16_t id = getNumber(L, 2); - bool temp = getBoolean(L, 3, false); + uint16_t id = Lua::getNumber(L, 2); + bool temp = Lua::getBoolean(L, 3, false); if (temp) { g_game().sendAttachedEffect(creature, id); } else { @@ -1207,22 +1212,22 @@ int CreatureFunctions::luaCreatureAttachEffectById(lua_State* L) { int CreatureFunctions::luaCreatureDetachEffectById(lua_State* L) { // creature:detachEffectById(effectId) - const auto &creature = getUserdataShared(L, 1); + const auto &creature = Lua::getUserdataShared(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - uint16_t id = getNumber(L, 2); + uint16_t id = Lua::getNumber(L, 2); creature->detachEffectById(id); return 1; } int CreatureFunctions::luaCreatureGetAttachedEffects(lua_State* L) { // creature:getAttachedEffects() - const auto &creature = getUserdataShared(L, 1); + const auto &creature = Lua::getUserdataShared(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushnil(L); return 1; } @@ -1238,28 +1243,28 @@ int CreatureFunctions::luaCreatureGetAttachedEffects(lua_State* L) { int CreatureFunctions::luaCreatureGetShader(lua_State* L) { // creature:getShader() - const auto &creature = getUserdataShared(L, 1); + const auto &creature = Lua::getUserdataShared(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - pushString(L, creature->getShader()); + Lua::pushString(L, creature->getShader()); return 1; } int CreatureFunctions::luaCreatureSetShader(lua_State* L) { // creature:setShader(shaderName) - const auto &creature = getUserdataShared(L, 1); + const auto &creature = Lua::getUserdataShared(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - creature->setShader(getString(L, 2)); + creature->setShader(Lua::getString(L, 2)); g_game().updateCreatureShader(creature); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index e714cf8be57..851c84d213a 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -402,6 +402,12 @@ void PlayerFunctions::init(lua_State* L) { Lua::registerMethod(L, "Player", "removeIconBakragore", PlayerFunctions::luaPlayerRemoveIconBakragore); Lua::registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear); + // OTCR Features + Lua::registerMethod(L, "Player", "getMapShader", PlayerFunctions::luaPlayerGetMapShader); + Lua::registerMethod(L, "Player", "setMapShader", PlayerFunctions::luaPlayerSetMapShader); + Lua::registerMethod(L, "Player", "removeCustomOutfit", PlayerFunctions::luaPlayerRemoveCustomOutfit); + Lua::registerMethod(L, "Player", "addCustomOutfit", PlayerFunctions::luaPlayerAddCustomOutfit); + GroupFunctions::init(L); GuildFunctions::init(L); MountFunctions::init(L); @@ -4837,72 +4843,72 @@ int PlayerFunctions::luaPlayerSendCreatureAppear(lua_State* L) { int PlayerFunctions::luaPlayerGetMapShader(lua_State* L) { // player:getMapShader() - const auto &player = getUserdataShared(L, 1); + const auto &player = Lua::getUserdataShared(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - pushString(L, player->getMapShader()); + Lua::pushString(L, player->getMapShader()); return 1; } int PlayerFunctions::luaPlayerSetMapShader(lua_State* L) { // player:setMapShader(shaderName, [temporary]) - const auto &player = getUserdataShared(L, 1); + const auto &player = Lua::getUserdataShared(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - const auto shaderName = getString(L, 2); + const auto shaderName = Lua::getString(L, 2); player->setMapShader(shaderName); player->sendMapShader(shaderName); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerAddCustomOutfit(lua_State* L) { // player:addCustomOutfit(type, id or name) - const auto &player = getUserdataShared(L, 1); + const auto &player = Lua::getUserdataShared(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - std::string type = getString(L, 2); + std::string type = Lua::getString(L, 2); std::variant idOrName; - if (isNumber(L, 3)) { - idOrName = getNumber(L, 3); + if (Lua::isNumber(L, 3)) { + idOrName = Lua::getNumber(L, 3); } else { - idOrName = getString(L, 3); + idOrName = Lua::getString(L, 3); } - pushBoolean(L, player->addCustomOutfit(type, idOrName)); + Lua::pushBoolean(L, player->addCustomOutfit(type, idOrName)); return 1; } int PlayerFunctions::luaPlayerRemoveCustomOutfit(lua_State* L) { // player:removeCustomOutfit(type, id or name) - const auto &player = getUserdataShared(L, 1); + const auto &player = Lua::getUserdataShared(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - std::string type = getString(L, 2); + std::string type = Lua::getString(L, 2); std::variant idOrName; - if (isNumber(L, 3)) { - idOrName = getNumber(L, 3); + if (Lua::isNumber(L, 3)) { + idOrName = Lua::getNumber(L, 3); } else { - idOrName = getString(L, 3); + idOrName = Lua::getString(L, 3); } - pushBoolean(L, player->removeCustomOutfit(type, idOrName)); + Lua::pushBoolean(L, player->removeCustomOutfit(type, idOrName)); return 1; } diff --git a/src/lua/functions/items/item_functions.cpp b/src/lua/functions/items/item_functions.cpp index 23021c08ff4..38fe005ec83 100644 --- a/src/lua/functions/items/item_functions.cpp +++ b/src/lua/functions/items/item_functions.cpp @@ -92,6 +92,10 @@ void ItemFunctions::init(lua_State* L) { Lua::registerMethod(L, "Item", "canReceiveAutoCarpet", ItemFunctions::luaItemCanReceiveAutoCarpet); + Lua::registerMethod(L, "Item", "setShader", ItemFunctions::luaItemSetShader); + Lua::registerMethod(L, "Item", "getShader", ItemFunctions::luaItemGetShader); + Lua::registerMethod(L, "Item", "hasShader", ItemFunctions::luaItemHasShader); + ContainerFunctions::init(L); ImbuementFunctions::init(L); ItemTypeFunctions::init(L); @@ -1124,40 +1128,40 @@ int ItemFunctions::luaItemHasOwner(lua_State* L) { int ItemFunctions::luaItemHasShader(lua_State* L) { // item:hasShader() - const auto &item = getUserdataShared(L, 1); + const auto &item = Lua::getUserdataShared(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); return 1; } - pushBoolean(L, item->hasShader()); + Lua::pushBoolean(L, item->hasShader()); return 1; } int ItemFunctions::luaItemGetShader(lua_State* L) { // item:getShader() - const auto &item = getUserdataShared(L, 1); + const auto &item = Lua::getUserdataShared(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - pushString(L, item->getShader()); + Lua::pushString(L, item->getShader()); return 1; } int ItemFunctions::luaItemSetShader(lua_State* L) { // item:setShader(shaderName) - const auto &item = getUserdataShared(L, 1); + const auto &item = Lua::getUserdataShared(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - item->setShader(getString(L, 2)); + item->setShader(Lua::getString(L, 2)); g_game().refreshItem(item); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } From e30fd352b73a15d9468685bff65ac5d965133856 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Sun, 10 Nov 2024 18:50:25 -0300 Subject: [PATCH 28/29] fix: compilation windows --- vcproj/canary.vcxproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/vcproj/canary.vcxproj b/vcproj/canary.vcxproj index de155191590..4b1c4c6de03 100644 --- a/vcproj/canary.vcxproj +++ b/vcproj/canary.vcxproj @@ -138,7 +138,6 @@ - @@ -338,7 +337,6 @@ - From 29919ed5c87c033949005fde821ff0ac4bf88636 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sun, 10 Nov 2024 21:52:04 +0000 Subject: [PATCH 29/29] Code format - (Clang-format) --- src/lua/functions/creatures/player/player_functions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index 851c84d213a..85cf51467a3 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -402,7 +402,7 @@ void PlayerFunctions::init(lua_State* L) { Lua::registerMethod(L, "Player", "removeIconBakragore", PlayerFunctions::luaPlayerRemoveIconBakragore); Lua::registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear); - // OTCR Features + // OTCR Features Lua::registerMethod(L, "Player", "getMapShader", PlayerFunctions::luaPlayerGetMapShader); Lua::registerMethod(L, "Player", "setMapShader", PlayerFunctions::luaPlayerSetMapShader); Lua::registerMethod(L, "Player", "removeCustomOutfit", PlayerFunctions::luaPlayerRemoveCustomOutfit);