More multiprotocol support
This commit is contained in:
parent
e393bc245d
commit
c795eb91ab
|
@ -92,7 +92,7 @@ end
|
|||
local function onLoginWait(message, time)
|
||||
CharacterList.destroyLoadBox()
|
||||
|
||||
waitingWindow = g_ui.loadUI('waitinglist.otui')
|
||||
waitingWindow = g_ui.displayUI('waitinglist.otui')
|
||||
|
||||
local label = waitingWindow:getChildById('infoLabel')
|
||||
label:setText(message)
|
||||
|
|
|
@ -168,7 +168,8 @@ function EnterGame.doLogin()
|
|||
end })
|
||||
|
||||
g_game.chooseRsa(G.host)
|
||||
g_game.setProtocolVersion(protocol)
|
||||
g_game.setClientVersion(protocol)
|
||||
modules.game_tibiafiles.load()
|
||||
protocolLogin:login(G.host, G.port, G.account, G.password)
|
||||
end
|
||||
|
||||
|
|
|
@ -72,7 +72,14 @@ function connect(object, arg1, arg2, arg3)
|
|||
end
|
||||
end
|
||||
|
||||
function disconnect(object, signalsAndSlots)
|
||||
function disconnect(object, arg1, arg2)
|
||||
local signalsAndSlots
|
||||
if type(arg1) == 'string' then
|
||||
signalsAndSlots = { [arg1] = arg2 }
|
||||
else
|
||||
signalsAndSlots = arg1
|
||||
end
|
||||
|
||||
for signal,slot in pairs(signalsAndSlots) do
|
||||
if not object[signal] then
|
||||
elseif type(object[signal]) == 'function' then
|
||||
|
@ -231,11 +238,19 @@ end
|
|||
|
||||
function signalcall(param, ...)
|
||||
if type(param) == 'function' then
|
||||
return param(...)
|
||||
local status, ret = pcall(param, ...)
|
||||
if status then
|
||||
return ret
|
||||
else
|
||||
perror(ret)
|
||||
end
|
||||
elseif type(param) == 'table' then
|
||||
for k,v in pairs(param) do
|
||||
if v(...) then
|
||||
return true
|
||||
local status, ret = pcall(v, ...)
|
||||
if status then
|
||||
if ret then return true end
|
||||
else
|
||||
perror(ret)
|
||||
end
|
||||
end
|
||||
elseif func ~= nil then
|
||||
|
|
|
@ -91,7 +91,7 @@ end
|
|||
function addAllCreatures()
|
||||
local spectators = {}
|
||||
local player = g_game.getLocalPlayer()
|
||||
if player then
|
||||
if g_game.isOnline() then
|
||||
creatures = g_map.getSpectators(player:getPosition(), false)
|
||||
for i, creature in ipairs(creatures) do
|
||||
if creature ~= player and doCreatureFitFilters(creature) then
|
||||
|
@ -129,7 +129,7 @@ end
|
|||
|
||||
function checkCreatures(forceRecheck)
|
||||
local player = g_game.getLocalPlayer()
|
||||
if player then
|
||||
if g_game.isOnline() then
|
||||
local spectators = {}
|
||||
|
||||
-- reloading list of spectators
|
||||
|
|
|
@ -135,10 +135,6 @@ function toggle()
|
|||
end
|
||||
end
|
||||
|
||||
function onMiniWindowClose()
|
||||
combatControlsButton:setOn(false)
|
||||
end
|
||||
|
||||
function onSetFightMode(self, selectedFightButton)
|
||||
if selectedFightButton == nil then return end
|
||||
local buttonId = selectedFightButton:getId()
|
||||
|
|
|
@ -27,7 +27,6 @@ MiniWindow
|
|||
!text: tr('Combat Controls')
|
||||
icon: combatcontrols.png
|
||||
height: 48
|
||||
@onClose: CombatControls.onMiniWindowClose()
|
||||
&save: true
|
||||
|
||||
MiniWindowContents
|
||||
|
|
|
@ -37,14 +37,14 @@ function clean()
|
|||
end
|
||||
end
|
||||
|
||||
local function refreshContainerItems(container)
|
||||
function refreshContainerItems(container)
|
||||
for slot=0,container:getCapacity()-1 do
|
||||
local itemWidget = container.itemsPanel:getChildById('item' .. slot)
|
||||
itemWidget:setItem(container:getItem(slot))
|
||||
end
|
||||
end
|
||||
|
||||
local function onContainerOpen(container, previousContainer)
|
||||
function onContainerOpen(container, previousContainer)
|
||||
local containerWindow
|
||||
if previousContainer then
|
||||
containerWindow = previousContainer.window
|
||||
|
|
|
@ -2,7 +2,7 @@ Icons = {}
|
|||
Icons[1] = { tooltip = tr('You are poisoned'), path = '/game_healthinfo/icons/poisoned.png', id = 'condition_poisoned' }
|
||||
Icons[2] = { tooltip = tr('You are burning'), path = '/game_healthinfo/icons/burning.png', id = 'condition_burning' }
|
||||
Icons[4] = { tooltip = tr('You are electrified'), path = '/game_healthinfo/icons/electrified.png', id = 'condition_electrified' }
|
||||
Icons[8] = { tooltip = tr('You are freezing'), path = '/game_healthinfo/icons/drunk.png', id = 'condition_drunk' }
|
||||
Icons[8] = { tooltip = tr('You are drunk'), path = '/game_healthinfo/icons/drunk.png', id = 'condition_drunk' }
|
||||
Icons[16] = { tooltip = tr('You are protected by a magic shield'), path = '/game_healthinfo/icons/magic_shield.png', id = 'condition_magic_shield' }
|
||||
Icons[32] = { tooltip = tr('You are paralysed'), path = '/game_healthinfo/icons/slowed.png', id = 'condition_slowed' }
|
||||
Icons[64] = { tooltip = tr('You are hasted'), path = '/game_healthinfo/icons/haste.png', id = 'condition_haste' }
|
||||
|
|
|
@ -238,6 +238,7 @@ function startTradeWith(thing)
|
|||
end
|
||||
|
||||
function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
if not g_game.isOnline() then return end
|
||||
local menu = g_ui.createWidget('PopupMenu')
|
||||
|
||||
if lookThing then
|
||||
|
@ -297,52 +298,50 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
|||
|
||||
else
|
||||
local localPlayer = g_game.getLocalPlayer()
|
||||
if localPlayer then
|
||||
if g_game.getAttackingCreature() ~= creatureThing then
|
||||
menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end)
|
||||
else
|
||||
menu:addOption(tr('Stop Attack'), function() g_game.cancelAttack() end)
|
||||
if g_game.getAttackingCreature() ~= creatureThing then
|
||||
menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end)
|
||||
else
|
||||
menu:addOption(tr('Stop Attack'), function() g_game.cancelAttack() end)
|
||||
end
|
||||
|
||||
if g_game.getFollowingCreature() ~= creatureThing then
|
||||
menu:addOption(tr('Follow'), function() g_game.follow(creatureThing) end)
|
||||
else
|
||||
menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end)
|
||||
end
|
||||
|
||||
if creatureThing:asPlayer() then
|
||||
menu:addSeparator()
|
||||
local creatureName = creatureThing:getName()
|
||||
menu:addOption(tr('Message to %s', creatureName), function() g_game.openPrivateChannel(creatureName) end)
|
||||
if modules.game_console.getOwnPrivateTab() then
|
||||
menu:addOption(tr('Invite to private chat'), function() g_game.inviteToOwnChannel(creatureName) end)
|
||||
menu:addOption(tr('Exclude from private chat'), function() g_game.excludeFromOwnChannel(creatureName) end) -- [TODO] must be removed after message's popup labels been implemented
|
||||
end
|
||||
if (not Player:hasVip(creatureName)) then
|
||||
menu:addOption(tr('Add to VIP list'), function() g_game.addVip(creatureName) end)
|
||||
end
|
||||
|
||||
if g_game.getFollowingCreature() ~= creatureThing then
|
||||
menu:addOption(tr('Follow'), function() g_game.follow(creatureThing) end)
|
||||
else
|
||||
menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end)
|
||||
end
|
||||
local localPlayerShield = localPlayer:asCreature():getShield()
|
||||
local creatureShield = creatureThing:getShield()
|
||||
|
||||
if creatureThing:asPlayer() then
|
||||
menu:addSeparator()
|
||||
local creatureName = creatureThing:getName()
|
||||
menu:addOption(tr('Message to %s', creatureName), function() g_game.openPrivateChannel(creatureName) end)
|
||||
if modules.game_console.getOwnPrivateTab() then
|
||||
menu:addOption(tr('Invite to private chat'), function() g_game.inviteToOwnChannel(creatureName) end)
|
||||
menu:addOption(tr('Exclude from private chat'), function() g_game.excludeFromOwnChannel(creatureName) end) -- [TODO] must be removed after message's popup labels been implemented
|
||||
if localPlayerShield == ShieldNone or localPlayerShield == ShieldWhiteBlue then
|
||||
if creatureShield == ShieldWhiteYellow then
|
||||
menu:addOption(tr('Join %s\'s Party', creatureThing:getName()), function() g_game.partyJoin(creatureThing:getId()) end)
|
||||
else
|
||||
menu:addOption(tr('Invite to Party'), function() g_game.partyInvite(creatureThing:getId()) end)
|
||||
end
|
||||
if (not Player:hasVip(creatureName)) then
|
||||
menu:addOption(tr('Add to VIP list'), function() g_game.addVip(creatureName) end)
|
||||
elseif localPlayerShield == ShieldWhiteYellow then
|
||||
if creatureShield == ShieldWhiteBlue then
|
||||
menu:addOption(tr('Revoke %s\'s Invitation', creatureThing:getName()), function() g_game.partyRevokeInvitation(creatureThing:getId()) end)
|
||||
end
|
||||
|
||||
local localPlayerShield = localPlayer:asCreature():getShield()
|
||||
local creatureShield = creatureThing:getShield()
|
||||
|
||||
if localPlayerShield == ShieldNone or localPlayerShield == ShieldWhiteBlue then
|
||||
if creatureShield == ShieldWhiteYellow then
|
||||
menu:addOption(tr('Join %s\'s Party', creatureThing:getName()), function() g_game.partyJoin(creatureThing:getId()) end)
|
||||
else
|
||||
menu:addOption(tr('Invite to Party'), function() g_game.partyInvite(creatureThing:getId()) end)
|
||||
end
|
||||
elseif localPlayerShield == ShieldWhiteYellow then
|
||||
if creatureShield == ShieldWhiteBlue then
|
||||
menu:addOption(tr('Revoke %s\'s Invitation', creatureThing:getName()), function() g_game.partyRevokeInvitation(creatureThing:getId()) end)
|
||||
end
|
||||
elseif localPlayerShield == ShieldYellow or localPlayerShield == ShieldYellowSharedExp or localPlayerShield == ShieldYellowNoSharedExpBlink or localPlayerShield == ShieldYellowNoSharedExp then
|
||||
if creatureShield == ShieldWhiteBlue then
|
||||
menu:addOption(tr('Revoke %s\'s Invitation', creatureThing:getName()), function() g_game.partyRevokeInvitation(creatureThing:getId()) end)
|
||||
elseif creatureShield == ShieldBlue or creatureShield == ShieldBlueSharedExp or creatureShield == ShieldBlueNoSharedExpBlink or creatureShield == ShieldBlueNoSharedExp then
|
||||
menu:addOption(tr('Pass Leadership to %s', creatureThing:getName()), function() g_game.partyPassLeadership(creatureThing:getId()) end)
|
||||
else
|
||||
menu:addOption(tr('Invite to Party'), function() g_game.partyInvite(creatureThing:getId()) end)
|
||||
end
|
||||
elseif localPlayerShield == ShieldYellow or localPlayerShield == ShieldYellowSharedExp or localPlayerShield == ShieldYellowNoSharedExpBlink or localPlayerShield == ShieldYellowNoSharedExp then
|
||||
if creatureShield == ShieldWhiteBlue then
|
||||
menu:addOption(tr('Revoke %s\'s Invitation', creatureThing:getName()), function() g_game.partyRevokeInvitation(creatureThing:getId()) end)
|
||||
elseif creatureShield == ShieldBlue or creatureShield == ShieldBlueSharedExp or creatureShield == ShieldBlueNoSharedExpBlink or creatureShield == ShieldBlueNoSharedExp then
|
||||
menu:addOption(tr('Pass Leadership to %s', creatureThing:getName()), function() g_game.partyPassLeadership(creatureThing:getId()) end)
|
||||
else
|
||||
menu:addOption(tr('Invite to Party'), function() g_game.partyInvite(creatureThing:getId()) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -43,7 +43,7 @@ end
|
|||
function refresh()
|
||||
local player = g_game.getLocalPlayer()
|
||||
for i=InventorySlotFirst,InventorySlotLast do
|
||||
if player then
|
||||
if g_game.isOnline() then
|
||||
onInventoryChange(player, i, player:getInventoryItem(i))
|
||||
else
|
||||
onInventoryChange(player, i, nil)
|
||||
|
@ -67,8 +67,9 @@ end
|
|||
|
||||
-- hooked events
|
||||
function onInventoryChange(player, slot, item, oldItem)
|
||||
if slot >= InventorySlotPurse then return end
|
||||
local itemWidget = inventoryPanel:getChildById('slot' .. slot)
|
||||
if(item) then
|
||||
if item then
|
||||
itemWidget:setStyle('Item')
|
||||
itemWidget:setItem(item)
|
||||
else
|
||||
|
|
|
@ -38,7 +38,7 @@ end
|
|||
local function parseMarketEnter(msg)
|
||||
local balance = msg:getU32()
|
||||
local vocation = -1
|
||||
if g_game.getProtocolVersion() < 950 then
|
||||
if g_game.getClientVersion() < 950 then
|
||||
vocation = msg:getU8() -- get vocation id
|
||||
end
|
||||
local offers = msg:getU8()
|
||||
|
@ -74,7 +74,8 @@ local function parseMarketDetail(msg)
|
|||
end
|
||||
|
||||
local purchaseStats = {}
|
||||
if msg:getU8() == 0x01 then
|
||||
local count = msg:getU8()
|
||||
for i=1,count do
|
||||
local transactions = msg:getU32() -- transaction count
|
||||
local totalPrice = msg:getU32() -- total price
|
||||
local highestPrice = msg:getU32() -- highest price
|
||||
|
@ -84,7 +85,8 @@ local function parseMarketDetail(msg)
|
|||
end
|
||||
|
||||
local saleStats = {}
|
||||
if msg:getU8() == 0x01 then
|
||||
count = msg:getU8()
|
||||
for i=1,count do
|
||||
local transactions = msg:getU32() -- transaction count
|
||||
local totalPrice = msg:getU32() -- total price
|
||||
local highestPrice = msg:getU32() -- highest price
|
||||
|
|
|
@ -67,6 +67,7 @@ function loadReasons()
|
|||
local actions = g_game.getGMActions()
|
||||
for reason, actionFlags in pairs(actions) do
|
||||
local label = g_ui.createWidget('RVListLabel', reasonsTextList)
|
||||
label.onFocusChange = onSelectReason
|
||||
label:setText(rvreasons[reason])
|
||||
label.reasonId = reason
|
||||
label.actionFlags = actionFlags
|
||||
|
|
|
@ -2,7 +2,6 @@ RVListLabel < Label
|
|||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
@onFocusChange: function (self, focused) RuleViolation.onSelectReason(self, focused) end
|
||||
|
||||
$focus:
|
||||
background-color: #ffffff22
|
||||
|
@ -109,7 +108,7 @@ MainWindow
|
|||
width: 64
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
@onClick: RuleViolation.hide()
|
||||
@onClick: hide()
|
||||
|
||||
Button
|
||||
!text: tr('Ok')
|
||||
|
@ -117,4 +116,4 @@ MainWindow
|
|||
margin-right: 5
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: parent.bottom
|
||||
@onClick: RuleViolation.report()
|
||||
@onClick: report()
|
|
@ -47,7 +47,7 @@ end
|
|||
function parseTextMessage(msg)
|
||||
local msgtype = msg:getU8()
|
||||
local text = msg:getString()
|
||||
msgtype = getMessageTypes(g_game.getProtocolVersion())[msgtype]
|
||||
msgtype = getMessageTypes(g_game.getClientVersion())[msgtype]
|
||||
signalcall(g_game.onTextMessage, msgtype, text)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
function init()
|
||||
if not g_things.loadDat('/game_tibiafiles/Tibia.dat') then
|
||||
fatal(tr("Unable to load dat file, please place a valid Tibia dat in modules/game_tibiafiles/Tibia.dat"))
|
||||
end
|
||||
if not g_sprites.loadSpr('/game_tibiafiles/Tibia.spr') then
|
||||
fatal(tr("Unable to load spr file, please place a valid Tibia spr in modules/game_tibiafiles/Tibia.spr"))
|
||||
if g_game.getClientVersion() ~= 0 then
|
||||
load()
|
||||
end
|
||||
end
|
||||
|
||||
function terminate()
|
||||
function load()
|
||||
local version = g_game.getClientVersion()
|
||||
local datPath = resolvepath(version .. '/Tibia.dat')
|
||||
local sprPath = resolvepath(version .. '/Tibia.spr')
|
||||
if not g_things.loadDat(datPath) then
|
||||
fatal(tr("Unable to load dat file, please place a valid dat in '%s'", datPath))
|
||||
end
|
||||
if not g_sprites.loadSpr(sprPath) then
|
||||
fatal(tr("Unable to load spr file, please place a valid spr in '%s'", sprPath))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -71,6 +71,9 @@ CIPSOFT_RSA = "1321277432058722840622950990822933849527763264961655079678763618"
|
|||
"2907336840325241747827401343576296990629870233111328210165697754" ..
|
||||
"88792221429527047321331896351555606801473202394175817"
|
||||
|
||||
-- set to the latest Tibia.pic signature to make otclient compatible with official tibia
|
||||
PIC_SIGNATURE = 1337606793
|
||||
|
||||
OsTypes = {
|
||||
Linux = 1,
|
||||
Windows = 2,
|
||||
|
|
|
@ -11,6 +11,7 @@ InventorySlotLeg = 7
|
|||
InventorySlotFeet = 8
|
||||
InventorySlotFinger = 9
|
||||
InventorySlotAmmo = 10
|
||||
InventorySlotPurse = 11
|
||||
|
||||
InventorySlotFirst = 1
|
||||
InventorySlotLast = 10
|
||||
|
|
|
@ -1,89 +1,11 @@
|
|||
-- @docclass
|
||||
ProtocolLogin = extends(Protocol)
|
||||
|
||||
-- set to the latest Tibia.pic signature to make otclient compatible with official tibia
|
||||
local PIC_SIGNATURE = 1337606793
|
||||
|
||||
LoginServerError = 10
|
||||
LoginServerMotd = 20
|
||||
LoginServerUpdateNeeded = 30
|
||||
LoginServerCharacterList = 100
|
||||
|
||||
|
||||
-- private functions
|
||||
local function sendLoginPacket(protocol)
|
||||
local msg = OutputMessage.create()
|
||||
msg:addU8(ClientOpcodes.ClientEnterAccount)
|
||||
msg:addU16(g_game.getOsType())
|
||||
msg:addU16(g_game.getProtocolVersion())
|
||||
|
||||
msg:addU32(g_things.getDatSignature())
|
||||
msg:addU32(g_sprites.getSprSignature())
|
||||
msg:addU32(PIC_SIGNATURE)
|
||||
|
||||
local paddingBytes = 128
|
||||
msg:addU8(0) -- first RSA byte must be 0
|
||||
paddingBytes = paddingBytes - 1
|
||||
|
||||
-- xtea key
|
||||
protocol:generateXteaKey()
|
||||
local xteaKey = protocol:getXteaKey()
|
||||
msg:addU32(xteaKey[1])
|
||||
msg:addU32(xteaKey[2])
|
||||
msg:addU32(xteaKey[3])
|
||||
msg:addU32(xteaKey[4])
|
||||
paddingBytes = paddingBytes - 16
|
||||
|
||||
if g_game.getFeature(GameProtocolChecksum) then
|
||||
protocol:enableChecksum()
|
||||
end
|
||||
|
||||
if g_game.getFeature(GameAccountNames) then
|
||||
msg:addString(protocol.accountName)
|
||||
msg:addString(protocol.accountPassword)
|
||||
paddingBytes = paddingBytes - (4 + string.len(protocol.accountName) + string.len(protocol.accountPassword))
|
||||
else
|
||||
msg:addU32(tonumber(protocol.accountName))
|
||||
msg:addString(protocol.accountPassword)
|
||||
paddingBytes = paddingBytes - (6 + string.len(protocol.accountPassword))
|
||||
end
|
||||
|
||||
msg:addPaddingBytes(paddingBytes, 0)
|
||||
msg:encryptRsa(128, g_game.getRsa())
|
||||
|
||||
protocol:send(msg)
|
||||
protocol:enableXteaEncryption()
|
||||
protocol:recv()
|
||||
end
|
||||
|
||||
-- events
|
||||
function ProtocolLogin:onConnect()
|
||||
self:connectCallback(self)
|
||||
end
|
||||
|
||||
function ProtocolLogin:onRecv(msg)
|
||||
while not msg:eof() do
|
||||
local opcode = msg:getU8()
|
||||
if opcode == LoginServerError then
|
||||
self:parseError(msg)
|
||||
elseif opcode == LoginServerMotd then
|
||||
self:parseMotd(msg)
|
||||
elseif opcode == LoginServerUpdateNeeded then
|
||||
signalcall(self.onError, self, tr("Client needs update."))
|
||||
elseif opcode == LoginServerCharacterList then
|
||||
self:parseCharacterList(msg)
|
||||
else
|
||||
self:parseOpcode(opcode, msg)
|
||||
end
|
||||
end
|
||||
self:disconnect()
|
||||
end
|
||||
|
||||
-- public functions
|
||||
function ProtocolLogin.create()
|
||||
return ProtocolLogin.internalCreate()
|
||||
end
|
||||
|
||||
function ProtocolLogin:login(host, port, accountName, accountPassword)
|
||||
if string.len(accountName) == 0 or string.len(accountPassword) == 0 then
|
||||
signalcall(self.onError, self, tr("You must enter an account name and password."))
|
||||
|
@ -105,6 +27,73 @@ function ProtocolLogin:cancelLogin()
|
|||
self:disconnect()
|
||||
end
|
||||
|
||||
function ProtocolLogin:sendLoginPacket()
|
||||
local msg = OutputMessage.create()
|
||||
msg:addU8(ClientOpcodes.ClientEnterAccount)
|
||||
msg:addU16(g_game.getOsType())
|
||||
msg:addU16(g_game.getClientVersion())
|
||||
|
||||
msg:addU32(g_things.getDatSignature())
|
||||
msg:addU32(g_sprites.getSprSignature())
|
||||
msg:addU32(PIC_SIGNATURE)
|
||||
|
||||
local paddingBytes = 128
|
||||
msg:addU8(0) -- first RSA byte must be 0
|
||||
paddingBytes = paddingBytes - 1
|
||||
|
||||
-- xtea key
|
||||
self:generateXteaKey()
|
||||
local xteaKey = self:getXteaKey()
|
||||
msg:addU32(xteaKey[1])
|
||||
msg:addU32(xteaKey[2])
|
||||
msg:addU32(xteaKey[3])
|
||||
msg:addU32(xteaKey[4])
|
||||
paddingBytes = paddingBytes - 16
|
||||
|
||||
if g_game.getFeature(GameProtocolChecksum) then
|
||||
self:enableChecksum()
|
||||
end
|
||||
|
||||
if g_game.getFeature(GameAccountNames) then
|
||||
msg:addString(self.accountName)
|
||||
msg:addString(self.accountPassword)
|
||||
paddingBytes = paddingBytes - (4 + string.len(self.accountName) + string.len(self.accountPassword))
|
||||
else
|
||||
msg:addU32(tonumber(self.accountName))
|
||||
msg:addString(self.accountPassword)
|
||||
paddingBytes = paddingBytes - (6 + string.len(self.accountPassword))
|
||||
end
|
||||
|
||||
msg:addPaddingBytes(paddingBytes, 0)
|
||||
msg:encryptRsa(128, g_game.getRsa())
|
||||
|
||||
self:send(msg)
|
||||
self:enableXteaEncryption()
|
||||
self:recv()
|
||||
end
|
||||
|
||||
function ProtocolLogin:onConnect()
|
||||
self:sendLoginPacket()
|
||||
end
|
||||
|
||||
function ProtocolLogin:onRecv(msg)
|
||||
while not msg:eof() do
|
||||
local opcode = msg:getU8()
|
||||
if opcode == LoginServerError then
|
||||
self:parseError(msg)
|
||||
elseif opcode == LoginServerMotd then
|
||||
self:parseMotd(msg)
|
||||
elseif opcode == LoginServerUpdateNeeded then
|
||||
signalcall(self.onError, self, tr("Client needs update."))
|
||||
elseif opcode == LoginServerCharacterList then
|
||||
self:parseCharacterList(msg)
|
||||
else
|
||||
self:parseOpcode(opcode, msg)
|
||||
end
|
||||
end
|
||||
self:disconnect()
|
||||
end
|
||||
|
||||
function ProtocolLogin:parseError(msg)
|
||||
local errorMessage = msg:getString()
|
||||
signalcall(self.onError, self, errorMessage)
|
||||
|
|
|
@ -37,14 +37,14 @@ static const std::string glslMainWithTexCoordsVertexShader = "\n\
|
|||
void main()\n\
|
||||
{\n\
|
||||
gl_Position = calculatePosition();\n\
|
||||
v_TexCoord = (u_TextureMatrix * vec3(a_TexCoord,1)).xy;\n\
|
||||
v_TexCoord = (u_TextureMatrix * vec3(a_TexCoord,1.0)).xy;\n\
|
||||
}\n";
|
||||
|
||||
static std::string glslPositionOnlyVertexShader = "\n\
|
||||
attribute highp vec2 a_Vertex;\n\
|
||||
uniform highp mat3 u_ProjectionMatrix;\n\
|
||||
highp vec4 calculatePosition() {\n\
|
||||
return vec4(u_ProjectionMatrix * vec3(a_Vertex.xy, 1), 1);\n\
|
||||
return vec4(u_ProjectionMatrix * vec3(a_Vertex.xy, 1.0), 1.0);\n\
|
||||
}\n";
|
||||
|
||||
static const std::string glslMainFragmentShader = "\n\
|
||||
|
|
|
@ -336,6 +336,7 @@ void Application::registerLuaFunctions()
|
|||
g_lua.bindClassMemberFunction<UIWidget>("getChildByIndex", &UIWidget::getChildByIndex);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("recursiveGetChildById", &UIWidget::recursiveGetChildById);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("recursiveGetChildByPos", &UIWidget::recursiveGetChildByPos);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("recursiveGetChildren", &UIWidget::recursiveGetChildren);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("recursiveGetChildrenByPos", &UIWidget::recursiveGetChildrenByPos);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("recursiveGetChildrenByMarginPos", &UIWidget::recursiveGetChildrenByMarginPos);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("backwardsGetWidgetById", &UIWidget::backwardsGetWidgetById);
|
||||
|
|
|
@ -56,7 +56,7 @@ private:
|
|||
SoundSourcePtr createSoundSource(const std::string& filename);
|
||||
uint loadFileIntoBuffer(const SoundFilePtr& soundFile);
|
||||
|
||||
std::map<std::string, SoundBufferPtr> m_buffers;
|
||||
std::unordered_map<std::string, SoundBufferPtr> m_buffers;
|
||||
std::vector<SoundSourcePtr> m_sources;
|
||||
SoundSourcePtr m_musicSource;
|
||||
ALCdevice *m_device;
|
||||
|
|
|
@ -81,7 +81,7 @@ protected:
|
|||
|
||||
private:
|
||||
bool updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anchorGroup, UIWidgetPtr first = nullptr);
|
||||
std::map<UIWidgetPtr, UIAnchorGroup> m_anchorsGroups;
|
||||
std::unordered_map<UIWidgetPtr, UIAnchorGroup> m_anchorsGroups;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1130,6 +1130,18 @@ UIWidgetPtr UIWidget::recursiveGetChildByPos(const Point& childPos, bool wantsPh
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
UIWidgetList UIWidget::recursiveGetChildren()
|
||||
{
|
||||
UIWidgetList children;
|
||||
for(const UIWidgetPtr& child : m_children) {
|
||||
UIWidgetList subChildren = child->recursiveGetChildren();
|
||||
if(!subChildren.empty())
|
||||
children.insert(children.end(), subChildren.begin(), subChildren.end());
|
||||
children.push_back(child);
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
UIWidgetList UIWidget::recursiveGetChildrenByPos(const Point& childPos)
|
||||
{
|
||||
UIWidgetList children;
|
||||
|
|
|
@ -147,6 +147,7 @@ public:
|
|||
UIWidgetPtr getChildByIndex(int index);
|
||||
UIWidgetPtr recursiveGetChildById(const std::string& id);
|
||||
UIWidgetPtr recursiveGetChildByPos(const Point& childPos, bool wantsPhantom);
|
||||
UIWidgetList recursiveGetChildren();
|
||||
UIWidgetList recursiveGetChildrenByPos(const Point& childPos);
|
||||
UIWidgetList recursiveGetChildrenByMarginPos(const Point& childPos);
|
||||
UIWidgetPtr backwardsGetWidgetById(const std::string& id);
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
uint8 getSkull() { return m_skull; }
|
||||
uint8 getShield() { return m_shield; }
|
||||
uint8 getEmblem() { return m_emblem; }
|
||||
bool getPassable() { return m_passable; }
|
||||
bool isPassable() { return m_passable; }
|
||||
Point getDrawOffset();
|
||||
Point getWalkOffset() { return m_walkOffset; }
|
||||
|
||||
|
|
|
@ -39,15 +39,16 @@ Game::Game()
|
|||
{
|
||||
resetGameStates();
|
||||
m_protocolVersion = 0;
|
||||
setProtocolVersion(PROTOCOL);
|
||||
}
|
||||
|
||||
void Game::resetGameStates()
|
||||
{
|
||||
m_online = false;
|
||||
m_denyBotCall = false;
|
||||
m_dead = false;
|
||||
m_mounted = false;
|
||||
m_serverBeat = 50;
|
||||
m_seq = 0;
|
||||
m_canReportBugs = false;
|
||||
m_fightMode = Otc::FightBalanced;
|
||||
m_chaseMode = Otc::DontChase;
|
||||
|
@ -104,15 +105,9 @@ void Game::processLoginWait(const std::string& message, int time)
|
|||
g_lua.callGlobalField("g_game", "onLoginWait", message, time);
|
||||
}
|
||||
|
||||
void Game::processGameStart(const LocalPlayerPtr& localPlayer, int serverBeat, bool canReportBugs)
|
||||
void Game::processGameStart()
|
||||
{
|
||||
// reset the new game state
|
||||
resetGameStates();
|
||||
|
||||
m_localPlayer = localPlayer;
|
||||
m_localPlayer->setName(m_characterName);
|
||||
m_serverBeat = serverBeat;
|
||||
m_canReportBugs = canReportBugs;
|
||||
m_online = true;
|
||||
|
||||
// synchronize fight modes with the server
|
||||
m_protocolGame->sendChangeFightModes(m_fightMode, m_chaseMode, m_safeFight);
|
||||
|
@ -401,9 +396,9 @@ void Game::processQuestLine(int questId, const std::vector<std::tuple<std::strin
|
|||
g_lua.callGlobalField("g_game", "onQuestLine", questId, questMissions);
|
||||
}
|
||||
|
||||
void Game::processAttackCancel()
|
||||
void Game::processAttackCancel(uint seq)
|
||||
{
|
||||
if(isAttacking())
|
||||
if(isAttacking() && (seq == 0 || m_seq == seq))
|
||||
setAttackingCreature(nullptr);
|
||||
}
|
||||
|
||||
|
@ -423,6 +418,12 @@ void Game::loginWorld(const std::string& account, const std::string& password, c
|
|||
if(m_protocolVersion == 0)
|
||||
stdext::throw_exception("Must set a valid game protocol version before logging.");
|
||||
|
||||
// reset the new game state
|
||||
resetGameStates();
|
||||
|
||||
m_localPlayer = LocalPlayerPtr(new LocalPlayer);
|
||||
m_localPlayer->setName(m_characterName);
|
||||
|
||||
m_protocolGame = ProtocolGamePtr(new ProtocolGame);
|
||||
m_protocolGame->login(account, password, worldHost, (uint16)worldPort, characterName);
|
||||
m_characterName = characterName;
|
||||
|
@ -505,15 +506,10 @@ void Game::autoWalk(const std::vector<Otc::Direction>& dirs)
|
|||
|
||||
Otc::Direction direction = dirs.front();
|
||||
TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
|
||||
if(toTile && toTile->isWalkable())
|
||||
if(toTile && toTile->isWalkable() && !m_localPlayer->isAutoWalking())
|
||||
m_localPlayer->preWalk(direction);
|
||||
|
||||
forceWalk(direction);
|
||||
|
||||
std::vector<Otc::Direction> nextDirs = dirs;
|
||||
nextDirs.erase(nextDirs.begin());
|
||||
if(nextDirs.size() > 0)
|
||||
m_protocolGame->sendAutoWalk(nextDirs);
|
||||
m_protocolGame->sendAutoWalk(dirs);
|
||||
|
||||
g_lua.callGlobalField("g_game", "onAutoWalk", direction);
|
||||
}
|
||||
|
@ -737,7 +733,7 @@ void Game::attack(const CreaturePtr& creature)
|
|||
cancelFollow();
|
||||
|
||||
setAttackingCreature(creature);
|
||||
m_protocolGame->sendAttack(creature ? creature->getId() : 0);
|
||||
m_protocolGame->sendAttack(creature ? creature->getId() : 0, ++m_seq);
|
||||
}
|
||||
|
||||
void Game::follow(const CreaturePtr& creature)
|
||||
|
@ -751,7 +747,7 @@ void Game::follow(const CreaturePtr& creature)
|
|||
cancelAttack();
|
||||
|
||||
setFollowingCreature(creature);
|
||||
m_protocolGame->sendFollow(creature ? creature->getId() : 0);
|
||||
m_protocolGame->sendFollow(creature ? creature->getId() : 0, ++m_seq);
|
||||
}
|
||||
|
||||
void Game::cancelAttackAndFollow()
|
||||
|
@ -885,7 +881,7 @@ void Game::partyShareExperience(bool active)
|
|||
{
|
||||
if(!canPerformGameAction())
|
||||
return;
|
||||
m_protocolGame->sendShareExperience(active, 0);
|
||||
m_protocolGame->sendShareExperience(active);
|
||||
}
|
||||
|
||||
void Game::requestOutfit()
|
||||
|
@ -1084,15 +1080,16 @@ bool Game::checkBotProtection()
|
|||
bool Game::canPerformGameAction()
|
||||
{
|
||||
// we can only perform game actions if we meet these conditions:
|
||||
// - the game is online
|
||||
// - the local player exists
|
||||
// - the local player is not dead
|
||||
// - we have a game protocol
|
||||
// - the game protocol is connected
|
||||
// - its not a bot action
|
||||
return m_localPlayer && !m_dead && m_protocolGame && m_protocolGame->isConnected() && checkBotProtection();
|
||||
return m_online && m_localPlayer && !m_dead && m_protocolGame && m_protocolGame->isConnected() && checkBotProtection();
|
||||
}
|
||||
|
||||
void Game::setProtocolVersion(int version)
|
||||
void Game::setClientVersion(int version)
|
||||
{
|
||||
if(isOnline())
|
||||
stdext::throw_exception("Unable to change client version while online");
|
||||
|
@ -1147,6 +1144,8 @@ void Game::setProtocolVersion(int version)
|
|||
}
|
||||
|
||||
m_protocolVersion = version;
|
||||
|
||||
g_lua.callGlobalField("g_game", "onClientVersionChange", version);
|
||||
}
|
||||
|
||||
void Game::setAttackingCreature(const CreaturePtr& creature)
|
||||
|
|
|
@ -48,7 +48,7 @@ protected:
|
|||
void processLoginAdvice(const std::string& message);
|
||||
void processLoginWait(const std::string& message, int time);
|
||||
|
||||
void processGameStart(const LocalPlayerPtr& localPlayer, int serverBeat, bool canReportBugs);
|
||||
void processGameStart();
|
||||
void processGameEnd();
|
||||
void processDeath(int penality);
|
||||
|
||||
|
@ -56,7 +56,7 @@ protected:
|
|||
void processInventoryChange(int slot, const ItemPtr& item);
|
||||
void processCreatureMove(const CreaturePtr& creature, const Position& oldPos, const Position& newPos);
|
||||
void processCreatureTeleport(const CreaturePtr& creature);
|
||||
void processAttackCancel();
|
||||
void processAttackCancel(uint seq);
|
||||
void processWalkCancel(Otc::Direction direction);
|
||||
|
||||
// message related
|
||||
|
@ -232,17 +232,16 @@ public:
|
|||
void setFeature(Otc::GameFeature feature) { m_features.set(feature, false); }
|
||||
bool getFeature(Otc::GameFeature feature) { return m_features.test(feature); }
|
||||
|
||||
void setProtocolVersion(int version);
|
||||
int getProtocolVersion() { return m_protocolVersion; }
|
||||
void setClientVersion(int version);
|
||||
int getClientVersion() { return m_protocolVersion; }
|
||||
|
||||
void setRSA(const std::string& rsa);
|
||||
std::string getRSA() { return m_rsa; }
|
||||
|
||||
bool canPerformGameAction();
|
||||
bool canReportBugs() { return m_canReportBugs; }
|
||||
bool checkBotProtection();
|
||||
|
||||
bool isOnline() { return !!m_localPlayer; }
|
||||
bool isOnline() { return m_online; }
|
||||
bool isDead() { return m_dead; }
|
||||
bool isAttacking() { return !!m_attackingCreature; }
|
||||
bool isFollowing() { return !!m_followingCreature; }
|
||||
|
@ -253,7 +252,10 @@ public:
|
|||
std::map<int, Vip> getVips() { return m_vips; }
|
||||
CreaturePtr getAttackingCreature() { return m_attackingCreature; }
|
||||
CreaturePtr getFollowingCreature() { return m_followingCreature; }
|
||||
void setServerBeat(int beat) { m_serverBeat = beat; }
|
||||
int getServerBeat() { return m_serverBeat; }
|
||||
void setCanReportBugs(bool enable) { m_canReportBugs = enable; }
|
||||
bool canReportBugs() { return m_canReportBugs; }
|
||||
LocalPlayerPtr getLocalPlayer() { return m_localPlayer; }
|
||||
ProtocolGamePtr getProtocolGame() { return m_protocolGame; }
|
||||
std::string getCharacterName() { return m_characterName; }
|
||||
|
@ -275,10 +277,12 @@ private:
|
|||
std::map<int, ContainerPtr> m_containers;
|
||||
std::map<int, Vip> m_vips;
|
||||
|
||||
bool m_online;
|
||||
bool m_denyBotCall;
|
||||
bool m_dead;
|
||||
bool m_mounted;
|
||||
int m_serverBeat;
|
||||
uint m_seq;
|
||||
Otc::FightModes m_fightMode;
|
||||
Otc::ChaseModes m_chaseMode;
|
||||
bool m_safeFight;
|
||||
|
|
|
@ -187,8 +187,8 @@ void Item::setOtbId(uint16 id)
|
|||
{
|
||||
if(!g_things.isValidOtbId(id))
|
||||
id = 0;
|
||||
auto otbType = g_things.getItemType(id);
|
||||
m_id = otbType->getClientId();
|
||||
auto itemType = g_things.getItemType(id);
|
||||
m_id = itemType->getClientId();
|
||||
m_otbId = id;
|
||||
}
|
||||
|
||||
|
|
|
@ -194,8 +194,8 @@ void OTClient::registerLuaFunctions()
|
|||
g_lua.bindSingletonFunction("g_game", "getServerBeat", &Game::getServerBeat, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getLocalPlayer", &Game::getLocalPlayer, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getProtocolGame", &Game::getProtocolGame, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getProtocolVersion", &Game::getProtocolVersion, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "setProtocolVersion", &Game::setProtocolVersion, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getClientVersion", &Game::getClientVersion, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "setClientVersion", &Game::setClientVersion, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getCharacterName", &Game::getCharacterName, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getWorldName", &Game::getWorldName, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getGMActions", &Game::getGMActions, &g_game);
|
||||
|
|
|
@ -518,7 +518,7 @@ void Map::saveOtcm(const std::string& fileName)
|
|||
// version 1 header
|
||||
fin->addString("OTCM 1.0"); // map description
|
||||
fin->addU32(g_things.getDatSignature());
|
||||
fin->addU16(g_game.getProtocolVersion());
|
||||
fin->addU16(g_game.getClientVersion());
|
||||
fin->addString(g_game.getWorldName());
|
||||
|
||||
// go back and rewrite where the map data starts
|
||||
|
|
|
@ -175,7 +175,7 @@ public:
|
|||
|
||||
private:
|
||||
TileMap m_tiles;
|
||||
std::map<uint32, CreaturePtr> m_knownCreatures;
|
||||
std::unordered_map<uint32, CreaturePtr> m_knownCreatures;
|
||||
std::array<std::vector<MissilePtr>, Otc::MAX_Z+1> m_floorMissiles;
|
||||
std::vector<AnimatedTextPtr> m_animatedTexts;
|
||||
std::vector<StaticTextPtr> m_staticTexts;
|
||||
|
|
|
@ -81,6 +81,6 @@ void OTClient::terminate()
|
|||
{
|
||||
g_map.terminate();
|
||||
g_things.terminate();
|
||||
g_sprites.termiante();
|
||||
g_sprites.terminate();
|
||||
g_shaders.terminate();
|
||||
}
|
||||
|
|
|
@ -135,7 +135,8 @@ namespace Proto {
|
|||
GameServerMarketEnter = 246, // 944
|
||||
GameServerMarketLeave = 247, // 944
|
||||
GameServerMarketDetail = 248, // 944
|
||||
GameServerMarketBrowse = 249 // 944
|
||||
GameServerMarketBrowse = 249, // 944
|
||||
GameServerShowModalDialog = 250 // 960
|
||||
};
|
||||
|
||||
enum ClientOpcodes {
|
||||
|
|
|
@ -44,8 +44,7 @@ void ProtocolGame::onConnect()
|
|||
{
|
||||
Protocol::onConnect();
|
||||
|
||||
// must create local player before parsing anything
|
||||
m_localPlayer = LocalPlayerPtr(new LocalPlayer);
|
||||
m_localPlayer = g_game.getLocalPlayer();
|
||||
|
||||
if(g_game.getFeature(Otc::GameProtocolChecksum))
|
||||
enableChecksum();
|
||||
|
|
|
@ -79,14 +79,14 @@ public:
|
|||
void sendOpenPrivateChannel(const std::string& receiver);
|
||||
void sendCloseNpcChannel();
|
||||
void sendChangeFightModes(Otc::FightModes fightMode, Otc::ChaseModes chaseMode, bool safeFight);
|
||||
void sendAttack(uint creatureId);
|
||||
void sendFollow(uint creatureId);
|
||||
void sendAttack(uint creatureId, uint seq);
|
||||
void sendFollow(uint creatureId, uint seq);
|
||||
void sendInviteToParty(uint creatureId);
|
||||
void sendJoinParty(uint creatureId);
|
||||
void sendRevokeInvitation(uint creatureId);
|
||||
void sendPassLeadership(uint creatureId);
|
||||
void sendLeaveParty();
|
||||
void sendShareExperience(bool active, int unknown);
|
||||
void sendShareExperience(bool active);
|
||||
void sendOpenOwnChannel();
|
||||
void sendInviteToOwnChannel(const std::string& name);
|
||||
void sendExcludeFromOwnChannel(const std::string& name);
|
||||
|
@ -166,9 +166,9 @@ private:
|
|||
void parsePlayerSkills(const InputMessagePtr& msg);
|
||||
void parsePlayerState(const InputMessagePtr& msg);
|
||||
void parsePlayerCancelAttack(const InputMessagePtr& msg);
|
||||
void parseSpellDelay(const InputMessagePtr& msg);
|
||||
void parseSpellGroupDelay(const InputMessagePtr& msg);
|
||||
void parseMultiUseDelay(const InputMessagePtr& msg);
|
||||
void parseSpellCooldown(const InputMessagePtr& msg);
|
||||
void parseSpellGroupCooldown(const InputMessagePtr& msg);
|
||||
void parseMultiUseCooldown(const InputMessagePtr& msg);
|
||||
void parseCreatureSpeak(const InputMessagePtr& msg);
|
||||
void parseChannelList(const InputMessagePtr& msg);
|
||||
void parseOpenChannel(const InputMessagePtr& msg);
|
||||
|
@ -198,15 +198,17 @@ private:
|
|||
void parseChannelEvent(const InputMessagePtr& msg);
|
||||
void parseItemInfo(const InputMessagePtr& msg);
|
||||
void parsePlayerInventory(const InputMessagePtr& msg);
|
||||
void parseShowModalDialog(const InputMessagePtr& msg);
|
||||
void parseExtendedOpcode(const InputMessagePtr& msg);
|
||||
|
||||
public:
|
||||
void setMapDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height);
|
||||
int setFloorDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height, int offset, int skip);
|
||||
void setTileDescription(const InputMessagePtr& msg, Position position);
|
||||
int setTileDescription(const InputMessagePtr& msg, Position position);
|
||||
|
||||
Outfit getOutfit(const InputMessagePtr& msg);
|
||||
ThingPtr getThing(const InputMessagePtr& msg);
|
||||
ThingPtr getMappedThing(const InputMessagePtr& msg);
|
||||
CreaturePtr getCreature(const InputMessagePtr& msg, int type = 0);
|
||||
ItemPtr getItem(const InputMessagePtr& msg, int id = 0);
|
||||
Position getPosition(const InputMessagePtr& msg);
|
||||
|
|
|
@ -35,13 +35,18 @@
|
|||
|
||||
void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
||||
{
|
||||
int opcode = 0;
|
||||
int prevOpcode = 0;
|
||||
int opcode = -1;
|
||||
int prevOpcode = -1;
|
||||
|
||||
try {
|
||||
while(!msg->eof()) {
|
||||
opcode = msg->getU8();
|
||||
|
||||
if(!m_gameInitialized && opcode >= Proto::GameServerFirstGameOpcode) {
|
||||
g_game.processGameStart();
|
||||
m_gameInitialized = true;
|
||||
}
|
||||
|
||||
// try to parse in lua first
|
||||
int readPos = msg->getReadPos();
|
||||
if(callLuaField<bool>("onOpcode", opcode, msg))
|
||||
|
@ -49,9 +54,6 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
|||
else
|
||||
msg->setReadPos(readPos); // restore read pos
|
||||
|
||||
if(!m_gameInitialized && opcode > Proto::GameServerFirstGameOpcode)
|
||||
g_logger.warning("received a game opcode from the server, but the game is not initialized yet, this is a server side bug");
|
||||
|
||||
switch(opcode) {
|
||||
case Proto::GameServerInitGame:
|
||||
parseInitGame(msg);
|
||||
|
@ -70,8 +72,8 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
|||
break;
|
||||
case Proto::GameServerPing:
|
||||
case Proto::GameServerPingBack:
|
||||
if((opcode == Proto::GameServerPing && g_game.getProtocolVersion() >= 953) ||
|
||||
(opcode == Proto::GameServerPingBack && g_game.getProtocolVersion() < 953))
|
||||
if((opcode == Proto::GameServerPing && g_game.getClientVersion() >= 953) ||
|
||||
(opcode == Proto::GameServerPingBack && g_game.getClientVersion() < 953))
|
||||
parsePingBack(msg);
|
||||
else
|
||||
parsePing(msg);
|
||||
|
@ -279,13 +281,13 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
|||
break;
|
||||
// PROTOCOL>=870
|
||||
case Proto::GameServerSpellDelay:
|
||||
parseSpellDelay(msg);
|
||||
parseSpellCooldown(msg);
|
||||
break;
|
||||
case Proto::GameServerSpellGroupDelay:
|
||||
parseSpellGroupDelay(msg);
|
||||
parseSpellGroupCooldown(msg);
|
||||
break;
|
||||
case Proto::GameServerMultiUseDelay:
|
||||
parseMultiUseDelay(msg);
|
||||
parseMultiUseCooldown(msg);
|
||||
break;
|
||||
// PROTOCOL>=910
|
||||
case Proto::GameServerChannelEvent:
|
||||
|
@ -306,7 +308,7 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
|||
parseExtendedOpcode(msg);
|
||||
break;
|
||||
default:
|
||||
stdext::throw_exception("unknown opcode");
|
||||
stdext::throw_exception(stdext::format("unhandled opcode %d", (int)opcode));
|
||||
break;
|
||||
}
|
||||
prevOpcode = opcode;
|
||||
|
@ -319,13 +321,13 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
|||
|
||||
void ProtocolGame::parseInitGame(const InputMessagePtr& msg)
|
||||
{
|
||||
m_gameInitialized = true;
|
||||
uint playerId = msg->getU32();
|
||||
int serverBeat = msg->getU16();
|
||||
bool canReportBugs = msg->getU8();
|
||||
|
||||
m_localPlayer->setId(playerId);
|
||||
g_game.processGameStart(m_localPlayer, serverBeat, canReportBugs);
|
||||
g_game.setServerBeat(serverBeat);
|
||||
g_game.setCanReportBugs(canReportBugs);
|
||||
}
|
||||
|
||||
void ProtocolGame::parseGMActions(const InputMessagePtr& msg)
|
||||
|
@ -334,9 +336,9 @@ void ProtocolGame::parseGMActions(const InputMessagePtr& msg)
|
|||
|
||||
int numViolationReasons;
|
||||
|
||||
if(g_game.getProtocolVersion() >= 860)
|
||||
if(g_game.getClientVersion() >= 860)
|
||||
numViolationReasons = 20;
|
||||
else if(g_game.getProtocolVersion() >= 854)
|
||||
else if(g_game.getClientVersion() >= 854)
|
||||
numViolationReasons = 19;
|
||||
else
|
||||
numViolationReasons = 32;
|
||||
|
@ -454,7 +456,7 @@ void ProtocolGame::parseTileAddThing(const InputMessagePtr& msg)
|
|||
Position pos = getPosition(msg);
|
||||
int stackPos = -1;
|
||||
|
||||
if(g_game.getProtocolVersion() >= 854)
|
||||
if(g_game.getClientVersion() >= 854)
|
||||
stackPos = msg->getU8();
|
||||
|
||||
ThingPtr thing = getThing(msg);
|
||||
|
@ -463,54 +465,54 @@ void ProtocolGame::parseTileAddThing(const InputMessagePtr& msg)
|
|||
|
||||
void ProtocolGame::parseTileTransformThing(const InputMessagePtr& msg)
|
||||
{
|
||||
Position pos = getPosition(msg);
|
||||
int stackPos = msg->getU8();
|
||||
ThingPtr thing = getMappedThing(msg);
|
||||
ThingPtr newThing = getThing(msg);
|
||||
|
||||
ThingPtr thing = getThing(msg);
|
||||
if(thing) {
|
||||
if(!g_map.removeThingByPos(pos, stackPos))
|
||||
g_logger.traceError("could not remove thing");
|
||||
g_map.addThing(thing, pos, stackPos);
|
||||
if(!thing) {
|
||||
g_logger.traceError("no thing");
|
||||
return;
|
||||
}
|
||||
|
||||
Position pos = thing->getPosition();
|
||||
int stackpos = thing->getStackpos();
|
||||
assert(thing->getStackPriority() == newThing->getStackPriority());
|
||||
|
||||
if(!g_map.removeThing(thing)) {
|
||||
g_logger.traceError("unable to remove thing");
|
||||
return;
|
||||
}
|
||||
|
||||
g_map.addThing(newThing, pos, stackpos);
|
||||
}
|
||||
|
||||
void ProtocolGame::parseTileRemoveThing(const InputMessagePtr& msg)
|
||||
{
|
||||
Position pos = getPosition(msg);
|
||||
int stackPos = msg->getU8();
|
||||
ThingPtr thing = getMappedThing(msg);
|
||||
if(!thing) {
|
||||
g_logger.traceError("no thing");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!g_map.removeThingByPos(pos, stackPos))
|
||||
g_logger.traceError("could not remove thing");
|
||||
g_map.removeThing(thing);
|
||||
}
|
||||
|
||||
void ProtocolGame::parseCreatureMove(const InputMessagePtr& msg)
|
||||
{
|
||||
Position oldPos = getPosition(msg);
|
||||
int oldStackpos = msg->getU8();
|
||||
ThingPtr thing = getMappedThing(msg);
|
||||
Position newPos = getPosition(msg);
|
||||
|
||||
ThingPtr thing = g_map.getThing(oldPos, oldStackpos);
|
||||
if(!thing) {
|
||||
g_logger.traceError("could not get thing");
|
||||
if(!thing || !thing->isCreature()) {
|
||||
g_logger.traceError("no creature found to move");
|
||||
return;
|
||||
}
|
||||
|
||||
CreaturePtr creature = thing->asCreature();
|
||||
if(!creature) {
|
||||
g_logger.traceError("thing is not a creature");
|
||||
return;
|
||||
}
|
||||
|
||||
// update map tiles
|
||||
if(!g_map.removeThing(thing))
|
||||
g_logger.traceError("could not remove thing");
|
||||
|
||||
int stackPos = -2;
|
||||
|
||||
// older protocols stores creatures in reverse order
|
||||
if(!g_game.getProtocolVersion() >= 854)
|
||||
// newer protocols stores creatures in reverse order
|
||||
if(!g_game.getClientVersion() >= 854)
|
||||
stackPos = -1;
|
||||
|
||||
g_map.removeThing(thing);
|
||||
g_map.addThing(thing, newPos, stackPos);
|
||||
}
|
||||
|
||||
|
@ -887,7 +889,7 @@ void ProtocolGame::parsePlayerStats(const InputMessagePtr& msg)
|
|||
m_localPlayer->setStamina(stamina);
|
||||
m_localPlayer->setSoul(soul);
|
||||
|
||||
if(g_game.getProtocolVersion() >= 910)
|
||||
if(g_game.getClientVersion() >= 910)
|
||||
m_localPlayer->setSpeed(msg->getU16());
|
||||
|
||||
if(g_game.getFeature(Otc::GamePlayerRegenerationTime))
|
||||
|
@ -918,29 +920,28 @@ void ProtocolGame::parsePlayerState(const InputMessagePtr& msg)
|
|||
|
||||
void ProtocolGame::parsePlayerCancelAttack(const InputMessagePtr& msg)
|
||||
{
|
||||
if(g_game.getProtocolVersion() >= 860)
|
||||
msg->getU32(); // unknown
|
||||
uint seq = 0;
|
||||
if(g_game.getClientVersion() >= 860)
|
||||
seq = msg->getU32();
|
||||
|
||||
g_game.processAttackCancel();
|
||||
g_game.processAttackCancel(seq);
|
||||
}
|
||||
|
||||
void ProtocolGame::parseSpellDelay(const InputMessagePtr& msg)
|
||||
void ProtocolGame::parseSpellCooldown(const InputMessagePtr& msg)
|
||||
{
|
||||
msg->getU16(); // spell id
|
||||
msg->getU16(); // cooldown
|
||||
msg->getU8(); // unknown
|
||||
msg->getU32(); // cooldown
|
||||
}
|
||||
|
||||
void ProtocolGame::parseSpellGroupDelay(const InputMessagePtr& msg)
|
||||
void ProtocolGame::parseSpellGroupCooldown(const InputMessagePtr& msg)
|
||||
{
|
||||
msg->getU16(); // spell id
|
||||
msg->getU16(); // cooldown
|
||||
msg->getU8(); // unknown
|
||||
msg->getU8(); // group id
|
||||
msg->getU32(); // cooldown
|
||||
}
|
||||
|
||||
void ProtocolGame::parseMultiUseDelay(const InputMessagePtr& msg)
|
||||
void ProtocolGame::parseMultiUseCooldown(const InputMessagePtr& msg)
|
||||
{
|
||||
//TODO
|
||||
msg->getU32(); // cooldown
|
||||
}
|
||||
|
||||
void ProtocolGame::parseCreatureSpeak(const InputMessagePtr& msg)
|
||||
|
@ -1225,18 +1226,36 @@ void ProtocolGame::parseChannelEvent(const InputMessagePtr& msg)
|
|||
|
||||
void ProtocolGame::parseItemInfo(const InputMessagePtr& msg)
|
||||
{
|
||||
/*int count = msg.getU16() - 1;
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
int unknown1 = msg->getU8();
|
||||
int unknown2 = msg->getU16();
|
||||
std::string unknown3 = msg->getString();
|
||||
}*/
|
||||
int size = msg->getU8();
|
||||
for(int i=0;i<size;++i) {
|
||||
msg->getU16(); // id
|
||||
msg->getU8(); // subtype
|
||||
msg->getString(); // description
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolGame::parsePlayerInventory(const InputMessagePtr& msg)
|
||||
{
|
||||
//TODO
|
||||
int size = msg->getU16();
|
||||
for(int i=0;i<size;++i) {
|
||||
msg->getU16(); // id
|
||||
msg->getU8(); // subtype
|
||||
msg->getU16(); // count
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolGame::parseShowModalDialog(const InputMessagePtr& msg)
|
||||
{
|
||||
msg->getU32(); // id
|
||||
msg->getString(); // title
|
||||
msg->getString(); // message
|
||||
int size = msg->getU8();
|
||||
for(int i=0;i<size;++i) {
|
||||
msg->getString(); // button name
|
||||
msg->getU8(); // button value
|
||||
}
|
||||
msg->getU8(); // default escape button
|
||||
msg->getU8(); // default enter button
|
||||
}
|
||||
|
||||
void ProtocolGame::parseExtendedOpcode(const InputMessagePtr& msg)
|
||||
|
@ -1275,51 +1294,41 @@ int ProtocolGame::setFloorDescription(const InputMessagePtr& msg, int x, int y,
|
|||
for(int nx = 0; nx < width; nx++) {
|
||||
for(int ny = 0; ny < height; ny++) {
|
||||
Position tilePos(x + nx + offset, y + ny + offset, z);
|
||||
|
||||
// clean pre stored tiles
|
||||
g_map.cleanTile(tilePos);
|
||||
|
||||
if(skip == 0) {
|
||||
int tileOpt = msg->peekU16();
|
||||
if(tileOpt >= 0xFF00)
|
||||
skip = (msg->getU16() & 0xFF);
|
||||
else {
|
||||
setTileDescription(msg, tilePos);
|
||||
skip = (msg->getU16() & 0xFF);
|
||||
}
|
||||
}
|
||||
else
|
||||
if(skip == 0)
|
||||
skip = setTileDescription(msg, tilePos);
|
||||
else {
|
||||
g_map.cleanTile(tilePos);
|
||||
skip--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return skip;
|
||||
}
|
||||
|
||||
void ProtocolGame::setTileDescription(const InputMessagePtr& msg, Position position)
|
||||
int ProtocolGame::setTileDescription(const InputMessagePtr& msg, Position position)
|
||||
{
|
||||
if(g_game.getFeature(Otc::GameEnvironmentEffect))
|
||||
msg->getU16(); // environment effect
|
||||
|
||||
|
||||
g_map.cleanTile(position);
|
||||
|
||||
int stackPos = 0;
|
||||
while(true) {
|
||||
int inspectItemId = msg->peekU16();
|
||||
if(inspectItemId >= 0xFF00) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if(stackPos >= 10)
|
||||
g_logger.traceError(stdext::format("too many things, stackpos=%d, pos=%s", stackPos, stdext::to_string(position)));
|
||||
bool gotEffect = 0;
|
||||
for(int stackPos=0;stackPos<256;stackPos++) {
|
||||
if(msg->peekU16() >= 0xff00)
|
||||
return msg->getU16() & 0xff;
|
||||
|
||||
ThingPtr thing = getThing(msg);
|
||||
g_map.addThing(thing, position, -2);
|
||||
if(g_game.getFeature(Otc::GameEnvironmentEffect) && !gotEffect) {
|
||||
msg->getU16(); // environment effect
|
||||
gotEffect = true;
|
||||
continue;
|
||||
}
|
||||
stackPos++;
|
||||
|
||||
if(stackPos > 10)
|
||||
g_logger.traceError(stdext::format("too many things, pos=%s, stackpos=%d", stdext::to_string(position), stackPos));
|
||||
|
||||
ThingPtr thing = getThing(msg);
|
||||
g_map.addThing(thing, position, -2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Outfit ProtocolGame::getOutfit(const InputMessagePtr& msg)
|
||||
{
|
||||
Outfit outfit;
|
||||
|
@ -1376,6 +1385,31 @@ ThingPtr ProtocolGame::getThing(const InputMessagePtr& msg)
|
|||
return thing;
|
||||
}
|
||||
|
||||
ThingPtr ProtocolGame::getMappedThing(const InputMessagePtr& msg)
|
||||
{
|
||||
ThingPtr thing;
|
||||
uint16 x = msg->getU16();
|
||||
|
||||
if(x != 0xffff) {
|
||||
Position pos;
|
||||
pos.x = x;
|
||||
pos.y = msg->getU16();
|
||||
pos.z = msg->getU8();
|
||||
uint8 stackpos = msg->getU8();
|
||||
assert(stackpos != 255);
|
||||
thing = g_map.getThing(pos, stackpos);
|
||||
if(!thing)
|
||||
g_logger.traceError(stdext::format("no thing at pos:%s, stackpos:%d", stdext::to_string(pos), stackpos));
|
||||
} else {
|
||||
uint32 id = msg->getU32();
|
||||
thing = g_map.getCreatureById(id);
|
||||
if(!thing)
|
||||
g_logger.traceError(stdext::format("no creature with id %u", id));
|
||||
}
|
||||
|
||||
return thing;
|
||||
}
|
||||
|
||||
CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
||||
{
|
||||
if(type == 0)
|
||||
|
@ -1397,7 +1431,7 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
|||
uint id = msg->getU32();
|
||||
|
||||
int creatureType;
|
||||
if(g_game.getProtocolVersion() >= 910)
|
||||
if(g_game.getClientVersion() >= 910)
|
||||
creatureType = msg->getU8();
|
||||
else {
|
||||
if(id >= Proto::PlayerStartId && id < Proto::PlayerEndId)
|
||||
|
@ -1416,8 +1450,13 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
|||
|
||||
if(id == m_localPlayer->getId())
|
||||
creature = m_localPlayer;
|
||||
else if(creatureType == Proto::CreatureTypePlayer)
|
||||
creature = PlayerPtr(new Player);
|
||||
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)
|
||||
|
@ -1447,13 +1486,13 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
|||
|
||||
// emblem is sent only when the creature is not known
|
||||
int emblem = -1;
|
||||
bool passable = false;
|
||||
bool unpass = true;
|
||||
|
||||
if(g_game.getFeature(Otc::GameCreatureEmblems) && !known)
|
||||
emblem = msg->getU8();
|
||||
|
||||
if(g_game.getProtocolVersion() >= 854)
|
||||
passable = (msg->getU8() == 0);
|
||||
if(g_game.getClientVersion() >= 854)
|
||||
unpass = msg->getU8();
|
||||
|
||||
if(creature) {
|
||||
creature->setHealthPercent(healthPercent);
|
||||
|
@ -1465,7 +1504,7 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
|||
creature->setShield(shield);
|
||||
if(emblem != -1)
|
||||
creature->setEmblem(emblem);
|
||||
creature->setPassable(passable);
|
||||
creature->setPassable(!unpass);
|
||||
|
||||
if(creature == m_localPlayer && !m_localPlayer->isKnown())
|
||||
m_localPlayer->setKnown(true);
|
||||
|
@ -1481,11 +1520,11 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
|||
if(creature)
|
||||
creature->turn(direction);
|
||||
|
||||
if(g_game.getProtocolVersion() >= 953) {
|
||||
bool passable = msg->getU8();
|
||||
if(g_game.getClientVersion() >= 953) {
|
||||
bool unpass = msg->getU8();
|
||||
|
||||
if(creature)
|
||||
creature->setPassable(passable);
|
||||
creature->setPassable(!unpass);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -1502,7 +1541,7 @@ ItemPtr ProtocolGame::getItem(const InputMessagePtr& msg, int id)
|
|||
|
||||
ItemPtr item = Item::create(id);
|
||||
if(item->getId() == 0)
|
||||
stdext::throw_exception("unable to create item with invalid id 0");
|
||||
stdext::throw_exception(stdext::format("unable to create item with invalid id %d", id));
|
||||
|
||||
if(item->isStackable() || item->isFluidContainer() || item->isSplash() || item->isChargeable())
|
||||
item->setCountOrSubType(msg->getU8());
|
||||
|
@ -1511,7 +1550,7 @@ ItemPtr ProtocolGame::getItem(const InputMessagePtr& msg, int id)
|
|||
if(item->getAnimationPhases() > 1) {
|
||||
// 0xfe => random phase
|
||||
// 0xff => async?
|
||||
msg->getU8();
|
||||
msg->getU8(); // phase
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRando
|
|||
msg->addU8(Proto::ClientEnterGame);
|
||||
|
||||
msg->addU16(g_lua.callGlobalField<int>("g_game", "getOs"));
|
||||
msg->addU16(g_game.getProtocolVersion());
|
||||
msg->addU16(g_game.getClientVersion());
|
||||
|
||||
int paddingBytes = 128;
|
||||
msg->addU8(0); // first RSA byte must be 0
|
||||
|
@ -509,21 +509,21 @@ void ProtocolGame::sendChangeFightModes(Otc::FightModes fightMode, Otc::ChaseMod
|
|||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendAttack(uint creatureId)
|
||||
void ProtocolGame::sendAttack(uint creatureId, uint seq)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientAttack);
|
||||
msg->addU32(creatureId);
|
||||
msg->addU32(0);
|
||||
msg->addU32(0);
|
||||
msg->addU32(seq);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendFollow(uint creatureId)
|
||||
void ProtocolGame::sendFollow(uint creatureId, uint seq)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientFollow);
|
||||
msg->addU32(creatureId);
|
||||
msg->addU32(seq);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
|
@ -566,14 +566,14 @@ void ProtocolGame::sendLeaveParty()
|
|||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendShareExperience(bool active, int unknown)
|
||||
void ProtocolGame::sendShareExperience(bool active)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientShareExperience);
|
||||
msg->addU8(active ? 0x01 : 0x00);
|
||||
|
||||
if(g_game.getProtocolVersion() < 910)
|
||||
msg->addU8(unknown);
|
||||
if(g_game.getClientVersion() < 910)
|
||||
msg->addU8(0);
|
||||
|
||||
send(msg);
|
||||
}
|
||||
|
|
|
@ -34,18 +34,18 @@ SpriteManager::SpriteManager()
|
|||
m_signature = 0;
|
||||
}
|
||||
|
||||
void SpriteManager::termiante()
|
||||
void SpriteManager::terminate()
|
||||
{
|
||||
unload();
|
||||
}
|
||||
|
||||
bool SpriteManager::loadSpr(const std::string& file)
|
||||
{
|
||||
m_spritesCount = 0;
|
||||
m_signature = 0;
|
||||
m_loaded = false;
|
||||
try {
|
||||
m_spritesFile = g_resources.openFile(file);
|
||||
if(!m_spritesFile)
|
||||
return false;
|
||||
|
||||
// cache file buffer to avoid lags from hard drive
|
||||
m_spritesFile->cache();
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class SpriteManager
|
|||
public:
|
||||
SpriteManager();
|
||||
|
||||
void termiante();
|
||||
void terminate();
|
||||
|
||||
bool loadSpr(const std::string& file);
|
||||
void unload();
|
||||
|
|
|
@ -66,7 +66,7 @@ ContainerPtr Thing::getParentContainer()
|
|||
int Thing::getStackpos()
|
||||
{
|
||||
if(m_position.x == 65535 && asItem()) // is inside a container
|
||||
return 0;
|
||||
return m_position.z;
|
||||
else if(const TilePtr& tile = getTile())
|
||||
return tile->getThingStackpos(asThing());
|
||||
else {
|
||||
|
|
|
@ -59,16 +59,17 @@ void ThingTypeManager::terminate()
|
|||
|
||||
bool ThingTypeManager::loadDat(const std::string& file)
|
||||
{
|
||||
m_datLoaded = false;
|
||||
m_datSignature = 0;
|
||||
try {
|
||||
FileStreamPtr fin = g_resources.openFile(file);
|
||||
if(!fin)
|
||||
stdext::throw_exception("unable to open file");
|
||||
|
||||
m_datSignature = fin->getU32();
|
||||
|
||||
int numThings[ThingLastCategory];
|
||||
for(int category = 0; category < ThingLastCategory; ++category) {
|
||||
int count = fin->getU16() + 1;
|
||||
m_thingTypes[category].clear();
|
||||
m_thingTypes[category].resize(count, m_nullThingType);
|
||||
}
|
||||
|
||||
|
@ -114,9 +115,9 @@ void ThingTypeManager::loadOtb(const std::string& file)
|
|||
|
||||
m_itemTypes.resize(root->getChildren().size(), m_nullItemType);
|
||||
for(const BinaryTreePtr& node : root->getChildren()) {
|
||||
ItemTypePtr otbType(new ItemType);
|
||||
otbType->unserialize(node);
|
||||
addItemType(otbType);
|
||||
ItemTypePtr itemType(new ItemType);
|
||||
itemType->unserialize(node);
|
||||
addItemType(itemType);
|
||||
}
|
||||
|
||||
m_otbLoaded = true;
|
||||
|
@ -171,25 +172,25 @@ void ThingTypeManager::parseItemType(uint16 id, TiXmlElement* elem)
|
|||
addItemType(newType);
|
||||
}
|
||||
|
||||
ItemTypePtr otbType = getItemType(serverId);
|
||||
otbType->setName(elem->Attribute("name"));
|
||||
ItemTypePtr itemType = getItemType(serverId);
|
||||
itemType->setName(elem->Attribute("name"));
|
||||
for(TiXmlElement* attrib = elem->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) {
|
||||
if(attrib->ValueStr() != "attribute")
|
||||
break;
|
||||
|
||||
if(attrib->Attribute("key") == "description") {
|
||||
otbType->setDesc(attrib->Attribute("value"));
|
||||
itemType->setDesc(attrib->Attribute("value"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThingTypeManager::addItemType(const ItemTypePtr& otbType)
|
||||
void ThingTypeManager::addItemType(const ItemTypePtr& itemType)
|
||||
{
|
||||
uint16 id = otbType->getServerId();
|
||||
uint16 id = itemType->getServerId();
|
||||
if(m_itemTypes.size() <= id)
|
||||
m_itemTypes.resize(id+1, m_nullItemType);
|
||||
m_itemTypes[id] = otbType;
|
||||
m_itemTypes[id] = itemType;
|
||||
}
|
||||
|
||||
const ItemTypePtr& ThingTypeManager::findOtbForClientId(uint16 id)
|
||||
|
@ -197,9 +198,9 @@ const ItemTypePtr& ThingTypeManager::findOtbForClientId(uint16 id)
|
|||
if(m_itemTypes.empty())
|
||||
return m_nullItemType;
|
||||
|
||||
for(const ItemTypePtr& otbType : m_itemTypes) {
|
||||
if(otbType->getClientId() == id)
|
||||
return otbType;
|
||||
for(const ItemTypePtr& itemType : m_itemTypes) {
|
||||
if(itemType->getClientId() == id)
|
||||
return itemType;
|
||||
}
|
||||
|
||||
return m_nullItemType;
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
void loadXml(const std::string& file);
|
||||
void parseItemType(uint16 id, TiXmlElement *elem);
|
||||
|
||||
void addItemType(const ItemTypePtr& otbType);
|
||||
void addItemType(const ItemTypePtr& itemType);
|
||||
const ItemTypePtr& findOtbForClientId(uint16 id);
|
||||
|
||||
const ThingTypePtr& getNullThingType() { return m_nullThingType; }
|
||||
|
|
|
@ -392,7 +392,7 @@ bool Tile::isWalkable()
|
|||
return false;
|
||||
|
||||
if(CreaturePtr creature = thing->asCreature()) {
|
||||
if(!creature->getPassable())
|
||||
if(!creature->isPassable())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -405,7 +405,7 @@ bool Tile::isPathable()
|
|||
return false;
|
||||
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isNotPathable())
|
||||
if(thing->isNotPathable() || thing->isCreature())
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -507,4 +507,13 @@ void Tile::update()
|
|||
if(c != 0)
|
||||
m_minimapColorByte = c;
|
||||
}
|
||||
|
||||
// check stack priorities
|
||||
// this code exists to find stackpos bugs faster
|
||||
int lastPriority = 0;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
int priority = thing->getStackPriority();
|
||||
assert(lastPriority <= priority);
|
||||
lastPriority = priority;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue