From ad86d1e344a815288dbebe7ab379b54d18c9d446 Mon Sep 17 00:00:00 2001 From: Renato Date: Wed, 29 Mar 2023 23:02:53 -0300 Subject: [PATCH 1/8] first commit --- src/game.cpp | 100 +++++++++++++++++++++++++------------------ src/game.h | 3 ++ src/luascript.cpp | 31 ++++++++++++++ src/luascript.h | 3 ++ src/player.h | 14 +++++- src/protocolgame.cpp | 22 ++++++++-- src/protocolgame.h | 3 ++ 7 files changed, 131 insertions(+), 45 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 424e8a8..d8cedce 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -6045,7 +6045,7 @@ void Game::playerBrowseMarket(Player* player, uint16_t spriteId) const MarketOfferList& sellOffers = IOMarket::getActiveOffers(MARKETACTION_SELL, it.id); player->sendMarketBrowseItem(it.id, buyOffers, sellOffers); player->sendMarketDetail(it.id); - } +} void Game::playerBrowseMarketOwnOffers(Player * player) { @@ -6107,59 +6107,59 @@ void Game::playerCreateMarketOffer(Player * player, uint8_t type, uint16_t sprit fee = 100000; } #else -} else if (fee > 1000) { - fee = 1000; -} + } else if (fee > 1000) { + fee = 1000; + } #endif -if (type == MARKETACTION_SELL) { - if (fee > player->bankBalance) { - return; - } + if (type == MARKETACTION_SELL) { + if (fee > player->bankBalance) { + return; + } - DepotChest* depotChest = player->getDepotChest(player->getLastDepotId(), false); - if (!depotChest) { - return; - } + DepotChest* depotChest = player->getDepotChest(player->getLastDepotId(), false); + if (!depotChest) { + return; + } - std::vector itemList = getMarketItemList(it.wareId, amount, depotChest, player->getInbox()); - if (itemList.empty()) { - return; - } + std::vector itemList = getMarketItemList(it.wareId, amount, depotChest, player->getInbox()); + if (itemList.empty()) { + return; + } - if (it.stackable) { - uint16_t tmpAmount = amount; - for (Item* item : itemList) { - uint16_t removeCount = std::min(tmpAmount, item->getItemCount()); - tmpAmount -= removeCount; - internalRemoveItem(item, removeCount); - if (tmpAmount == 0) { - break; + if (it.stackable) { + uint16_t tmpAmount = amount; + for (Item* item : itemList) { + uint16_t removeCount = std::min(tmpAmount, item->getItemCount()); + tmpAmount -= removeCount; + internalRemoveItem(item, removeCount); + if (tmpAmount == 0) { + break; + } + } + } else { + for (Item* item : itemList) { + internalRemoveItem(item); } } + + player->bankBalance -= fee; } else { - for (Item* item : itemList) { - internalRemoveItem(item); + uint64_t totalPrice = static_cast(price) * amount; + totalPrice += fee; + if (totalPrice > player->bankBalance) { + return; } - } - player->bankBalance -= fee; -} else { - uint64_t totalPrice = static_cast(price) * amount; - totalPrice += fee; - if (totalPrice > player->bankBalance) { - return; + player->bankBalance -= totalPrice; } - player->bankBalance -= totalPrice; -} - -IOMarket::createOffer(player->getGUID(), static_cast(type), it.id, amount, price, anonymous); + IOMarket::createOffer(player->getGUID(), static_cast(type), it.id, amount, price, anonymous); -player->sendMarketEnter(player->getLastDepotId()); -const MarketOfferList& buyOffers = IOMarket::getActiveOffers(MARKETACTION_BUY, it.id); -const MarketOfferList& sellOffers = IOMarket::getActiveOffers(MARKETACTION_SELL, it.id); -player->sendMarketBrowseItem(it.id, buyOffers, sellOffers); + player->sendMarketEnter(player->getLastDepotId()); + const MarketOfferList& buyOffers = IOMarket::getActiveOffers(MARKETACTION_BUY, it.id); + const MarketOfferList& sellOffers = IOMarket::getActiveOffers(MARKETACTION_SELL, it.id); + player->sendMarketBrowseItem(it.id, buyOffers, sellOffers); } void Game::playerCancelMarketOffer(Player* player, uint32_t timestamp, uint16_t counter) @@ -6826,3 +6826,21 @@ bool Game::reload(ReloadTypes_t reloadType) } return true; } + +void Game::addAttchedEffect(const Creature* creature, uint16_t effectId) +{ + SpectatorVector spectators; + map.getSpectators(spectators, creature->getPosition(), false, true); + for (Creature* spectator : spectators) { + spectator->getPlayer()->sendAddAttchedEffect(creature, effectId); + } +} + +void Game::removeAttchedEffect(const Creature* creature, uint16_t effectId) +{ + SpectatorVector spectators; + map.getSpectators(spectators, creature->getPosition(), false, true); + for (Creature* spectator : spectators) { + spectator->getPlayer()->sendRemoveAttchedEffect(creature, effectId); + } +} diff --git a/src/game.h b/src/game.h index 8a1a083..94aa22b 100644 --- a/src/game.h +++ b/src/game.h @@ -546,6 +546,9 @@ class Game void addDistanceEffect(const Position& fromPos, const Position& toPos, uint8_t effect); static void addDistanceEffect(const SpectatorVector& spectators, const Position& fromPos, const Position& toPos, uint8_t effect); + void addAttchedEffect(const Creature* creature, uint16_t effectId); + void removeAttchedEffect(const Creature* creature, uint16_t effectId); + void updateCreatureData(const Creature* creature); void startDecay(Item* item); diff --git a/src/luascript.cpp b/src/luascript.cpp index 9b52b45..242d877 100644 --- a/src/luascript.cpp +++ b/src/luascript.cpp @@ -2659,6 +2659,9 @@ void LuaScriptInterface::registerFunctions() registerMethod("Creature", "getZone", LuaScriptInterface::luaCreatureGetZone); + registerMethod("Creature", "addAttchedEffect", LuaScriptInterface::luaCreatureAddAttchedEffect); + registerMethod("Creature", "removeAttchedEffect", LuaScriptInterface::luaCreatureRemoveAttchedEffect); + // Player registerClass("Player", "Creature", LuaScriptInterface::luaPlayerCreate); registerMetaMethod("Player", "__eq", LuaScriptInterface::luaUserdataCompare); @@ -16948,3 +16951,31 @@ void LuaEnvironment::executeTimerEvent(uint32_t eventIndex) luaL_unref(luaState, LUA_REGISTRYINDEX, parameter); } } + +int LuaScriptInterface::luaCreatureAddAttchedEffect(lua_State* L) +{ + // creature:addAttchedEffect(effectId) + Creature* creature = getUserdata(L, 1); + if (!creature) { + lua_pushnil(L); + return 1; + } + + uint16_t effectId = getNumber(L, 2); + g_game.addAttchedEffect(creature, effectId); + return 1; +} + +int LuaScriptInterface::luaCreatureRemoveAttchedEffect(lua_State* L) +{ + // creature:addAttchedEffect(effectId) + Creature* creature = getUserdata(L, 1); + if (!creature) { + lua_pushnil(L); + return 1; + } + + uint16_t effectId = getNumber(L, 2); + g_game.addAttchedEffect(creature, effectId); + return 1; +} diff --git a/src/luascript.h b/src/luascript.h index 35d69f6..84e67a9 100644 --- a/src/luascript.h +++ b/src/luascript.h @@ -846,6 +846,9 @@ class LuaScriptInterface static int luaCreatureGetZone(lua_State* L); + static int luaCreatureAddAttchedEffect(lua_State* L); + static int luaCreatureRemoveAttchedEffect(lua_State* L); + // Player static int luaPlayerCreate(lua_State* L); diff --git a/src/player.h b/src/player.h index 33d11d1..45ead6c 100644 --- a/src/player.h +++ b/src/player.h @@ -985,6 +985,18 @@ class Player final : public Creature, public Cylinder } #endif + void sendAddAttchedEffect(const Creature * creature, uint16_t effectId) { + if (client) { + client->sendAddAttchedEffect(creature, effectId); + } + } + + void sendRemoveAttchedEffect(const Creature * creature, uint16_t effectId) { + if (client) { + client->sendRemoveAttchedEffect(creature, effectId); + } + } + //event methods void onUpdateTileItem(const Tile * tile, const Position & pos, const Item * oldItem, const ItemType & oldType, const Item * newItem, const ItemType & newType) override; @@ -1779,6 +1791,6 @@ class Player final : public Creature, public Cylinder friend class Actions; friend class IOLoginData; friend class ProtocolGame; - }; +}; #endif diff --git a/src/protocolgame.cpp b/src/protocolgame.cpp index c2120f4..93577cc 100644 --- a/src/protocolgame.cpp +++ b/src/protocolgame.cpp @@ -449,7 +449,7 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg) #else g_dispatcher.addTask(std::bind(&ProtocolGame::login, getThis(), std::move(accountName), std::move(password), std::move(characterName), operatingSystem, TFCoperatingSystem)); #endif - } +} void ProtocolGame::onConnect() { @@ -843,7 +843,7 @@ void ProtocolGame::checkCreatureAsKnown(uint32_t id, bool& known, uint32_t & rem } else { removedKnown = 0; } - } +} bool ProtocolGame::canSee(const Creature * c) const { @@ -4669,7 +4669,7 @@ void ProtocolGame::sendAddCreature(const Creature * creature, const Position & p sendMarketStatistics(); #endif player->sendIcons(); - } +} void ProtocolGame::sendMoveCreature(const Creature * creature, const Position & newPos, int32_t newStackPos, const Position & oldPos, int32_t oldStackPos, bool teleport) { @@ -6603,3 +6603,19 @@ uint8_t ProtocolGame::translateMessageClassToClient(MessageClasses messageType) } #endif } + +void ProtocolGame::sendAddAttchedEffect(const Creature * creature, uint16_t effectId) { + playermsg.reset(); + playermsg.addByte(0x34); + playermsg.add(creature->getID()); + playermsg.add(effectId); + writeToOutputBuffer(playermsg); +} + +void ProtocolGame::sendRemoveAttchedEffect(const Creature * creature, uint16_t effectId) { + playermsg.reset(); + playermsg.addByte(0x35); + playermsg.add(creature->getID()); + playermsg.add(effectId); + writeToOutputBuffer(playermsg); +} diff --git a/src/protocolgame.h b/src/protocolgame.h index 4b93a69..d11cf13 100644 --- a/src/protocolgame.h +++ b/src/protocolgame.h @@ -445,6 +445,9 @@ class ProtocolGame final : public Protocol void sendModalWindow(const ModalWindow& modalWindow); #endif + void sendAddAttchedEffect(const Creature* creature, uint16_t effectId); + void sendRemoveAttchedEffect(const Creature* creature, uint16_t effectId); + //Help functions // translate a tile to clientreadable format From 0f3a7a5158dffd8b249ac59b25e7a0cc49c052a1 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Mon, 3 Apr 2023 20:25:24 -0300 Subject: [PATCH 2/8] item shader support --- src/protocolgame.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/protocolgame.cpp b/src/protocolgame.cpp index 77c9b7c..4b1fda1 100644 --- a/src/protocolgame.cpp +++ b/src/protocolgame.cpp @@ -5981,6 +5981,9 @@ void ProtocolGame::AddItem(const Item * item) playermsg.addByte(podiumVisible ? static_cast(podiumVisible->getInt()) : 0x01); } #endif + + auto shader = item->getCustomAttribute("shader"); + playermsg.addString(shader ? shader->getString() : ""); } void ProtocolGame::parseExtendedOpcode(NetworkMessage & msg) const From a2b8b0dc1deb30f4f84794b931172d57e33c3150 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Mon, 3 Apr 2023 20:58:41 -0300 Subject: [PATCH 3/8] creature shader support --- data/creaturescripts/scripts/login.lua | 4 ++++ src/creature.h | 5 ++++ src/game.cpp | 8 +++++++ src/game.h | 1 + src/luascript.cpp | 32 ++++++++++++++++++++++++++ src/luascript.h | 3 +++ src/player.h | 8 ++++++- src/protocolgame.cpp | 10 ++++++++ src/protocolgame.h | 1 + 9 files changed, 71 insertions(+), 1 deletion(-) diff --git a/data/creaturescripts/scripts/login.lua b/data/creaturescripts/scripts/login.lua index 51593ba..67b3cb3 100644 --- a/data/creaturescripts/scripts/login.lua +++ b/data/creaturescripts/scripts/login.lua @@ -29,6 +29,10 @@ function onLogin(player) player:setVocation(vocation:getDemotion()) end + if player:getGroup():getAccess() then + player:setShader("Outfit - Rainbow") + end + -- Events player:registerEvent('PlayerDeath') player:registerEvent('DropLoot') diff --git a/src/creature.h b/src/creature.h index 0bdac94..4d6a741 100644 --- a/src/creature.h +++ b/src/creature.h @@ -481,6 +481,9 @@ class Creature : virtual public Thing bool getPathTo(const Position& targetPos, std::vector& dirList, const FindPathParams& fpp) const; bool getPathTo(const Position& targetPos, std::vector& dirList, int32_t minTargetDist, int32_t maxTargetDist, bool fullPathSearch = true, bool clearSight = true, int32_t maxSearchDist = 0) const; + std::string getShader() const { return shader; } + void setShader(const std::string& shaderName) { shader = shaderName; } + void incrementReferenceCounter() { ++referenceCounter; } @@ -511,6 +514,8 @@ class Creature : virtual public Thing using CountMap = std::map; CountMap damageMap; + std::string shader; + std::vector summons; CreatureEventList eventsList; ConditionList conditions; diff --git a/src/game.cpp b/src/game.cpp index 38ea861..9b3cc33 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -6923,4 +6923,12 @@ void Game::removeAttchedEffect(const Creature* creature, uint16_t effectId) for (Creature* spectator : spectators) { spectator->getPlayer()->sendRemoveAttchedEffect(creature, effectId); } +} + +void Game::sendCreatureShader(const Creature* creature, const std::string& shaderName) { + SpectatorVector spectators; + map.getSpectators(spectators, creature->getPosition(), false, true); + for (Creature* spectator : spectators) { + spectator->getPlayer()->sendShader(creature, shaderName); + } } \ No newline at end of file diff --git a/src/game.h b/src/game.h index 147136a..1755bed 100644 --- a/src/game.h +++ b/src/game.h @@ -548,6 +548,7 @@ class Game void addAttchedEffect(const Creature* creature, uint16_t effectId); void removeAttchedEffect(const Creature* creature, uint16_t effectId); + void sendCreatureShader(const Creature* creature, const std::string& shaderName); void updateCreatureData(const Creature* creature) const; diff --git a/src/luascript.cpp b/src/luascript.cpp index 20d852c..38e17fb 100644 --- a/src/luascript.cpp +++ b/src/luascript.cpp @@ -2616,6 +2616,9 @@ void LuaScriptInterface::registerFunctions() registerMethod("Creature", "getLight", luaCreatureGetLight); registerMethod("Creature", "setLight", luaCreatureSetLight); + registerMethod("Creature", "getShader", luaCreatureGetShader); + registerMethod("Creature", "setShader", luaCreatureSetShader); + registerMethod("Creature", "getSpeed", luaCreatureGetSpeed); registerMethod("Creature", "getBaseSpeed", luaCreatureGetBaseSpeed); registerMethod("Creature", "changeSpeed", luaCreatureChangeSpeed); @@ -16981,3 +16984,32 @@ int LuaScriptInterface::luaCreatureRemoveAttchedEffect(lua_State* L) g_game.addAttchedEffect(creature, effectId); return 1; } + +int LuaScriptInterface::luaCreatureGetShader(lua_State* L) +{ + // creature:getShader() + const auto* creature = getUserdata(L, 1); + if (creature) { + pushString(L, creature->getShader()); + } else { + lua_pushnil(L); + } + + return 1; +} + +int LuaScriptInterface::luaCreatureSetShader(lua_State* L) +{ + // creature:setShader(shaderName) + auto* creature = getUserdata(L, 1); + if (!creature) { + lua_pushnil(L); + return 1; + } + + creature->setShader(getString(L, 2)); + g_game.sendCreatureShader(creature, creature->getShader()); + + pushBoolean(L, true); + return 1; +} diff --git a/src/luascript.h b/src/luascript.h index eb8e459..ac7cd9b 100644 --- a/src/luascript.h +++ b/src/luascript.h @@ -802,6 +802,9 @@ class LuaScriptInterface static int luaCreatureGetLight(lua_State* L); static int luaCreatureSetLight(lua_State* L); + static int luaCreatureGetShader(lua_State* L); + static int luaCreatureSetShader(lua_State* L); + static int luaCreatureGetSpeed(lua_State* L); static int luaCreatureGetBaseSpeed(lua_State* L); static int luaCreatureChangeSpeed(lua_State* L); diff --git a/src/player.h b/src/player.h index 61a4eeb..85c9084 100644 --- a/src/player.h +++ b/src/player.h @@ -1027,6 +1027,12 @@ class Player final : public Creature, public Cylinder } } + void sendShader(const Creature * creature, const std::string & shaderName) { + if (client) { + client->sendShader(creature, shaderName); + } + } + //event methods void onUpdateTileItem(const Tile * tile, const Position & pos, const Item * oldItem, const ItemType & oldType, const Item * newItem, const ItemType & newType) override; @@ -1839,6 +1845,6 @@ class Player final : public Creature, public Cylinder friend class Actions; friend class IOLoginData; friend class ProtocolGame; -}; + }; #endif diff --git a/src/protocolgame.cpp b/src/protocolgame.cpp index 4b1fda1..1de942e 100644 --- a/src/protocolgame.cpp +++ b/src/protocolgame.cpp @@ -5547,6 +5547,8 @@ void ProtocolGame::AddCreature(const Creature * creature, const bool known, cons #if CLIENT_VERSION >= 854 playermsg.addByte(player->canWalkthroughEx(creature) ? 0x00 : 0x01); #endif + + playermsg.addString(player->getShader()); } void ProtocolGame::AddPlayerStats() const @@ -6624,4 +6626,12 @@ void ProtocolGame::sendRemoveAttchedEffect(const Creature * creature, uint16_t e playermsg.add(creature->getID()); playermsg.add(effectId); writeToOutputBuffer(playermsg); +} + +void ProtocolGame::sendShader(const Creature * creature, const std::string & shaderName) { + playermsg.reset(); + playermsg.addByte(0x36); + playermsg.add(creature->getID()); + playermsg.addString(shaderName); + writeToOutputBuffer(playermsg); } \ No newline at end of file diff --git a/src/protocolgame.h b/src/protocolgame.h index f51650f..73fe2d0 100644 --- a/src/protocolgame.h +++ b/src/protocolgame.h @@ -446,6 +446,7 @@ class ProtocolGame final : public Protocol void sendAddAttchedEffect(const Creature* creature, uint16_t effectId); void sendRemoveAttchedEffect(const Creature* creature, uint16_t effectId); + void sendShader(const Creature* creature, const std::string& shaderName); //Help functions From 9e7094fa2a7ea0a5a97d94e8940c528b4835f63b Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Mon, 3 Apr 2023 22:02:24 -0300 Subject: [PATCH 4/8] update --- data/creaturescripts/scripts/login.lua | 2 +- src/game.cpp | 4 ++-- src/game.h | 2 +- src/luascript.cpp | 2 +- src/protocolgame.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data/creaturescripts/scripts/login.lua b/data/creaturescripts/scripts/login.lua index 67b3cb3..55f9ab3 100644 --- a/data/creaturescripts/scripts/login.lua +++ b/data/creaturescripts/scripts/login.lua @@ -29,7 +29,7 @@ function onLogin(player) player:setVocation(vocation:getDemotion()) end - if player:getGroup():getAccess() then + if player:getGroup():getAccess() and player:getAccountType() >= ACCOUNT_TYPE_GAMEMASTER then player:setShader("Outfit - Rainbow") end diff --git a/src/game.cpp b/src/game.cpp index 9b3cc33..0040e9a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -6925,10 +6925,10 @@ void Game::removeAttchedEffect(const Creature* creature, uint16_t effectId) } } -void Game::sendCreatureShader(const Creature* creature, const std::string& shaderName) { +void Game::updateCreatureShader(const Creature* creature) { SpectatorVector spectators; map.getSpectators(spectators, creature->getPosition(), false, true); for (Creature* spectator : spectators) { - spectator->getPlayer()->sendShader(creature, shaderName); + spectator->getPlayer()->sendShader(creature, creature->getShader()); } } \ No newline at end of file diff --git a/src/game.h b/src/game.h index 1755bed..3364643 100644 --- a/src/game.h +++ b/src/game.h @@ -548,7 +548,7 @@ class Game void addAttchedEffect(const Creature* creature, uint16_t effectId); void removeAttchedEffect(const Creature* creature, uint16_t effectId); - void sendCreatureShader(const Creature* creature, const std::string& shaderName); + void updateCreatureShader(const Creature* creature); void updateCreatureData(const Creature* creature) const; diff --git a/src/luascript.cpp b/src/luascript.cpp index 38e17fb..0af5e1b 100644 --- a/src/luascript.cpp +++ b/src/luascript.cpp @@ -17008,7 +17008,7 @@ int LuaScriptInterface::luaCreatureSetShader(lua_State* L) } creature->setShader(getString(L, 2)); - g_game.sendCreatureShader(creature, creature->getShader()); + g_game.updateCreatureShader(creature); pushBoolean(L, true); return 1; diff --git a/src/protocolgame.cpp b/src/protocolgame.cpp index 1de942e..f4f09ae 100644 --- a/src/protocolgame.cpp +++ b/src/protocolgame.cpp @@ -5548,7 +5548,7 @@ void ProtocolGame::AddCreature(const Creature * creature, const bool known, cons playermsg.addByte(player->canWalkthroughEx(creature) ? 0x00 : 0x01); #endif - playermsg.addString(player->getShader()); + playermsg.addString(creature->getShader()); } void ProtocolGame::AddPlayerStats() const From aed64432fabb24c6ba263a17a6a2f3c4aa667afd Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Wed, 5 Apr 2023 17:52:28 -0300 Subject: [PATCH 5/8] refreshItem --- src/game.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++ src/game.h | 1 + src/item.h | 19 ++++++++++++++++++ src/luascript.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++ src/luascript.h | 4 ++++ src/protocolgame.cpp | 5 ++--- 6 files changed, 118 insertions(+), 3 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 0040e9a..c566284 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -6931,4 +6931,50 @@ void Game::updateCreatureShader(const Creature* creature) { for (Creature* spectator : spectators) { spectator->getPlayer()->sendShader(creature, creature->getShader()); } +} + +void Game::refreshItem(const Item* 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 = creature->getPlayer()->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) { + SpectatorVector spectators; + g_game.map.getSpectators(spectators, container->getPosition(), false, true, 2, 2, 2, 2); + + //send to client + for (auto spectator : spectators) { + spectator->getPlayer()->sendUpdateContainerItem(container, index, item); + } + } + + return; + } + + if (const auto tile = parent->getTile()) { + + SpectatorVector spectators; + g_game.map.getSpectators(spectators, tile->getPosition(), true, true); + + //send to client + for (auto spectator : spectators) { + if (const Player* tmpPlayer = spectator->getPlayer()) { + tmpPlayer->sendUpdateTileItem(tile, tile->getPosition(), item); + } + } + return; + } } \ No newline at end of file diff --git a/src/game.h b/src/game.h index 3364643..c0cf20c 100644 --- a/src/game.h +++ b/src/game.h @@ -549,6 +549,7 @@ class Game void addAttchedEffect(const Creature* creature, uint16_t effectId); void removeAttchedEffect(const Creature* creature, uint16_t effectId); void updateCreatureShader(const Creature* creature); + void refreshItem(const Item* item); void updateCreatureData(const Creature* creature) const; diff --git a/src/item.h b/src/item.h index 0eafbce..8619bdc 100644 --- a/src/item.h +++ b/src/item.h @@ -1097,6 +1097,25 @@ class Item : virtual public Thing return !parent || parent->isRemoved(); } + void setShader(const std::string& shaderName) { + if (shaderName.empty()) { + removeCustomAttribute("shader"); + return; + } + + ItemAttributes::CustomAttribute val; + val.set(shaderName); + + std::string key = "shader"; + setCustomAttribute(key, val); + } + + bool hasShader() const { return getCustomAttribute("shader") != nullptr; } + std::string getShader() const { + auto shader = getCustomAttribute("shader"); + return shader ? shader->getString() : ""; + } + protected: Cylinder* parent = nullptr; diff --git a/src/luascript.cpp b/src/luascript.cpp index 0af5e1b..6176f40 100644 --- a/src/luascript.cpp +++ b/src/luascript.cpp @@ -2558,6 +2558,10 @@ void LuaScriptInterface::registerFunctions() registerMethod("Item", "hasProperty", luaItemHasProperty); registerMethod("Item", "isLoadedFromMap", luaItemIsLoadedFromMap); + registerMethod("Item", "setShader", luaItemSetShader); + registerMethod("Item", "getShader", luaItemGetShader); + registerMethod("Item", "hasShader", luaItemHasShader); + // Container registerClass("Container", "Item", luaContainerCreate); registerMetaMethod("Container", "__eq", luaUserdataCompare); @@ -7173,6 +7177,48 @@ int LuaScriptInterface::luaItemIsLoadedFromMap(lua_State* L) return 1; } +int LuaScriptInterface::luaItemHasShader(lua_State* L) +{ + // item:getShader() + const auto* item = getUserdata(L, 1); + if (item) { + pushBoolean(L, item->hasShader()); + } else { + lua_pushnil(L); + } + + return 1; +} + +int LuaScriptInterface::luaItemGetShader(lua_State* L) +{ + // item:getShader() + const auto* item = getUserdata(L, 1); + if (item) { + pushString(L, item->getShader()); + } else { + lua_pushnil(L); + } + + return 1; +} + +int LuaScriptInterface::luaItemSetShader(lua_State* L) +{ + // item:setShader(shaderName) + auto* item = getUserdata(L, 1); + if (!item) { + lua_pushnil(L); + return 1; + } + + item->setShader(getString(L, 2)); + g_game.refreshItem(item); + + pushBoolean(L, true); + return 1; +} + // Container int LuaScriptInterface::luaContainerCreate(lua_State* L) { diff --git a/src/luascript.h b/src/luascript.h index ac7cd9b..0cedc55 100644 --- a/src/luascript.h +++ b/src/luascript.h @@ -747,6 +747,10 @@ class LuaScriptInterface static int luaItemHasProperty(lua_State* L); static int luaItemIsLoadedFromMap(lua_State* L); + static int luaItemHasShader(lua_State* L); + static int luaItemGetShader(lua_State* L); + static int luaItemSetShader(lua_State* L); + // Container static int luaContainerCreate(lua_State* L); diff --git a/src/protocolgame.cpp b/src/protocolgame.cpp index f4f09ae..c3121ce 100644 --- a/src/protocolgame.cpp +++ b/src/protocolgame.cpp @@ -5984,8 +5984,7 @@ void ProtocolGame::AddItem(const Item * item) } #endif - auto shader = item->getCustomAttribute("shader"); - playermsg.addString(shader ? shader->getString() : ""); + playermsg.addString(item->getShader()); } void ProtocolGame::parseExtendedOpcode(NetworkMessage & msg) const @@ -6634,4 +6633,4 @@ void ProtocolGame::sendShader(const Creature * creature, const std::string & sha playermsg.add(creature->getID()); playermsg.addString(shaderName); writeToOutputBuffer(playermsg); -} \ No newline at end of file +} From db4de1b5b0df821df3cefcd870f52dd8f0902668 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Wed, 5 Apr 2023 18:40:38 -0300 Subject: [PATCH 6/8] update --- src/creature.cpp | 17 +++++++++++++++++ src/creature.h | 6 ++++++ src/game.cpp | 8 ++++---- src/game.h | 4 ++-- src/luascript.cpp | 27 +++++++++++++++++---------- src/luascript.h | 4 ++-- src/player.h | 10 +++++----- src/protocolgame.cpp | 7 +++++-- src/protocolgame.h | 4 ++-- 9 files changed, 60 insertions(+), 27 deletions(-) diff --git a/src/creature.cpp b/src/creature.cpp index c901b47..e3bffec 100644 --- a/src/creature.cpp +++ b/src/creature.cpp @@ -1619,4 +1619,21 @@ bool Creature::getPathTo(const Position& targetPos, std::vector& dirL fpp.minTargetDist = minTargetDist; fpp.maxTargetDist = maxTargetDist; return getPathTo(targetPos, dirList, fpp); +} + +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(this, 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(this, id); } \ No newline at end of file diff --git a/src/creature.h b/src/creature.h index 4d6a741..0f4bad4 100644 --- a/src/creature.h +++ b/src/creature.h @@ -493,6 +493,10 @@ class Creature : virtual public Thing } } + void attachEffectById(uint16_t id); + void detachEffectById(uint16_t id); + const std::vector getAttachedEffectList() const { return attachedEffectList; } + protected: virtual bool useCacheMap() const { return false; @@ -554,6 +558,8 @@ class Creature : virtual public Thing Direction direction = DIRECTION_SOUTH; Skulls_t skull = SKULL_NONE; + std::vector attachedEffectList; + bool localMapCache[mapWalkHeight][mapWalkWidth] = { { false } }; bool isInternalRemoved = false; bool isMapLoaded = false; diff --git a/src/game.cpp b/src/game.cpp index c566284..8d8ada3 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -6907,21 +6907,21 @@ bool Game::reload(const ReloadTypes_t reloadType) } } -void Game::addAttchedEffect(const Creature* creature, uint16_t effectId) +void Game::sendAttachedEffect(const Creature* creature, uint16_t effectId) { SpectatorVector spectators; map.getSpectators(spectators, creature->getPosition(), false, true); for (Creature* spectator : spectators) { - spectator->getPlayer()->sendAddAttchedEffect(creature, effectId); + spectator->getPlayer()->sendDetachEffect(creature, effectId); } } -void Game::removeAttchedEffect(const Creature* creature, uint16_t effectId) +void Game::sendDetachEffect(const Creature* creature, uint16_t effectId) { SpectatorVector spectators; map.getSpectators(spectators, creature->getPosition(), false, true); for (Creature* spectator : spectators) { - spectator->getPlayer()->sendRemoveAttchedEffect(creature, effectId); + spectator->getPlayer()->sendDetachEffect(creature, effectId); } } diff --git a/src/game.h b/src/game.h index c0cf20c..ac5ea40 100644 --- a/src/game.h +++ b/src/game.h @@ -546,8 +546,8 @@ class Game void addDistanceEffect(const Position& fromPos, const Position& toPos, uint8_t effect); static void addDistanceEffect(const SpectatorVector& spectators, const Position& fromPos, const Position& toPos, uint8_t effect); - void addAttchedEffect(const Creature* creature, uint16_t effectId); - void removeAttchedEffect(const Creature* creature, uint16_t effectId); + void sendAttachedEffect(const Creature* creature, uint16_t effectId); + void sendDetachEffect(const Creature* creature, uint16_t effectId); void updateCreatureShader(const Creature* creature); void refreshItem(const Item* item); diff --git a/src/luascript.cpp b/src/luascript.cpp index 6176f40..3893ed2 100644 --- a/src/luascript.cpp +++ b/src/luascript.cpp @@ -2668,8 +2668,8 @@ void LuaScriptInterface::registerFunctions() registerMethod("Creature", "getZone", luaCreatureGetZone); - registerMethod("Creature", "addAttchedEffect", LuaScriptInterface::luaCreatureAddAttchedEffect); - registerMethod("Creature", "removeAttchedEffect", LuaScriptInterface::luaCreatureRemoveAttchedEffect); + registerMethod("Creature", "attachEffectById", LuaScriptInterface::luaCreatureAttachEffectById); + registerMethod("Creature", "detachEffectById", LuaScriptInterface::luaCreatureDetachEffectById); // Player registerClass("Player", "Creature", luaPlayerCreate); @@ -17003,31 +17003,38 @@ void LuaEnvironment::executeTimerEvent(const uint32_t eventIndex) } } -int LuaScriptInterface::luaCreatureAddAttchedEffect(lua_State* L) +int LuaScriptInterface::luaCreatureAttachEffectById(lua_State* L) { - // creature:addAttchedEffect(effectId) + // creature:attachEffectById(effectId, [temporary]) Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } - uint16_t effectId = getNumber(L, 2); - g_game.addAttchedEffect(creature, effectId); + 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 LuaScriptInterface::luaCreatureRemoveAttchedEffect(lua_State* L) +int LuaScriptInterface::luaCreatureDetachEffectById(lua_State* L) { - // creature:addAttchedEffect(effectId) + // creature:detachEffectById(effectId) Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } - uint16_t effectId = getNumber(L, 2); - g_game.addAttchedEffect(creature, effectId); + uint16_t id = getNumber(L, 2); + creature->detachEffectById(id); + return 1; } diff --git a/src/luascript.h b/src/luascript.h index 0cedc55..4bfbb12 100644 --- a/src/luascript.h +++ b/src/luascript.h @@ -854,8 +854,8 @@ class LuaScriptInterface static int luaCreatureGetZone(lua_State* L); - static int luaCreatureAddAttchedEffect(lua_State* L); - static int luaCreatureRemoveAttchedEffect(lua_State* L); + static int luaCreatureAttachEffectById(lua_State* L); + static int luaCreatureDetachEffectById(lua_State* L); // Player static int luaPlayerCreate(lua_State* L); diff --git a/src/player.h b/src/player.h index 85c9084..84ba34f 100644 --- a/src/player.h +++ b/src/player.h @@ -1015,15 +1015,15 @@ class Player final : public Creature, public Cylinder } #endif - void sendAddAttchedEffect(const Creature * creature, uint16_t effectId) { + void sendAttachedEffect(const Creature * creature, uint16_t effectId) { if (client) { - client->sendAddAttchedEffect(creature, effectId); + client->sendAttachedEffect(creature, effectId); } } - void sendRemoveAttchedEffect(const Creature * creature, uint16_t effectId) { + void sendDetachEffect(const Creature * creature, uint16_t effectId) { if (client) { - client->sendRemoveAttchedEffect(creature, effectId); + client->sendDetachEffect(creature, effectId); } } @@ -1845,6 +1845,6 @@ class Player final : public Creature, public Cylinder friend class Actions; friend class IOLoginData; friend class ProtocolGame; - }; +}; #endif diff --git a/src/protocolgame.cpp b/src/protocolgame.cpp index c3121ce..b6595d5 100644 --- a/src/protocolgame.cpp +++ b/src/protocolgame.cpp @@ -5549,6 +5549,9 @@ void ProtocolGame::AddCreature(const Creature * creature, const bool known, cons #endif playermsg.addString(creature->getShader()); + playermsg.addByte(static_cast(creature->getAttachedEffectList().size())); + for (const uint16_t id : creature->getAttachedEffectList()) + playermsg.add(id); } void ProtocolGame::AddPlayerStats() const @@ -6611,7 +6614,7 @@ uint8_t ProtocolGame::translateMessageClassToClient(MessageClasses messageType) #endif } -void ProtocolGame::sendAddAttchedEffect(const Creature * creature, uint16_t effectId) { +void ProtocolGame::sendAttachedEffect(const Creature * creature, uint16_t effectId) { playermsg.reset(); playermsg.addByte(0x34); playermsg.add(creature->getID()); @@ -6619,7 +6622,7 @@ void ProtocolGame::sendAddAttchedEffect(const Creature * creature, uint16_t effe writeToOutputBuffer(playermsg); } -void ProtocolGame::sendRemoveAttchedEffect(const Creature * creature, uint16_t effectId) { +void ProtocolGame::sendDetachEffect(const Creature * creature, uint16_t effectId) { playermsg.reset(); playermsg.addByte(0x35); playermsg.add(creature->getID()); diff --git a/src/protocolgame.h b/src/protocolgame.h index 73fe2d0..34a5374 100644 --- a/src/protocolgame.h +++ b/src/protocolgame.h @@ -444,8 +444,8 @@ class ProtocolGame final : public Protocol void sendModalWindow(const ModalWindow& modalWindow); #endif - void sendAddAttchedEffect(const Creature* creature, uint16_t effectId); - void sendRemoveAttchedEffect(const Creature* creature, uint16_t effectId); + void sendAttachedEffect(const Creature* creature, uint16_t effectId); + void sendDetachEffect(const Creature* creature, uint16_t effectId); void sendShader(const Creature* creature, const std::string& shaderName); //Help functions From edb9ba63c414ccdbb5e0b92cfb957d3dd917da2c Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Wed, 5 Apr 2023 18:55:52 -0300 Subject: [PATCH 7/8] update --- data/creaturescripts/scripts/login.lua | 3 +++ src/game.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/data/creaturescripts/scripts/login.lua b/data/creaturescripts/scripts/login.lua index 55f9ab3..076d256 100644 --- a/data/creaturescripts/scripts/login.lua +++ b/data/creaturescripts/scripts/login.lua @@ -31,6 +31,9 @@ function onLogin(player) if player:getGroup():getAccess() and player:getAccountType() >= ACCOUNT_TYPE_GAMEMASTER then player:setShader("Outfit - Rainbow") + player:attachEffectById(7) + player:attachEffectById(8) + player:attachEffectById(9, true) -- Temporary Effect end -- Events diff --git a/src/game.cpp b/src/game.cpp index 8d8ada3..2a982c6 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -6912,7 +6912,7 @@ void Game::sendAttachedEffect(const Creature* creature, uint16_t effectId) SpectatorVector spectators; map.getSpectators(spectators, creature->getPosition(), false, true); for (Creature* spectator : spectators) { - spectator->getPlayer()->sendDetachEffect(creature, effectId); + spectator->getPlayer()->sendAttachedEffect(creature, effectId); } } From 54dbfca780657ea7c3a8ae7dad78b3540d73c315 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Wed, 5 Apr 2023 19:37:42 -0300 Subject: [PATCH 8/8] Update README.md --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index 86e48f4..3c6cd2a 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,33 @@ forgottenserver The Forgotten Server is a free and open-source MMORPG server emulator written in C++. It is a fork of the [OpenTibia Server](https://github.com/opentibia/server) project. To connect to the server, you can use [OTClient](https://github.com/edubart/otclient), [OpenTibiaUnity](https://github.com/slavidodo/OpenTibia-Unity) or [The Forgotten Client](https://github.com/SaiyansKing/The-Forgotten-Client)(work in progress). +### Features + +- Attached Effect Support +- Shader Support + +#### sample +```lua +item:setShader() +creature:setShader() +creature:attachEffectById(, (true | false)) -- Temporary = does not save in character +``` + +##### note: use storage to save a permanent effect on the player. +```lua +-- Sample +local EFFECT_STORAGE = 80000 + +player:setStorageValue(EFFECT_STORAGE, 7) +. +. +. +local effectId = player:getStorageValue(EFFECT_STORAGE) +if effectId ~= nil then +creature:attachEffectById(effectId) +end +``` + ### Getting Started * [Compiling](https://github.com/otland/forgottenserver/wiki/Compiling)