diff --git a/modules/game/thing.lua b/modules/game/thing.lua index 9f8c6162..cf9d2b2b 100644 --- a/modules/game/thing.lua +++ b/modules/game/thing.lua @@ -44,7 +44,7 @@ function Game.createThingMenu(menuPosition, lookThing, useThing, creatureThing) if creatureThing:asPlayer() then menu:addSeparator() menu:addOption('Message to ' .. creatureThing:getName(), function() print('message') end) - menu:addOption('Add to VIP list', function() print('vip') end) + menu:addOption('Add to VIP list', function() Game.addVip(creatureThing:getName()) end) menu:addOption('Ignore ' .. creatureThing:getName(), function() print('ignore') end) menu:addOption('Invite to Party', function() print('invite to party') end) end diff --git a/modules/game_viplist/viplist.lua b/modules/game_viplist/viplist.lua index 8f346bd0..7c6873dc 100644 --- a/modules/game_viplist/viplist.lua +++ b/modules/game_viplist/viplist.lua @@ -43,5 +43,16 @@ function Game.onVipStateChange(id, online) label.vipOnline = online end +function VipList.onVipListLabelMousePress(widget, mousePos, mouseButton) + if mouseButton ~= MouseRightButton then return end + + local vipList = vipWindow:getChildById('vipList') + + local menu = createWidget('PopupMenu') + menu:addOption('Remove from VIP list', function() if widget then Game.removeVip(widget:getId():sub(4)) vipList:removeChild(widget) end end) + menu:display(mousePos) +end + + connect(Game, { onLogin = VipList.create, onLogout = VipList.destroy }) diff --git a/modules/game_viplist/viplist.otui b/modules/game_viplist/viplist.otui index 567d8dcf..f4e2b8a2 100644 --- a/modules/game_viplist/viplist.otui +++ b/modules/game_viplist/viplist.otui @@ -1,6 +1,7 @@ VipListLabel < GameLabel font: verdana-11px-monochrome margin-left: 5 + &onMousePress: VipList.onVipListLabelMousePress MiniWindow id: vipWindow diff --git a/src/otclient/core/game.cpp b/src/otclient/core/game.cpp index 333ebc5f..23361fea 100644 --- a/src/otclient/core/game.cpp +++ b/src/otclient/core/game.cpp @@ -235,10 +235,32 @@ void Game::talkPrivate(int channelType, const std::string& receiver, const std:: void Game::openOutfitWindow() { + if(!m_online) + return; + m_protocolGame->sendGetOutfit(); } void Game::setOutfit(const Outfit& outfit) { + if(!m_online) + return; + m_protocolGame->sendSetOutfit(outfit); } + +void Game::addVip(const std::string& name) +{ + if(!m_online || name.empty()) + return; + + m_protocolGame->sendAddVip(name); +} + +void Game::removeVip(int playerId) +{ + if(!m_online) + return; + + m_protocolGame->sendRemoveVip(playerId); +} diff --git a/src/otclient/core/game.h b/src/otclient/core/game.h index 4e241c8a..189fdbce 100644 --- a/src/otclient/core/game.h +++ b/src/otclient/core/game.h @@ -57,6 +57,8 @@ public: void talkPrivate(int channelType, const std::string& receiver, const std::string& message); void openOutfitWindow(); void setOutfit(const Outfit& outfit); + void addVip(const std::string& name); + void removeVip(int playerId); int getThingStackpos(const ThingPtr& thing); bool isOnline() { return m_online; } diff --git a/src/otclient/core/tile.cpp b/src/otclient/core/tile.cpp index 2a26084b..c13a2470 100644 --- a/src/otclient/core/tile.cpp +++ b/src/otclient/core/tile.cpp @@ -288,6 +288,24 @@ bool Tile::isLookPossible() return true; } +bool Tile::isClickable() +{ + bool hasGround = false, hasOnBottom = false, hasIgnoreLook = false; + for(const ThingPtr& thing : m_things) { + ThingType *type = thing->getType(); + if(type->properties[ThingType::IsGround]) + hasGround = true; + if(type->properties[ThingType::IsOnBottom]) + hasOnBottom = true; + if(type->properties[ThingType::IgnoreLook]) + hasIgnoreLook = true; + + if((hasGround || hasOnBottom) && !hasIgnoreLook) + return true; + } + return false; +} + bool Tile::hasCreature() { for(const ThingPtr& thing : m_things) diff --git a/src/otclient/core/tile.h b/src/otclient/core/tile.h index f1c5d430..af482130 100644 --- a/src/otclient/core/tile.h +++ b/src/otclient/core/tile.h @@ -59,8 +59,7 @@ public: bool isLookPossible(); bool hasCreature(); bool isEmpty(); - - void useItem(); + bool isClickable(); TilePtr asTile() { return std::static_pointer_cast(shared_from_this()); } diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index 8aa3df15..7b260238 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -69,6 +69,8 @@ void OTClient::registerLuaFunctions() g_lua.bindClassStaticFunction("attack", std::bind(&Game::attack, &g_game, _1)); g_lua.bindClassStaticFunction("follow", std::bind(&Game::follow, &g_game, _1)); g_lua.bindClassStaticFunction("rotate", std::bind(&Game::rotate, &g_game, _1)); + g_lua.bindClassStaticFunction("addVip", std::bind(&Game::addVip, &g_game, _1)); + g_lua.bindClassStaticFunction("removeVip", std::bind(&Game::removeVip, &g_game, _1)); g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UIItem::create); diff --git a/src/otclient/net/protocolgame.h b/src/otclient/net/protocolgame.h index 669f1882..378fb702 100644 --- a/src/otclient/net/protocolgame.h +++ b/src/otclient/net/protocolgame.h @@ -96,7 +96,7 @@ public: void sendGetOutfit(); void sendSetOutfit(const Outfit& outfit); void sendAddVip(const std::string& name); - void sendRemoveVip(int id); + void sendRemoveVip(int playerId); void sendGetQuestLog(); void sendGetQuestLine(int questId); diff --git a/src/otclient/net/protocolgamesend.cpp b/src/otclient/net/protocolgamesend.cpp index 2e5a5726..a63cb3ca 100644 --- a/src/otclient/net/protocolgamesend.cpp +++ b/src/otclient/net/protocolgamesend.cpp @@ -555,11 +555,11 @@ void ProtocolGame::sendAddVip(const std::string& name) send(oMsg); } -void ProtocolGame::sendRemoveVip(int id) +void ProtocolGame::sendRemoveVip(int playerId) { OutputMessage oMsg; oMsg.addU8(Otc::ClientRemoveBuddy); - oMsg.addU32(id); + oMsg.addU32(playerId); send(oMsg); } diff --git a/src/otclient/ui/uimap.cpp b/src/otclient/ui/uimap.cpp index 09cfd8ce..7969c259 100644 --- a/src/otclient/ui/uimap.cpp +++ b/src/otclient/ui/uimap.cpp @@ -74,17 +74,19 @@ bool UIMap::onMousePress(const Point& mousePos, Fw::MouseButton button) // Get tile TilePtr tile = nullptr; - // We must check every floor, from top to bottom + // We must check every floor, from top to bottom to check for a clickable tile int firstFloor = g_map.getFirstVisibleFloor(); tilePos.perspectiveUp(tilePos.z - firstFloor); for(int i = firstFloor; i <= Map::MAX_Z; i++) { tile = g_map.getTile(tilePos); - if(tile && !tile->isEmpty() && tile->getGround()) + if(tile && tile->isClickable()) break; tilePos.coveredDown(); } - if(!tile || tile->isEmpty()) + // todo: get creature, using walkOffset etc. + + if(!tile || !tile->isClickable()) return true; if(button == Fw::MouseLeftButton) {