Browse field, locked & paginated container support

This commit is contained in:
Sam 2014-07-15 23:19:08 +02:00
parent 32d1ed5c6a
commit 2a57a5f7d0
14 changed files with 177 additions and 21 deletions

View File

@ -1,3 +1,8 @@
PageButton < Button
size: 30 18
margin: 1
ContainerWindow < MiniWindow ContainerWindow < MiniWindow
height: 150 height: 150
@ -25,6 +30,35 @@ ContainerWindow < MiniWindow
$pressed: $pressed:
image-clip: 42 28 14 14 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 MiniWindowContents
padding-right: 0 padding-right: 0
layout: layout:

View File

@ -3,9 +3,8 @@ function init()
connect(Container, { onOpen = onContainerOpen, connect(Container, { onOpen = onContainerOpen,
onClose = onContainerClose, onClose = onContainerClose,
onAddItem = onContainerAddItem, onSizeChange = onContainerChangeSize,
onUpdateItem = onContainerUpdateItem, onUpdateItem = onContainerUpdateItem })
onRemoveItem = onContainerRemoveItem })
connect(Game, { onGameEnd = clean() }) connect(Game, { onGameEnd = clean() })
reloadContainers() reloadContainers()
@ -14,9 +13,8 @@ end
function terminate() function terminate()
disconnect(Container, { onOpen = onContainerOpen, disconnect(Container, { onOpen = onContainerOpen,
onClose = onContainerClose, onClose = onContainerClose,
onAddItem = onContainerAddItem, onSizeChange = onContainerChangeSize,
onUpdateItem = onContainerUpdateItem, onUpdateItem = onContainerUpdateItem })
onRemoveItem = onContainerRemoveItem })
disconnect(Game, { onGameEnd = clean() }) disconnect(Game, { onGameEnd = clean() })
end end
@ -46,6 +44,38 @@ function refreshContainerItems(container)
local itemWidget = container.itemsPanel:getChildById('item' .. slot) local itemWidget = container.itemsPanel:getChildById('item' .. slot)
itemWidget:setItem(container:getItem(slot)) itemWidget:setItem(container:getItem(slot))
end 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 end
function onContainerOpen(container, previousContainer) function onContainerOpen(container, previousContainer)
@ -88,11 +118,18 @@ function onContainerOpen(container, previousContainer)
itemWidget:setItem(container:getItem(slot)) itemWidget:setItem(container:getItem(slot))
itemWidget:setMargin(0) itemWidget:setMargin(0)
itemWidget.position = container:getSlotPosition(slot) itemWidget.position = container:getSlotPosition(slot)
if not container:isUnlocked() then
itemWidget:setBorderColor('red')
end
end end
container.window = containerWindow container.window = containerWindow
container.itemsPanel = containerPanel container.itemsPanel = containerPanel
toggleContainerPages(containerWindow, container:hasPages())
refreshContainerPages(container)
local layout = containerPanel:getLayout() local layout = containerPanel:getLayout()
local cellSize = layout:getCellSize() local cellSize = layout:getCellSize()
containerWindow:setContentMinimumHeight(cellSize.height) containerWindow:setContentMinimumHeight(cellSize.height)
@ -110,7 +147,7 @@ function onContainerClose(container)
destroy(container) destroy(container)
end end
function onContainerAddItem(container, slot, item) function onContainerChangeSize(container, size)
if not container.window then return end if not container.window then return end
refreshContainerItems(container) refreshContainerItems(container)
end end
@ -120,8 +157,3 @@ function onContainerUpdateItem(container, slot, item, oldItem)
local itemWidget = container.itemsPanel:getChildById('item' .. slot) local itemWidget = container.itemsPanel:getChildById('item' .. slot)
itemWidget:setItem(item) itemWidget:setItem(item)
end end
function onContainerRemoveItem(container, slot, item)
if not container.window then return end
refreshContainerItems(container)
end

View File

@ -467,6 +467,10 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
if useThing:isRotateable() then if useThing:isRotateable() then
menu:addOption(tr('Rotate'), function() g_game.rotate(useThing) end) menu:addOption(tr('Rotate'), function() g_game.rotate(useThing) end)
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 end
if lookThing and not lookThing:isCreature() and not lookThing:isNotMoveable() and lookThing:isPickupable() then if lookThing and not lookThing:isCreature() and not lookThing:isNotMoveable() and lookThing:isPickupable() then

View File

@ -117,6 +117,8 @@ GamePVPMode = 50
GameWritableDate = 51 GameWritableDate = 51
GameAdditionalVipInfo = 52 GameAdditionalVipInfo = 52
GameSpritesAlphaChannel = 56 GameSpritesAlphaChannel = 56
GamePremiumExpiration = 57
GameBrowseField = 58
TextColors = { TextColors = {
red = '#f55e5e', --'#c83200' red = '#f55e5e', --'#c83200'

View File

@ -389,6 +389,7 @@ namespace Otc
GameHideNpcNames = 55, GameHideNpcNames = 55,
GameSpritesAlphaChannel = 56, GameSpritesAlphaChannel = 56,
GamePremiumExpiration = 57, GamePremiumExpiration = 57,
GameBrowseField = 58,
LastGameFeature = 101 LastGameFeature = 101
}; };

View File

@ -57,9 +57,22 @@ void Container::onClose()
void Container::onAddItem(const ItemPtr& item, int slot) 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(); updateItemsPositions();
callLuaField("onSizeChange", m_size);
callLuaField("onAddItem", slot, item); callLuaField("onAddItem", slot, item);
} }
@ -80,6 +93,7 @@ void Container::onAddItems(const std::vector<ItemPtr>& items)
void Container::onUpdateItem(int slot, const ItemPtr& item) void Container::onUpdateItem(int slot, const ItemPtr& item)
{ {
slot -= m_firstIndex;
if(slot < 0 || slot >= (int)m_items.size()) { if(slot < 0 || slot >= (int)m_items.size()) {
g_logger.traceError("slot not found"); g_logger.traceError("slot not found");
return; return;
@ -92,8 +106,15 @@ void Container::onUpdateItem(int slot, const ItemPtr& item)
callLuaField("onUpdateItem", slot, item, oldItem); 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()) { if(slot < 0 || slot >= (int)m_items.size()) {
g_logger.traceError("slot not found"); g_logger.traceError("slot not found");
return; return;
@ -102,8 +123,16 @@ void Container::onRemoveItem(int slot)
ItemPtr item = m_items[slot]; ItemPtr item = m_items[slot];
m_items.erase(m_items.begin() + slot); m_items.erase(m_items.begin() + slot);
if(lastItem) {
onAddItem(lastItem, m_firstIndex + m_capacity - 1);
m_size--;
}
m_size--;
updateItemsPositions(); updateItemsPositions();
callLuaField("onSizeChange", m_size);
callLuaField("onRemoveItem", slot, item); callLuaField("onRemoveItem", slot, item);
} }

View File

@ -57,7 +57,7 @@ protected:
void onAddItem(const ItemPtr& item, int slot); void onAddItem(const ItemPtr& item, int slot);
void onAddItems(const std::vector<ItemPtr>& items); void onAddItems(const std::vector<ItemPtr>& items);
void onUpdateItem(int slot, const ItemPtr& item); void onUpdateItem(int slot, const ItemPtr& item);
void onRemoveItem(int slot); void onRemoveItem(int slot, const ItemPtr& lastItem);
friend class Game; friend class Game;

View File

@ -308,7 +308,9 @@ void Game::processCloseContainer(int containerId)
{ {
ContainerPtr container = getContainer(containerId); ContainerPtr container = getContainer(containerId);
if(!container) { 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; return;
} }
@ -338,7 +340,7 @@ void Game::processContainerUpdateItem(int containerId, int slot, const ItemPtr&
container->onUpdateItem(slot, item); 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); ContainerPtr container = getContainer(containerId);
if(!container) { if(!container) {
@ -346,7 +348,7 @@ void Game::processContainerRemoveItem(int containerId, int slot)
return; return;
} }
container->onRemoveItem(slot); container->onRemoveItem(slot, lastItem);
} }
void Game::processInventoryChange(int slot, const ItemPtr& item) 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); 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() void Game::ping()
{ {
if(!m_protocolGame || !m_protocolGame->isConnected()) if(!m_protocolGame || !m_protocolGame->isConnected())
@ -1558,6 +1574,10 @@ void Game::setProtocolVersion(int version)
enableFeature(Otc::GameThingMarks); enableFeature(Otc::GameThingMarks);
} }
if(version >= 984) {
enableFeature(Otc::GameBrowseField);
}
if(version >= 1000) { if(version >= 1000) {
enableFeature(Otc::GamePVPMode); enableFeature(Otc::GamePVPMode);
} }

View File

@ -85,7 +85,7 @@ protected:
void processCloseContainer(int containerId); void processCloseContainer(int containerId);
void processContainerAddItem(int containerId, const ItemPtr& item, int slot); void processContainerAddItem(int containerId, const ItemPtr& item, int slot);
void processContainerUpdateItem(int containerId, int slot, const ItemPtr& item); 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 // channel related
void processChannelList(const std::vector<std::tuple<int, std::string> >& channelList); void processChannelList(const std::vector<std::tuple<int, std::string> >& channelList);
@ -258,6 +258,10 @@ public:
// >= 970 modal dialog // >= 970 modal dialog
void answerModalDialog(int dialog, int button, int choice); 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 reportRuleViolation2();
void ping(); void ping();
void setPingDelay(int delay) { m_pingDelay = delay; } void setPingDelay(int delay) { m_pingDelay = delay; }

View File

@ -295,6 +295,8 @@ void Client::registerLuaFunctions()
g_lua.bindSingletonFunction("g_game", "disableFeature", &Game::disableFeature, &g_game); 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", "isGM", &Game::isGM, &g_game);
g_lua.bindSingletonFunction("g_game", "answerModalDialog", &Game::answerModalDialog, &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.bindSingletonFunction("g_game", "getLastWalkDir", &Game::getLastWalkDir, &g_game);
g_lua.registerSingletonClass("g_shaders"); g_lua.registerSingletonClass("g_shaders");

View File

@ -228,6 +228,8 @@ namespace Proto {
ClientCancelAttackAndFollow = 190, ClientCancelAttackAndFollow = 190,
ClientUpdateTile = 201, ClientUpdateTile = 201,
ClientRefreshContainer = 202, ClientRefreshContainer = 202,
ClientBrowseField = 203,
ClientSeekInContainer = 204,
ClientRequestOutfit = 210, ClientRequestOutfit = 210,
ClientChangeOutfit = 211, ClientChangeOutfit = 211,
ClientMount = 212, // 870 ClientMount = 212, // 870

View File

@ -111,6 +111,8 @@ public:
void sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation); 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 sendRequestItemInfo(int itemId, int subType, int index);
void sendAnswerModalDialog(int dialog, int button, int choice); void sendAnswerModalDialog(int dialog, int button, int choice);
void sendBrowseField(const Position& position);
void sendSeekInContainer(int cid, int index);
// otclient only // otclient only
void sendChangeMapAwareRange(int xrange, int yrange); void sendChangeMapAwareRange(int xrange, int yrange);

View File

@ -686,16 +686,17 @@ void ProtocolGame::parseContainerRemoveItem(const InputMessagePtr& msg)
{ {
int containerId = msg->getU8(); int containerId = msg->getU8();
int slot; int slot;
ItemPtr lastItem;
if(g_game.getFeature(Otc::GameContainerPagination)) { if(g_game.getFeature(Otc::GameContainerPagination)) {
slot = msg->getU16(); slot = msg->getU16();
int itemId = msg->getU16(); int itemId = msg->getU16();
if(itemId != 0) if(itemId != 0)
getItem(msg, itemId); lastItem = getItem(msg, itemId);
} else { } else {
slot = msg->getU8(); slot = msg->getU8();
} }
g_game.processContainerRemoveItem(containerId, slot); g_game.processContainerRemoveItem(containerId, slot, lastItem);
} }
void ProtocolGame::parseAddInventoryItem(const InputMessagePtr& msg) void ProtocolGame::parseAddInventoryItem(const InputMessagePtr& msg)

View File

@ -831,6 +831,29 @@ void ProtocolGame::sendAnswerModalDialog(int dialog, int button, int choice)
send(msg); 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) void ProtocolGame::sendChangeMapAwareRange(int xrange, int yrange)
{ {
if(!g_game.getFeature(Otc::GameChangeMapAwareRange)) if(!g_game.getFeature(Otc::GameChangeMapAwareRange))