From ee322f743381ec8b4c55df53ec116ef2ec4cb4d8 Mon Sep 17 00:00:00 2001 From: Joao Pasqualini Costa Date: Tue, 14 Nov 2023 11:58:24 -0300 Subject: [PATCH 1/8] Now it is possible to attache effects to tiles and set where it will be drawn --- modules/gamelib/gamelib.otmod | 1 + modules/gamelib/thing.lua | 4 ++ modules/gamelib/tile.lua | 39 ++++++++++++ src/CMakeLists.txt | 1 + src/client/attachableobject.cpp | 102 ++++++++++++++++++++++++++++++ src/client/attachableobject.h | 52 +++++++++++++++ src/client/attachedeffect.h | 14 ++++ src/client/luafunctions.cpp | 18 ++++-- src/client/thing.cpp | 109 +++++++------------------------- src/client/thing.h | 24 +++---- src/client/tile.cpp | 8 ++- src/client/tile.h | 5 +- vc17/otclient.vcxproj | 2 + vc17/otclient.vcxproj.filters | 6 ++ 14 files changed, 275 insertions(+), 110 deletions(-) create mode 100644 modules/gamelib/tile.lua create mode 100644 src/client/attachableobject.cpp create mode 100644 src/client/attachableobject.h diff --git a/modules/gamelib/gamelib.otmod b/modules/gamelib/gamelib.otmod index 4e066fb4b0..846c3287fa 100644 --- a/modules/gamelib/gamelib.otmod +++ b/modules/gamelib/gamelib.otmod @@ -19,6 +19,7 @@ Module dofile 'textmessages' dofile 'thing' dofile 'spells' + dofile 'tile' dofile 'eventcontroller' dofile 'controller' diff --git a/modules/gamelib/thing.lua b/modules/gamelib/thing.lua index 08cf79edb2..e26e5d3ef2 100644 --- a/modules/gamelib/thing.lua +++ b/modules/gamelib/thing.lua @@ -48,3 +48,7 @@ SpriteMaskRed = 1 SpriteMaskGreen = 2 SpriteMaskBlue = 3 SpriteMaskYellow = 4 + +function Thing:isTile() + return false +end diff --git a/modules/gamelib/tile.lua b/modules/gamelib/tile.lua new file mode 100644 index 0000000000..7b6b26f926 --- /dev/null +++ b/modules/gamelib/tile.lua @@ -0,0 +1,39 @@ +function Tile:isTile() + return true +end + +function Tile:isCreature() + return false +end + +function Tile:isLocalPlayer() + return false +end + +function Tile:isNpc() + return false +end + +function Tile:isMonster() + return false +end + +function Tile:isPlayer() + return false +end + +function Tile:isEffect() + return false +end + +function Tile:isMissile() + return false +end + +function Tile:isItem() + return false +end + +function Tile:isContainer() + return false +end diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 254210a352..dc8e6a408b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -234,6 +234,7 @@ endif() set(SOURCE_FILES client/animatedtext.cpp client/animator.cpp + client/attachableobject.cpp client/attachedeffect.cpp client/attachedeffectmanager.cpp client/client.cpp diff --git a/src/client/attachableobject.cpp b/src/client/attachableobject.cpp new file mode 100644 index 0000000000..9fb4347c93 --- /dev/null +++ b/src/client/attachableobject.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2010-2022 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "attachableobject.h" +#include "tile.h" + +#include +#include + +void AttachableObject::attachEffect(const AttachedEffectPtr& obj) { + if (!obj) + return; + + onStartAttachEffect(obj); + + if (obj->isHidedOwner()) + ++m_ownerHidden; + + if (obj->getDuration() > 0) { + g_dispatcher.scheduleEvent([self = std::static_pointer_cast(shared_from_this()), effectId = obj->getId()]() { + self->detachEffectById(effectId); + }, obj->getDuration()); + } + + m_attachedEffects.emplace_back(obj); + g_dispatcher.addEvent([effect = obj, self = std::static_pointer_cast(shared_from_this())] { + self->onDispatcherAttachEffect(effect); + effect->callLuaField("onAttach", self->attachedObjectToLuaObject()); + }); +} + +bool AttachableObject::detachEffectById(uint16_t id) { + const auto it = std::find_if(m_attachedEffects.begin(), m_attachedEffects.end(), + [id](const AttachedEffectPtr& obj) { return obj->getId() == id; }); + + if (it == m_attachedEffects.end()) + return false; + + onDetachEffect(*it); + m_attachedEffects.erase(it); + + return true; +} + +void AttachableObject::onDetachEffect(const AttachedEffectPtr& effect) { + if (effect->isHidedOwner()) + --m_ownerHidden; + + onStartDetachEffect(effect); + + effect->callLuaField("onDetach", attachedObjectToLuaObject()); +} + +void AttachableObject::clearAttachedEffects() { + for (const auto& e : m_attachedEffects) + onDetachEffect(e); + m_attachedEffects.clear(); +} + +AttachedEffectPtr AttachableObject::getAttachedEffectById(uint16_t id) { + const auto it = std::find_if(m_attachedEffects.begin(), m_attachedEffects.end(), + [id](const AttachedEffectPtr& obj) { return obj->getId() == id; }); + + if (it == m_attachedEffects.end()) + return nullptr; + + return *it; +} + +void AttachableObject::drawAttachedEffect(const Point& dest, LightView* lightView, bool isOnTop, AttachedEffectDrawPlace drawPlace) +{ + for (const auto& effect : m_attachedEffects) { + if (effect->getDrawPlace() != drawPlace) + continue; + + effect->draw(dest, isOnTop, lightView); + if (effect->getLoop() == 0) { + g_dispatcher.addEvent([self = std::static_pointer_cast(shared_from_this()), effectId = effect->getId()]() { + self->detachEffectById(effectId); + }); + } + } +} diff --git a/src/client/attachableobject.h b/src/client/attachableobject.h new file mode 100644 index 0000000000..a19ebf942e --- /dev/null +++ b/src/client/attachableobject.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010-2022 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once +#include "attachedeffect.h" + + // @bindclass +#pragma pack(push,1) // disable memory alignment +class AttachableObject : public LuaObject +{ +public: + void attachEffect(const AttachedEffectPtr& obj); + void clearAttachedEffects(); + bool detachEffectById(uint16_t id); + AttachedEffectPtr getAttachedEffectById(uint16_t id); + + virtual LuaObjectPtr attachedObjectToLuaObject() = 0; + virtual void onStartAttachEffect(const AttachedEffectPtr& effect) { }; + virtual void onDispatcherAttachEffect(const AttachedEffectPtr& effect) { }; + virtual void onStartDetachEffect(const AttachedEffectPtr& effect) { }; + + bool isOwnerHidden() { return m_ownerHidden > 0; } + + const std::vector& getAttachedEffects() { return m_attachedEffects; }; + +protected: + void drawAttachedEffect(const Point& dest, LightView* lightView, bool isOnTop, AttachedEffectDrawPlace drawPlace = AttachedEffectDrawPlace::DEFAULT); + void onDetachEffect(const AttachedEffectPtr& effect); + + std::vector m_attachedEffects; + uint8_t m_ownerHidden{ 0 }; +}; +#pragma pack(pop) diff --git a/src/client/attachedeffect.h b/src/client/attachedeffect.h index 2f8dd891c9..f0d12cf1dd 100644 --- a/src/client/attachedeffect.h +++ b/src/client/attachedeffect.h @@ -25,6 +25,16 @@ #include "thingtype.h" #include "outfit.h" +enum class AttachedEffectDrawPlace : uint8_t +{ + DEFAULT, + BEFORE_GROUND, + BEFORE_ITEM, + BEFORE_CREATURE, + BEFORE_EFFECTS, + LAST, +}; + class AttachedEffect : public LuaObject { public: @@ -72,6 +82,9 @@ class AttachedEffect : public LuaObject void attachEffect(const AttachedEffectPtr& e) { m_effects.emplace_back(e); } + AttachedEffectDrawPlace getDrawPlace() { return m_drawPlace; } + void setDrawPlace(AttachedEffectDrawPlace drawPlace) { m_drawPlace = drawPlace; } + private: int getCurrentAnimationPhase(); @@ -86,6 +99,7 @@ class AttachedEffect : public LuaObject uint8_t m_speed{ 100 }; uint8_t m_opacity{ 100 }; uint8_t m_lastAnimation{ 0 }; + AttachedEffectDrawPlace m_drawPlace{ AttachedEffectDrawPlace::DEFAULT }; uint16_t m_id{ 0 }; uint16_t m_duration{ 0 }; diff --git a/src/client/luafunctions.cpp b/src/client/luafunctions.cpp index e023a41784..d44259d246 100644 --- a/src/client/luafunctions.cpp +++ b/src/client/luafunctions.cpp @@ -52,6 +52,7 @@ #include "uiminimap.h" #include "uiprogressrect.h" #include "uisprite.h" +#include "attachableobject.h" #ifdef FRAMEWORK_EDITOR #include "houses.h" @@ -391,7 +392,14 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("getSize", &Container::getSize); g_lua.bindClassMemberFunction("getFirstIndex", &Container::getFirstIndex); - g_lua.registerClass(); + g_lua.registerClass(); + g_lua.bindClassMemberFunction("getAttachedEffects", &AttachableObject::getAttachedEffects); + g_lua.bindClassMemberFunction("attachEffect", &AttachableObject::attachEffect); + g_lua.bindClassMemberFunction("detachEffectById", &AttachableObject::detachEffectById); + g_lua.bindClassMemberFunction("getAttachedEffectById", &AttachableObject::getAttachedEffectById); + g_lua.bindClassMemberFunction("clearAttachedEffects", &AttachableObject::clearAttachedEffects); + + g_lua.registerClass(); g_lua.bindClassMemberFunction("setId", &Thing::setId); g_lua.bindClassMemberFunction("setShader", &Thing::setShader); g_lua.bindClassMemberFunction("setPosition", &Thing::setPosition); @@ -434,11 +442,6 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("isTopEffect", &Thing::isTopEffect); g_lua.bindClassMemberFunction("isLyingCorpse", &Thing::isLyingCorpse); g_lua.bindClassMemberFunction("getDefaultAction", &Thing::getDefaultAction); - g_lua.bindClassMemberFunction("getAttachedEffects", &Thing::getAttachedEffects); - g_lua.bindClassMemberFunction("attachEffect", &Thing::attachEffect); - g_lua.bindClassMemberFunction("detachEffectById", &Thing::detachEffectById); - g_lua.bindClassMemberFunction("getAttachedEffectById", &Thing::getAttachedEffectById); - g_lua.bindClassMemberFunction("clearAttachedEffects", &Thing::clearAttachedEffects); g_lua.bindClassMemberFunction("getClassification", &Thing::getClassification); #ifdef FRAMEWORK_EDITOR @@ -690,6 +693,7 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("canDrawOnUI", &AttachedEffect::canDrawOnUI); g_lua.bindClassMemberFunction("setCanDrawOnUI", &AttachedEffect::setCanDrawOnUI); g_lua.bindClassMemberFunction("attachEffect", &AttachedEffect::attachEffect); + g_lua.bindClassMemberFunction("setDrawPlace", &AttachedEffect::setDrawPlace); g_lua.registerClass(); g_lua.bindClassStaticFunction("create", [] { return std::make_shared(); }); @@ -756,7 +760,7 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("setResourceBalance", &LocalPlayer::setResourceBalance); g_lua.bindClassMemberFunction("getTotalMoney", &LocalPlayer::getTotalMoney); - g_lua.registerClass(); + g_lua.registerClass(); g_lua.bindClassMemberFunction("clean", &Tile::clean); g_lua.bindClassMemberFunction("addThing", &Tile::addThing); g_lua.bindClassMemberFunction("getThing", &Tile::getThing); diff --git a/src/client/thing.cpp b/src/client/thing.cpp index 8ba9c590c0..1621195ad1 100644 --- a/src/client/thing.cpp +++ b/src/client/thing.cpp @@ -97,71 +97,40 @@ void Thing::setShader(const std::string_view name) { m_shader = g_shaders.getShader(name.data()); } -void Thing::attachEffect(const AttachedEffectPtr& obj) { - if (!obj) - return; - +void Thing::onStartAttachEffect(const AttachedEffectPtr& effect) { if (isCreature()) { - if (obj->m_thingType && (obj->m_thingType->isCreature() || obj->m_thingType->isMissile())) - obj->m_direction = static_self_cast()->getDirection(); - } - - if (obj->isHidedOwner()) - ++m_hidden; - - if (obj->getDuration() > 0) { - g_dispatcher.scheduleEvent([self = static_self_cast(), effectId = obj->getId()]() { - self->detachEffectById(effectId); - }, obj->getDuration()); - } - - if (obj->isDisabledWalkAnimation() && isCreature()) { - const auto& creature = static_self_cast(); - creature->setDisableWalkAnimation(true); - } - - m_attachedEffects.emplace_back(obj); - g_dispatcher.addEvent([effect = obj, self = static_self_cast()] { - if (effect->isTransform() && self->isCreature() && effect->m_thingType) { - const auto& creature = self->static_self_cast(); - const auto& outfit = creature->getOutfit(); - if (outfit.isTemp()) - return; - - effect->m_outfitOwner = outfit; - - Outfit newOutfit = outfit; - newOutfit.setTemp(true); - newOutfit.setCategory(effect->m_thingType->getCategory()); - if (newOutfit.isCreature()) - newOutfit.setId(effect->m_thingType->getId()); - else - newOutfit.setAuxId(effect->m_thingType->getId()); - - creature->setOutfit(newOutfit); + if (effect->isDisabledWalkAnimation()) { + const auto& creature = static_self_cast(); + creature->setDisableWalkAnimation(true); } - effect->callLuaField("onAttach", self->asLuaObject()); - }); + if (effect->m_thingType && (effect->m_thingType->isCreature() || effect->m_thingType->isMissile())) + effect->m_direction = static_self_cast()->getDirection(); + } } -bool Thing::detachEffectById(uint16_t id) { - const auto it = std::find_if(m_attachedEffects.begin(), m_attachedEffects.end(), - [id](const AttachedEffectPtr& obj) { return obj->getId() == id; }); +void Thing::onDispatcherAttachEffect(const AttachedEffectPtr& effect) { + if (effect->isTransform() && isCreature() && effect->m_thingType) { + const auto& creature = static_self_cast(); + const auto& outfit = creature->getOutfit(); + if (outfit.isTemp()) + return; - if (it == m_attachedEffects.end()) - return false; + effect->m_outfitOwner = outfit; - onDetachEffect(*it); - m_attachedEffects.erase(it); + Outfit newOutfit = outfit; + newOutfit.setTemp(true); + newOutfit.setCategory(effect->m_thingType->getCategory()); + if (newOutfit.isCreature()) + newOutfit.setId(effect->m_thingType->getId()); + else + newOutfit.setAuxId(effect->m_thingType->getId()); - return true; + creature->setOutfit(newOutfit); + } } -void Thing::onDetachEffect(const AttachedEffectPtr& effect) { - if (effect->isHidedOwner()) - --m_hidden; - +void Thing::onStartDetachEffect(const AttachedEffectPtr& effect) { if (isCreature()) { const auto& creature = static_self_cast(); @@ -172,34 +141,4 @@ void Thing::onDetachEffect(const AttachedEffectPtr& effect) { creature->setOutfit(effect->m_outfitOwner); } } - - effect->callLuaField("onDetach", asLuaObject()); -} - -void Thing::clearAttachedEffects() { - for (const auto& e : m_attachedEffects) - onDetachEffect(e); - m_attachedEffects.clear(); -} - -AttachedEffectPtr Thing::getAttachedEffectById(uint16_t id) { - const auto it = std::find_if(m_attachedEffects.begin(), m_attachedEffects.end(), - [id](const AttachedEffectPtr& obj) { return obj->getId() == id; }); - - if (it == m_attachedEffects.end()) - return nullptr; - - return *it; -} - -void Thing::drawAttachedEffect(const Point& dest, LightView* lightView, bool isOnTop) -{ - for (const auto& effect : m_attachedEffects) { - effect->draw(dest, isOnTop, lightView); - if (effect->getLoop() == 0) { - g_dispatcher.addEvent([self = static_self_cast(), effectId = effect->getId()]() { - self->detachEffectById(effectId); - }); - } - } } \ No newline at end of file diff --git a/src/client/thing.h b/src/client/thing.h index fdb09aa6e7..e8a29c1fb6 100644 --- a/src/client/thing.h +++ b/src/client/thing.h @@ -30,14 +30,17 @@ #include "spritemanager.h" #include "thingtype.h" #include "thingtypemanager.h" +#include "attachableobject.h" // @bindclass #pragma pack(push,1) // disable memory alignment -class Thing : public LuaObject +class Thing : public AttachableObject { public: virtual void draw(const Point& /*dest*/, bool drawThings = true, LightView* /*lightView*/ = nullptr) {} + LuaObjectPtr attachedObjectToLuaObject() override { return asLuaObject(); } + virtual void setId(uint32_t /*id*/) {} virtual void setPosition(const Position& position, uint8_t stackPos = 0, bool hasElevation = false); @@ -182,19 +185,12 @@ class Thing : public LuaObject bool isMarked() { return m_markedColor != Color::white; } void setMarkColor(const Color& color) { if (m_markedColor != color) m_markedColor = color; } - bool isHided() { return m_hidden > 0; } - - void attachEffect(const AttachedEffectPtr& obj); - void clearAttachedEffects(); - bool detachEffectById(uint16_t id); - AttachedEffectPtr getAttachedEffectById(uint16_t id); - - const std::vector& getAttachedEffects() { return m_attachedEffects; }; + bool isHided() { return isOwnerHidden(); } + void onStartAttachEffect(const AttachedEffectPtr& effect) override; + void onDispatcherAttachEffect(const AttachedEffectPtr& effect) override; + void onStartDetachEffect(const AttachedEffectPtr& effect) override; protected: - void drawAttachedEffect(const Point& dest, LightView* lightView, bool isOnTop); - - void onDetachEffect(const AttachedEffectPtr& effect); void setAttachedEffectDirection(Otc::Direction dir) const { for (const auto& effect : m_attachedEffects) { @@ -203,8 +199,6 @@ class Thing : public LuaObject } } - uint8_t m_hidden{ 0 }; - uint8_t m_numPatternX{ 0 }; uint8_t m_numPatternY{ 0 }; uint8_t m_numPatternZ{ 0 }; @@ -221,8 +215,6 @@ class Thing : public LuaObject PainterShaderProgramPtr m_shader; std::function m_shaderAction{ nullptr }; - std::vector m_attachedEffects; - private: bool m_canDraw{ true }; }; diff --git a/src/client/tile.cpp b/src/client/tile.cpp index 1776848ce1..8bc7bd0c06 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -48,6 +48,7 @@ void Tile::draw(const Point& dest, const MapPosInfo& mapRect, int flags, bool is m_drawElevation = 0; m_lastDrawDest = dest; + drawAttachedEffect(dest, lightView, false, AttachedEffectDrawPlace::BEFORE_GROUND); for (const auto& thing : m_things) { if (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom()) break; @@ -55,6 +56,7 @@ void Tile::draw(const Point& dest, const MapPosInfo& mapRect, int flags, bool is drawThing(thing, dest, flags, lightView); } + drawAttachedEffect(dest, lightView, false, AttachedEffectDrawPlace::BEFORE_ITEM); if (hasCommonItem()) { for (auto it = m_things.rbegin(); it != m_things.rend(); ++it) { const auto& item = *it; @@ -63,14 +65,18 @@ void Tile::draw(const Point& dest, const MapPosInfo& mapRect, int flags, bool is } } + drawAttachedEffect(dest, lightView, false, AttachedEffectDrawPlace::BEFORE_CREATURE); // after we render 2x2 lying corpses, we must redraw previous creatures/ontop above them for (const auto& tile : m_tilesRedraw) { tile->drawCreature(tile->m_lastDrawDest, mapRect, flags, isCovered, true, lightView); tile->drawTop(tile->m_lastDrawDest, flags, true, lightView); } - drawCreature(dest, mapRect, flags, isCovered, false, lightView); + + drawAttachedEffect(dest, lightView, false, AttachedEffectDrawPlace::BEFORE_EFFECTS); drawTop(dest, flags, false, lightView); + + drawAttachedEffect(dest, lightView, false, AttachedEffectDrawPlace::DEFAULT); updateWidget(dest, mapRect); } diff --git a/src/client/tile.h b/src/client/tile.h index 73486987b4..343693ad93 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -27,6 +27,7 @@ #include "effect.h" #include "item.h" #include "mapview.h" +#include "attachableobject.h" #ifdef FRAMEWORK_EDITOR enum tileflags_t : uint32_t @@ -88,11 +89,13 @@ enum TileThingType : uint32_t CORRECT_CORPSE = 1 << 25 }; -class Tile : public LuaObject +class Tile : public AttachableObject { public: Tile(const Position& position); + LuaObjectPtr attachedObjectToLuaObject() override { return asLuaObject(); } + void onAddInMapView(); void draw(const Point& dest, const MapPosInfo& mapRect, int flags, bool isCovered, LightView* lightView = nullptr); diff --git a/vc17/otclient.vcxproj b/vc17/otclient.vcxproj index 4e5a726a99..5a72bb26cc 100644 --- a/vc17/otclient.vcxproj +++ b/vc17/otclient.vcxproj @@ -206,6 +206,7 @@ cmd /c "start ../vcpkg_installed\$(VcpkgTriplet)\$(VcpkgTriplet)\tools\protobuf\ + @@ -356,6 +357,7 @@ cmd /c "start ../vcpkg_installed\$(VcpkgTriplet)\$(VcpkgTriplet)\tools\protobuf\ + diff --git a/vc17/otclient.vcxproj.filters b/vc17/otclient.vcxproj.filters index b4547e0517..04f550a23b 100644 --- a/vc17/otclient.vcxproj.filters +++ b/vc17/otclient.vcxproj.filters @@ -534,6 +534,9 @@ Source Files\protobuf + + Source Files\client + Source Files\client @@ -1046,6 +1049,9 @@ Header Files\protobuf + + Header Files\client + Header Files\client From adcebbb2c9c19fd52a7cbdb6953ef73a39a6ed5e Mon Sep 17 00:00:00 2001 From: Joao Pasqualini Costa Date: Tue, 14 Nov 2023 21:38:16 -0300 Subject: [PATCH 2/8] Fix build error with unity, compile framework first and then client. --- src/CMakeLists.txt | 95 +++++++++++++++++---------------- src/client/attachableobject.cpp | 2 - src/client/attachableobject.h | 7 +-- src/client/thing.h | 1 - 4 files changed, 52 insertions(+), 53 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dc8e6a408b..056bb70a1d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -232,53 +232,6 @@ endif() # OTClient source files configuration # ***************************************************************************** set(SOURCE_FILES - client/animatedtext.cpp - client/animator.cpp - client/attachableobject.cpp - client/attachedeffect.cpp - client/attachedeffectmanager.cpp - client/client.cpp - client/container.cpp - client/creature.cpp - client/creatures.cpp - client/effect.cpp - client/game.cpp - client/gameconfig.cpp - client/houses.cpp - client/item.cpp - client/itemtype.cpp - client/lightview.cpp - client/localplayer.cpp - client/luafunctions.cpp - client/luavaluecasts.cpp - client/map.cpp - client/mapio.cpp - client/mapview.cpp - client/minimap.cpp - client/missile.cpp - client/outfit.cpp - client/player.cpp - client/position.cpp - client/protocolcodes.cpp - client/protocolgame.cpp - client/protocolgameparse.cpp - client/protocolgamesend.cpp - client/shadermanager.cpp - client/spriteappearances.cpp - client/spritemanager.cpp - client/statictext.cpp - client/thing.cpp - client/thingtype.cpp - client/thingtypemanager.cpp - client/tile.cpp - client/towns.cpp - client/uicreature.cpp - client/uiitem.cpp - client/uimap.cpp - client/uimapanchorlayout.cpp - client/uiminimap.cpp - client/uiprogressrect.cpp - client/uisprite.cpp framework/core/adaptativeframecounter.cpp framework/core/application.cpp framework/core/asyncdispatcher.cpp @@ -379,6 +332,54 @@ set(SOURCE_FILES framework/util/color.cpp framework/util/crypt.cpp + client/animatedtext.cpp + client/animator.cpp + client/attachableobject.cpp + client/attachedeffect.cpp + client/attachedeffectmanager.cpp + client/client.cpp + client/container.cpp + client/creature.cpp + client/creatures.cpp + client/effect.cpp + client/game.cpp + client/gameconfig.cpp + client/houses.cpp + client/item.cpp + client/itemtype.cpp + client/lightview.cpp + client/localplayer.cpp + client/luafunctions.cpp + client/luavaluecasts.cpp + client/map.cpp + client/mapio.cpp + client/mapview.cpp + client/minimap.cpp + client/missile.cpp + client/outfit.cpp + client/player.cpp + client/position.cpp + client/protocolcodes.cpp + client/protocolgame.cpp + client/protocolgameparse.cpp + client/protocolgamesend.cpp + client/shadermanager.cpp + client/spriteappearances.cpp + client/spritemanager.cpp + client/statictext.cpp + client/thing.cpp + client/thingtype.cpp + client/thingtypemanager.cpp + client/tile.cpp + client/towns.cpp + client/uicreature.cpp + client/uiitem.cpp + client/uimap.cpp + client/uimapanchorlayout.cpp + client/uiminimap.cpp + client/uiprogressrect.cpp + client/uisprite.cpp + protobuf/appearances.pb.cc main.cpp androidmain.cpp diff --git a/src/client/attachableobject.cpp b/src/client/attachableobject.cpp index 9fb4347c93..bad79c309d 100644 --- a/src/client/attachableobject.cpp +++ b/src/client/attachableobject.cpp @@ -21,10 +21,8 @@ */ #include "attachableobject.h" -#include "tile.h" #include -#include void AttachableObject::attachEffect(const AttachedEffectPtr& obj) { if (!obj) diff --git a/src/client/attachableobject.h b/src/client/attachableobject.h index a19ebf942e..9ffb5ccdc9 100644 --- a/src/client/attachableobject.h +++ b/src/client/attachableobject.h @@ -22,12 +22,14 @@ #pragma once #include "attachedeffect.h" +#include - // @bindclass -#pragma pack(push,1) // disable memory alignment class AttachableObject : public LuaObject { public: + AttachableObject() = default; + virtual ~AttachableObject() = default; + void attachEffect(const AttachedEffectPtr& obj); void clearAttachedEffects(); bool detachEffectById(uint16_t id); @@ -49,4 +51,3 @@ class AttachableObject : public LuaObject std::vector m_attachedEffects; uint8_t m_ownerHidden{ 0 }; }; -#pragma pack(pop) diff --git a/src/client/thing.h b/src/client/thing.h index e8a29c1fb6..efccbc1e44 100644 --- a/src/client/thing.h +++ b/src/client/thing.h @@ -25,7 +25,6 @@ #include #include #include -#include "attachedeffect.h" #include "declarations.h" #include "spritemanager.h" #include "thingtype.h" From fdc347492de176d47694e950892753f7d51a6048 Mon Sep 17 00:00:00 2001 From: Joao Pasqualini Costa Date: Wed, 15 Nov 2023 09:17:17 -0300 Subject: [PATCH 3/8] Add light to attached effects and use draw conductor to set draw order --- modules/game_attachedeffects/lib.lua | 7 +++++++ src/client/attachableobject.cpp | 5 +---- src/client/attachableobject.h | 2 +- src/client/attachedeffect.cpp | 10 ++++++++-- src/client/attachedeffect.h | 19 ++++++------------- src/client/luafunctions.cpp | 3 ++- 6 files changed, 25 insertions(+), 21 deletions(-) diff --git a/modules/game_attachedeffects/lib.lua b/modules/game_attachedeffects/lib.lua index 5d9f29262c..661cde423d 100644 --- a/modules/game_attachedeffects/lib.lua +++ b/modules/game_attachedeffects/lib.lua @@ -26,6 +26,13 @@ local executeConfig = function(attachedEffect, config) attachedEffect:setOpacity(config.opacity) end + if config.color then + attachedEffect:setColor({ + color = config.color.color or 0, + intensity = config.color.intensity or 0 + }) + end + if config.duration ~= nil and config.duration > 0 then attachedEffect:setDuration(config.duration) end diff --git a/src/client/attachableobject.cpp b/src/client/attachableobject.cpp index bad79c309d..93401f9c3d 100644 --- a/src/client/attachableobject.cpp +++ b/src/client/attachableobject.cpp @@ -84,12 +84,9 @@ AttachedEffectPtr AttachableObject::getAttachedEffectById(uint16_t id) { return *it; } -void AttachableObject::drawAttachedEffect(const Point& dest, LightView* lightView, bool isOnTop, AttachedEffectDrawPlace drawPlace) +void AttachableObject::drawAttachedEffect(const Point& dest, LightView* lightView, bool isOnTop) { for (const auto& effect : m_attachedEffects) { - if (effect->getDrawPlace() != drawPlace) - continue; - effect->draw(dest, isOnTop, lightView); if (effect->getLoop() == 0) { g_dispatcher.addEvent([self = std::static_pointer_cast(shared_from_this()), effectId = effect->getId()]() { diff --git a/src/client/attachableobject.h b/src/client/attachableobject.h index 9ffb5ccdc9..0c4d9378e4 100644 --- a/src/client/attachableobject.h +++ b/src/client/attachableobject.h @@ -45,7 +45,7 @@ class AttachableObject : public LuaObject const std::vector& getAttachedEffects() { return m_attachedEffects; }; protected: - void drawAttachedEffect(const Point& dest, LightView* lightView, bool isOnTop, AttachedEffectDrawPlace drawPlace = AttachedEffectDrawPlace::DEFAULT); + void drawAttachedEffect(const Point& dest, LightView* lightView, bool isOnTop); void onDetachEffect(const AttachedEffectPtr& effect); std::vector m_attachedEffects; diff --git a/src/client/attachedeffect.cpp b/src/client/attachedeffect.cpp index dd7724bc13..ba05f08532 100644 --- a/src/client/attachedeffect.cpp +++ b/src/client/attachedeffect.cpp @@ -23,6 +23,8 @@ #include "attachedeffect.h" #include "shadermanager.h" #include "gameconfig.h" +#include "lightview.h" + #include #include @@ -60,12 +62,16 @@ void AttachedEffect::draw(const Point& dest, bool isOnTop, LightView* lightView) if (m_opacity < 100) g_drawPool.setOpacity(getOpacity(), true); const auto& point = dest - (dirControl.offset * g_drawPool.getScaleFactor()); + if (lightView && m_light.intensity > 0) + lightView->addLightSource(dest, m_light); if (m_texture) { const auto& size = (m_size.isUnset() ? m_texture->getSize() : m_size) * g_drawPool.getScaleFactor(); - g_drawPool.addTexturedRect(Rect(point, size), m_texture->get(m_frame, m_animationTimer)); + const auto& texture = m_texture->get(m_frame, m_animationTimer); + const auto& rect = Rect(Point(), texture->getSize()); + g_drawPool.addTexturedRect(Rect(point, size), texture, rect, Color::white, { .order = getDrawOrder() }); } else { - m_thingType->draw(point, 0, m_direction, 0, 0, animation, Color::white, true, lightView); + m_thingType->draw(point, 0, m_direction, 0, 0, animation, Color::white, true, lightView, {.order = getDrawOrder()}); } } diff --git a/src/client/attachedeffect.h b/src/client/attachedeffect.h index f0d12cf1dd..ca215ea214 100644 --- a/src/client/attachedeffect.h +++ b/src/client/attachedeffect.h @@ -25,16 +25,6 @@ #include "thingtype.h" #include "outfit.h" -enum class AttachedEffectDrawPlace : uint8_t -{ - DEFAULT, - BEFORE_GROUND, - BEFORE_ITEM, - BEFORE_CREATURE, - BEFORE_EFFECTS, - LAST, -}; - class AttachedEffect : public LuaObject { public: @@ -82,8 +72,10 @@ class AttachedEffect : public LuaObject void attachEffect(const AttachedEffectPtr& e) { m_effects.emplace_back(e); } - AttachedEffectDrawPlace getDrawPlace() { return m_drawPlace; } - void setDrawPlace(AttachedEffectDrawPlace drawPlace) { m_drawPlace = drawPlace; } + DrawOrder getDrawOrder() { return m_drawOrder; } + void setDrawOrder(DrawOrder drawOrder) { m_drawOrder = drawOrder; } + const Light& getLight() const { return m_light; } + void setLight(const Light& light) { m_light = light; } private: int getCurrentAnimationPhase(); @@ -99,7 +91,7 @@ class AttachedEffect : public LuaObject uint8_t m_speed{ 100 }; uint8_t m_opacity{ 100 }; uint8_t m_lastAnimation{ 0 }; - AttachedEffectDrawPlace m_drawPlace{ AttachedEffectDrawPlace::DEFAULT }; + DrawOrder m_drawOrder{ DrawOrder::FIRST }; uint16_t m_id{ 0 }; uint16_t m_duration{ 0 }; @@ -112,6 +104,7 @@ class AttachedEffect : public LuaObject bool m_disableWalkAnimation{ false }; Outfit m_outfitOwner; + Light m_light; uint16_t m_thingId{ 0 }; ThingCategory m_thingCategory{ ThingInvalidCategory }; diff --git a/src/client/luafunctions.cpp b/src/client/luafunctions.cpp index d44259d246..0556381b67 100644 --- a/src/client/luafunctions.cpp +++ b/src/client/luafunctions.cpp @@ -693,7 +693,8 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("canDrawOnUI", &AttachedEffect::canDrawOnUI); g_lua.bindClassMemberFunction("setCanDrawOnUI", &AttachedEffect::setCanDrawOnUI); g_lua.bindClassMemberFunction("attachEffect", &AttachedEffect::attachEffect); - g_lua.bindClassMemberFunction("setDrawPlace", &AttachedEffect::setDrawPlace); + g_lua.bindClassMemberFunction("setDrawOrder", &AttachedEffect::setDrawOrder); + g_lua.bindClassMemberFunction("setLight", &AttachedEffect::setLight); g_lua.registerClass(); g_lua.bindClassStaticFunction("create", [] { return std::make_shared(); }); From 1e2b76f574dda2ec42d03f38a29189099cdceca8 Mon Sep 17 00:00:00 2001 From: Joao Pasqualini Costa Date: Wed, 15 Nov 2023 09:25:24 -0300 Subject: [PATCH 4/8] Missing file --- src/client/tile.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/client/tile.cpp b/src/client/tile.cpp index 8bc7bd0c06..5716a29027 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -48,7 +48,6 @@ void Tile::draw(const Point& dest, const MapPosInfo& mapRect, int flags, bool is m_drawElevation = 0; m_lastDrawDest = dest; - drawAttachedEffect(dest, lightView, false, AttachedEffectDrawPlace::BEFORE_GROUND); for (const auto& thing : m_things) { if (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom()) break; @@ -56,7 +55,6 @@ void Tile::draw(const Point& dest, const MapPosInfo& mapRect, int flags, bool is drawThing(thing, dest, flags, lightView); } - drawAttachedEffect(dest, lightView, false, AttachedEffectDrawPlace::BEFORE_ITEM); if (hasCommonItem()) { for (auto it = m_things.rbegin(); it != m_things.rend(); ++it) { const auto& item = *it; @@ -65,18 +63,15 @@ void Tile::draw(const Point& dest, const MapPosInfo& mapRect, int flags, bool is } } - drawAttachedEffect(dest, lightView, false, AttachedEffectDrawPlace::BEFORE_CREATURE); // after we render 2x2 lying corpses, we must redraw previous creatures/ontop above them for (const auto& tile : m_tilesRedraw) { tile->drawCreature(tile->m_lastDrawDest, mapRect, flags, isCovered, true, lightView); tile->drawTop(tile->m_lastDrawDest, flags, true, lightView); } - drawCreature(dest, mapRect, flags, isCovered, false, lightView); - drawAttachedEffect(dest, lightView, false, AttachedEffectDrawPlace::BEFORE_EFFECTS); + drawCreature(dest, mapRect, flags, isCovered, false, lightView); drawTop(dest, flags, false, lightView); - - drawAttachedEffect(dest, lightView, false, AttachedEffectDrawPlace::DEFAULT); + drawAttachedEffect(dest, lightView, false); updateWidget(dest, mapRect); } From d8b6e676f788b437ea597063d6d5fcf61fd4cd0d Mon Sep 17 00:00:00 2001 From: Joao Pasqualini Costa Date: Wed, 15 Nov 2023 09:40:47 -0300 Subject: [PATCH 5/8] Fix typo --- modules/game_attachedeffects/lib.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/game_attachedeffects/lib.lua b/modules/game_attachedeffects/lib.lua index 661cde423d..93902d09f2 100644 --- a/modules/game_attachedeffects/lib.lua +++ b/modules/game_attachedeffects/lib.lua @@ -26,10 +26,10 @@ local executeConfig = function(attachedEffect, config) attachedEffect:setOpacity(config.opacity) end - if config.color then - attachedEffect:setColor({ - color = config.color.color or 0, - intensity = config.color.intensity or 0 + if config.light then + attachedEffect:setLight({ + color = config.light.color or 0, + intensity = config.light.intensity or 0 }) end From 3dfb62f81e4c1963a83c6e7438e35f0b1b13ea1b Mon Sep 17 00:00:00 2001 From: Joao Pasqualini Costa Date: Wed, 15 Nov 2023 10:09:46 -0300 Subject: [PATCH 6/8] Draw order option --- modules/game_attachedeffects/lib.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/game_attachedeffects/lib.lua b/modules/game_attachedeffects/lib.lua index 93902d09f2..049fd97730 100644 --- a/modules/game_attachedeffects/lib.lua +++ b/modules/game_attachedeffects/lib.lua @@ -33,6 +33,10 @@ local executeConfig = function(attachedEffect, config) }) end + if config.drawOrder then + attachedEffect:setDrawOrder(config.drawOrder) + end + if config.duration ~= nil and config.duration > 0 then attachedEffect:setDuration(config.duration) end From a98fbdc2261baef4edafe15eff4828b7afeb8dcd Mon Sep 17 00:00:00 2001 From: Joao Pasqualini Costa Date: Wed, 15 Nov 2023 16:40:48 -0300 Subject: [PATCH 7/8] fix: attached effect erasing when teleporting --- src/client/tile.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/tile.h b/src/client/tile.h index 343693ad93..c2c1395214 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -145,7 +145,7 @@ class Tile : public AttachableObject bool isSingleDimension() { return (m_thingTypeFlag & TileThingType::NOT_SINGLE_DIMENSION) == 0 && m_walkingCreatures.empty(); } bool isLookPossible() { return (m_thingTypeFlag & TileThingType::BLOCK_PROJECTTILE) == 0; } bool isEmpty() { return m_things.empty(); } - bool isDrawable() { return !isEmpty() || !m_walkingCreatures.empty() || !m_effects.empty(); } + bool isDrawable() { return !isEmpty() || !m_walkingCreatures.empty() || !m_effects.empty() || !m_attachedEffects.empty(); } bool isCovered(int8_t firstFloor); bool isCompletelyCovered(uint8_t firstFloor, bool resetCache); @@ -180,7 +180,7 @@ class Tile : public AttachableObject bool canRender(uint32_t& flags, const Position& cameraPosition, AwareRange viewPort); bool canErase() { - return m_walkingCreatures.empty() && m_effects.empty() && isEmpty() && m_minimapColor == 0 + return m_walkingCreatures.empty() && m_effects.empty() && isEmpty() && m_minimapColor == 0 && m_attachedEffects.empty() #ifdef FRAMEWORK_EDITOR && m_flags == 0 #endif From 63a35f6a13bab3c8fe8bceea68db9181620d9284 Mon Sep 17 00:00:00 2001 From: Joao Pasqualini Costa Date: Sat, 18 Nov 2023 12:42:20 -0300 Subject: [PATCH 8/8] Imrpove documentation --- modules/game_attachedeffects/attachedeffects.lua | 1 + modules/game_attachedeffects/effects.lua | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/game_attachedeffects/attachedeffects.lua b/modules/game_attachedeffects/attachedeffects.lua index eb81a0e4ef..a341910d34 100644 --- a/modules/game_attachedeffects/attachedeffects.lua +++ b/modules/game_attachedeffects/attachedeffects.lua @@ -5,6 +5,7 @@ controller = Controller:new() g_game.getLocalPlayer():attachEffect(g_attachedEffects.getById(1)) g_game.getLocalPlayer():attachEffect(g_attachedEffects.getById(2)) g_game.getLocalPlayer():attachEffect(g_attachedEffects.getById(3)) + g_game.getLocalPlayer():getTile():attachEffect(g_attachedEffects.getById(1)) end function controller:onGameEnd() diff --git a/modules/game_attachedeffects/effects.lua b/modules/game_attachedeffects/effects.lua index 64671016f5..ea6553e58e 100644 --- a/modules/game_attachedeffects/effects.lua +++ b/modules/game_attachedeffects/effects.lua @@ -4,6 +4,7 @@ speed, disableWalkAnimation, shader, drawOnUI, opacity duration, loop, transform, hideOwner, size{width, height} offset{x, y, onTop}, dirOffset[dir]{x, y, onTop}, + light { color, intensity}, drawOrder(only for tiles), onAttach, onDetach } ]] --