Browse field, locked & paginated container support
This commit is contained in:
		
							parent
							
								
									32d1ed5c6a
								
							
						
					
					
						commit
						2a57a5f7d0
					
				|  | @ -1,3 +1,8 @@ | |||
| PageButton < Button | ||||
|   size: 30 18 | ||||
|   margin: 1 | ||||
| 
 | ||||
| 
 | ||||
| ContainerWindow < MiniWindow | ||||
|   height: 150 | ||||
| 
 | ||||
|  | @ -25,6 +30,35 @@ ContainerWindow < MiniWindow | |||
|     $pressed: | ||||
|       image-clip: 42 28 14 14 | ||||
| 
 | ||||
|   Panel | ||||
|     id: pagePanel | ||||
|     anchors.left: parent.left | ||||
|     anchors.right: parent.right | ||||
|     anchors.top: miniwindowTopBar.bottom | ||||
|     height: 20 | ||||
|     margin: 2 3 0 3 | ||||
|     background: #00000066 | ||||
|     visible: false | ||||
| 
 | ||||
|     Label | ||||
|       id: pageLabel | ||||
|       anchors.top: parent.top | ||||
|       anchors.horizontalCenter: parent.horizontalCenter | ||||
|       margin-top: 2 | ||||
|       text-auto-resize: true | ||||
| 
 | ||||
|     PageButton | ||||
|       id: prevPageButton | ||||
|       text: < | ||||
|       anchors.top: parent.top | ||||
|       anchors.left: parent.left | ||||
| 
 | ||||
|     PageButton | ||||
|       id: nextPageButton | ||||
|       text: > | ||||
|       anchors.top: parent.top | ||||
|       anchors.right: parent.right | ||||
| 
 | ||||
|   MiniWindowContents | ||||
|     padding-right: 0 | ||||
|     layout: | ||||
|  |  | |||
|  | @ -3,9 +3,8 @@ function init() | |||
| 
 | ||||
|   connect(Container, { onOpen = onContainerOpen, | ||||
|                        onClose = onContainerClose, | ||||
|                        onAddItem = onContainerAddItem, | ||||
|                        onUpdateItem = onContainerUpdateItem, | ||||
|                        onRemoveItem = onContainerRemoveItem }) | ||||
|                        onSizeChange = onContainerChangeSize, | ||||
|                        onUpdateItem = onContainerUpdateItem }) | ||||
|   connect(Game, { onGameEnd = clean() }) | ||||
| 
 | ||||
|   reloadContainers() | ||||
|  | @ -14,9 +13,8 @@ end | |||
| function terminate() | ||||
|   disconnect(Container, { onOpen = onContainerOpen, | ||||
|                           onClose = onContainerClose, | ||||
|                           onAddItem = onContainerAddItem, | ||||
|                           onUpdateItem = onContainerUpdateItem, | ||||
|                           onRemoveItem = onContainerRemoveItem }) | ||||
|                           onSizeChange = onContainerChangeSize, | ||||
|                           onUpdateItem = onContainerUpdateItem }) | ||||
|   disconnect(Game, { onGameEnd = clean() }) | ||||
| end | ||||
| 
 | ||||
|  | @ -46,6 +44,38 @@ function refreshContainerItems(container) | |||
|     local itemWidget = container.itemsPanel:getChildById('item' .. slot) | ||||
|     itemWidget:setItem(container:getItem(slot)) | ||||
|   end | ||||
| 
 | ||||
|   if container:hasPages() then | ||||
|     refreshContainerPages(container) | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| function toggleContainerPages(containerWindow, pages) | ||||
|   containerWindow:getChildById('miniwindowScrollBar'):setMarginTop(pages and 42 or 22) | ||||
|   containerWindow:getChildById('contentsPanel'):setMarginTop(pages and 42 or 22) | ||||
|   containerWindow:getChildById('pagePanel'):setVisible(pages) | ||||
| end | ||||
| 
 | ||||
| function refreshContainerPages(container) | ||||
|   local currentPage = 1 + math.floor(container:getFirstIndex() / container:getCapacity()) | ||||
|   local pages = 1 + math.floor(math.max(0, (container:getSize() - 1)) / container:getCapacity()) | ||||
|   container.window:recursiveGetChildById('pageLabel'):setText(string.format('Page %i of %i', currentPage, pages)) | ||||
| 
 | ||||
|   local prevPageButton = container.window:recursiveGetChildById('prevPageButton') | ||||
|   if currentPage == 1 then | ||||
|     prevPageButton:setEnabled(false) | ||||
|   else | ||||
|     prevPageButton:setEnabled(true) | ||||
|     prevPageButton.onClick = function() g_game.seekInContainer(container:getId(), container:getFirstIndex() - container:getCapacity()) end | ||||
|   end | ||||
| 
 | ||||
|   local nextPageButton = container.window:recursiveGetChildById('nextPageButton') | ||||
|   if currentPage >= pages then | ||||
|     nextPageButton:setEnabled(false) | ||||
|   else | ||||
|     nextPageButton:setEnabled(true) | ||||
|     nextPageButton.onClick = function() g_game.seekInContainer(container:getId(), container:getFirstIndex() + container:getCapacity()) end | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| function onContainerOpen(container, previousContainer) | ||||
|  | @ -88,11 +118,18 @@ function onContainerOpen(container, previousContainer) | |||
|     itemWidget:setItem(container:getItem(slot)) | ||||
|     itemWidget:setMargin(0) | ||||
|     itemWidget.position = container:getSlotPosition(slot) | ||||
| 
 | ||||
|     if not container:isUnlocked() then | ||||
|       itemWidget:setBorderColor('red') | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   container.window = containerWindow | ||||
|   container.itemsPanel = containerPanel | ||||
| 
 | ||||
|   toggleContainerPages(containerWindow, container:hasPages()) | ||||
|   refreshContainerPages(container) | ||||
| 
 | ||||
|   local layout = containerPanel:getLayout() | ||||
|   local cellSize = layout:getCellSize() | ||||
|   containerWindow:setContentMinimumHeight(cellSize.height) | ||||
|  | @ -110,7 +147,7 @@ function onContainerClose(container) | |||
|   destroy(container) | ||||
| end | ||||
| 
 | ||||
| function onContainerAddItem(container, slot, item) | ||||
| function onContainerChangeSize(container, size) | ||||
|   if not container.window then return end | ||||
|   refreshContainerItems(container) | ||||
| end | ||||
|  | @ -120,8 +157,3 @@ function onContainerUpdateItem(container, slot, item, oldItem) | |||
|   local itemWidget = container.itemsPanel:getChildById('item' .. slot) | ||||
|   itemWidget:setItem(item) | ||||
| end | ||||
| 
 | ||||
| function onContainerRemoveItem(container, slot, item) | ||||
|   if not container.window then return end | ||||
|   refreshContainerItems(container) | ||||
| end | ||||
|  |  | |||
|  | @ -467,6 +467,10 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing) | |||
|     if useThing:isRotateable() then | ||||
|       menu:addOption(tr('Rotate'), function() g_game.rotate(useThing) end) | ||||
|     end | ||||
| 
 | ||||
|     if g_game.getFeature(GameBrowseField) and useThing:getPosition().x ~= 0xffff then | ||||
|       menu:addOption(tr('Browse Field'), function() g_game.browseField(useThing:getPosition()) end) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   if lookThing and not lookThing:isCreature() and not lookThing:isNotMoveable() and lookThing:isPickupable() then | ||||
|  |  | |||
|  | @ -117,6 +117,8 @@ GamePVPMode = 50 | |||
| GameWritableDate = 51 | ||||
| GameAdditionalVipInfo = 52 | ||||
| GameSpritesAlphaChannel = 56 | ||||
| GamePremiumExpiration = 57 | ||||
| GameBrowseField = 58 | ||||
| 
 | ||||
| TextColors = { | ||||
|   red       = '#f55e5e', --'#c83200' | ||||
|  |  | |||
|  | @ -389,6 +389,7 @@ namespace Otc | |||
|         GameHideNpcNames = 55, | ||||
|         GameSpritesAlphaChannel = 56, | ||||
|         GamePremiumExpiration = 57, | ||||
|         GameBrowseField = 58, | ||||
| 
 | ||||
|         LastGameFeature = 101 | ||||
|     }; | ||||
|  |  | |||
|  | @ -57,9 +57,22 @@ void Container::onClose() | |||
| 
 | ||||
| void Container::onAddItem(const ItemPtr& item, int slot) | ||||
| { | ||||
|     m_items.push_front(item); | ||||
|     slot -= m_firstIndex; | ||||
| 
 | ||||
|     m_size++; | ||||
|     // indicates that there is a new item on next page
 | ||||
|     if(m_hasPages && slot > m_capacity) { | ||||
|         callLuaField("onSizeChange", m_size); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if(slot == 0) | ||||
|         m_items.push_front(item); | ||||
|     else | ||||
|         m_items.push_back(item); | ||||
|     updateItemsPositions(); | ||||
| 
 | ||||
|     callLuaField("onSizeChange", m_size); | ||||
|     callLuaField("onAddItem", slot, item); | ||||
| } | ||||
| 
 | ||||
|  | @ -80,6 +93,7 @@ void Container::onAddItems(const std::vector<ItemPtr>& items) | |||
| 
 | ||||
| void Container::onUpdateItem(int slot, const ItemPtr& item) | ||||
| { | ||||
|     slot -= m_firstIndex; | ||||
|     if(slot < 0 || slot >= (int)m_items.size()) { | ||||
|         g_logger.traceError("slot not found"); | ||||
|         return; | ||||
|  | @ -92,8 +106,15 @@ void Container::onUpdateItem(int slot, const ItemPtr& item) | |||
|     callLuaField("onUpdateItem", slot, item, oldItem); | ||||
| } | ||||
| 
 | ||||
| void Container::onRemoveItem(int slot) | ||||
| void Container::onRemoveItem(int slot, const ItemPtr& lastItem) | ||||
| { | ||||
|     slot -= m_firstIndex; | ||||
|     if(m_hasPages && slot >= (int)m_items.size()) { | ||||
|         m_size--; | ||||
|         callLuaField("onSizeChange", m_size); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if(slot < 0 || slot >= (int)m_items.size()) { | ||||
|         g_logger.traceError("slot not found"); | ||||
|         return; | ||||
|  | @ -102,8 +123,16 @@ void Container::onRemoveItem(int slot) | |||
|     ItemPtr item = m_items[slot]; | ||||
|     m_items.erase(m_items.begin() + slot); | ||||
| 
 | ||||
| 
 | ||||
|     if(lastItem) { | ||||
|         onAddItem(lastItem, m_firstIndex + m_capacity - 1); | ||||
|         m_size--; | ||||
|     } | ||||
|     m_size--; | ||||
| 
 | ||||
|     updateItemsPositions(); | ||||
| 
 | ||||
|     callLuaField("onSizeChange", m_size); | ||||
|     callLuaField("onRemoveItem", slot, item); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ protected: | |||
|     void onAddItem(const ItemPtr& item, int slot); | ||||
|     void onAddItems(const std::vector<ItemPtr>& items); | ||||
|     void onUpdateItem(int slot, const ItemPtr& item); | ||||
|     void onRemoveItem(int slot); | ||||
|     void onRemoveItem(int slot, const ItemPtr& lastItem); | ||||
| 
 | ||||
|     friend class Game; | ||||
| 
 | ||||
|  |  | |||
|  | @ -308,7 +308,9 @@ void Game::processCloseContainer(int containerId) | |||
| { | ||||
|     ContainerPtr container = getContainer(containerId); | ||||
|     if(!container) { | ||||
|         g_logger.traceError("container not found"); | ||||
|         /* happens if you close and restart client with container opened
 | ||||
|          * g_logger.traceError("container not found"); | ||||
|          */ | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -338,7 +340,7 @@ void Game::processContainerUpdateItem(int containerId, int slot, const ItemPtr& | |||
|     container->onUpdateItem(slot, item); | ||||
| } | ||||
| 
 | ||||
| void Game::processContainerRemoveItem(int containerId, int slot) | ||||
| void Game::processContainerRemoveItem(int containerId, int slot, const ItemPtr& lastItem) | ||||
| { | ||||
|     ContainerPtr container = getContainer(containerId); | ||||
|     if(!container) { | ||||
|  | @ -346,7 +348,7 @@ void Game::processContainerRemoveItem(int containerId, int slot) | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     container->onRemoveItem(slot); | ||||
|     container->onRemoveItem(slot, lastItem); | ||||
| } | ||||
| 
 | ||||
| void Game::processInventoryChange(int slot, const ItemPtr& item) | ||||
|  | @ -1404,6 +1406,20 @@ void Game::answerModalDialog(int dialog, int button, int choice) | |||
|     m_protocolGame->sendAnswerModalDialog(dialog, button, choice); | ||||
| } | ||||
| 
 | ||||
| void Game::browseField(const Position& position) | ||||
| { | ||||
|     if(!canPerformGameAction()) | ||||
|         return; | ||||
|     m_protocolGame->sendBrowseField(position); | ||||
| } | ||||
| 
 | ||||
| void Game::seekInContainer(int cid, int index) | ||||
| { | ||||
|     if(!canPerformGameAction()) | ||||
|         return; | ||||
|     m_protocolGame->sendSeekInContainer(cid, index); | ||||
| } | ||||
| 
 | ||||
| void Game::ping() | ||||
| { | ||||
|     if(!m_protocolGame || !m_protocolGame->isConnected()) | ||||
|  | @ -1558,6 +1574,10 @@ void Game::setProtocolVersion(int version) | |||
|         enableFeature(Otc::GameThingMarks); | ||||
|     } | ||||
| 
 | ||||
|     if(version >= 984) { | ||||
|         enableFeature(Otc::GameBrowseField); | ||||
|     } | ||||
| 
 | ||||
|     if(version >= 1000) { | ||||
|         enableFeature(Otc::GamePVPMode); | ||||
|     } | ||||
|  |  | |||
|  | @ -85,7 +85,7 @@ protected: | |||
|     void processCloseContainer(int containerId); | ||||
|     void processContainerAddItem(int containerId, const ItemPtr& item, int slot); | ||||
|     void processContainerUpdateItem(int containerId, int slot, const ItemPtr& item); | ||||
|     void processContainerRemoveItem(int containerId, int slot); | ||||
|     void processContainerRemoveItem(int containerId, int slot, const ItemPtr& lastItem); | ||||
| 
 | ||||
|     // channel related
 | ||||
|     void processChannelList(const std::vector<std::tuple<int, std::string> >& channelList); | ||||
|  | @ -258,6 +258,10 @@ public: | |||
|     // >= 970 modal dialog
 | ||||
|     void answerModalDialog(int dialog, int button, int choice); | ||||
| 
 | ||||
|     // >= 984 browse field
 | ||||
|     void browseField(const Position& position); | ||||
|     void seekInContainer(int cid, int index); | ||||
| 
 | ||||
|     //void reportRuleViolation2();
 | ||||
|     void ping(); | ||||
|     void setPingDelay(int delay) { m_pingDelay = delay; } | ||||
|  |  | |||
|  | @ -295,6 +295,8 @@ void Client::registerLuaFunctions() | |||
|     g_lua.bindSingletonFunction("g_game", "disableFeature", &Game::disableFeature, &g_game); | ||||
|     g_lua.bindSingletonFunction("g_game", "isGM", &Game::isGM, &g_game); | ||||
|     g_lua.bindSingletonFunction("g_game", "answerModalDialog", &Game::answerModalDialog, &g_game); | ||||
|     g_lua.bindSingletonFunction("g_game", "browseField", &Game::browseField, &g_game); | ||||
|     g_lua.bindSingletonFunction("g_game", "seekInContainer", &Game::seekInContainer, &g_game); | ||||
|     g_lua.bindSingletonFunction("g_game", "getLastWalkDir", &Game::getLastWalkDir, &g_game); | ||||
| 
 | ||||
|     g_lua.registerSingletonClass("g_shaders"); | ||||
|  |  | |||
|  | @ -228,6 +228,8 @@ namespace Proto { | |||
|         ClientCancelAttackAndFollow         = 190, | ||||
|         ClientUpdateTile                    = 201, | ||||
|         ClientRefreshContainer              = 202, | ||||
|         ClientBrowseField                   = 203, | ||||
|         ClientSeekInContainer               = 204, | ||||
|         ClientRequestOutfit                 = 210, | ||||
|         ClientChangeOutfit                  = 211, | ||||
|         ClientMount                         = 212, // 870
 | ||||
|  |  | |||
|  | @ -111,6 +111,8 @@ public: | |||
|     void sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation); | ||||
|     void sendRequestItemInfo(int itemId, int subType, int index); | ||||
|     void sendAnswerModalDialog(int dialog, int button, int choice); | ||||
|     void sendBrowseField(const Position& position); | ||||
|     void sendSeekInContainer(int cid, int index); | ||||
| 
 | ||||
|     // otclient only
 | ||||
|     void sendChangeMapAwareRange(int xrange, int yrange); | ||||
|  |  | |||
|  | @ -686,16 +686,17 @@ void ProtocolGame::parseContainerRemoveItem(const InputMessagePtr& msg) | |||
| { | ||||
|     int containerId = msg->getU8(); | ||||
|     int slot; | ||||
|     ItemPtr lastItem; | ||||
|     if(g_game.getFeature(Otc::GameContainerPagination)) { | ||||
|         slot = msg->getU16(); | ||||
| 
 | ||||
|         int itemId = msg->getU16(); | ||||
|         if(itemId != 0) | ||||
|             getItem(msg, itemId); | ||||
|             lastItem = getItem(msg, itemId); | ||||
|     } else { | ||||
|         slot = msg->getU8(); | ||||
|     } | ||||
|     g_game.processContainerRemoveItem(containerId, slot); | ||||
|     g_game.processContainerRemoveItem(containerId, slot, lastItem); | ||||
| } | ||||
| 
 | ||||
| void ProtocolGame::parseAddInventoryItem(const InputMessagePtr& msg) | ||||
|  |  | |||
|  | @ -831,6 +831,29 @@ void ProtocolGame::sendAnswerModalDialog(int dialog, int button, int choice) | |||
|     send(msg); | ||||
| } | ||||
| 
 | ||||
| void ProtocolGame::sendBrowseField(const Position& position) | ||||
| { | ||||
|     if(!g_game.getFeature(Otc::GameBrowseField)) | ||||
|         return; | ||||
| 
 | ||||
|     OutputMessagePtr msg(new OutputMessage); | ||||
|     msg->addU8(Proto::ClientBrowseField); | ||||
|     addPosition(msg, position); | ||||
|     send(msg); | ||||
| } | ||||
| 
 | ||||
| void ProtocolGame::sendSeekInContainer(int cid, int index) | ||||
| { | ||||
|     if(!g_game.getFeature(Otc::GameContainerPagination)) | ||||
|         return; | ||||
| 
 | ||||
|     OutputMessagePtr msg(new OutputMessage); | ||||
|     msg->addU8(Proto::ClientSeekInContainer); | ||||
|     msg->addU8(cid); | ||||
|     msg->addU16(index); | ||||
|     send(msg); | ||||
| } | ||||
| 
 | ||||
| void ProtocolGame::sendChangeMapAwareRange(int xrange, int yrange) | ||||
| { | ||||
|     if(!g_game.getFeature(Otc::GameChangeMapAwareRange)) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Sam
						Sam