diff --git a/CMakeLists.txt b/CMakeLists.txt index f37d01bd..294890df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,7 @@ SET(SOURCES src/framework/ui/uiframecounter.cpp # otclient ui src/otclient/ui/uiitem.cpp + src/otclient/ui/uicreature.cpp src/otclient/ui/uimap.cpp # otclient net diff --git a/modules/core_styles/core_styles.otmod b/modules/core_styles/core_styles.otmod index 57fcf37c..38823be7 100644 --- a/modules/core_styles/core_styles.otmod +++ b/modules/core_styles/core_styles.otmod @@ -14,5 +14,6 @@ Module importStyles 'styles/windows.otui' importStyles 'styles/listboxes.otui' importStyles 'styles/items.otui' + importStyles 'styles/creatures.otui' return true diff --git a/modules/core_styles/styles/creatures.otui b/modules/core_styles/styles/creatures.otui new file mode 100644 index 00000000..d03a18da --- /dev/null +++ b/modules/core_styles/styles/creatures.otui @@ -0,0 +1,6 @@ +Creature < UICreature + size: 66 66 + creature-margin: 1 + border-image: + source: /core_styles/images/panel_flat.png + border: 1 diff --git a/modules/otclient/otclient.otmod b/modules/otclient/otclient.otmod index 1ffe3485..c5425b89 100644 --- a/modules/otclient/otclient.otmod +++ b/modules/otclient/otclient.otmod @@ -14,4 +14,5 @@ Module - viplist - textmessage - chat + - outfit diff --git a/modules/outfit/outfit.lua b/modules/outfit/outfit.lua new file mode 100644 index 00000000..da65e3cb --- /dev/null +++ b/modules/outfit/outfit.lua @@ -0,0 +1,41 @@ +Outfit = {} + +-- private variables +local window = nil + +-- public functions +function Outfit.test() + local button = UIButton.create() + UI.root:addChild(button) + button:setText('Set Outfit') + button:setStyle('Button') + button:moveTo({x = 0, y = 100}) + button:setWidth('100') + button:setHeight('30') + button.onClick = function() Game.openOutfitWindow() end +end + +function Outfit.create(creature, outfitList) + if window ~= nil then + Outfit.destroy() + end + + window = loadUI("/outfit/outfit.otui", UI.root) + + local creatureWidget = window:getChildById('creature') + creatureWidget:setCreature(creature) +end + +function Outfit.destroy() + window:destroy() + window = nil +end + +-- private functions + +-- hooked events + +connect(Game, { onOpenOutfitWindow = Outfit.create, + onLogout = Outfit.destroy }) + +connect(Game, { onLogin = Outfit.test }) diff --git a/modules/outfit/outfit.otmod b/modules/outfit/outfit.otmod new file mode 100644 index 00000000..e43042e5 --- /dev/null +++ b/modules/outfit/outfit.otmod @@ -0,0 +1,10 @@ +Module + name: outfit + description: Change local player outfit + author: OTClient team + website: https://github.com/edubart/otclient + onLoad: | + require 'outfit' + return true + + diff --git a/modules/outfit/outfit.otui b/modules/outfit/outfit.otui new file mode 100644 index 00000000..118dc097 --- /dev/null +++ b/modules/outfit/outfit.otui @@ -0,0 +1,40 @@ +Window + title: Select Outfit + + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + + Creature + id: creature + anchors.top: parent.top + anchors.left: parent.left + margin.top: 30 + margin.left: 20 + + HorizontalSeparator + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: next.top + margin.left: 16 + margin.right: 16 + margin.bottom: 10 + + Button + id: buttonOk + text: Ok + width: 64 + anchors.right: next.left + anchors.bottom: parent.bottom + margin.bottom: 16 + margin.right: 16 + onClick: Outfit.accept() + + Button + id: buttonCancel + text: Cancel + width: 64 + anchors.right: parent.right + anchors.bottom: parent.bottom + margin.bottom: 16 + margin.right: 16 + onClick: Outfit.destroy() diff --git a/src/otclient/core/game.cpp b/src/otclient/core/game.cpp index dbcd8559..a27205d6 100644 --- a/src/otclient/core/game.cpp +++ b/src/otclient/core/game.cpp @@ -179,3 +179,8 @@ void Game::talkPrivate(int channelType, const std::string& receiver, const std:: m_protocolGame->sendTalk(channelType, 0, receiver, message); } + +void Game::openOutfitWindow() +{ + m_protocolGame->sendGetOutfit(); +} diff --git a/src/otclient/core/game.h b/src/otclient/core/game.h index c0f6ae25..9565f674 100644 --- a/src/otclient/core/game.h +++ b/src/otclient/core/game.h @@ -52,6 +52,7 @@ public: void turn(Otc::Direction direction); void talkChannel(int channelType, int channelId, const std::string& message); void talkPrivate(int channelType, const std::string& receiver, const std::string& message); + void openOutfitWindow(); bool isOnline() { return m_online; } diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index bacad4bf..814d53a4 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -50,6 +50,10 @@ public: virtual const ThingType& getType() = 0; int getAnimationPhases() { return getType().dimensions[ThingType::AnimationPhases]; } + void setXPattern(int xPattern) { m_xPattern = xPattern; } + void setYPattern(int yPattern) { m_yPattern = yPattern; } + void setZPattern(int zPattern) { m_zPattern = zPattern; } + ThingPtr asThing() { return std::static_pointer_cast(shared_from_this()); } virtual ItemPtr asItem() { return nullptr; } virtual CreaturePtr asCreature() { return nullptr; } diff --git a/src/otclient/net/protocolgame.h b/src/otclient/net/protocolgame.h index e222563a..27d67614 100644 --- a/src/otclient/net/protocolgame.h +++ b/src/otclient/net/protocolgame.h @@ -56,6 +56,7 @@ public: void sendTurnWest(); void sendUseItem(const Position& position, int itemId, int stackpos, int index); void sendTalk(int channelType, int channelId, const std::string& receiver, const std::string& message); + void sendGetOutfit(); void sendAddVip(const std::string& name); void sendRemoveVip(int id); diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index dd75f6c4..5eb18b5d 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -838,14 +838,27 @@ void ProtocolGame::parseFloorChangeDown(InputMessage& msg) void ProtocolGame::parseOutfitWindow(InputMessage& msg) { - internalGetOutfit(msg); - uint8 outfitCount = msg.getU8(); + Outfit outfit = internalGetOutfit(msg); + typedef std::tuple OutfitInfo; + std::vector outfitList; + + uint8 outfitCount = msg.getU8(); for(int i = 0; i < outfitCount; i++) { - msg.getU16(); // outfit id - msg.getString(); // outfit name - msg.getU8(); // addons + uint16 outfitId = msg.getU16(); + std::string outfitName = msg.getString(); + uint8 outfitAddons = msg.getU8(); + + outfitList.push_back(OutfitInfo(outfitId, outfitName, outfitAddons)); } + + CreaturePtr creature = CreaturePtr(new Creature); + creature->setXPattern(2); + creature->setOutfit(outfit); + + g_dispatcher.addEvent([=] { + g_lua.callGlobalField("Game", "onOpenOutfitWindow", creature, outfitList); + }); } void ProtocolGame::parseVipState(InputMessage& msg) diff --git a/src/otclient/net/protocolgamesend.cpp b/src/otclient/net/protocolgamesend.cpp index c4122f9f..55e14a7e 100644 --- a/src/otclient/net/protocolgamesend.cpp +++ b/src/otclient/net/protocolgamesend.cpp @@ -195,6 +195,13 @@ void ProtocolGame::sendTalk(int channelType, int channelId, const std::string& r send(oMsg); } +void ProtocolGame::sendGetOutfit() +{ + OutputMessage oMsg; + oMsg.addU8(Otc::ClientGetOutfit); + send(oMsg); +} + void ProtocolGame::sendAddVip(const std::string& name) { OutputMessage oMsg; diff --git a/src/otclient/otclientluafunctions.cpp b/src/otclient/otclientluafunctions.cpp index 515a6904..2cd4e4d2 100644 --- a/src/otclient/otclientluafunctions.cpp +++ b/src/otclient/otclientluafunctions.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include void OTClient::registerLuaFunctions() @@ -65,12 +66,18 @@ void OTClient::registerLuaFunctions() g_lua.bindClassStaticFunction("cancelLogin", std::bind(&Game::cancelLogin, &g_game)); g_lua.bindClassStaticFunction("isOnline", std::bind(&Game::isOnline, &g_game)); g_lua.bindClassStaticFunction("isOnline", std::bind(&Game::isOnline, &g_game)); + g_lua.bindClassStaticFunction("openOutfitWindow", std::bind(&Game::openOutfitWindow, &g_game)); g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UIItem::create); g_lua.bindClassMemberFunction("getItem", &UIItem::getItem); g_lua.bindClassMemberFunction("setItem", &UIItem::setItem); + g_lua.registerClass(); + g_lua.bindClassStaticFunction("create", &UICreature::create); + g_lua.bindClassMemberFunction("getCreature", &UICreature::getCreature); + g_lua.bindClassMemberFunction("setCreature", &UICreature::setCreature); + g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UIWidget::create); diff --git a/src/otclient/ui/uicreature.cpp b/src/otclient/ui/uicreature.cpp new file mode 100644 index 00000000..c1760414 --- /dev/null +++ b/src/otclient/ui/uicreature.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010-2011 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 "uicreature.h" +#include +#include + +void UICreature::setup() +{ + UIWidget::setup(); +} + +void UICreature::render() +{ + renderSelf(); + + if(m_creature) { + g_graphics.bindColor(Fw::white); + m_creature->draw(m_rect.bottomRight() - Point(32, 32) + m_creatureMargin); + } + + renderChildren(); +} + +void UICreature::onStyleApply(const OTMLNodePtr& styleNode) +{ + for(OTMLNodePtr node : styleNode->children()) { + if(node->tag() == "creature-margin") + m_creatureMargin = node->value(); + } + + UIWidget::onStyleApply(styleNode); +} diff --git a/src/otclient/ui/uicreature.h b/src/otclient/ui/uicreature.h new file mode 100644 index 00000000..de4bf43a --- /dev/null +++ b/src/otclient/ui/uicreature.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010-2011 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. + */ + +#ifndef UICREATURE_H +#define UICREATURE_H + +#include "declarations.h" +#include +#include + +class UICreature : public UIWidget +{ +public: + void setup(); + void render(); + + void setCreature(const CreaturePtr& creature) { m_creature = creature; } + CreaturePtr getCreature() { return m_creature; } + +protected: + virtual void onStyleApply(const OTMLNodePtr& styleNode); + +private: + CreaturePtr m_creature; + int m_creatureMargin; +}; + +#endif