Added Market/MarketProtocol module to begin the construction of the Market! Fixed some Minor Issues, and Some Cosmetics
* Added new protocol lib. * Added missing Game Features to game/const.lua * Added new Market module that will handle the market/market protocols too. * Finished Market protocol and begun on the market structure (MarketOffer etc). * Removed any traces of market protocol in the core (I think). * Moved minimap images to /images. * Removed old zoom images for minimap. * Fixed a bug with randomize outfit.
|
@ -16,5 +16,6 @@ Module
|
|||
dofile 'settings'
|
||||
dofile 'keyboard'
|
||||
dofile 'mouse'
|
||||
dofile 'protocol'
|
||||
|
||||
dofiles 'ui'
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
GameServerOpcodes = {
|
||||
GameServerInitGame = 10,
|
||||
GameServerGMActions = 11,
|
||||
GameServerLoginError = 20,
|
||||
GameServerLoginAdvice = 21,
|
||||
GameServerLoginWait = 22,
|
||||
GameServerPingBack = 29,
|
||||
GameServerPing = 30,
|
||||
GameServerChallange = 31,
|
||||
GameServerDeath = 40,
|
||||
|
||||
-- all in game opcodes must be greater than 50
|
||||
GameServerFirstGameOpcode = 50,
|
||||
|
||||
-- otclient ONLY
|
||||
GameServerExtendedOpcode = 50,
|
||||
|
||||
-- NOTE: add any custom opcodes in this range
|
||||
-- 51 - 99
|
||||
|
||||
-- original tibia ONLY
|
||||
GameServerFullMap = 100,
|
||||
GameServerMapTopRow = 101,
|
||||
GameServerMapRightRow = 102,
|
||||
GameServerMapBottomRow = 103,
|
||||
GameServerMapLeftRow = 104,
|
||||
GameServerUpdateTile = 105,
|
||||
GameServerCreateOnMap = 106,
|
||||
GameServerChangeOnMap = 107,
|
||||
GameServerDeleteOnMap = 108,
|
||||
GameServerMoveCreature = 109,
|
||||
GameServerOpenContainer = 110,
|
||||
GameServerCloseContainer = 111,
|
||||
GameServerCreateContainer = 112,
|
||||
GameServerChangeInContainer = 113,
|
||||
GameServerDeleteInContainer = 114,
|
||||
GameServerSetInventory = 120,
|
||||
GameServerDeleteInventory = 121,
|
||||
GameServerOpenNpcTrade = 122,
|
||||
GameServerPlayerGoods = 123,
|
||||
GameServerCloseNpcTrade = 124,
|
||||
GameServerOwnTrade = 125,
|
||||
GameServerCounterTrade = 126,
|
||||
GameServerCloseTrade = 127,
|
||||
GameServerAmbient = 130,
|
||||
GameServerGraphicalEffect = 131,
|
||||
GameServerTextEffect = 132,
|
||||
GameServerMissleEffect = 133,
|
||||
GameServerMarkCreature = 134,
|
||||
GameServerTrappers = 135,
|
||||
GameServerCreatureHealth = 140,
|
||||
GameServerCreatureLight = 141,
|
||||
GameServerCreatureOutfit = 142,
|
||||
GameServerCreatureSpeed = 143,
|
||||
GameServerCreatureSkull = 144,
|
||||
GameServerCreatureParty = 145,
|
||||
GameServerCreatureUnpass = 146,
|
||||
GameServerEditText = 150,
|
||||
GameServerEditList = 151,
|
||||
GameServerPlayerDataBasic = 159, -- 910
|
||||
GameServerPlayerData = 160,
|
||||
GameServerPlayerSkills = 161,
|
||||
GameServerPlayerState = 162,
|
||||
GameServerClearTarget = 163,
|
||||
GameServerSpellDelay = 164, --870
|
||||
GameServerSpellGroupDelay = 165, -- 870
|
||||
GameServerMultiUseDelay = 166, -- 870
|
||||
GameServerTalk = 170,
|
||||
GameServerChannels = 171,
|
||||
GameServerOpenChannel = 172,
|
||||
GameServerOpenPrivateChannel = 173,
|
||||
GameServerRuleViolationChannel = 174,
|
||||
GameServerRuleViolationRemove = 175,
|
||||
GameServerRuleViolationCancel = 176,
|
||||
GameServerRuleViolationLock = 177,
|
||||
GameServerOpenOwnChannel = 178,
|
||||
GameServerCloseChannel = 179,
|
||||
GameServerTextMessage = 180,
|
||||
GameServerCancelWalk = 181,
|
||||
GameServerWalkWait = 182,
|
||||
GameServerFloorChangeUp = 190,
|
||||
GameServerFloorChangeDown = 191,
|
||||
GameServerChooseOutfit = 200,
|
||||
GameServerVipAdd = 210,
|
||||
GameServerVipLogin = 211,
|
||||
GameServerVipLogout = 212,
|
||||
GameServerTutorialHint = 220,
|
||||
GameServerAutomapFlag = 221,
|
||||
GameServerQuestLog = 240,
|
||||
GameServerQuestLine = 241,
|
||||
GameServerChannelEvent = 243, -- 910
|
||||
GameServerItemInfo = 244, -- 910
|
||||
GameServerPlayerInventory = 245, -- 910
|
||||
GameServerMarketEnter = 246, -- 944
|
||||
GameServerMarketLeave = 247, -- 944
|
||||
GameServerMarketDetail = 248, -- 944
|
||||
GameServerMarketBrowse = 249 -- 944
|
||||
}
|
||||
|
||||
ClientOpcodes = {
|
||||
ClientEnterAccount = 1,
|
||||
ClientEnterGame = 10,
|
||||
ClientLeaveGame = 20,
|
||||
ClientPing = 29,
|
||||
ClientPingBack = 30,
|
||||
|
||||
-- all in game opcodes must be equal or greater than 50
|
||||
ClientFirstGameOpcode = 50,
|
||||
|
||||
-- otclient ONLY
|
||||
ClientExtendedOpcode = 50,
|
||||
|
||||
-- NOTE: add any custom opcodes in this range
|
||||
-- 51 - 99
|
||||
|
||||
-- original tibia ONLY
|
||||
ClientAutoWalk = 100,
|
||||
ClientWalkNorth = 101,
|
||||
ClientWalkEast = 102,
|
||||
ClientWalkSouth = 103,
|
||||
ClientWalkWest = 104,
|
||||
ClientStop = 105,
|
||||
ClientWalkNorthEast = 106,
|
||||
ClientWalkSouthEast = 107,
|
||||
ClientWalkSouthWest = 108,
|
||||
ClientWalkNorthWest = 109,
|
||||
ClientTurnNorth = 111,
|
||||
ClientTurnEast = 112,
|
||||
ClientTurnSouth = 113,
|
||||
ClientTurnWest = 114,
|
||||
ClientEquipItem = 119, -- 910
|
||||
ClientMove = 120,
|
||||
ClientInspectNpcTrade = 121,
|
||||
ClientBuyItem = 122,
|
||||
ClientSellItem = 123,
|
||||
ClientCloseNpcTrade = 124,
|
||||
ClientRequestTrade = 125,
|
||||
ClientInspectTrade = 126,
|
||||
ClientAcceptTrade = 127,
|
||||
ClientRejectTrade = 128,
|
||||
ClientUseItem = 130,
|
||||
ClientUseItemWith = 131,
|
||||
ClientUseOnCreature = 132,
|
||||
ClientRotateItem = 133,
|
||||
ClientCloseContainer = 135,
|
||||
ClientUpContainer = 136,
|
||||
ClientEditText = 137,
|
||||
ClientEditList = 138,
|
||||
ClientLook = 140,
|
||||
ClientTalk = 150,
|
||||
ClientRequestChannels = 151,
|
||||
ClientJoinChannel = 152,
|
||||
ClientLeaveChannel = 153,
|
||||
ClientOpenPrivateChannel = 154,
|
||||
ClientCloseNpcChannel = 158,
|
||||
ClientChangeFightModes = 160,
|
||||
ClientAttack = 161,
|
||||
ClientFollow = 162,
|
||||
ClientInviteToParty = 163,
|
||||
ClientJoinParty = 164,
|
||||
ClientRevokeInvitation = 165,
|
||||
ClientPassLeadership = 166,
|
||||
ClientLeaveParty = 167,
|
||||
ClientShareExperience = 168,
|
||||
ClientDisbandParty = 169,
|
||||
ClientOpenOwnChannel = 170,
|
||||
ClientInviteToOwnChannel = 171,
|
||||
ClientExcludeFromOwnChannel = 172,
|
||||
ClientCancelAttackAndFollow = 190,
|
||||
ClientRefreshContainer = 202,
|
||||
ClientRequestOutfit = 210,
|
||||
ClientChangeOutfit = 211,
|
||||
ClientMount = 212, -- 870
|
||||
ClientAddVip = 220,
|
||||
ClientRemoveVip = 221,
|
||||
ClientBugReport = 230,
|
||||
ClientRuleViolation = 231,
|
||||
ClientDebugReport = 232,
|
||||
ClientRequestQuestLog = 240,
|
||||
ClientRequestQuestLine = 241,
|
||||
ClientNewRuleViolation = 242, -- 910
|
||||
ClientRequestItemInfo = 243, -- 910
|
||||
ClientMarketLeave = 244, -- 944
|
||||
ClientMarketBrowse = 245, -- 944
|
||||
ClientMarketCreate = 246, -- 944
|
||||
ClientMarketCancel = 247, -- 944
|
||||
ClientMarketAccept = 248 -- 944
|
||||
}
|
|
@ -34,9 +34,6 @@ SouthEast = 5
|
|||
SouthWest = 6
|
||||
NorthWest = 7
|
||||
|
||||
ClientEnterAccount = 1
|
||||
ClientEnterGame = 10
|
||||
|
||||
LoginServerError = 10
|
||||
LoginServerMotd = 20
|
||||
LoginServerUpdateNeeded = 30
|
||||
|
@ -64,6 +61,8 @@ GameCreaturePassableInfo = 18
|
|||
GameItemAnimationPhase = 19
|
||||
GameTrucatedPingOpcode = 20
|
||||
GameReverseCreatureStack = 21
|
||||
GameMagicEffectU16 = 22
|
||||
GamePlayerMarket = 23
|
||||
|
||||
OTSERV_RSA = "109120132967399429278860960508995541528237502902798129123468757937266291492576446330739696001110603907230888610072655818825358503429057592827629436413108566029093628212635953836686562675849720620786279431090218017681061521755056710823876476444260558147179707119674283982419152118103759076030616683978566631413"
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ Module
|
|||
- game_shaders
|
||||
- game_playerdeath
|
||||
- game_playermount
|
||||
- game_market
|
||||
|
||||
@onLoad: |
|
||||
dofile 'const'
|
||||
|
@ -40,3 +41,4 @@ Module
|
|||
|
||||
dofile 'creature'
|
||||
dofile 'player'
|
||||
dofile 'market'
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
MarketAction = {
|
||||
Buy = 0,
|
||||
Sell = 1
|
||||
}
|
||||
|
||||
MarketRequest = {
|
||||
MyOffers = 0xFFFE,
|
||||
MyHistory = 0xFFFF
|
||||
}
|
||||
|
||||
MarketOfferState = {
|
||||
Active = 0,
|
||||
Cancelled = 1,
|
||||
Expired = 2,
|
||||
Accepted = 3,
|
||||
AcceptedEx = 255
|
||||
}
|
||||
|
||||
MarketItemDescription = {
|
||||
Armor = 1,
|
||||
Attack = 2,
|
||||
Container = 3,
|
||||
Defense = 4,
|
||||
General = 5,
|
||||
DecayTime = 6,
|
||||
Combat = 7,
|
||||
MinLevel = 8,
|
||||
MinMagicLevel = 9,
|
||||
Vocation = 10,
|
||||
Rune = 11,
|
||||
Ability = 12,
|
||||
Charges = 13,
|
||||
WeaponName = 14,
|
||||
Weight = 15,
|
||||
|
||||
First = Armor,
|
||||
Last = Weight
|
||||
}
|
|
@ -4,7 +4,7 @@ ProtocolLogin = extends(Protocol)
|
|||
-- private functions
|
||||
local function sendLoginPacket(protocol)
|
||||
local msg = OutputMessage.create()
|
||||
msg:addU8(ClientEnterAccount)
|
||||
msg:addU8(ClientOpcodes.ClientEnterAccount)
|
||||
msg:addU16(1) -- todo: ClientOs
|
||||
msg:addU16(g_game.getClientVersion())
|
||||
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
Market = {}
|
||||
|
||||
local marketWindow
|
||||
|
||||
function Market.init()
|
||||
g_ui.importStyle('market.otui')
|
||||
|
||||
end
|
||||
|
||||
function Market.terminate()
|
||||
marketWindow = nil
|
||||
Market = nil
|
||||
end
|
||||
|
||||
function Market.onMarketEnter(depotItems, offers, balance)
|
||||
-- open market window
|
||||
-- populate market?
|
||||
print('onMarketEnter')
|
||||
print(offers)
|
||||
print(balance)
|
||||
print('depotItems:')
|
||||
for k, item in pairs(depotItems) do
|
||||
print('id- '..item[1])
|
||||
print('count- '..item[2])
|
||||
end
|
||||
end
|
||||
|
||||
function Market.onMarketLeave()
|
||||
-- close market window?
|
||||
print('onMarketLeave')
|
||||
end
|
||||
|
||||
function Market.onMarketDetail(itemId, descriptions, purchaseStats, saleStats)
|
||||
-- populate market widget
|
||||
print('onMarketDetail')
|
||||
print(itemId)
|
||||
print('descriptions:')
|
||||
for k, desc in pairs(descriptions) do
|
||||
print('type- '..desc[1])
|
||||
print('description- '..desc[2])
|
||||
end
|
||||
print('purchaseStats:')
|
||||
for k, stat in pairs(purchaseStats) do
|
||||
print('transactions- '..stat[1])
|
||||
print('total price- '..stat[2])
|
||||
print('highest price- '..stat[3])
|
||||
print('lowest price- '..stat[4])
|
||||
end
|
||||
print('saleStats:')
|
||||
for k, stat in pairs(saleStats) do
|
||||
print('transactions- '..stat[1])
|
||||
print('total price- '..stat[2])
|
||||
print('highest price- '..stat[3])
|
||||
print('lowest price- '..stat[4])
|
||||
end
|
||||
end
|
||||
|
||||
function Market.onMarketBrowse(offers)
|
||||
-- populate market widget
|
||||
print('onMarketBrowse')
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
Module
|
||||
name: game_market
|
||||
description: Manage the Players Market system
|
||||
author: BeniS
|
||||
website: www.otclient.info
|
||||
|
||||
dependencies:
|
||||
- game
|
||||
|
||||
@onLoad: |
|
||||
dofile 'marketoffer'
|
||||
dofile 'marketprotocol'
|
||||
dofile 'market'
|
||||
MarketProtocol.init()
|
||||
Market.init()
|
||||
|
||||
@onUnload: |
|
||||
MarketProtocol.terminate()
|
||||
Market.terminate()
|
|
@ -0,0 +1,29 @@
|
|||
MarketWindow < MainWindow
|
||||
id: marketWindow
|
||||
!text: tr('Market')
|
||||
size: 350 155
|
||||
|
||||
Label
|
||||
!text: tr('Alas! Brave adventurer, you have met a sad fate.\nBut do not despair, for the gods will bring you back\ninto this world in exchange for a small sacrifice\n\nSimply click on Ok to resume your journeys!')
|
||||
width: 550
|
||||
height: 140
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
margin-left: 10
|
||||
margin-top: 2
|
||||
|
||||
Button
|
||||
id: buttonOk
|
||||
!text: tr('Ok')
|
||||
width: 64
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
margin-left: 160
|
||||
|
||||
Button
|
||||
id: buttonCancel
|
||||
!text: tr('Cancel')
|
||||
width: 64
|
||||
anchors.left: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-left: 5
|
|
@ -0,0 +1,137 @@
|
|||
MarketOffer = {}
|
||||
MarketOffer.__index = MarketOffer
|
||||
|
||||
local OFFER_TIMESTAMP = 1
|
||||
local OFFER_COUNTER = 2
|
||||
|
||||
MarketOffer.new = function(offerId, action, itemId, amount, price, playerName, state)
|
||||
local offer = {
|
||||
id = {},
|
||||
action = nil,
|
||||
item = 0,
|
||||
amount = 0,
|
||||
price = 0,
|
||||
player = '',
|
||||
state = 0
|
||||
}
|
||||
|
||||
if not offerId or type(offerId) ~= 'table' then
|
||||
g_logger.error('MarketOffer.new - invalid offer id provided.')
|
||||
end
|
||||
offer.id = offerId
|
||||
|
||||
action = tonumber(action)
|
||||
if action ~= MarketAction.Buy and action ~= MarketAction.Sell then
|
||||
g_logger.error('MarketOffer.new - invalid action provided.')
|
||||
end
|
||||
offer.action = action
|
||||
|
||||
offer.item = itemId
|
||||
offer.amount = amount
|
||||
offer.price = price
|
||||
offer.player = playerName
|
||||
|
||||
state = tonumber(state)
|
||||
if state ~= MarketOfferState.Active and state ~= MarketOfferState.Cancelled
|
||||
and state ~= MarketOfferState.Expired and state ~= MarketOfferState.Accepted then
|
||||
g_logger.error('MarketOffer.new - invalid state provided.')
|
||||
end
|
||||
offer.state = state
|
||||
|
||||
setmetatable(offer, MarketOffer)
|
||||
return offer
|
||||
end
|
||||
|
||||
function MarketOffer:isEqual(offer)
|
||||
return self.offer[OFFER_TIMESTAMP] == offer[OFFER_TIMESTAMP] and self.offer[OFFER_COUNTER] == offer[OFFER_COUNTER]
|
||||
end
|
||||
|
||||
function MarketOffer:isLessThan(offer)
|
||||
return self.offer[OFFER_TIMESTAMP] <= offer[OFFER_TIMESTAMP] and self.offer[OFFER_COUNTER] < offer[OFFER_COUNTER]
|
||||
end
|
||||
|
||||
function MarketOffer:isNull(offer)
|
||||
return table.empty(self.id)
|
||||
end
|
||||
|
||||
-- Sets/Gets
|
||||
|
||||
function MarketOffer:setId(id)
|
||||
if not id or type(id) ~= 'table' then
|
||||
g_logger.error('MarketOffer.setId - invalid id provided.')
|
||||
end
|
||||
self.id = id
|
||||
end
|
||||
|
||||
function MarketOffer:getId()
|
||||
return self.id
|
||||
end
|
||||
|
||||
function MarketOffer:setItem(item)
|
||||
if not item or type(item) ~= 'number' then
|
||||
g_logger.error('MarketOffer.setItem - invalid item id provided.')
|
||||
end
|
||||
self.item = item
|
||||
end
|
||||
|
||||
function MarketOffer:getItem()
|
||||
return self.item
|
||||
end
|
||||
|
||||
function MarketOffer:setAmount(amount)
|
||||
if not amount or type(amount) ~= 'number' then
|
||||
g_logger.error('MarketOffer.setAmount - invalid amount provided.')
|
||||
end
|
||||
self.amount = amount
|
||||
end
|
||||
|
||||
function MarketOffer:getAmount()
|
||||
return self.amount
|
||||
end
|
||||
|
||||
function MarketOffer:setPrice(price)
|
||||
if not price or type(price) ~= 'number' then
|
||||
g_logger.error('MarketOffer.setPrice - invalid price provided.')
|
||||
end
|
||||
self.price = price
|
||||
end
|
||||
|
||||
function MarketOffer:getPrice()
|
||||
return self.price
|
||||
end
|
||||
|
||||
function MarketOffer:setPlayer(player)
|
||||
if not player or type(player) ~= 'number' then
|
||||
g_logger.error('MarketOffer.setPlayer - invalid player provided.')
|
||||
end
|
||||
self.player = player
|
||||
end
|
||||
|
||||
function MarketOffer:getPlayer()
|
||||
return self.player
|
||||
end
|
||||
|
||||
function MarketOffer:setState(state)
|
||||
if not state or type(state) ~= 'number' then
|
||||
g_logger.error('MarketOffer.setState - invalid state provided.')
|
||||
end
|
||||
self.state = state
|
||||
end
|
||||
|
||||
function MarketOffer:getState()
|
||||
return self.state
|
||||
end
|
||||
|
||||
function MarketOffer:getTimeStamp()
|
||||
if table.empty(self.id) or #self.id < OFFER_TIMESTAMP then
|
||||
return
|
||||
end
|
||||
return self.id[OFFER_TIMESTAMP]
|
||||
end
|
||||
|
||||
function MarketOffer:getCounter()
|
||||
if table.empty(self.id) or #self.id < OFFER_COUNTER then
|
||||
return
|
||||
end
|
||||
return self.id[OFFER_COUNTER]
|
||||
end
|
|
@ -0,0 +1,204 @@
|
|||
MarketProtocol = {}
|
||||
|
||||
local market
|
||||
|
||||
-- private functions
|
||||
|
||||
function parseOpcode(protocol, opcode, msg)
|
||||
if not g_game.getFeature(GamePlayerMarket) then
|
||||
return false
|
||||
end
|
||||
|
||||
-- process msg
|
||||
if opcode == GameServerOpcodes.GameServerMarketEnter then
|
||||
parseMarketEnter(msg)
|
||||
elseif opcode == GameServerOpcodes.GameServerMarketLeave then
|
||||
parseMarketLeave(msg)
|
||||
elseif opcode == GameServerOpcodes.GameServerMarketDetail then
|
||||
parseMarketDetail(msg)
|
||||
elseif opcode == GameServerOpcodes.GameServerMarketBrowse then
|
||||
parseMarketBrowse(msg)
|
||||
else
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function send(msg)
|
||||
print(msg:getMessageSize())
|
||||
g_game.getProtocolGame():safeSend(msg)
|
||||
end
|
||||
|
||||
function readMarketOffer(msg, action, var)
|
||||
local timestamp = msg:getU32()
|
||||
local counter = msg:getU16()
|
||||
|
||||
local itemId = 0
|
||||
if var == MarketRequest.MyOffers or var == MarketRequest.MyHistory then
|
||||
itemId = msg:getU16()
|
||||
else
|
||||
itemId = var
|
||||
end
|
||||
|
||||
local amount = msg:getU16()
|
||||
local price = msg:getU32()
|
||||
local playerName
|
||||
local state = MarketOfferState.Active
|
||||
if var == MarketRequest.MyHistory then
|
||||
state = msg:getU8()
|
||||
else
|
||||
playerName = msg:getString()
|
||||
end
|
||||
|
||||
return MarketOffer.new({timestamp, counter}, action, itemId, amount, price, playerName, state)
|
||||
end
|
||||
|
||||
-- parsing protocols
|
||||
|
||||
function parseMarketEnter(msg)
|
||||
local balance = msg:getU32()
|
||||
local offers = msg:getU8()
|
||||
local depotItems = {}
|
||||
|
||||
local depotCount = (msg:getU16() - 1)
|
||||
for i = 0, depotCount do
|
||||
local itemId = msg:getU16() -- item id
|
||||
local itemCount = msg:getU16() -- item count
|
||||
|
||||
table.insert(depotItems, {itemId, itemCount})
|
||||
end
|
||||
|
||||
Market.onMarketEnter(depotItems, offers, balance)
|
||||
end
|
||||
|
||||
function parseMarketLeave(msg)
|
||||
Market.onMarketLeave()
|
||||
end
|
||||
|
||||
function parseMarketDetail(msg)
|
||||
local itemId = msg:getU16()
|
||||
|
||||
local descriptions = {}
|
||||
for i = MarketItemDescription.First, MarketItemDescription.Last do
|
||||
if msg:peekU16() ~= 0x00 then
|
||||
table.insert(descriptions, {i, msg:getString()})
|
||||
else
|
||||
msg:getU16()
|
||||
end
|
||||
end
|
||||
|
||||
local purchaseStats = {}
|
||||
if msg:getU8() == 0x01 then
|
||||
local transactions = msg:getU32() -- transaction count
|
||||
local totalPrice = msg:getU32() -- total price
|
||||
local highestPrice = msg:getU32() -- highest price
|
||||
local lowestPrice = msg: getU32() -- lowest price
|
||||
|
||||
table.insert(purchaseStats, {transaction, totalPrice, highestPrice, lowestPrice})
|
||||
end
|
||||
|
||||
local saleStats = {}
|
||||
if msg:getU8() == 0x01 then
|
||||
local transactions = msg:getU32() -- transaction count
|
||||
local totalPrice = msg:getU32() -- total price
|
||||
local highestPrice = msg:getU32() -- highest price
|
||||
local lowestPrice = msg: getU32() -- lowest price
|
||||
|
||||
table.insert(saleStats, {transaction, totalPrice, highestPrice, lowestPrice})
|
||||
end
|
||||
|
||||
Market.onMarketDetail(itemId, descriptions, purchaseStats, saleStats)
|
||||
end
|
||||
|
||||
function parseMarketBrowse(msg)
|
||||
local var = msg:getU16()
|
||||
local offers = {}
|
||||
|
||||
local buyOfferCount = (msg:getU32() - 1)
|
||||
for i = 0, buyOfferCount do
|
||||
table.insert(offers, readMarketOffer(msg, MarketAction.Buy, var))
|
||||
end
|
||||
|
||||
local sellOfferCount = (msg:getU32() - 1)
|
||||
for i = 0, sellOfferCount do
|
||||
table.insert(offers, readMarketOffer(msg, MarketAction.Sell, var))
|
||||
end
|
||||
|
||||
Market.onMarketBrowse(offers)
|
||||
end
|
||||
|
||||
-- public functions
|
||||
|
||||
function MarketProtocol.init()
|
||||
connect(ProtocolGame, { onOpcode = parseOpcode } )
|
||||
|
||||
end
|
||||
|
||||
function MarketProtocol.terminate()
|
||||
disconnect(ProtocolGame, { onOpcode = parseOpcode } )
|
||||
|
||||
market = nil
|
||||
MarketProtocol = nil
|
||||
end
|
||||
|
||||
-- sending protocols
|
||||
|
||||
function MarketProtocol.sendMarketLeave()
|
||||
if g_game.getFeature(GamePlayerMarket) then
|
||||
local msg = OutputMessage.create()
|
||||
msg:addU8(ClientOpcodes.ClientMarketLeave)
|
||||
send(msg)
|
||||
else
|
||||
g_logger.error('MarketProtocol.sendMarketLeave does not support the current protocol.')
|
||||
end
|
||||
end
|
||||
|
||||
function MarketProtocol.sendMarketBrowse(browseId)
|
||||
if g_game.getFeature(GamePlayerMarket) then
|
||||
local msg = OutputMessage.create()
|
||||
msg:addU8(ClientOpcodes.ClientMarketBrowse)
|
||||
msg:addU16(browseId)
|
||||
send(msg)
|
||||
else
|
||||
g_logger.error('MarketProtocol.sendMarketBrowse does not support the current protocol.')
|
||||
end
|
||||
end
|
||||
|
||||
function MarketProtocol.sendMarketCreateOffer(type, spriteId, amount, price, anonymous)
|
||||
if g_game.getFeature(GamePlayerMarket) then
|
||||
local msg = OutputMessage.create()
|
||||
msg:addU8(ClientOpcodes.ClientMarketCreate)
|
||||
msg:addU8(type)
|
||||
msg:addU16(spriteId)
|
||||
msg:addU16(amount)
|
||||
msg:addU32(price)
|
||||
msg:addU8(anonymous)
|
||||
send(msg)
|
||||
else
|
||||
g_logger.error('MarketProtocol.sendMarketCreateOffer does not support the current protocol.')
|
||||
end
|
||||
end
|
||||
|
||||
function MarketProtocol.sendMarketCancelOffer(counter)
|
||||
if g_game.getFeature(GamePlayerMarket) then
|
||||
local msg = OutputMessage.create()
|
||||
msg:addU8(ClientOpcodes.ClientMarketCancel)
|
||||
msg:addU32(os.time())
|
||||
msg:addU16(counter)
|
||||
send(msg)
|
||||
else
|
||||
g_logger.error('MarketProtocol.sendMarketCancelOffer does not support the current protocol.')
|
||||
end
|
||||
end
|
||||
|
||||
function MarketProtocol.sendMarketAcceptOffer(counter)
|
||||
if g_game.getFeature(GamePlayerMarket) then
|
||||
local msg = OutputMessage.create()
|
||||
msg:addU8(ClientOpcodes.ClientMarketAccept)
|
||||
msg:addU32(os.time())
|
||||
msg:addU16(counter)
|
||||
send(msg)
|
||||
else
|
||||
g_logger.error('MarketProtocol.sendMarketAcceptOffer does not support the current protocol.')
|
||||
end
|
||||
end
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 836 B After Width: | Height: | Size: 836 B |
Before Width: | Height: | Size: 819 B After Width: | Height: | Size: 819 B |
|
@ -9,16 +9,16 @@ MapControl < Button
|
|||
icon-clip: 0 16 16 16
|
||||
|
||||
FloorUpControl < MapControl
|
||||
icon-source: /game_minimap/floor_up.png
|
||||
icon-source: /game_minimap/images/floor_up.png
|
||||
|
||||
FloorDownControl < MapControl
|
||||
icon-source: /game_minimap/floor_down.png
|
||||
icon-source: /game_minimap/images/floor_down.png
|
||||
|
||||
ZoomOutControl < MapControl
|
||||
//image-source: /game_minimap/zoom_out.png
|
||||
//image-source: /game_minimap/images/zoom_out.png
|
||||
|
||||
ZoomInControl < MapControl
|
||||
//image-source: /game_minimap/zoom_in.png
|
||||
//image-source: /game_minimap/images/zoom_in.png
|
||||
|
||||
MiniWindow
|
||||
id: minimapWindow
|
||||
|
|
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.1 KiB |
|
@ -233,6 +233,7 @@ function Outfit.destroy()
|
|||
mountCreature = nil
|
||||
currentColorBox = nil
|
||||
currentClotheButtonBox = nil
|
||||
colorBoxes = {}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ Module
|
|||
name: game_playermount
|
||||
description: Manage player mounts
|
||||
author: BeniS
|
||||
website: www.otclient.infox
|
||||
website: www.otclient.info
|
||||
|
||||
@onLoad: |
|
||||
dofile 'playermount'
|
||||
|
|
|
@ -32,7 +32,7 @@ class InputMessage : public LuaObject
|
|||
public:
|
||||
enum {
|
||||
BUFFER_MAXSIZE = 16384,
|
||||
MAX_HEADER_SIZE = 8,
|
||||
MAX_HEADER_SIZE = 8
|
||||
};
|
||||
|
||||
InputMessage();
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace Otc
|
|||
ANIMATED_TEXT_DURATION = 1000,
|
||||
STATIC_DURATION_PER_CHARACTER = 60,
|
||||
MIN_STATIC_TEXT_DURATION = 3000,
|
||||
MAX_STATIC_TEXT_WIDTH = 200,
|
||||
MAX_STATIC_TEXT_WIDTH = 200
|
||||
};
|
||||
|
||||
enum DrawFlags {
|
||||
|
@ -309,6 +309,7 @@ namespace Otc
|
|||
GameTrucatedPingOpcode,
|
||||
GameReverseCreatureStack,
|
||||
GameMagicEffectU16,
|
||||
GamePlayerMarket,
|
||||
LastGameFeature
|
||||
};
|
||||
|
||||
|
@ -317,7 +318,7 @@ namespace Otc
|
|||
PATHFIND_SAME_POSITION,
|
||||
PATHFIND_IMPOSSIBLE,
|
||||
PATHFIND_TOO_FAR,
|
||||
PATHFIND_NO_WAY,
|
||||
PATHFIND_NO_WAY
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ Game g_game;
|
|||
Game::Game()
|
||||
{
|
||||
resetGameStates();
|
||||
setClientVersion(860);
|
||||
setClientVersion(954);
|
||||
}
|
||||
|
||||
void Game::resetGameStates()
|
||||
|
@ -1135,6 +1135,10 @@ void Game::setClientVersion(int clientVersion)
|
|||
enableFeature(Otc::GameItemAnimationPhase);
|
||||
}
|
||||
|
||||
if(clientVersion >= 940) {
|
||||
enableFeature(Otc::GamePlayerMarket);
|
||||
}
|
||||
|
||||
if(clientVersion >= 953) {
|
||||
enableFeature(Otc::GameCreaturePassableInfo);
|
||||
enableFeature(Otc::GameTrucatedPingOpcode);
|
||||
|
|
|
@ -301,13 +301,6 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
|||
case Proto::GameServerPlayerInventory:
|
||||
parsePlayerInventory(msg);
|
||||
break;
|
||||
// PROTOCOL>=944
|
||||
/*
|
||||
case Proto::GameServerMarketEnter:
|
||||
case Proto::GameServerMarketLeave:
|
||||
case Proto::GameServerMarketDetail:
|
||||
case Proto::GameServerMarketBrowse:
|
||||
*/
|
||||
// otclient ONLY
|
||||
case Proto::GameServerExtendedOpcode:
|
||||
parseExtendedOpcode(msg);
|
||||
|
@ -1135,7 +1128,6 @@ void ProtocolGame::parseOpenOutfitWindow(const InputMessagePtr& msg)
|
|||
Outfit currentOutfit = getOutfit(msg);
|
||||
|
||||
std::vector<std::tuple<int, std::string, int> > outfitList;
|
||||
std::vector<std::tuple<int, std::string> > mountList;
|
||||
int outfitCount = msg->getU8();
|
||||
for(int i = 0; i < outfitCount; i++) {
|
||||
int outfitId = msg->getU16();
|
||||
|
@ -1145,6 +1137,7 @@ void ProtocolGame::parseOpenOutfitWindow(const InputMessagePtr& msg)
|
|||
outfitList.push_back(std::make_tuple(outfitId, outfitName, outfitAddons));
|
||||
}
|
||||
|
||||
std::vector<std::tuple<int, std::string> > mountList;
|
||||
if(g_game.getFeature(Otc::GamePlayerMounts)) {
|
||||
int mountCount = msg->getU8();
|
||||
for(int i = 0; i < mountCount; ++i) {
|
||||
|
|