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 'settings'
|
||||||
dofile 'keyboard'
|
dofile 'keyboard'
|
||||||
dofile 'mouse'
|
dofile 'mouse'
|
||||||
|
dofile 'protocol'
|
||||||
|
|
||||||
dofiles 'ui'
|
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
|
SouthWest = 6
|
||||||
NorthWest = 7
|
NorthWest = 7
|
||||||
|
|
||||||
ClientEnterAccount = 1
|
|
||||||
ClientEnterGame = 10
|
|
||||||
|
|
||||||
LoginServerError = 10
|
LoginServerError = 10
|
||||||
LoginServerMotd = 20
|
LoginServerMotd = 20
|
||||||
LoginServerUpdateNeeded = 30
|
LoginServerUpdateNeeded = 30
|
||||||
|
@ -64,6 +61,8 @@ GameCreaturePassableInfo = 18
|
||||||
GameItemAnimationPhase = 19
|
GameItemAnimationPhase = 19
|
||||||
GameTrucatedPingOpcode = 20
|
GameTrucatedPingOpcode = 20
|
||||||
GameReverseCreatureStack = 21
|
GameReverseCreatureStack = 21
|
||||||
|
GameMagicEffectU16 = 22
|
||||||
|
GamePlayerMarket = 23
|
||||||
|
|
||||||
OTSERV_RSA = "109120132967399429278860960508995541528237502902798129123468757937266291492576446330739696001110603907230888610072655818825358503429057592827629436413108566029093628212635953836686562675849720620786279431090218017681061521755056710823876476444260558147179707119674283982419152118103759076030616683978566631413"
|
OTSERV_RSA = "109120132967399429278860960508995541528237502902798129123468757937266291492576446330739696001110603907230888610072655818825358503429057592827629436413108566029093628212635953836686562675849720620786279431090218017681061521755056710823876476444260558147179707119674283982419152118103759076030616683978566631413"
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ Module
|
||||||
- game_shaders
|
- game_shaders
|
||||||
- game_playerdeath
|
- game_playerdeath
|
||||||
- game_playermount
|
- game_playermount
|
||||||
|
- game_market
|
||||||
|
|
||||||
@onLoad: |
|
@onLoad: |
|
||||||
dofile 'const'
|
dofile 'const'
|
||||||
|
@ -40,3 +41,4 @@ Module
|
||||||
|
|
||||||
dofile 'creature'
|
dofile 'creature'
|
||||||
dofile 'player'
|
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
|
-- private functions
|
||||||
local function sendLoginPacket(protocol)
|
local function sendLoginPacket(protocol)
|
||||||
local msg = OutputMessage.create()
|
local msg = OutputMessage.create()
|
||||||
msg:addU8(ClientEnterAccount)
|
msg:addU8(ClientOpcodes.ClientEnterAccount)
|
||||||
msg:addU16(1) -- todo: ClientOs
|
msg:addU16(1) -- todo: ClientOs
|
||||||
msg:addU16(g_game.getClientVersion())
|
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
|
icon-clip: 0 16 16 16
|
||||||
|
|
||||||
FloorUpControl < MapControl
|
FloorUpControl < MapControl
|
||||||
icon-source: /game_minimap/floor_up.png
|
icon-source: /game_minimap/images/floor_up.png
|
||||||
|
|
||||||
FloorDownControl < MapControl
|
FloorDownControl < MapControl
|
||||||
icon-source: /game_minimap/floor_down.png
|
icon-source: /game_minimap/images/floor_down.png
|
||||||
|
|
||||||
ZoomOutControl < MapControl
|
ZoomOutControl < MapControl
|
||||||
//image-source: /game_minimap/zoom_out.png
|
//image-source: /game_minimap/images/zoom_out.png
|
||||||
|
|
||||||
ZoomInControl < MapControl
|
ZoomInControl < MapControl
|
||||||
//image-source: /game_minimap/zoom_in.png
|
//image-source: /game_minimap/images/zoom_in.png
|
||||||
|
|
||||||
MiniWindow
|
MiniWindow
|
||||||
id: minimapWindow
|
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
|
mountCreature = nil
|
||||||
currentColorBox = nil
|
currentColorBox = nil
|
||||||
currentClotheButtonBox = nil
|
currentClotheButtonBox = nil
|
||||||
|
colorBoxes = {}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ Module
|
||||||
name: game_playermount
|
name: game_playermount
|
||||||
description: Manage player mounts
|
description: Manage player mounts
|
||||||
author: BeniS
|
author: BeniS
|
||||||
website: www.otclient.infox
|
website: www.otclient.info
|
||||||
|
|
||||||
@onLoad: |
|
@onLoad: |
|
||||||
dofile 'playermount'
|
dofile 'playermount'
|
||||||
|
|
|
@ -32,7 +32,7 @@ class InputMessage : public LuaObject
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
BUFFER_MAXSIZE = 16384,
|
BUFFER_MAXSIZE = 16384,
|
||||||
MAX_HEADER_SIZE = 8,
|
MAX_HEADER_SIZE = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
InputMessage();
|
InputMessage();
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace Otc
|
||||||
ANIMATED_TEXT_DURATION = 1000,
|
ANIMATED_TEXT_DURATION = 1000,
|
||||||
STATIC_DURATION_PER_CHARACTER = 60,
|
STATIC_DURATION_PER_CHARACTER = 60,
|
||||||
MIN_STATIC_TEXT_DURATION = 3000,
|
MIN_STATIC_TEXT_DURATION = 3000,
|
||||||
MAX_STATIC_TEXT_WIDTH = 200,
|
MAX_STATIC_TEXT_WIDTH = 200
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DrawFlags {
|
enum DrawFlags {
|
||||||
|
@ -309,6 +309,7 @@ namespace Otc
|
||||||
GameTrucatedPingOpcode,
|
GameTrucatedPingOpcode,
|
||||||
GameReverseCreatureStack,
|
GameReverseCreatureStack,
|
||||||
GameMagicEffectU16,
|
GameMagicEffectU16,
|
||||||
|
GamePlayerMarket,
|
||||||
LastGameFeature
|
LastGameFeature
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -317,7 +318,7 @@ namespace Otc
|
||||||
PATHFIND_SAME_POSITION,
|
PATHFIND_SAME_POSITION,
|
||||||
PATHFIND_IMPOSSIBLE,
|
PATHFIND_IMPOSSIBLE,
|
||||||
PATHFIND_TOO_FAR,
|
PATHFIND_TOO_FAR,
|
||||||
PATHFIND_NO_WAY,
|
PATHFIND_NO_WAY
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ Game g_game;
|
||||||
Game::Game()
|
Game::Game()
|
||||||
{
|
{
|
||||||
resetGameStates();
|
resetGameStates();
|
||||||
setClientVersion(860);
|
setClientVersion(954);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::resetGameStates()
|
void Game::resetGameStates()
|
||||||
|
@ -1135,6 +1135,10 @@ void Game::setClientVersion(int clientVersion)
|
||||||
enableFeature(Otc::GameItemAnimationPhase);
|
enableFeature(Otc::GameItemAnimationPhase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(clientVersion >= 940) {
|
||||||
|
enableFeature(Otc::GamePlayerMarket);
|
||||||
|
}
|
||||||
|
|
||||||
if(clientVersion >= 953) {
|
if(clientVersion >= 953) {
|
||||||
enableFeature(Otc::GameCreaturePassableInfo);
|
enableFeature(Otc::GameCreaturePassableInfo);
|
||||||
enableFeature(Otc::GameTrucatedPingOpcode);
|
enableFeature(Otc::GameTrucatedPingOpcode);
|
||||||
|
|
|
@ -301,13 +301,6 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
||||||
case Proto::GameServerPlayerInventory:
|
case Proto::GameServerPlayerInventory:
|
||||||
parsePlayerInventory(msg);
|
parsePlayerInventory(msg);
|
||||||
break;
|
break;
|
||||||
// PROTOCOL>=944
|
|
||||||
/*
|
|
||||||
case Proto::GameServerMarketEnter:
|
|
||||||
case Proto::GameServerMarketLeave:
|
|
||||||
case Proto::GameServerMarketDetail:
|
|
||||||
case Proto::GameServerMarketBrowse:
|
|
||||||
*/
|
|
||||||
// otclient ONLY
|
// otclient ONLY
|
||||||
case Proto::GameServerExtendedOpcode:
|
case Proto::GameServerExtendedOpcode:
|
||||||
parseExtendedOpcode(msg);
|
parseExtendedOpcode(msg);
|
||||||
|
@ -1135,7 +1128,6 @@ void ProtocolGame::parseOpenOutfitWindow(const InputMessagePtr& msg)
|
||||||
Outfit currentOutfit = getOutfit(msg);
|
Outfit currentOutfit = getOutfit(msg);
|
||||||
|
|
||||||
std::vector<std::tuple<int, std::string, int> > outfitList;
|
std::vector<std::tuple<int, std::string, int> > outfitList;
|
||||||
std::vector<std::tuple<int, std::string> > mountList;
|
|
||||||
int outfitCount = msg->getU8();
|
int outfitCount = msg->getU8();
|
||||||
for(int i = 0; i < outfitCount; i++) {
|
for(int i = 0; i < outfitCount; i++) {
|
||||||
int outfitId = msg->getU16();
|
int outfitId = msg->getU16();
|
||||||
|
@ -1145,6 +1137,7 @@ void ProtocolGame::parseOpenOutfitWindow(const InputMessagePtr& msg)
|
||||||
outfitList.push_back(std::make_tuple(outfitId, outfitName, outfitAddons));
|
outfitList.push_back(std::make_tuple(outfitId, outfitName, outfitAddons));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::tuple<int, std::string> > mountList;
|
||||||
if(g_game.getFeature(Otc::GamePlayerMounts)) {
|
if(g_game.getFeature(Otc::GamePlayerMounts)) {
|
||||||
int mountCount = msg->getU8();
|
int mountCount = msg->getU8();
|
||||||
for(int i = 0; i < mountCount; ++i) {
|
for(int i = 0; i < mountCount; ++i) {
|
||||||
|
|