This commit is contained in:
OTCv8 2020-09-11 01:13:37 +02:00
parent cf931af49e
commit dfd69fd3b5
19 changed files with 308 additions and 79 deletions

View File

@ -35,6 +35,8 @@ itemDetailsPanel = nil
itemStatsPanel = nil itemStatsPanel = nil
myOffersPanel = nil myOffersPanel = nil
currentOffersPanel = nil currentOffersPanel = nil
myCurrentOffersTab = nil
myOfferHistoryTab = nil
offerHistoryPanel = nil offerHistoryPanel = nil
itemsPanel = nil itemsPanel = nil
selectedOffer = {} selectedOffer = {}
@ -69,10 +71,12 @@ buyCancelButton = nil
sellCancelButton = nil sellCancelButton = nil
buyMyOfferTable = nil buyMyOfferTable = nil
sellMyOfferTable = nil sellMyOfferTable = nil
myOfferHistoryTabel = nil
offerExhaust = {} offerExhaust = {}
marketOffers = {} marketOffers = {}
marketItems = {} marketItems = {}
marketItemNames = {}
information = {} information = {}
currentItems = {} currentItems = {}
lastCreatedOffer = 0 lastCreatedOffer = 0
@ -114,7 +118,7 @@ local function isItemValid(item, category, searchFilter)
if filterLevel and marketData.requiredLevel and player:getLevel() < marketData.requiredLevel then if filterLevel and marketData.requiredLevel and player:getLevel() < marketData.requiredLevel then
return false return false
end end
if filterVocation and marketData.restrictVocation > 0 then if filterVocation and marketData.restrictVocation and marketData.restrictVocation > 0 then
local voc = Bit.bit(information.vocation) local voc = Bit.bit(information.vocation)
if not Bit.hasBit(marketData.restrictVocation, voc) then if not Bit.hasBit(marketData.restrictVocation, voc) then
return false return false
@ -146,6 +150,7 @@ local function clearMyOffers()
marketOffers[MarketAction.Sell] = {} marketOffers[MarketAction.Sell] = {}
buyMyOfferTable:clearData() buyMyOfferTable:clearData()
sellMyOfferTable:clearData() sellMyOfferTable:clearData()
myOfferHistoryTabel:clearData()
end end
local function clearFilters() local function clearFilters()
@ -181,14 +186,17 @@ local function addOffer(offer, offerType)
local amount = offer:getAmount() local amount = offer:getAmount()
local price = offer:getPrice() local price = offer:getPrice()
local timestamp = offer:getTimeStamp() local timestamp = offer:getTimeStamp()
local itemName = offer:getItem():getMarketData().name local itemName = marketItemNames[offer:getItem():getId()]
if not itemName then
itemName = offer:getItem():getMarketData().name
end
buyOfferTable:toggleSorting(false) buyOfferTable:toggleSorting(false)
sellOfferTable:toggleSorting(false) sellOfferTable:toggleSorting(false)
buyMyOfferTable:toggleSorting(false) buyMyOfferTable:toggleSorting(false)
sellMyOfferTable:toggleSorting(false) sellMyOfferTable:toggleSorting(false)
if amount < 1 then return false end if amount < 1 then return false end
if offerType == MarketAction.Buy then if offerType == MarketAction.Buy then
if offer.warn then if offer.warn then
@ -202,7 +210,7 @@ local function addOffer(offer, offerType)
{text = comma_value(price*amount), sortvalue = price*amount}, {text = comma_value(price*amount), sortvalue = price*amount},
{text = comma_value(price), sortvalue = price}, {text = comma_value(price), sortvalue = price},
{text = amount}, {text = amount},
{text = string.gsub(os.date('%c', timestamp), " ", " "), sortvalue = timestamp} {text = string.gsub(os.date('%H:%M %d/%m/%y', timestamp), " ", " "), sortvalue = timestamp}
}) })
else else
row = buyOfferTable:addRow({ row = buyOfferTable:addRow({
@ -210,7 +218,7 @@ local function addOffer(offer, offerType)
{text = amount}, {text = amount},
{text = comma_value(price*amount), sortvalue = price*amount}, {text = comma_value(price*amount), sortvalue = price*amount},
{text = comma_value(price), sortvalue = price}, {text = comma_value(price), sortvalue = price},
{text = string.gsub(os.date('%c', timestamp), " ", " ")} {text = string.gsub(os.date('%H:%M %d/%m/%y', timestamp), " ", " ")}
}) })
end end
row.ref = id row.ref = id
@ -231,7 +239,7 @@ local function addOffer(offer, offerType)
{text = comma_value(price*amount), sortvalue = price*amount}, {text = comma_value(price*amount), sortvalue = price*amount},
{text = comma_value(price), sortvalue = price}, {text = comma_value(price), sortvalue = price},
{text = amount}, {text = amount},
{text = string.gsub(os.date('%c', timestamp), " ", " "), sortvalue = timestamp} {text = string.gsub(os.date('%H:%M %d/%m/%y', timestamp), " ", " "), sortvalue = timestamp}
}) })
else else
row = sellOfferTable:addRow({ row = sellOfferTable:addRow({
@ -239,7 +247,7 @@ local function addOffer(offer, offerType)
{text = amount}, {text = amount},
{text = comma_value(price*amount), sortvalue = price*amount}, {text = comma_value(price*amount), sortvalue = price*amount},
{text = comma_value(price), sortvalue = price}, {text = comma_value(price), sortvalue = price},
{text = string.gsub(os.date('%c', timestamp), " ", " "), sortvalue = timestamp} {text = string.gsub(os.date('%H:%M %d/%m/%y', timestamp), " ", " "), sortvalue = timestamp}
}) })
end end
row.ref = id row.ref = id
@ -343,6 +351,40 @@ local function updateOffers(offers)
end end
end end
local function updateHistoryOffers(offers)
myOfferHistoryTabel:toggleSorting(false)
for _, offer in ipairs(offers) do
local offerType = offer:getType()
local id = offer:getId()
local player = offer:getPlayer()
local amount = offer:getAmount()
local price = offer:getPrice()
local timestamp = offer:getTimeStamp()
local itemName = marketItemNames[offer:getItem():getId()]
if not itemName then
itemName = offer:getItem():getMarketData().name
end
local offerTypeName = "?"
if offerType == MarketAction.Buy then
offerTypeName = "Buy"
elseif offerType == MarketAction.Sell then
offerTypeName = "Sell"
end
local row = myOfferHistoryTabel:addRow({
{text = offerTypeName},
{text = itemName},
{text = comma_value(price*amount), sortvalue = price*amount},
{text = comma_value(price), sortvalue = price},
{text = amount},
{text = string.gsub(os.date('%H:%M %d/%m/%y', timestamp), " ", " "), sortvalue = timestamp}
})
end
myOfferHistoryTabel:toggleSorting(false)
myOfferHistoryTabel:sort()
end
local function updateDetails(itemId, descriptions, purchaseStats, saleStats) local function updateDetails(itemId, descriptions, purchaseStats, saleStats)
if not selectedItem then if not selectedItem then
return return
@ -698,13 +740,45 @@ local function onMarketMessage(messageMode, message)
Market.displayMessage(message) Market.displayMessage(message)
end end
local function initMarketItems() local function initMarketItems(items)
for c = MarketCategory.First, MarketCategory.Last do for c = MarketCategory.First, MarketCategory.Last do
marketItems[c] = {} marketItems[c] = {}
end end
marketItemNames = {}
-- save a list of items which are already added -- save a list of items which are already added
local itemSet = {} local itemSet = {}
-- parse items send by server
if items then
for _, entry in ipairs(items) do
local item = Item.create(entry.id)
local thingType = g_things.getThingType(entry.id, ThingCategoryItem)
if item and thingType and not marketItemNames[entry.id] then
-- create new marketItem block
local marketItem = {
displayItem = item,
thingType = thingType,
marketData = {
name = entry.name,
category = entry.category,
requiredLevel = 0,
restrictVocation = 0,
showAs = entry.id,
tradeAs = entry.id
}
}
-- add new market item
if marketItems[entry.category] ~= nil then
table.insert(marketItems[entry.category], marketItem)
marketItemNames[entry.id] = entry.name
end
end
end
Market.updateCategories()
return
end
-- populate all market items -- populate all market items
local types = g_things.findThingTypeByAttr(ThingAttrMarket, 0) local types = g_things.findThingTypeByAttr(ThingAttrMarket, 0)
@ -777,16 +851,31 @@ local function initInterface()
offersTabBar:setContentWidget(myOffersPanel:getChildById('offersTabContent')) offersTabBar:setContentWidget(myOffersPanel:getChildById('offersTabContent'))
currentOffersPanel = g_ui.loadUI('ui/myoffers/currentoffers') currentOffersPanel = g_ui.loadUI('ui/myoffers/currentoffers')
offersTabBar:addTab(tr('Current Offers'), currentOffersPanel) myCurrentOffersTab = offersTabBar:addTab(tr('Current Offers'), currentOffersPanel)
offerHistoryPanel = g_ui.loadUI('ui/myoffers/offerhistory') offerHistoryPanel = g_ui.loadUI('ui/myoffers/offerhistory')
offersTabBar:addTab(tr('Offer History'), offerHistoryPanel) myOfferHistoryTab = offersTabBar:addTab(tr('Offer History'), offerHistoryPanel)
balanceLabel = marketWindow:getChildById('balanceLabel') balanceLabel = marketWindow:getChildById('balanceLabel')
mainTabBar.onTabChange = function(widget, tab) mainTabBar.onTabChange = function(widget, tab)
if tab == myOffersTab then if tab == myOffersTab then
Market.refreshMyOffers() local ctab = offersTabBar:getCurrentTab()
if ctab == myCurrentOffersTab then
Market.refreshMyOffers()
elseif ctab == myOfferHistoryTab then
Market.refreshMyOffersHistory()
end
else
Market.refreshOffers()
end
end
offersTabBar.onTabChange = function(widget, tab)
if tab == myCurrentOffersTab then
Market.refreshMyOffers()
elseif tab == myOfferHistoryTab then
Market.refreshMyOffersHistory()
end end
end end
@ -859,6 +948,8 @@ local function initInterface()
-- setup my offers -- setup my offers
buyMyOfferTable = currentOffersPanel:recursiveGetChildById('myBuyingTable') buyMyOfferTable = currentOffersPanel:recursiveGetChildById('myBuyingTable')
sellMyOfferTable = currentOffersPanel:recursiveGetChildById('mySellingTable') sellMyOfferTable = currentOffersPanel:recursiveGetChildById('mySellingTable')
myOfferHistoryTabel = offerHistoryPanel:recursiveGetChildById('myHistoryTable')
buyMyOfferTable.onSelectionChange = onSelectMyBuyOffer buyMyOfferTable.onSelectionChange = onSelectMyBuyOffer
sellMyOfferTable.onSelectionChange = onSelectMySellOffer sellMyOfferTable.onSelectionChange = onSelectMySellOffer
@ -878,6 +969,7 @@ local function initInterface()
buyMyOfferTable:setSorting(3, TABLE_SORTING_DESC) buyMyOfferTable:setSorting(3, TABLE_SORTING_DESC)
sellMyOfferTable:setSorting(3, TABLE_SORTING_DESC) sellMyOfferTable:setSorting(3, TABLE_SORTING_DESC)
myOfferHistoryTabel:setSorting(6, TABLE_SORTING_DESC)
end end
function init() function init()
@ -937,9 +1029,18 @@ function Market.updateCategories()
subCategoryList:clearOptions() subCategoryList:clearOptions()
local categories = {} local categories = {}
local addedCategories = {}
for _, c in ipairs(g_things.getMarketCategories()) do for _, c in ipairs(g_things.getMarketCategories()) do
table.insert(categories, getMarketCategoryName(c) or "Unknown") table.insert(categories, getMarketCategoryName(c) or "Unknown")
addedCategories[c] = true
end end
for c, items in ipairs(marketItems) do
if #items > 0 and not addedCategories[c] then
table.insert(categories, getMarketCategoryName(c) or "Unknown")
addedCategories[c] = true
end
end
table.sort(categories) table.sort(categories)
for _, c in ipairs(categories) do for _, c in ipairs(categories) do
categoryList:addOption(c) categoryList:addOption(c)
@ -993,6 +1094,9 @@ function Market.isOfferSelected(type)
end end
function Market.getDepotCount(itemId) function Market.getDepotCount(itemId)
if not information.depotItems then
return 0
end
return information.depotItems[itemId] or 0 return information.depotItems[itemId] or 0
end end
@ -1108,7 +1212,12 @@ function Market.refreshOffers()
if Market.isItemSelected() then if Market.isItemSelected() then
Market.onItemBoxChecked(selectedItem.ref) Market.onItemBoxChecked(selectedItem.ref)
else else
Market.refreshMyOffers() local ctab = offersTabBar:getCurrentTab()
if ctab == myCurrentOffersTab then
Market.refreshMyOffers()
elseif ctab == myOfferHistoryTab then
Market.refreshMyOffersHistory()
end
end end
end end
@ -1117,6 +1226,11 @@ function Market.refreshMyOffers()
MarketProtocol.sendMarketBrowseMyOffers() MarketProtocol.sendMarketBrowseMyOffers()
end end
function Market.refreshMyOffersHistory()
clearMyOffers()
MarketProtocol.sendMarketBrowseMyHistory()
end
function Market.loadMarketItems(category) function Market.loadMarketItems(category)
clearItems() clearItems()
@ -1242,9 +1356,9 @@ end
-- protocol callback functions -- protocol callback functions
function Market.onMarketEnter(depotItems, offers, balance, vocation) function Market.onMarketEnter(depotItems, offers, balance, vocation, items)
if not loaded then if not loaded or (items and #items > 0) then
initMarketItems() initMarketItems(items)
loaded = true loaded = true
end end
@ -1301,8 +1415,12 @@ function Market.onMarketDetail(itemId, descriptions, purchaseStats, saleStats)
updateDetails(itemId, descriptions, purchaseStats, saleStats) updateDetails(itemId, descriptions, purchaseStats, saleStats)
end end
function Market.onMarketBrowse(offers) function Market.onMarketBrowse(offers, offersType)
updateOffers(offers) if offersType == MarketRequest.MyHistory then
updateHistoryOffers(offers)
else
updateOffers(offers)
end
end end
function Market.onCoinBalance(coins, transferableCoins) function Market.onCoinBalance(coins, transferableCoins)

View File

@ -39,15 +39,31 @@ end
-- parsing protocols -- parsing protocols
local function parseMarketEnter(protocol, msg) local function parseMarketEnter(protocol, msg)
local items
if g_game.getClientVersion() < 944 then
items = {}
local itemsCount = msg:getU16()
for i = 1, itemsCount do
local itemId = msg:getU16()
local category = msg:getU8()
local name = msg:getString()
table.insert(items, {
id = itemId,
category = category,
name = name
})
end
end
local balance local balance
if g_game.getClientVersion() >= 981 then if g_game.getClientVersion() >= 981 or g_game.getClientVersion() < 944 then
balance = msg:getU64() balance = msg:getU64()
else else
balance = msg:getU32() balance = msg:getU32()
end end
local vocation = -1 local vocation = -1
if g_game.getClientVersion() < 950 then if g_game.getClientVersion() >= 944 and g_game.getClientVersion() < 950 then
vocation = msg:getU8() -- get vocation id vocation = msg:getU8() -- get vocation id
end end
local offers = msg:getU8() local offers = msg:getU8()
@ -61,7 +77,7 @@ local function parseMarketEnter(protocol, msg)
depotItems[itemId] = itemCount depotItems[itemId] = itemCount
end end
signalcall(Market.onMarketEnter, depotItems, offers, balance, vocation) signalcall(Market.onMarketEnter, depotItems, offers, balance, vocation, items)
return true return true
end end
@ -134,7 +150,7 @@ local function parseMarketBrowse(protocol, msg)
table.insert(offers, readMarketOffer(msg, MarketAction.Sell, var)) table.insert(offers, readMarketOffer(msg, MarketAction.Sell, var))
end end
signalcall(Market.onMarketBrowse, offers) signalcall(Market.onMarketBrowse, offers, var)
return true return true
end end
@ -215,6 +231,10 @@ function MarketProtocol.sendMarketBrowseMyOffers()
MarketProtocol.sendMarketBrowse(MarketRequest.MyOffers) MarketProtocol.sendMarketBrowse(MarketRequest.MyOffers)
end end
function MarketProtocol.sendMarketBrowseMyHistory()
MarketProtocol.sendMarketBrowse(MarketRequest.MyHistory)
end
function MarketProtocol.sendMarketCreateOffer(type, spriteId, amount, price, anonymous) function MarketProtocol.sendMarketCreateOffer(type, spriteId, amount, price, anonymous)
if g_game.getFeature(GamePlayerMarket) then if g_game.getFeature(GamePlayerMarket) then
local msg = OutputMessage.create() local msg = OutputMessage.create()

View File

@ -46,17 +46,18 @@ Panel
text-offset: 0 2 text-offset: 0 2
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
margin-top: 44 margin-top: 20
margin-left: 6 margin-left: 6
Table Table
id: mySellingTable id: mySellingTable
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: prev.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: 150 height: 160
margin-top: 5 margin-top: 5
margin-bottom: 5 margin-bottom: 5
margin-left: 6
margin-right: 6 margin-right: 6
padding: 1 padding: 1
focusable: false focusable: false
@ -82,10 +83,10 @@ Panel
width: 125 width: 125
OfferTableHeaderColumn OfferTableHeaderColumn
!text: tr('Amount') !text: tr('Amount')
width: 110 width: 100
OfferTableHeaderColumn OfferTableHeaderColumn
!text: tr('Auction End') !text: tr('Auction End')
width: 110 width: 120
TableData TableData
id: mySellingTableData id: mySellingTableData
@ -103,34 +104,35 @@ Panel
step: 28 step: 28
pixels-scroll: true pixels-scroll: true
Label
!text: tr('Buy Offers')
font: verdana-11px-rounded
text-offset: 0 2
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 20
margin-left: 6
Button Button
id: buyCancelButton id: buyCancelButton
!text: tr('Cancel') !text: tr('Cancel')
anchors.right: parent.right anchors.right: parent.right
anchors.top: prev.bottom anchors.bottom: prev.bottom
margin-top: 5 margin-top: 5
margin-right: 6 margin-right: 6
width: 80 width: 80
enabled: false enabled: false
Label
!text: tr('Buy Offers')
font: verdana-11px-rounded
text-offset: 0 2
anchors.top: prev.top
anchors.left: parent.left
margin-top: 9
margin-left: 6
Table Table
id: myBuyingTable id: myBuyingTable
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: prev.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
margin-top: 5 margin-top: 5
margin-bottom: 5 margin-bottom: 5
margin-left: 6
margin-right: 6 margin-right: 6
height: 150 height: 160
padding: 1 padding: 1
focusable: false focusable: false
background-color: #222833 background-color: #222833
@ -155,10 +157,10 @@ Panel
width: 125 width: 125
OfferTableHeaderColumn OfferTableHeaderColumn
!text: tr('Amount') !text: tr('Amount')
width: 110 width: 100
OfferTableHeaderColumn OfferTableHeaderColumn
!text: tr('Auction End') !text: tr('Auction End')
width: 110 width: 120
TableData TableData
id: myBuyingTableData id: myBuyingTableData

View File

@ -2,8 +2,60 @@ Panel
background-color: #22283399 background-color: #22283399
margin: 1 margin: 1
Label Table
!text: tr('Offer History') id: myHistoryTable
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
margin-left: 10 anchors.right: parent.right
height: 390
margin-top: 5
margin-bottom: 5
margin-left: 8
margin-right: 8
padding: 1
focusable: false
background-color: #222833
border-width: 1
border-color: #191f27
table-data: myHistoryTableData
row-style: OfferTableRow
column-style: OfferTableColumn
header-column-style: false
header-row-style: false
OfferTableHeaderRow
id: header
OfferTableHeaderColumn
!text: tr('Action')
width: 60
OfferTableHeaderColumn
!text: tr('Item Name')
width: 140
OfferTableHeaderColumn
!text: tr('Total Price')
width: 115
OfferTableHeaderColumn
!text: tr('Piece Price')
width: 115
OfferTableHeaderColumn
!text: tr('Amount')
width: 75
OfferTableHeaderColumn
!text: tr('Auction End')
width: 120
TableData
id: myHistoryTableData
anchors.bottom: myHistoryTable.bottom
anchors.left: myHistoryTable.left
anchors.right: myHistoryTable.right
margin-top: 2
vertical-scrollbar: myHistoryTableScrollBar
VerticalScrollBar
id: myHistoryTableScrollBar
anchors.top: myHistoryTable.top
anchors.bottom: myHistoryTable.bottom
anchors.right: myHistoryTable.right
step: 28
pixels-scroll: true

View File

@ -54,7 +54,9 @@ end
function setupSelector(widget, id, outfit, list) function setupSelector(widget, id, outfit, list)
widget:setId(id) widget:setId(id)
widget.title:setText(id:gsub("^%l", string.upper)) widget.title:setText(id:gsub("^%l", string.upper))
table.insert(list, 1, {0, "-"}) if id ~= "type" or #list == 0 then
table.insert(list, 1, {0, "-"})
end
local pos = 1 local pos = 1
for i, o in pairs(list) do for i, o in pairs(list) do

View File

@ -46,7 +46,7 @@ OutfitSelectorPanel < Panel
MainWindow MainWindow
!text: tr('Select Outfit') !text: tr('Select Outfit')
size: 540 330 size: 560 330
@onEnter: modules.game_outfit.accept() @onEnter: modules.game_outfit.accept()
@onEscape: modules.game_outfit.destroy() @onEscape: modules.game_outfit.destroy()
@ -162,7 +162,7 @@ MainWindow
layout: layout:
type: horizontalBox type: horizontalBox
fit-children: true fit-children: true
spacing: 3 spacing: 8
Button Button
id: outfitOkButton id: outfitOkButton

View File

@ -0,0 +1,7 @@
function init()
end
function terminate()
end

View File

@ -0,0 +1,11 @@
Module
name: game_protocol
description: Game protocol
author: otclientv8
website: http://otclient.ovh
scripts: [ protocol ]
sandboxed: true
autoload: true
autoload-priority: 500
@onLoad: init()
@onUnload: terminate()

View File

@ -202,11 +202,11 @@ MiniWindow
SmallSkillButton SmallSkillButton
id: skillId11 id: skillId11
SkillNameLabel SkillNameLabel
!text: tr('Life Leech Chance') !text: tr('Mana Leech Chance')
SkillValueLabel SkillValueLabel
SmallSkillButton SmallSkillButton
id: skillId12 id: skillId12
SkillNameLabel SkillNameLabel
!text: tr('Life Leech Amount') !text: tr('Mana Leech Amount')
SkillValueLabel SkillValueLabel

View File

@ -377,7 +377,6 @@ function walk(dir, ticks)
return return
elseif not toTile then elseif not toTile then
player:lockWalk(100) -- bug fix for missing stairs down on map player:lockWalk(100) -- bug fix for missing stairs down on map
return
else else
if g_app.isMobile() and dir <= Directions.West then if g_app.isMobile() and dir <= Directions.West then
turn(dir, ticks > 0) turn(dir, ticks > 0)

View File

@ -189,6 +189,7 @@ GameWingsAndAura = 104
GamePlayerStateU32 = 105 GamePlayerStateU32 = 105
GameOutfitShaders = 106 GameOutfitShaders = 106
GameForceAllowItemHotkeys = 107 GameForceAllowItemHotkeys = 107
GameCountU16 = 108
GamePacketSizeU32 = 110 GamePacketSizeU32 = 110
GamePacketCompression = 111 GamePacketCompression = 111

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -102,7 +102,7 @@ public:
void sendRefreshContainer(int containerId); void sendRefreshContainer(int containerId);
void sendRequestOutfit(); void sendRequestOutfit();
void sendChangeOutfit(const Outfit& outfit); void sendChangeOutfit(const Outfit& outfit);
void sendMountStatus(bool mount); void sendOutfitExtensionStatus(int mount = -1, int wings = -1, int aura = -1, int shader = -1);
void sendApplyImbuement(uint8_t slot, uint32_t imbuementId, bool protectionCharm); void sendApplyImbuement(uint8_t slot, uint32_t imbuementId, bool protectionCharm);
void sendClearImbuement(uint8_t slot); void sendClearImbuement(uint8_t slot);
void sendCloseImbuingWindow(); void sendCloseImbuingWindow();

View File

@ -1337,7 +1337,7 @@ void ProtocolGame::parseOpenNpcTrade(const InputMessagePtr& msg)
for (int i = 0; i < listCount; ++i) { for (int i = 0; i < listCount; ++i) {
uint16 itemId = msg->getU16(); uint16 itemId = msg->getU16();
uint8 count = msg->getU8(); uint16 count = g_game.getFeature(Otc::GameCountU16) ? msg->getU16() : msg->getU8();
ItemPtr item = Item::create(itemId); ItemPtr item = Item::create(itemId);
item->setCountOrSubType(count); item->setCountOrSubType(count);
@ -2653,7 +2653,7 @@ void ProtocolGame::parseItemInfo(const InputMessagePtr& msg)
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
ItemPtr item(new Item); ItemPtr item(new Item);
item->setId(msg->getU16()); item->setId(msg->getU16());
item->setCountOrSubType(msg->getU8()); item->setCountOrSubType(g_game.getFeature(Otc::GameCountU16) ? msg->getU16() : msg->getU8());
std::string desc = msg->getString(); std::string desc = msg->getString();
list.push_back(std::make_tuple(item, desc)); list.push_back(std::make_tuple(item, desc));
@ -3267,9 +3267,13 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
g_logger.traceError("server said that a creature is known, but it's not"); g_logger.traceError("server said that a creature is known, but it's not");
} else { } else {
uint removeId = msg->getU32(); uint removeId = msg->getU32();
g_map.removeCreatureById(removeId);
uint id = msg->getU32(); uint id = msg->getU32();
if (id == removeId) {
creature = g_map.getCreatureById(id);
} else {
g_map.removeCreatureById(removeId);
}
int creatureType; int creatureType;
if (g_game.getClientVersion() >= 910) if (g_game.getClientVersion() >= 910)
@ -3288,28 +3292,32 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
std::string name = g_game.formatCreatureName(msg->getString()); std::string name = g_game.formatCreatureName(msg->getString());
if (id == m_localPlayer->getId())
creature = m_localPlayer;
else if (creatureType == Proto::CreatureTypePlayer) {
// fixes a bug server side bug where GameInit is not sent and local player id is unknown
if (m_localPlayer->getId() == 0 && name == m_localPlayer->getName())
creature = m_localPlayer;
else
creature = PlayerPtr(new Player);
} else if (creatureType == Proto::CreatureTypeMonster)
creature = MonsterPtr(new Monster);
else if (creatureType == Proto::CreatureTypeNpc)
creature = NpcPtr(new Npc);
else if (creatureType == Proto::CreatureTypeSummonOwn) {
creature = MonsterPtr(new Monster);
} else
g_logger.traceError("creature type is invalid");
if (creature) { if (creature) {
creature->setId(id);
creature->setName(name); creature->setName(name);
} else {
if (id == m_localPlayer->getId())
creature = m_localPlayer;
else if (creatureType == Proto::CreatureTypePlayer) {
// fixes a bug server side bug where GameInit is not sent and local player id is unknown
if (m_localPlayer->getId() == 0 && name == m_localPlayer->getName())
creature = m_localPlayer;
else
creature = PlayerPtr(new Player);
} else if (creatureType == Proto::CreatureTypeMonster)
creature = MonsterPtr(new Monster);
else if (creatureType == Proto::CreatureTypeNpc)
creature = NpcPtr(new Npc);
else if (creatureType == Proto::CreatureTypeSummonOwn) {
creature = MonsterPtr(new Monster);
} else
g_logger.traceError("creature type is invalid");
g_map.addCreature(creature); if (creature) {
creature->setId(id);
creature->setName(name);
g_map.addCreature(creature);
}
} }
} }
@ -3431,7 +3439,7 @@ ItemPtr ProtocolGame::getItem(const InputMessagePtr& msg, int id, bool hasDescri
} }
if (item->isStackable() || item->isFluidContainer() || item->isSplash() || item->isChargeable()) if (item->isStackable() || item->isFluidContainer() || item->isSplash() || item->isChargeable())
item->setCountOrSubType(msg->getU8()); item->setCountOrSubType(g_game.getFeature(Otc::GameCountU16) ? msg->getU16() : msg->getU8());
else if (item->rawGetThingType()->isContainer() && g_game.getFeature(Otc::GameTibia12Protocol)) { else if (item->rawGetThingType()->isContainer() && g_game.getFeature(Otc::GameTibia12Protocol)) {
// not sure about this part // not sure about this part
uint8_t hasQuickLootFlags = msg->getU8(); uint8_t hasQuickLootFlags = msg->getU8();

View File

@ -348,7 +348,10 @@ void ProtocolGame::sendEquipItem(int itemId, int countOrSubType)
OutputMessagePtr msg(new OutputMessage); OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientEquipItem); msg->addU8(Proto::ClientEquipItem);
msg->addU16(itemId); msg->addU16(itemId);
msg->addU8(countOrSubType); if (g_game.getFeature(Otc::GameCountU16))
msg->addU16(countOrSubType);
else
msg->addU8(countOrSubType);
send(msg); send(msg);
} }
@ -360,7 +363,10 @@ void ProtocolGame::sendMove(const Position& fromPos, int thingId, int stackpos,
msg->addU16(thingId); msg->addU16(thingId);
msg->addU8(stackpos); msg->addU8(stackpos);
addPosition(msg, toPos); addPosition(msg, toPos);
msg->addU8(count); if(g_game.getFeature(Otc::GameCountU16))
msg->addU16(count);
else
msg->addU8(count);
send(msg); send(msg);
} }
@ -369,7 +375,10 @@ void ProtocolGame::sendInspectNpcTrade(int itemId, int count)
OutputMessagePtr msg(new OutputMessage); OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientInspectNpcTrade); msg->addU8(Proto::ClientInspectNpcTrade);
msg->addU16(itemId); msg->addU16(itemId);
msg->addU8(count); if (g_game.getFeature(Otc::GameCountU16))
msg->addU16(count);
else
msg->addU8(count);
send(msg); send(msg);
} }
@ -830,7 +839,7 @@ void ProtocolGame::sendChangeOutfit(const Outfit& outfit)
void ProtocolGame::sendOutfitExtensionStatus(int mount, int wings, int aura, int shader) void ProtocolGame::sendOutfitExtensionStatus(int mount, int wings, int aura, int shader)
{ {
if(g_game.getFeature(Otc::GamePlayerMounts) || g_game.getFeature(Otc::GameWingsAndAura) || g_game.getFeature(Otc::GameWingsAndAura)) { if(g_game.getFeature(Otc::GamePlayerMounts) || g_game.getFeature(Otc::GameWingsAndAura) || g_game.getFeature(Otc::GameOutfitShaders)) {
OutputMessagePtr msg(new OutputMessage); OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientMount); msg->addU8(Proto::ClientMount);
if (g_game.getFeature(Otc::GamePlayerMounts)) { if (g_game.getFeature(Otc::GamePlayerMounts)) {