restore containers

* implemente Container class
* restore module containers
* add lua bindings for std::map
* improve grid layout
* fixes in UIItem rendering
* changes in miniwindow design
This commit is contained in:
Eduardo Bart 2012-04-02 20:09:47 -03:00
parent 231ba17ba1
commit 90d3acce2a
23 changed files with 428 additions and 178 deletions

View File

@ -17,8 +17,9 @@ Module
- game_skills
- game_inventory
- game_combatcontrols
- game_battle
- game_containers
- game_viplist
- game_battle
- game_hotkeys
@onLoad: |

View File

@ -140,10 +140,10 @@ function GameInterface.createThingMenu(menuPosition, lookThing, useThing, creatu
if useThing then
if useThing:isContainer() then
if useThing:getParentContainer() then
menu:addOption('Open', function() g_game.open(useThing, useThing:getContainerId()) end)
menu:addOption('Open in new window', function() g_game.open(useThing, Containers.getFreeContainerId()) end)
menu:addOption('Open', function() g_game.open(useThing, useThing:getParentContainer()) end)
menu:addOption('Open in new window', function() g_game.open(useThing, nil) end)
else
menu:addOption('Open', function() g_game.open(useThing, Containers.getFreeContainerId()) end)
menu:addOption('Open', function() g_game.open(useThing, nil) end)
end
else
if useThing:isMultiUse() then
@ -256,10 +256,10 @@ function GameInterface.processMouseAction(menuPosition, mouseButton, autoWalk, l
elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
if useThing:isContainer() then
if useThing:getParentContainer() then
g_game.open(useThing, useThing:getContainerId())
g_game.open(useThing, useThing:getParentContainer())
return true
else
g_game.open(useThing, Containers.getFreeContainerId())
g_game.open(useThing, nil)
return true
end
elseif useThing:isMultiUse() then
@ -281,10 +281,10 @@ function GameInterface.processMouseAction(menuPosition, mouseButton, autoWalk, l
return true
elseif multiUseThing:isContainer() then
if multiUseThing:getParentContainer() then
g_game.open(multiUseThing, multiUseThing:getContainerId())
g_game.open(multiUseThing, multiUseThing:getParentContainer())
return true
else
g_game.open(multiUseThing, Containers.getFreeContainerId())
g_game.open(multiUseThing, nil)
return true
end
elseif multiUseThing:isMultiUse() then

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 626 B

After

Width:  |  Height:  |  Size: 758 B

View File

@ -1,5 +1,6 @@
Item < UIItem
size: 34 34
padding: 1
image-source: /core_styles/styles/images/item.png
font: verdana-11px-rounded
border-color: white

View File

@ -3,7 +3,7 @@ MiniWindow < UIMiniWindow
icon-rect: 4 4 16 16
width: 192
height: 200
text-offset: 26 5
text-offset: 24 5
text-align: topLeft
margin-bottom: 2
move-policy: free updated
@ -82,7 +82,7 @@ MiniWindowContents < ScrollablePanel
id: contentsPanel
anchors.fill: parent
margin-right: 14
padding: 25 6 6 6
padding: 24 3 3 5
vertical-scrollbar: miniwindowScrollBar
BorderlessGameWindow < UIWindow

View File

@ -36,7 +36,7 @@ table.insert(lifeBarColors, {percentAbove = -1, color = '#4F0000' } )
-- public functions
function Battle.init()
battleWindow = displayUI('battle.otui', GameInterface.getRightPanel())
battleWindow = displayUI('battle.otui', GameInterface.getLeftPanel())
battleButton = TopMenu.addGameToggleButton('battleButton', 'Battle (Ctrl+B)', 'battle.png', Battle.toggle)
battleButton:setOn(true)
Keyboard.bindKeyDown('Ctrl+B', Battle.toggle)

View File

@ -1,11 +1,35 @@
MiniWindow
size: 200 221
ContainerWindow < MiniWindow
height: 150
UIItem
id: containerItemWidget
virtual: true
item-id: 3253
size: 32 32
anchors.top: parent.top
anchors.left: parent.left
margin-top: -6
margin-left: -6
UIButton
id: upButton
anchors.top: minimizeButton.top
anchors.right: minimizeButton.left
margin-right: 3
size: 14 14
image-source: /game/images/miniwindowbuttons.png
image-clip: 42 0 14 14
$hover:
image-clip: 42 14 14 14
$pressed:
image-clip: 42 28 14 14
MiniWindowContents
padding: 27 6 6 8
layout:
type: grid
cell-size: 34 34
cell-spacing: 5
num-columns: 4
num-lines: 5
flow: true
auto-spacing: true

View File

@ -1,138 +1,90 @@
Containers = {}
-- private variables
local containers = {}
-- public functions
function Containers.clean()
containers = {}
local function refreshContainerItems(container)
for slot=0,container:getCapacity()-1 do
local itemWidget = container.itemsPanel:getChildById('item' .. slot)
itemWidget:setItem(container:getItem(slot))
end
end
function Containers.getFreeContainerId()
for i=0,15 do
if not containers[i] then
return i
local function onContainerOpen(container, previousContainer)
local containerWindow
if previousContainer then
containerWindow = previousContainer.window
previousContainer.window = nil
previousContainer.itemsPanel = nil
else
containerWindow = createWidget('ContainerWindow', GameInterface.getRightPanel())
end
end
return 0
end
-- hooked events
function Containers.onOpenContainer(containerId, itemId, name, capacity, hasParent, items)
local container = containers[containerId]
if container then
GameInterface.getRightPanel():removeChild(container)
containerWindow:setId('container' .. container:getId())
local containerPanel = containerWindow:getChildById('contentsPanel')
local containerItemWidget = containerWindow:getChildById('containerItemWidget')
containerWindow.onClose = function()
g_game.close(container)
containerWindow:hide()
end
container = displayUI('container.otui', GameInterface.getRightPanel())
local upButton = containerWindow:getChildById('upButton')
upButton.onClick = function()
g_game.openParent(container)
end
upButton:setVisible(container:hasParent())
local name = container:getName()
name = name:sub(1,1):upper() .. name:sub(2)
container:setText(name)
containerWindow:setText(name)
-- set icon, itemid
-- closebutton
-- resize
if hasParent then
-- parent button
containerItemWidget:setItemId(container:getItemId())
containerPanel:destroyChildren()
for slot=0,container:getCapacity()-1 do
local itemWidget = createWidget('Item', containerPanel)
itemWidget:setId('item' .. slot)
itemWidget:setItem(container:getItem(slot))
itemWidget.position = container:getSlotPosition(slot)
end
container.itemCount = #items
container.capacity = capacity
container.window = containerWindow
container.itemsPanel = containerPanel
end
for i=1,capacity do
local itemWidget = UIItem.create()
itemWidget:setStyle('Item')
container:addChild(itemWidget)
itemWidget.position = {x=65535, y=containerId+64, z=i-1}
local function onContainerClose(container)
local containerWindow = container.window
if containerWindow then
containerWindow:destroy()
end
end
if i <= #items then
local item = items[i]
item:setPosition(itemWidget.position)
local function onContainerAddItem(container, slot, item)
refreshContainerItems(container)
end
local function onContainerUpdateItem(container, slot, item, oldItem)
local itemWidget = container.itemsPanel:getChildById('item' .. slot)
itemWidget:setItem(item)
end
end
containers[containerId] = container
end
function Containers.onCloseContainer(containerId)
local container = containers[containerId]
if container then
GameInterface.getRightPanel():removeChild(container)
end
containers[containerId] = nil
local function onContainerRemoveItem(container, slot, item)
refreshContainerItems(container)
end
function Containers.onContainerAddItem(containerId, item)
local container = containers[containerId]
if not container or not item or container.itemCount >= container.capacity then return end
function Containers.init()
importStyle 'container.otui'
local i = container.itemCount
while i >= 1 do
local itemWidget = container:getChildByIndex(i)
if not itemWidget then return end
local nextItemWidget = container:getChildByIndex(i+1)
if not nextItemWidget then return end
local swapItem = itemWidget:getItem()
if swapItem then
swapItem:setPosition(nextItemWidget.position)
nextItemWidget:setItem(swapItem)
end
i = i - 1
end
local itemWidget = container:getChildByIndex(1)
if not itemWidget then return end
item:setPosition(itemWidget.position)
itemWidget:setItem(item)
container.itemCount = container.itemCount + 1
connect(Container, { onOpen = onContainerOpen,
onClose = onContainerClose,
onAddItem = onContainerAddItem,
onUpdateItem = onContainerUpdateItem,
onRemoveItem = onContainerRemoveItem })
end
function Containers.onContainerUpdateItem(containerId, slot, item)
local container = containers[containerId]
if not container then return end
local itemWidget = container:getChildByIndex(slot + 1)
if not itemWidget then return end
itemWidget:setItem(item)
item:setPosition(itemWidget.position)
function Containers.terminate()
disconnect(Container, { onOpen = onContainerOpen,
onClose = onContainerClose,
onAddItem = onContainerAddItem,
onUpdateItem = onContainerUpdateItem,
onRemoveItem = onContainerRemoveItem })
end
function Containers.onContainerRemoveItem(containerId, slot)
local container = containers[containerId]
if not container then return end
function Containers.clean()
local itemWidget = container:getChildByIndex(slot+1)
if not itemWidget then return end
itemWidget:setItem(nil)
for i=slot,container.itemCount-2 do
local itemWidget = container:getChildByIndex(i+1)
if not itemWidget then return end
local nextItemWidget = container:getChildByIndex(i+2)
if not nextItemWidget then return end
local item = nextItemWidget:getItem()
local pos = item:getPosition()
pos.z = pos.z - 1
item:setPosition(pos)
itemWidget:setItem(item)
nextItemWidget:setItem(nil)
end
container.itemCount = container.itemCount - 1
end
connect(g_game, { onGameStart = Containers.clean,
onGameEnd = Containers.clean,
onOpenContainer = Containers.onOpenContainer,
onCloseContainer = Containers.onCloseContainer,
onContainerAddItem = Containers.onContainerAddItem,
onContainerUpdateItem = Containers.onContainerUpdateItem,
onContainerRemoveItem = Containers.onContainerRemoveItem })

View File

@ -4,5 +4,12 @@ Module
author: OTClient team
website: https://github.com/edubart/otclient
dependecies:
- game
@onLoad: |
dofile 'containers'
Containers.init()
@onUnload: |
Containers.terminate()

View File

@ -135,6 +135,13 @@ void push_luavalue(const std::deque<T>& vec);
template<typename T>
bool luavalue_cast(int index, std::deque<T>& vec);
// map
template<class K, class V>
void push_luavalue(const std::map<K, V>& map);
template<class K, class V>
bool luavalue_cast(int index, std::map<K, V>& map);
// tuple
template<typename... Args>
void push_luavalue(const std::tuple<Args...>& tuple);
@ -299,6 +306,34 @@ bool luavalue_cast(int index, std::deque<T>& vec)
return false;
}
template<class K, class V>
void push_luavalue(const std::map<K, V>& map)
{
g_lua.newTable();
for(auto& it : map) {
push_luavalue(it.first);
push_luavalue(it.second);
g_lua.rawSet();
}
}
template<class K, class V>
bool luavalue_cast(int index, std::map<K, V>& map)
{
if(g_lua.isTable(index)) {
g_lua.pushNil();
while(g_lua.next(index < 0 ? index-1 : index)) {
K key;
V value;
if(luavalue_cast(-1, value) && luavalue_cast(-2, key))
map[key] = value;
g_lua.pop();
}
return true;
}
return false;
}
template<int N>
struct push_tuple_luavalue {
template<typename Tuple>

View File

@ -23,12 +23,14 @@
#include "uigridlayout.h"
#include "uiwidget.h"
#include <framework/core/eventdispatcher.h>
UIGridLayout::UIGridLayout(UIWidgetPtr parentWidget): UILayout(parentWidget)
{
m_cellSize = Size(16,16);
m_cellSpacing = 0;
m_numColumns = 1;
m_numLines = 1;
m_numLines = 0;
}
void UIGridLayout::applyStyle(const OTMLNodePtr& styleNode)
@ -49,6 +51,12 @@ void UIGridLayout::applyStyle(const OTMLNodePtr& styleNode)
setNumColumns(node->value<int>());
else if(node->tag() == "num-lines")
setNumLines(node->value<int>());
else if(node->tag() == "fit-children")
setFitChildren(node->value<bool>());
else if(node->tag() == "auto-spacing")
setAutoSpacing(node->value<bool>());
else if(node->tag() == "flow")
setFlow(node->value<bool>());
}
}
@ -71,24 +79,42 @@ bool UIGridLayout::internalUpdate()
Rect clippingRect = parentWidget->getClippingRect();
Point topLeft = clippingRect.topLeft();
int numColumns = m_numColumns;
if(m_flow && m_cellSize.width() > 0)
numColumns = clippingRect.width() / (m_cellSize.width() + m_cellSpacing);
int cellSpacing = m_cellSpacing;
if(m_autoSpacing && numColumns > 1)
cellSpacing = (clippingRect.width() - numColumns * m_cellSize.width()) / (numColumns - 1);
int index = 0;
int preferredHeight = 0;
for(const UIWidgetPtr& widget : widgets) {
if(!widget->isExplicitlyVisible())
continue;
int line = index / m_numColumns;
int column = index % m_numColumns;
Point virtualPos = Point(column * (m_cellSize.width() + m_cellSpacing), line * (m_cellSize.height() + m_cellSpacing));
Point pos = topLeft + virtualPos;
int line = index / numColumns;
int column = index % numColumns;
Point virtualPos = Point(column * (m_cellSize.width() + cellSpacing), line * (m_cellSize.height() + cellSpacing));
preferredHeight = virtualPos.y + m_cellSize.height();
Point pos = topLeft + virtualPos - parentWidget->getVirtualOffset();
if(widget->setRect(Rect(pos, m_cellSize)))
changed = true;
index++;
if(index >= m_numColumns * m_numLines)
if(m_numLines > 0 && index >= m_numColumns * m_numLines)
break;
}
preferredHeight += parentWidget->getPaddingTop() + parentWidget->getPaddingBottom();
if(m_fitChildren && preferredHeight != parentWidget->getHeight()) {
// must set the preferred height later
g_eventDispatcher.addEvent([=] {
parentWidget->setHeight(preferredHeight);
});
}
return changed;
}

View File

@ -40,6 +40,9 @@ public:
void setCellSpacing(int spacing) { m_cellSpacing = spacing; update(); }
void setNumColumns(int columns) { m_numColumns = columns; update(); }
void setNumLines(int lines) { m_numLines = lines; update(); }
void setAutoSpacing(bool enable) { m_autoSpacing = enable; update(); }
void setFitChildren(bool enable) { m_fitChildren = enable; update(); }
void setFlow(bool enable) { m_flow = enable; update(); }
virtual UIGridLayoutPtr asUIGridLayout() { return nullptr; }
@ -51,6 +54,9 @@ private:
int m_cellSpacing;
int m_numColumns;
int m_numLines;
Boolean<false> m_autoSpacing;
Boolean<false> m_fitChildren;
Boolean<false> m_flow;
};
#endif

View File

@ -48,7 +48,7 @@ bool UIHorizontalLayout::internalUpdate()
bool changed = false;
Rect clippingRect = parentWidget->getClippingRect();
Point pos = (m_alignRight) ? clippingRect.topRight() : clippingRect.topLeft();
int prefferedWidth = 0;
int preferredWidth = 0;
int gap;
for(const UIWidgetPtr& widget : widgets) {
@ -59,7 +59,7 @@ bool UIHorizontalLayout::internalUpdate()
gap = (m_alignRight) ? -(widget->getMarginRight()+widget->getWidth()) : widget->getMarginLeft();
pos.x += gap;
prefferedWidth += gap;
preferredWidth += gap;
if(widget->isFixedSize()) {
// center it
@ -77,16 +77,16 @@ bool UIHorizontalLayout::internalUpdate()
gap = (m_alignRight) ? -widget->getMarginLeft() : (widget->getWidth() + widget->getMarginRight());
gap += m_spacing;
pos.x += gap;
prefferedWidth += gap;
preferredWidth += gap;
}
prefferedWidth -= m_spacing;
prefferedWidth += parentWidget->getPaddingLeft() + parentWidget->getPaddingRight();
preferredWidth -= m_spacing;
preferredWidth += parentWidget->getPaddingLeft() + parentWidget->getPaddingRight();
if(m_fitChildren && prefferedWidth != parentWidget->getWidth()) {
// must set the preffered width later
if(m_fitChildren && preferredWidth != parentWidget->getWidth()) {
// must set the preferred width later
g_eventDispatcher.addEvent([=] {
parentWidget->setWidth(prefferedWidth);
parentWidget->setWidth(preferredWidth);
});
}

View File

@ -49,7 +49,7 @@ bool UIVerticalLayout::internalUpdate()
Rect clippingRect = parentWidget->getClippingRect();
Point pos = (m_alignBottom) ? clippingRect.bottomLeft() : clippingRect.topLeft();
int prefferedHeight = 0;
int preferredHeight = 0;
int gap;
for(const UIWidgetPtr& widget : widgets) {
@ -60,7 +60,7 @@ bool UIVerticalLayout::internalUpdate()
gap = (m_alignBottom) ? -(widget->getMarginBottom()+widget->getHeight()) : widget->getMarginTop();
pos.y += gap;
prefferedHeight += gap;
preferredHeight += gap;
if(widget->isFixedSize()) {
// center it
@ -78,16 +78,16 @@ bool UIVerticalLayout::internalUpdate()
gap = (m_alignBottom) ? -widget->getMarginTop() : (widget->getHeight() + widget->getMarginBottom());
gap += m_spacing;
pos.y += gap;
prefferedHeight += gap;
preferredHeight += gap;
}
prefferedHeight -= m_spacing;
prefferedHeight += parentWidget->getPaddingTop() + parentWidget->getPaddingBottom();
preferredHeight -= m_spacing;
preferredHeight += parentWidget->getPaddingTop() + parentWidget->getPaddingBottom();
if(m_fitChildren && prefferedHeight != parentWidget->getHeight()) {
// must set the preffered width later
if(m_fitChildren && preferredHeight != parentWidget->getHeight()) {
// must set the preferred width later
g_eventDispatcher.addEvent([=] {
parentWidget->setHeight(prefferedHeight);
parentWidget->setHeight(preferredHeight);
});
}

View File

@ -1300,10 +1300,10 @@ void UIWidget::onGeometryChange(const Rect& oldRect, const Rect& newRect)
updateText();
// move children that is outside the parent rect to inside again
for(const UIWidgetPtr& child : m_children) {
if(!child->isAnchored())
child->bindRectToParent();
}
//for(const UIWidgetPtr& child : m_children) {
//if(!child->isAnchored())
//child->bindRectToParent();
//}
}
void UIWidget::onLayoutUpdate()

View File

@ -21,3 +21,80 @@
*/
#include "container.h"
#include "item.h"
Container::Container()
{
m_id = -1;
m_itemId = 0;
m_capacity = 20;
m_name = "Container";
m_hasParent = false;
}
void Container::open(const ContainerPtr& previousContainer)
{
callLuaField("onOpen", previousContainer);
}
void Container::close()
{
callLuaField("onClose");
}
void Container::addItem(const ItemPtr& item)
{
m_items.push_front(item);
updateItemsPositions();
callLuaField("onAddItem", 0, item);
}
void Container::addItems(const std::vector<ItemPtr>& items)
{
for(const ItemPtr& item : items)
m_items.push_back(item);
updateItemsPositions();
}
void Container::updateItem(int slot, const ItemPtr& item)
{
if(slot < 0 || slot >= (int)m_items.size()) {
logTraceError("slot not found");
return;
}
ItemPtr oldItem = m_items[slot];
m_items[slot] = item;
item->setPosition(getSlotPosition(slot));
callLuaField("onUpdateItem", slot, item, oldItem);
}
void Container::removeItem(int slot)
{
if(slot < 0 || slot >= (int)m_items.size()) {
logTraceError("slot not found");
return;
}
ItemPtr item = m_items[slot];
m_items.erase(m_items.begin() + slot);
updateItemsPositions();
callLuaField("onRemoveItem", slot, item);
}
ItemPtr Container::getItem(int slot)
{
if(slot < 0 || slot >= (int)m_items.size())
return nullptr;
return m_items[slot];
}
void Container::updateItemsPositions()
{
for(int slot = 0; slot < (int)m_items.size(); ++slot)
m_items[slot]->setPosition(getSlotPosition(slot));
}

View File

@ -32,6 +32,39 @@ class Container : public LuaObject
public:
Container();
void open(const ContainerPtr& previousContainer);
void close();
void addItem(const ItemPtr& item);
void addItems(const std::vector<ItemPtr>& items);
void updateItem(int slot, const ItemPtr& item);
void removeItem(int slot);
ItemPtr getItem(int slot);
Position getSlotPosition(int slot) { return Position(0xffff, m_id | 0x40, slot); }
void setId(int id) { m_id = id; }
void setCapacity(int capacity) { m_capacity = capacity; }
void setName(std::string name) { m_name = name; }
void setItemId(uint16 itemId) { m_itemId = itemId; }
void setHasParent(bool hasParent) { m_hasParent = hasParent; }
std::string getName() { return m_name; }
int getId() { return m_id; }
int getCapacity() { return m_capacity; }
int getItemsCount() { return m_items.size(); }
uint16 getItemId() { return m_itemId; }
bool hasParent() { return m_hasParent; }
private:
void updateItemsPositions();
int m_id;
int m_capacity;
uint16 m_itemId;
std::string m_name;
bool m_hasParent;
std::deque<ItemPtr> m_items;
};
#endif

View File

@ -25,6 +25,7 @@
#include "map.h"
#include "tile.h"
#include "creature.h"
#include "container.h"
#include "statictext.h"
#include <framework/core/eventdispatcher.h>
#include <framework/ui/uimanager.h>
@ -166,30 +167,73 @@ void Game::processCreatureSpeak(const std::string& name, int level, Otc::SpeakTy
g_lua.callGlobalField("g_game", "onCreatureSpeak", name, level, type, message, channelId, creaturePos);
}
void Game::processOpenContainer(int containerId, int itemId, const std::string& name, int capacity, bool hasParent, const std::vector< ItemPtr >& items)
void Game::processOpenContainer(int containerId, int itemId, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items)
{
g_lua.callGlobalField("g_game", "onOpenContainer", containerId, itemId, name, capacity, hasParent, items);
ContainerPtr previousContainer = getContainer(containerId);
ContainerPtr container = ContainerPtr(new Container());
container->setId(containerId);
container->setCapacity(capacity);
container->setName(name);
container->setItemId(itemId);
container->setHasParent(hasParent);
m_containers[containerId] = container;
container->addItems(items);
container->open(previousContainer);
if(previousContainer)
previousContainer->close();
}
void Game::processCloseContainer(int containerId)
{
g_lua.callGlobalField("g_game", "onCloseContainer", containerId);
ContainerPtr container = getContainer(containerId);
if(!container) {
logTraceError("container not found");
return;
}
auto it = m_containers.find(container->getId());
if(it == m_containers.end() || it->second != container) {
logTraceError("invalid container");
return;
}
m_containers.erase(it);
container->close();
}
void Game::processContainerAddItem(int containerId, const ItemPtr& item)
{
item->setPosition(Position(65535, containerId + 0x40, 0));
g_lua.callGlobalField("g_game", "onContainerAddItem", containerId, item);
ContainerPtr container = getContainer(containerId);
if(!container) {
logTraceError("container not found");
return;
}
container->addItem(item);
}
void Game::processContainerUpdateItem(int containerId, int slot, const ItemPtr& item)
{
g_lua.callGlobalField("g_game", "onContainerUpdateItem", containerId, slot, item);
ContainerPtr container = getContainer(containerId);
if(!container) {
logTraceError("container not found");
return;
}
container->updateItem(slot, item);
}
void Game::processContainerRemoveItem(int containerId, int slot)
{
g_lua.callGlobalField("g_game", "onContainerRemoveItem", containerId, slot);
ContainerPtr container = getContainer(containerId);
if(!container) {
logTraceError("container not found");
return;
}
container->removeItem(slot);
}
void Game::processInventoryChange(int slot, const ItemPtr& item)
@ -542,19 +586,37 @@ void Game::useInventoryItemWith(int itemId, const ThingPtr& toThing)
m_protocolGame->sendUseItemWith(pos, itemId, 0, toThing->getPosition(), toThing->getId(), toThing->getStackpos());
}
void Game::open(const ItemPtr& item, int containerId)
void Game::open(const ItemPtr& item, const ContainerPtr& previousContainer)
{
if(!canPerformGameAction() || !item)
return;
m_protocolGame->sendUseItem(item->getPosition(), item->getId(), item->getStackpos(), containerId);
int id = 0;
if(!previousContainer) {
// find a free container id
while(m_containers.find(id) != m_containers.end())
id++;
} else {
id = previousContainer->getId();
}
m_protocolGame->sendUseItem(item->getPosition(), item->getId(), item->getStackpos(), id);
}
void Game::upContainer(int containerId)
void Game::openParent(const ContainerPtr& container)
{
if(!canPerformGameAction())
return;
m_protocolGame->sendUpContainer(containerId);
m_protocolGame->sendUpContainer(container->getId());
}
void Game::close(const ContainerPtr& container)
{
if(!canPerformGameAction())
return;
m_protocolGame->sendCloseContainer(container->getId());
}
void Game::refreshContainer()

View File

@ -139,8 +139,9 @@ public:
void useInventoryItemWith(int itemId, const ThingPtr& toThing);
// container related
void open(const ItemPtr& item, int containerId);
void upContainer(int containerId);
void open(const ItemPtr& item, const ContainerPtr& previousContainer);
void openParent(const ContainerPtr& container);
void close(const ContainerPtr& container);
void refreshContainer();
// attack/follow related
@ -218,6 +219,7 @@ public:
bool isFollowing() { return !!m_followingCreature; }
ContainerPtr getContainer(int index) { return m_containers[index]; }
std::map<int, ContainerPtr> getContainers() { return m_containers; }
CreaturePtr getAttackingCreature() { return m_attackingCreature; }
CreaturePtr getFollowingCreature() { return m_followingCreature; }
int getServerBeat() { return m_serverBeat; }

View File

@ -56,8 +56,10 @@ const TilePtr& Thing::getTile()
ContainerPtr Thing::getParentContainer()
{
if(m_position.x == 0xFFFF && m_position.y & 0x40)
return g_game.getContainer(m_position.z);
if(m_position.x == 0xffff && m_position.y & 0x40) {
int containerId = m_position.y ^ 0x40;
return g_game.getContainer(containerId);
}
return nullptr;
}

View File

@ -95,7 +95,8 @@ void OTClient::registerLuaFunctions()
g_lua.bindClassStaticFunction("g_game", "useInventoryItem", std::bind(&Game::useInventoryItem, &g_game, _1));
g_lua.bindClassStaticFunction("g_game", "useInventoryItemWith", std::bind(&Game::useInventoryItemWith, &g_game, _1, _2));
g_lua.bindClassStaticFunction("g_game", "open", std::bind(&Game::open, &g_game, _1, _2));
g_lua.bindClassStaticFunction("g_game", "upContainer", std::bind(&Game::upContainer, &g_game, _1));
g_lua.bindClassStaticFunction("g_game", "openParent", std::bind(&Game::openParent, &g_game, _1));
g_lua.bindClassStaticFunction("g_game", "close", std::bind(&Game::close, &g_game, _1));
g_lua.bindClassStaticFunction("g_game", "refreshContainer", std::bind(&Game::refreshContainer, &g_game));
g_lua.bindClassStaticFunction("g_game", "attack", std::bind(&Game::attack, &g_game, _1));
g_lua.bindClassStaticFunction("g_game", "cancelAttack", std::bind(&Game::cancelAttack, &g_game));
@ -147,6 +148,8 @@ void OTClient::registerLuaFunctions()
g_lua.bindClassStaticFunction("g_game", "isDead", std::bind(&Game::isDead, &g_game));
g_lua.bindClassStaticFunction("g_game", "isAttacking", std::bind(&Game::isAttacking, &g_game));
g_lua.bindClassStaticFunction("g_game", "isFollowing", std::bind(&Game::isFollowing, &g_game));
g_lua.bindClassStaticFunction("g_game", "getContainer", std::bind(&Game::getContainer, &g_game, _1));
g_lua.bindClassStaticFunction("g_game", "getContainers", std::bind(&Game::getContainers, &g_game));
g_lua.bindClassStaticFunction("g_game", "getAttackingCreature", std::bind(&Game::getAttackingCreature, &g_game));
g_lua.bindClassStaticFunction("g_game", "getFollowingCreature", std::bind(&Game::getFollowingCreature, &g_game));
g_lua.bindClassStaticFunction("g_game", "getServerBeat", std::bind(&Game::getServerBeat, &g_game));
@ -165,6 +168,26 @@ void OTClient::registerLuaFunctions()
g_lua.registerClass<ProtocolGame, Protocol>();
g_lua.registerClass<Container>();
g_lua.bindClassStaticFunction<Container>("create", []{ return ContainerPtr(new Container); });
g_lua.bindClassMemberFunction<Container>("open", &Container::open);
g_lua.bindClassMemberFunction<Container>("close", &Container::close);
g_lua.bindClassMemberFunction<Container>("addItem", &Container::addItem);
g_lua.bindClassMemberFunction<Container>("addItems", &Container::addItems);
g_lua.bindClassMemberFunction<Container>("updateItem", &Container::updateItem);
g_lua.bindClassMemberFunction<Container>("removeItem", &Container::removeItem);
g_lua.bindClassMemberFunction<Container>("getItem", &Container::getItem);
g_lua.bindClassMemberFunction<Container>("getSlotPosition", &Container::getSlotPosition);
g_lua.bindClassMemberFunction<Container>("setId", &Container::setId);
g_lua.bindClassMemberFunction<Container>("setCapacity", &Container::setCapacity);
g_lua.bindClassMemberFunction<Container>("setName", &Container::setName);
g_lua.bindClassMemberFunction<Container>("setItemId", &Container::setItemId);
g_lua.bindClassMemberFunction<Container>("setHasParent", &Container::setHasParent);
g_lua.bindClassMemberFunction<Container>("getName", &Container::getName);
g_lua.bindClassMemberFunction<Container>("getId", &Container::getId);
g_lua.bindClassMemberFunction<Container>("getCapacity", &Container::getCapacity);
g_lua.bindClassMemberFunction<Container>("getItemsCount", &Container::getItemsCount);
g_lua.bindClassMemberFunction<Container>("getItemId", &Container::getItemId);
g_lua.bindClassMemberFunction<Container>("hasParent", &Container::hasParent);
g_lua.registerClass<Thing>();
g_lua.bindClassMemberFunction<Thing>("setId", &Thing::setId);

View File

@ -35,18 +35,17 @@ void UIItem::drawSelf()
UIWidget::drawSelf();
if(m_item) {
Point topLeft = m_rect.bottomRight() - Point(32, 32) + Point(m_padding.left, m_padding.top);
Rect drawRect = getClippingRect();
float scaleFactor = std::min(drawRect.width() / 32.0f, drawRect.height() / 32.0f);
g_painter.setColor(Color::white);
m_item->draw(topLeft, 1, true);
m_item->draw(drawRect.topLeft(), scaleFactor, true);
if(m_font && m_item->isStackable() && m_item->getCount() > 1) {
std::string count = Fw::tostring(m_item->getCount());
g_painter.setColor(Color(231, 231, 231));
m_font->drawText(count, Rect(m_rect.topLeft(), m_rect.bottomRight() - Point(3, 0)), Fw::AlignBottomRight);
}
//m_font->renderText(Fw::unsafeCast<std::string>(m_item->getId()), m_rect);
}
}