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.
master
BeniS 12 years ago
parent 12d30f7355
commit b7ac6ce6d5

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

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,14 +38,14 @@ Game g_game;
Game::Game()
{
resetGameStates();
setClientVersion(860);
setClientVersion(954);
}
void Game::resetGameStates()
{
m_denyBotCall = false;
m_dead = false;
m_mounted = false;
m_mounted = false;
m_serverBeat = 50;
m_canReportBugs = false;
m_fightMode = Otc::FightBalanced;
@ -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) {

Loading…
Cancel
Save