Support for Protocols up to 10.71, Adventurer Blessing
This commit is contained in:
parent
6ab69b499d
commit
7f3f18f991
|
@ -45,13 +45,17 @@ CharacterWidget < UIWidget
|
||||||
MainWindow
|
MainWindow
|
||||||
id: charactersWindow
|
id: charactersWindow
|
||||||
!text: tr('Character List')
|
!text: tr('Character List')
|
||||||
size: 250 248
|
|
||||||
visible: false
|
visible: false
|
||||||
@onEnter: CharacterList.doLogin()
|
@onEnter: CharacterList.doLogin()
|
||||||
@onEscape: CharacterList.hide(true)
|
@onEscape: CharacterList.hide(true)
|
||||||
@onSetup: |
|
@onSetup: |
|
||||||
g_keyboard.bindKeyPress('Up', function() self:getChildById('characters'):focusPreviousChild(KeyboardFocusReason) end, self)
|
g_keyboard.bindKeyPress('Up', function() self:getChildById('characters'):focusPreviousChild(KeyboardFocusReason) end, self)
|
||||||
g_keyboard.bindKeyPress('Down', function() self:getChildById('characters'):focusNextChild(KeyboardFocusReason) end, self)
|
g_keyboard.bindKeyPress('Down', function() self:getChildById('characters'):focusNextChild(KeyboardFocusReason) end, self)
|
||||||
|
if g_game.getFeature(GamePreviewState) then
|
||||||
|
self:setSize({width = 350, height = 400})
|
||||||
|
else
|
||||||
|
self:setSize({width = 250, height = 248})
|
||||||
|
end
|
||||||
|
|
||||||
TextList
|
TextList
|
||||||
id: characters
|
id: characters
|
||||||
|
|
|
@ -59,6 +59,12 @@ local function onCharacterList(protocol, characters, account, otui)
|
||||||
loadBox:destroy()
|
loadBox:destroy()
|
||||||
loadBox = nil
|
loadBox = nil
|
||||||
|
|
||||||
|
for _, characterInfo in pairs(characters) do
|
||||||
|
if characterInfo.previewState and characterInfo.previewState ~= PreviewState.Default then
|
||||||
|
characterInfo.worldName = characterInfo.worldName .. ', Preview'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
CharacterList.create(characters, account, otui)
|
CharacterList.create(characters, account, otui)
|
||||||
CharacterList.show()
|
CharacterList.show()
|
||||||
|
|
||||||
|
@ -105,7 +111,7 @@ function EnterGame.init()
|
||||||
local port = g_settings.get('port')
|
local port = g_settings.get('port')
|
||||||
local autologin = g_settings.getBoolean('autologin')
|
local autologin = g_settings.getBoolean('autologin')
|
||||||
local clientVersion = g_settings.getInteger('client-version')
|
local clientVersion = g_settings.getInteger('client-version')
|
||||||
if clientVersion == 0 then clientVersion = 860 end
|
if clientVersion == 0 then clientVersion = 1071 end
|
||||||
|
|
||||||
if port == nil or port == 0 then port = 7171 end
|
if port == nil or port == 0 then port = 7171 end
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,10 @@ inventoryButton = nil
|
||||||
purseButton = nil
|
purseButton = nil
|
||||||
|
|
||||||
function init()
|
function init()
|
||||||
connect(LocalPlayer, { onInventoryChange = onInventoryChange })
|
connect(LocalPlayer, {
|
||||||
|
onInventoryChange = onInventoryChange,
|
||||||
|
onBlessingsChange = onBlessingsChange
|
||||||
|
})
|
||||||
connect(g_game, { onGameStart = refresh })
|
connect(g_game, { onGameStart = refresh })
|
||||||
|
|
||||||
g_keyboard.bindKeyDown('Ctrl+I', toggle)
|
g_keyboard.bindKeyDown('Ctrl+I', toggle)
|
||||||
|
@ -43,7 +46,10 @@ function init()
|
||||||
end
|
end
|
||||||
|
|
||||||
function terminate()
|
function terminate()
|
||||||
disconnect(LocalPlayer, { onInventoryChange = onInventoryChange })
|
disconnect(LocalPlayer, {
|
||||||
|
onInventoryChange = onInventoryChange,
|
||||||
|
onBlessingsChange = onBlessingsChange
|
||||||
|
})
|
||||||
disconnect(g_game, { onGameStart = refresh })
|
disconnect(g_game, { onGameStart = refresh })
|
||||||
|
|
||||||
g_keyboard.unbindKeyDown('Ctrl+I')
|
g_keyboard.unbindKeyDown('Ctrl+I')
|
||||||
|
@ -52,6 +58,21 @@ function terminate()
|
||||||
inventoryButton:destroy()
|
inventoryButton:destroy()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function toggleAdventurerStyle(hasBlessing)
|
||||||
|
for slot = InventorySlotFirst, InventorySlotLast do
|
||||||
|
local itemWidget = inventoryPanel:getChildById('slot' .. slot)
|
||||||
|
if itemWidget then
|
||||||
|
if hasBlessing then
|
||||||
|
itemWidget:setBorderWidth(1)
|
||||||
|
itemWidget:setBorderColor('#F7C80C')
|
||||||
|
else
|
||||||
|
itemWidget:setBorderWidth(0)
|
||||||
|
itemWidget:setBorderColor('white')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function refresh()
|
function refresh()
|
||||||
local player = g_game.getLocalPlayer()
|
local player = g_game.getLocalPlayer()
|
||||||
for i = InventorySlotFirst, InventorySlotPurse do
|
for i = InventorySlotFirst, InventorySlotPurse do
|
||||||
|
@ -60,6 +81,7 @@ function refresh()
|
||||||
else
|
else
|
||||||
onInventoryChange(player, i, nil)
|
onInventoryChange(player, i, nil)
|
||||||
end
|
end
|
||||||
|
toggleAdventurerStyle(Bit.hasBit(player:getBlessings(), Blessings.Adventurer))
|
||||||
end
|
end
|
||||||
|
|
||||||
purseButton:setVisible(g_game.getFeature(GamePurseSlot))
|
purseButton:setVisible(g_game.getFeature(GamePurseSlot))
|
||||||
|
@ -99,3 +121,10 @@ function onInventoryChange(player, slot, item, oldItem)
|
||||||
itemWidget:setItem(nil)
|
itemWidget:setItem(nil)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function onBlessingsChange(player, blessings, oldBlessings)
|
||||||
|
local hasAdventurerBlessing = Bit.hasBit(blessings, Blessings.Adventurer)
|
||||||
|
if hasAdventurerBlessing ~= Bit.hasBit(oldBlessings, Blessings.Adventurer) then
|
||||||
|
toggleAdventurerStyle(hasAdventurerBlessing)
|
||||||
|
end
|
||||||
|
end
|
|
@ -120,6 +120,13 @@ GameSpritesAlphaChannel = 56
|
||||||
GamePremiumExpiration = 57
|
GamePremiumExpiration = 57
|
||||||
GameBrowseField = 58
|
GameBrowseField = 58
|
||||||
GameEnhancedAnimations = 59
|
GameEnhancedAnimations = 59
|
||||||
|
GameOGLInformation = 60
|
||||||
|
GameMessageSizeCheck = 61
|
||||||
|
GamePreviewState = 62
|
||||||
|
GameLoginPacketEncryption = 63
|
||||||
|
GameClientVersion = 64
|
||||||
|
GameContentRevision = 65
|
||||||
|
GameExperienceBonus = 66
|
||||||
|
|
||||||
TextColors = {
|
TextColors = {
|
||||||
red = '#f55e5e', --'#c83200'
|
red = '#f55e5e', --'#c83200'
|
||||||
|
@ -201,7 +208,7 @@ CIPSOFT_RSA = "1321277432058722840622950990822933849527763264961655079678763618"
|
||||||
"88792221429527047321331896351555606801473202394175817"
|
"88792221429527047321331896351555606801473202394175817"
|
||||||
|
|
||||||
-- set to the latest Tibia.pic signature to make otclient compatible with official tibia
|
-- set to the latest Tibia.pic signature to make otclient compatible with official tibia
|
||||||
PIC_SIGNATURE = 0x53208400
|
PIC_SIGNATURE = 0x542100C1
|
||||||
|
|
||||||
OsTypes = {
|
OsTypes = {
|
||||||
Linux = 1,
|
Linux = 1,
|
||||||
|
@ -244,4 +251,20 @@ ExtendedIds = {
|
||||||
NeedsUpdate = 7
|
NeedsUpdate = 7
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PreviewState = {
|
||||||
|
Default = 0,
|
||||||
|
Inactive = 1,
|
||||||
|
Active = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
Blessings = {
|
||||||
|
None = 0,
|
||||||
|
Adventurer = 1,
|
||||||
|
SpiritualShielding = 2,
|
||||||
|
EmbraceOfTibia = 4,
|
||||||
|
FireOfSuns = 8,
|
||||||
|
WisdomOfSolitude = 16,
|
||||||
|
SparkOfPhoenix = 32
|
||||||
|
}
|
||||||
|
|
||||||
-- @}
|
-- @}
|
||||||
|
|
|
@ -53,38 +53,39 @@ end
|
||||||
|
|
||||||
function g_game.getSupportedClients()
|
function g_game.getSupportedClients()
|
||||||
return {
|
return {
|
||||||
740, 741, 750, 760, 770, 772,
|
740, 741, 750, 760, 770, 772,
|
||||||
780, 781, 782, 790, 792,
|
780, 781, 782, 790, 792,
|
||||||
|
|
||||||
800, 810, 811, 820, 821, 822,
|
800, 810, 811, 820, 821, 822,
|
||||||
830, 831, 840, 842, 850, 853,
|
830, 831, 840, 842, 850, 853,
|
||||||
854, 855, 857, 860, 861, 862,
|
854, 855, 857, 860, 861, 862,
|
||||||
870, 871,
|
870, 871,
|
||||||
|
|
||||||
900, 910, 920, 931, 940, 943,
|
900, 910, 920, 931, 940, 943,
|
||||||
944, 951, 952, 953, 954, 960,
|
944, 951, 952, 953, 954, 960,
|
||||||
961, 963, 970, 971, 972, 973,
|
961, 963, 970, 971, 972, 973,
|
||||||
980, 981, 982, 983, 984, 985,
|
980, 981, 982, 983, 984, 985,
|
||||||
986,
|
986,
|
||||||
|
|
||||||
1000, 1001, 1002, 1010, 1011,
|
1000, 1001, 1002, 1010, 1011,
|
||||||
1012, 1013, 1020, 1021, 1022,
|
1012, 1013, 1020, 1021, 1022,
|
||||||
1030, 1031, 1032, 1033, 1034,
|
1030, 1031, 1032, 1033, 1034,
|
||||||
1035, 1036, 1037, 1038, 1039,
|
1035, 1036, 1037, 1038, 1039,
|
||||||
1040, 1041, 1050, 1051, 1052,
|
1040, 1041, 1050, 1051, 1052,
|
||||||
1053, 1054, 1055, 1056, 1057,
|
1053, 1054, 1055, 1056, 1057,
|
||||||
1058, 1059, 1060, 1061
|
1058, 1059, 1060, 1061, 1062,
|
||||||
|
1063, 1064, 1070, 1071
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The client version and protocol version where
|
-- The client version and protocol version where
|
||||||
-- unsynchronized for some releases, not sure if this
|
-- unsynchronized for some releases, not sure if this
|
||||||
-- will be the normal standard.
|
-- will be the normal standard.
|
||||||
|
|
||||||
-- Client Version: Publicly given version when
|
-- Client Version: Publicly given version when
|
||||||
-- downloading Cipsoft client.
|
-- downloading Cipsoft client.
|
||||||
|
|
||||||
-- Protocol Version: Previously was the same as
|
-- Protocol Version: Previously was the same as
|
||||||
-- the client version, but was unsychronized in some
|
-- the client version, but was unsychronized in some
|
||||||
-- releases, now it needs to be verified and added here
|
-- releases, now it needs to be verified and added here
|
||||||
-- if it does not match the client version.
|
-- if it does not match the client version.
|
||||||
|
@ -92,7 +93,7 @@ end
|
||||||
-- Reason for defining both: The server now requires a
|
-- Reason for defining both: The server now requires a
|
||||||
-- Client version and Protocol version from the client.
|
-- Client version and Protocol version from the client.
|
||||||
|
|
||||||
-- Important: Use getClientVersion for specific protocol
|
-- Important: Use getClientVersion for specific protocol
|
||||||
-- features to ensure we are using the proper version.
|
-- features to ensure we are using the proper version.
|
||||||
|
|
||||||
function g_game.getClientProtocolVersion(client)
|
function g_game.getClientProtocolVersion(client)
|
||||||
|
|
|
@ -32,23 +32,28 @@ function ProtocolLogin:sendLoginPacket()
|
||||||
|
|
||||||
msg:addU16(g_game.getProtocolVersion())
|
msg:addU16(g_game.getProtocolVersion())
|
||||||
|
|
||||||
if g_game.getClientVersion() >= 980 then
|
if g_game.getFeature(GameClientVersion) then
|
||||||
msg:addU32(g_game.getClientVersion())
|
msg:addU32(g_game.getClientVersion())
|
||||||
end
|
end
|
||||||
|
|
||||||
msg:addU32(g_things.getDatSignature())
|
if g_game.getFeature(GameContentRevision) then
|
||||||
|
msg:addU16(g_things.getContentRevision())
|
||||||
|
msg:addU16(0)
|
||||||
|
else
|
||||||
|
msg:addU32(g_things.getDatSignature())
|
||||||
|
end
|
||||||
msg:addU32(g_sprites.getSprSignature())
|
msg:addU32(g_sprites.getSprSignature())
|
||||||
msg:addU32(PIC_SIGNATURE)
|
msg:addU32(PIC_SIGNATURE)
|
||||||
|
|
||||||
if g_game.getClientVersion() >= 980 then
|
if g_game.getFeature(GamePreviewState) then
|
||||||
msg:addU8(0) -- clientType
|
msg:addU8(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
local offset = msg:getMessageSize()
|
local offset = msg:getMessageSize()
|
||||||
|
if g_game.getFeature(GameLoginPacketEncryption) then
|
||||||
if g_game.getClientVersion() >= 770 then
|
|
||||||
-- first RSA byte must be 0
|
-- first RSA byte must be 0
|
||||||
msg:addU8(0)
|
msg:addU8(0)
|
||||||
|
|
||||||
-- xtea key
|
-- xtea key
|
||||||
self:generateXteaKey()
|
self:generateXteaKey()
|
||||||
local xteaKey = self:getXteaKey()
|
local xteaKey = self:getXteaKey()
|
||||||
|
@ -74,16 +79,23 @@ function ProtocolLogin:sendLoginPacket()
|
||||||
local paddingBytes = g_crypt.rsaGetSize() - (msg:getMessageSize() - offset)
|
local paddingBytes = g_crypt.rsaGetSize() - (msg:getMessageSize() - offset)
|
||||||
assert(paddingBytes >= 0)
|
assert(paddingBytes >= 0)
|
||||||
msg:addPaddingBytes(paddingBytes, 0)
|
msg:addPaddingBytes(paddingBytes, 0)
|
||||||
if g_game.getClientVersion() >= 770 then
|
if g_game.getFeature(GameLoginPacketEncryption) then
|
||||||
msg:encryptRsa()
|
msg:encryptRsa()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if g_game.getFeature(GameOGLInformation) then
|
||||||
|
msg:addU8(1) --unknown
|
||||||
|
msg:addU8(1) --unknown
|
||||||
|
msg:addString(g_graphics.getRenderer())
|
||||||
|
msg:addString(g_graphics.getVersion())
|
||||||
|
end
|
||||||
|
|
||||||
if g_game.getFeature(GameProtocolChecksum) then
|
if g_game.getFeature(GameProtocolChecksum) then
|
||||||
self:enableChecksum()
|
self:enableChecksum()
|
||||||
end
|
end
|
||||||
|
|
||||||
self:send(msg)
|
self:send(msg)
|
||||||
if g_game.getClientVersion() >= 770 then
|
if g_game.getFeature(GameLoginPacketEncryption) then
|
||||||
self:enableXteaEncryption()
|
self:enableXteaEncryption()
|
||||||
end
|
end
|
||||||
self:recv()
|
self:recv()
|
||||||
|
@ -141,7 +153,7 @@ function ProtocolLogin:parseCharacterList(msg)
|
||||||
world.worldName = msg:getString()
|
world.worldName = msg:getString()
|
||||||
world.worldIp = msg:getString()
|
world.worldIp = msg:getString()
|
||||||
world.worldPort = msg:getU16()
|
world.worldPort = msg:getU16()
|
||||||
msg:getU8() -- unknow byte?
|
world.previewState = msg:getU8()
|
||||||
worlds[worldId] = world
|
worlds[worldId] = world
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -153,6 +165,7 @@ function ProtocolLogin:parseCharacterList(msg)
|
||||||
character.worldName = worlds[worldId].worldName
|
character.worldName = worlds[worldId].worldName
|
||||||
character.worldIp = worlds[worldId].worldIp
|
character.worldIp = worlds[worldId].worldIp
|
||||||
character.worldPort = worlds[worldId].worldPort
|
character.worldPort = worlds[worldId].worldPort
|
||||||
|
character.previewState = worlds[worldId].previewState
|
||||||
characters[i] = character
|
characters[i] = character
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -165,8 +178,8 @@ function ProtocolLogin:parseCharacterList(msg)
|
||||||
character.worldIp = iptostring(msg:getU32())
|
character.worldIp = iptostring(msg:getU32())
|
||||||
character.worldPort = msg:getU16()
|
character.worldPort = msg:getU16()
|
||||||
|
|
||||||
if g_game.getClientVersion() >= 980 then
|
if g_game.getFeature(GamePreviewState) then
|
||||||
character.unknown = msg:getU8()
|
character.previewState = msg:getU8()
|
||||||
end
|
end
|
||||||
|
|
||||||
characters[i] = character
|
characters[i] = character
|
||||||
|
|
|
@ -328,7 +328,8 @@ namespace Otc
|
||||||
MessageRVRChannel = 46,
|
MessageRVRChannel = 46,
|
||||||
MessageRVRAnswer = 47,
|
MessageRVRAnswer = 47,
|
||||||
MessageRVRContinue = 48,
|
MessageRVRContinue = 48,
|
||||||
LastMessage = 49,
|
MessageGameHighlight = 49,
|
||||||
|
LastMessage = 50,
|
||||||
MessageInvalid = 255
|
MessageInvalid = 255
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -390,6 +391,13 @@ namespace Otc
|
||||||
GamePremiumExpiration = 57,
|
GamePremiumExpiration = 57,
|
||||||
GameBrowseField = 58,
|
GameBrowseField = 58,
|
||||||
GameEnhancedAnimations = 59,
|
GameEnhancedAnimations = 59,
|
||||||
|
GameOGLInformation = 60,
|
||||||
|
GameMessageSizeCheck = 61,
|
||||||
|
GamePreviewState = 62,
|
||||||
|
GameLoginPacketEncryption = 63,
|
||||||
|
GameClientVersion = 64,
|
||||||
|
GameContentRevision = 65,
|
||||||
|
GameExperienceBonus = 66,
|
||||||
|
|
||||||
LastGameFeature = 101
|
LastGameFeature = 101
|
||||||
};
|
};
|
||||||
|
@ -450,6 +458,16 @@ namespace Otc
|
||||||
PhaseRandom = 254,
|
PhaseRandom = 254,
|
||||||
PhaseAsync = 255
|
PhaseAsync = 255
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Blessings {
|
||||||
|
BlessingNone = 0,
|
||||||
|
BlessingAdventurer = 1,
|
||||||
|
BlessingSpiritualShielding = 1 << 1,
|
||||||
|
BlessingEmbraceOfTibia = 1 << 2,
|
||||||
|
BlessingFireOfSuns = 1 << 3,
|
||||||
|
BlessingWisdomOfSolitude = 1 << 4,
|
||||||
|
BlessingSparkOfPhoenix = 1 << 5
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1425,7 +1425,7 @@ void Game::setProtocolVersion(int version)
|
||||||
if(isOnline())
|
if(isOnline())
|
||||||
stdext::throw_exception("Unable to change protocol version while online");
|
stdext::throw_exception("Unable to change protocol version while online");
|
||||||
|
|
||||||
if(version != 0 && (version < 740 || version > 1051))
|
if(version != 0 && (version < 740 || version > 1071))
|
||||||
stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
|
stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
|
||||||
|
|
||||||
m_protocolVersion = version;
|
m_protocolVersion = version;
|
||||||
|
@ -1443,7 +1443,7 @@ void Game::setClientVersion(int version)
|
||||||
if(isOnline())
|
if(isOnline())
|
||||||
stdext::throw_exception("Unable to change client version while online");
|
stdext::throw_exception("Unable to change client version while online");
|
||||||
|
|
||||||
if(version != 0 && (version < 740 || version > 1051))
|
if(version != 0 && (version < 740 || version > 1071))
|
||||||
stdext::throw_exception(stdext::format("Client version %d not supported", version));
|
stdext::throw_exception(stdext::format("Client version %d not supported", version));
|
||||||
|
|
||||||
m_features.reset();
|
m_features.reset();
|
||||||
|
@ -1452,6 +1452,7 @@ void Game::setClientVersion(int version)
|
||||||
if(version >= 770) {
|
if(version >= 770) {
|
||||||
enableFeature(Otc::GameLooktypeU16);
|
enableFeature(Otc::GameLooktypeU16);
|
||||||
enableFeature(Otc::GameMessageStatements);
|
enableFeature(Otc::GameMessageStatements);
|
||||||
|
enableFeature(Otc::GameLoginPacketEncryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(version >= 780) {
|
if(version >= 780) {
|
||||||
|
@ -1475,6 +1476,7 @@ void Game::setClientVersion(int version)
|
||||||
|
|
||||||
if(version >= 841) {
|
if(version >= 841) {
|
||||||
enableFeature(Otc::GameChallengeOnLogin);
|
enableFeature(Otc::GameChallengeOnLogin);
|
||||||
|
enableFeature(Otc::GameMessageSizeCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(version >= 854) {
|
if(version >= 854) {
|
||||||
|
@ -1523,6 +1525,11 @@ void Game::setClientVersion(int version)
|
||||||
enableFeature(Otc::GameAdditionalVipInfo);
|
enableFeature(Otc::GameAdditionalVipInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(version >= 980) {
|
||||||
|
enableFeature(Otc::GamePreviewState);
|
||||||
|
enableFeature(Otc::GameClientVersion);
|
||||||
|
}
|
||||||
|
|
||||||
if(version >= 981) {
|
if(version >= 981) {
|
||||||
enableFeature(Otc::GameLoginPending);
|
enableFeature(Otc::GameLoginPending);
|
||||||
enableFeature(Otc::GameNewSpeedLaw);
|
enableFeature(Otc::GameNewSpeedLaw);
|
||||||
|
@ -1538,7 +1545,7 @@ void Game::setClientVersion(int version)
|
||||||
enableFeature(Otc::GamePVPMode);
|
enableFeature(Otc::GamePVPMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version >= 1035) {
|
if(version >= 1035) {
|
||||||
enableFeature(Otc::GameDoubleSkills);
|
enableFeature(Otc::GameDoubleSkills);
|
||||||
enableFeature(Otc::GameBaseSkillU16);
|
enableFeature(Otc::GameBaseSkillU16);
|
||||||
}
|
}
|
||||||
|
@ -1556,6 +1563,18 @@ void Game::setClientVersion(int version)
|
||||||
enableFeature(Otc::GameEnhancedAnimations);
|
enableFeature(Otc::GameEnhancedAnimations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(version >= 1054) {
|
||||||
|
enableFeature(Otc::GameExperienceBonus);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(version >= 1061) {
|
||||||
|
enableFeature(Otc::GameOGLInformation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(version >= 1071) {
|
||||||
|
enableFeature(Otc::GameContentRevision);
|
||||||
|
}
|
||||||
|
|
||||||
m_clientVersion = version;
|
m_clientVersion = version;
|
||||||
|
|
||||||
g_lua.callGlobalField("g_game", "onClientVersionChange", version);
|
g_lua.callGlobalField("g_game", "onClientVersionChange", version);
|
||||||
|
|
|
@ -31,6 +31,7 @@ LocalPlayer::LocalPlayer()
|
||||||
{
|
{
|
||||||
m_states = 0;
|
m_states = 0;
|
||||||
m_vocation = 0;
|
m_vocation = 0;
|
||||||
|
m_blessings = Otc::BlessingNone;
|
||||||
m_walkLockExpiration = 0;
|
m_walkLockExpiration = 0;
|
||||||
|
|
||||||
m_skillsLevel.fill(-1);
|
m_skillsLevel.fill(-1);
|
||||||
|
@ -546,6 +547,16 @@ void LocalPlayer::setSpells(const std::vector<int>& spells)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocalPlayer::setBlessings(int blessings)
|
||||||
|
{
|
||||||
|
if(blessings != m_blessings) {
|
||||||
|
int oldBlessings = m_blessings;
|
||||||
|
m_blessings = blessings;
|
||||||
|
|
||||||
|
callLuaField("onBlessingsChange", blessings, oldBlessings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool LocalPlayer::hasSight(const Position& pos)
|
bool LocalPlayer::hasSight(const Position& pos)
|
||||||
{
|
{
|
||||||
return m_position.isInRange(pos, g_map.getAwareRange().left - 1, g_map.getAwareRange().top - 1);
|
return m_position.isInRange(pos, g_map.getAwareRange().left - 1, g_map.getAwareRange().top - 1);
|
||||||
|
|
|
@ -63,6 +63,7 @@ public:
|
||||||
void setRegenerationTime(double regenerationTime);
|
void setRegenerationTime(double regenerationTime);
|
||||||
void setOfflineTrainingTime(double offlineTrainingTime);
|
void setOfflineTrainingTime(double offlineTrainingTime);
|
||||||
void setSpells(const std::vector<int>& spells);
|
void setSpells(const std::vector<int>& spells);
|
||||||
|
void setBlessings(int blessings);
|
||||||
|
|
||||||
int getStates() { return m_states; }
|
int getStates() { return m_states; }
|
||||||
int getSkillLevel(Otc::Skill skill) { return m_skillsLevel[skill]; }
|
int getSkillLevel(Otc::Skill skill) { return m_skillsLevel[skill]; }
|
||||||
|
@ -88,6 +89,7 @@ public:
|
||||||
double getOfflineTrainingTime() { return m_offlineTrainingTime; }
|
double getOfflineTrainingTime() { return m_offlineTrainingTime; }
|
||||||
std::vector<int> getSpells() { return m_spells; }
|
std::vector<int> getSpells() { return m_spells; }
|
||||||
ItemPtr getInventoryItem(Otc::InventorySlot inventory) { return m_inventoryItems[inventory]; }
|
ItemPtr getInventoryItem(Otc::InventorySlot inventory) { return m_inventoryItems[inventory]; }
|
||||||
|
int getBlessings() { return m_blessings; }
|
||||||
|
|
||||||
bool hasSight(const Position& pos);
|
bool hasSight(const Position& pos);
|
||||||
bool isKnown() { return m_known; }
|
bool isKnown() { return m_known; }
|
||||||
|
@ -144,6 +146,7 @@ private:
|
||||||
|
|
||||||
int m_states;
|
int m_states;
|
||||||
int m_vocation;
|
int m_vocation;
|
||||||
|
int m_blessings;
|
||||||
|
|
||||||
double m_health;
|
double m_health;
|
||||||
double m_maxHealth;
|
double m_maxHealth;
|
||||||
|
|
|
@ -63,6 +63,7 @@ void Client::registerLuaFunctions()
|
||||||
g_lua.bindSingletonFunction("g_things", "isDatLoaded", &ThingTypeManager::isDatLoaded, &g_things);
|
g_lua.bindSingletonFunction("g_things", "isDatLoaded", &ThingTypeManager::isDatLoaded, &g_things);
|
||||||
g_lua.bindSingletonFunction("g_things", "isOtbLoaded", &ThingTypeManager::isOtbLoaded, &g_things);
|
g_lua.bindSingletonFunction("g_things", "isOtbLoaded", &ThingTypeManager::isOtbLoaded, &g_things);
|
||||||
g_lua.bindSingletonFunction("g_things", "getDatSignature", &ThingTypeManager::getDatSignature, &g_things);
|
g_lua.bindSingletonFunction("g_things", "getDatSignature", &ThingTypeManager::getDatSignature, &g_things);
|
||||||
|
g_lua.bindSingletonFunction("g_things", "getContentRevision", &ThingTypeManager::getContentRevision, &g_things);
|
||||||
g_lua.bindSingletonFunction("g_things", "getThingType", &ThingTypeManager::getThingType, &g_things);
|
g_lua.bindSingletonFunction("g_things", "getThingType", &ThingTypeManager::getThingType, &g_things);
|
||||||
g_lua.bindSingletonFunction("g_things", "getItemType", &ThingTypeManager::getItemType, &g_things);
|
g_lua.bindSingletonFunction("g_things", "getItemType", &ThingTypeManager::getItemType, &g_things);
|
||||||
g_lua.bindSingletonFunction("g_things", "getThingTypes", &ThingTypeManager::getThingTypes, &g_things);
|
g_lua.bindSingletonFunction("g_things", "getThingTypes", &ThingTypeManager::getThingTypes, &g_things);
|
||||||
|
@ -630,6 +631,7 @@ void Client::registerLuaFunctions()
|
||||||
g_lua.bindClassMemberFunction<LocalPlayer>("getTotalCapacity", &LocalPlayer::getTotalCapacity);
|
g_lua.bindClassMemberFunction<LocalPlayer>("getTotalCapacity", &LocalPlayer::getTotalCapacity);
|
||||||
g_lua.bindClassMemberFunction<LocalPlayer>("getInventoryItem", &LocalPlayer::getInventoryItem);
|
g_lua.bindClassMemberFunction<LocalPlayer>("getInventoryItem", &LocalPlayer::getInventoryItem);
|
||||||
g_lua.bindClassMemberFunction<LocalPlayer>("getVocation", &LocalPlayer::getVocation);
|
g_lua.bindClassMemberFunction<LocalPlayer>("getVocation", &LocalPlayer::getVocation);
|
||||||
|
g_lua.bindClassMemberFunction<LocalPlayer>("getBlessings", &LocalPlayer::getBlessings);
|
||||||
g_lua.bindClassMemberFunction<LocalPlayer>("isPremium", &LocalPlayer::isPremium);
|
g_lua.bindClassMemberFunction<LocalPlayer>("isPremium", &LocalPlayer::isPremium);
|
||||||
g_lua.bindClassMemberFunction<LocalPlayer>("isKnown", &LocalPlayer::isKnown);
|
g_lua.bindClassMemberFunction<LocalPlayer>("isKnown", &LocalPlayer::isKnown);
|
||||||
g_lua.bindClassMemberFunction<LocalPlayer>("isPreWalking", &LocalPlayer::isPreWalking);
|
g_lua.bindClassMemberFunction<LocalPlayer>("isPreWalking", &LocalPlayer::isPreWalking);
|
||||||
|
|
|
@ -28,7 +28,52 @@ std::map<uint8, uint8> messageModesMap;
|
||||||
|
|
||||||
void buildMessageModesMap(int version) {
|
void buildMessageModesMap(int version) {
|
||||||
messageModesMap.clear();
|
messageModesMap.clear();
|
||||||
if(version >= 1036) {
|
|
||||||
|
if(version >= 1055) { // might be 1054
|
||||||
|
messageModesMap[Otc::MessageNone] = 0;
|
||||||
|
messageModesMap[Otc::MessageSay] = 1;
|
||||||
|
messageModesMap[Otc::MessageWhisper] = 2;
|
||||||
|
messageModesMap[Otc::MessageYell] = 3;
|
||||||
|
messageModesMap[Otc::MessagePrivateFrom] = 4;
|
||||||
|
messageModesMap[Otc::MessagePrivateTo] = 5;
|
||||||
|
messageModesMap[Otc::MessageChannelManagement] = 6;
|
||||||
|
messageModesMap[Otc::MessageChannel] = 7;
|
||||||
|
messageModesMap[Otc::MessageChannelHighlight] = 8;
|
||||||
|
messageModesMap[Otc::MessageSpell] = 9;
|
||||||
|
//NpcFromStartBlock = 10
|
||||||
|
messageModesMap[Otc::MessageNpcFrom] = 11;
|
||||||
|
messageModesMap[Otc::MessageNpcTo] = 12;
|
||||||
|
messageModesMap[Otc::MessageGamemasterBroadcast] = 13;
|
||||||
|
messageModesMap[Otc::MessageGamemasterChannel] = 14;
|
||||||
|
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 15;
|
||||||
|
messageModesMap[Otc::MessageGamemasterPrivateTo] = 16;
|
||||||
|
messageModesMap[Otc::MessageLogin] = 17;
|
||||||
|
messageModesMap[Otc::MessageWarning] = 18; // Admin
|
||||||
|
messageModesMap[Otc::MessageGame] = 19;
|
||||||
|
messageModesMap[Otc::MessageGameHighlight] = 20;
|
||||||
|
messageModesMap[Otc::MessageFailure] = 21;
|
||||||
|
messageModesMap[Otc::MessageLook] = 22;
|
||||||
|
messageModesMap[Otc::MessageDamageDealed] = 23;
|
||||||
|
messageModesMap[Otc::MessageDamageReceived] = 24;
|
||||||
|
messageModesMap[Otc::MessageHeal] = 25;
|
||||||
|
messageModesMap[Otc::MessageExp] = 26;
|
||||||
|
messageModesMap[Otc::MessageDamageOthers] = 27;
|
||||||
|
messageModesMap[Otc::MessageHealOthers] = 28;
|
||||||
|
messageModesMap[Otc::MessageExpOthers] = 29;
|
||||||
|
messageModesMap[Otc::MessageStatus] = 30;
|
||||||
|
messageModesMap[Otc::MessageLoot] = 31;
|
||||||
|
messageModesMap[Otc::MessageTradeNpc] = 32;
|
||||||
|
messageModesMap[Otc::MessageGuild] = 33;
|
||||||
|
messageModesMap[Otc::MessagePartyManagement] = 34;
|
||||||
|
messageModesMap[Otc::MessageParty] = 35;
|
||||||
|
messageModesMap[Otc::MessageBarkLow] = 36;
|
||||||
|
messageModesMap[Otc::MessageBarkLoud] = 37;
|
||||||
|
messageModesMap[Otc::MessageReport] = 38;
|
||||||
|
messageModesMap[Otc::MessageHotkeyUse] = 39;
|
||||||
|
messageModesMap[Otc::MessageTutorialHint] = 40;
|
||||||
|
messageModesMap[Otc::MessageThankyou] = 41;
|
||||||
|
messageModesMap[Otc::MessageMarket] = 42;
|
||||||
|
} else if(version >= 1036) {
|
||||||
for(int i = Otc::MessageNone; i <= Otc::MessageBeyondLast; ++i) {
|
for(int i = Otc::MessageNone; i <= Otc::MessageBeyondLast; ++i) {
|
||||||
if(i >= Otc::MessageNpcTo)
|
if(i >= Otc::MessageNpcTo)
|
||||||
messageModesMap[i] = i + 1;
|
messageModesMap[i] = i + 1;
|
||||||
|
|
|
@ -107,6 +107,8 @@ namespace Proto {
|
||||||
GameServerCreatureType = 149,
|
GameServerCreatureType = 149,
|
||||||
GameServerEditText = 150,
|
GameServerEditText = 150,
|
||||||
GameServerEditList = 151,
|
GameServerEditList = 151,
|
||||||
|
GameServerBlessings = 156,
|
||||||
|
GameServerPreset = 157,
|
||||||
GameServerPremiumTrigger = 158, // 1038
|
GameServerPremiumTrigger = 158, // 1038
|
||||||
GameServerPlayerDataBasic = 159, // 950
|
GameServerPlayerDataBasic = 159, // 950
|
||||||
GameServerPlayerData = 160,
|
GameServerPlayerData = 160,
|
||||||
|
@ -130,6 +132,8 @@ namespace Proto {
|
||||||
GameServerTextMessage = 180,
|
GameServerTextMessage = 180,
|
||||||
GameServerCancelWalk = 181,
|
GameServerCancelWalk = 181,
|
||||||
GameServerWalkWait = 182,
|
GameServerWalkWait = 182,
|
||||||
|
GameServerUnjustifiedStats = 183,
|
||||||
|
GameServerPvpSituations = 184,
|
||||||
GameServerFloorChangeUp = 190,
|
GameServerFloorChangeUp = 190,
|
||||||
GameServerFloorChangeDown = 191,
|
GameServerFloorChangeDown = 191,
|
||||||
GameServerChooseOutfit = 200,
|
GameServerChooseOutfit = 200,
|
||||||
|
|
|
@ -56,7 +56,7 @@ void ProtocolGame::onRecv(const InputMessagePtr& inputMessage)
|
||||||
if(m_firstRecv) {
|
if(m_firstRecv) {
|
||||||
m_firstRecv = false;
|
m_firstRecv = false;
|
||||||
|
|
||||||
if(g_game.getClientVersion() >= 841) { // not sure since which version this is, but it seems to be after 8.40
|
if(g_game.getFeature(Otc::GameMessageSizeCheck)) {
|
||||||
int size = inputMessage->getU16();
|
int size = inputMessage->getU16();
|
||||||
if(size != inputMessage->getUnreadSize()) {
|
if(size != inputMessage->getUnreadSize()) {
|
||||||
g_logger.traceError("invalid message size");
|
g_logger.traceError("invalid message size");
|
||||||
|
|
|
@ -128,6 +128,10 @@ public:
|
||||||
void addPosition(const OutputMessagePtr& msg, const Position& position);
|
void addPosition(const OutputMessagePtr& msg, const Position& position);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void parseBlessings(const InputMessagePtr& msg);
|
||||||
|
void parseUnjustifiedStats(const InputMessagePtr& msg);
|
||||||
|
void parsePvpSituations(const InputMessagePtr& msg);
|
||||||
|
void parsePreset(const InputMessagePtr& msg);
|
||||||
void parseCreatureType(const InputMessagePtr& msg);
|
void parseCreatureType(const InputMessagePtr& msg);
|
||||||
void parsePlayerHelpers(const InputMessagePtr& msg);
|
void parsePlayerHelpers(const InputMessagePtr& msg);
|
||||||
void parseMessage(const InputMessagePtr& msg);
|
void parseMessage(const InputMessagePtr& msg);
|
||||||
|
|
|
@ -340,6 +340,19 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
||||||
case Proto::GameServerCreatureType:
|
case Proto::GameServerCreatureType:
|
||||||
parseCreatureType(msg);
|
parseCreatureType(msg);
|
||||||
break;
|
break;
|
||||||
|
// PROTOCOL>=1055
|
||||||
|
case Proto::GameServerBlessings:
|
||||||
|
parseBlessings(msg);
|
||||||
|
break;
|
||||||
|
case Proto::GameServerUnjustifiedStats:
|
||||||
|
parseUnjustifiedStats(msg);
|
||||||
|
break;
|
||||||
|
case Proto::GameServerPvpSituations:
|
||||||
|
parsePvpSituations(msg);
|
||||||
|
break;
|
||||||
|
case Proto::GameServerPreset:
|
||||||
|
parsePreset(msg);
|
||||||
|
break;
|
||||||
// otclient ONLY
|
// otclient ONLY
|
||||||
case Proto::GameServerExtendedOpcode:
|
case Proto::GameServerExtendedOpcode:
|
||||||
parseExtendedOpcode(msg);
|
parseExtendedOpcode(msg);
|
||||||
|
@ -372,6 +385,9 @@ void ProtocolGame::parseLogin(const InputMessagePtr& msg)
|
||||||
}
|
}
|
||||||
bool canReportBugs = msg->getU8();
|
bool canReportBugs = msg->getU8();
|
||||||
|
|
||||||
|
msg->getU8(); // can change pvp framing option
|
||||||
|
msg->getU8(); // expert mode enabled
|
||||||
|
|
||||||
m_localPlayer->setId(playerId);
|
m_localPlayer->setId(playerId);
|
||||||
g_game.setServerBeat(serverBeat);
|
g_game.setServerBeat(serverBeat);
|
||||||
g_game.setCanReportBugs(canReportBugs);
|
g_game.setCanReportBugs(canReportBugs);
|
||||||
|
@ -396,6 +412,34 @@ void ProtocolGame::parseEnterGame(const InputMessagePtr& msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseBlessings(const InputMessagePtr& msg)
|
||||||
|
{
|
||||||
|
uint16 blessings = msg->getU16();
|
||||||
|
m_localPlayer->setBlessings(blessings);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parsePreset(const InputMessagePtr& msg)
|
||||||
|
{
|
||||||
|
uint16 preset = msg->getU32();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseUnjustifiedStats(const InputMessagePtr& msg)
|
||||||
|
{
|
||||||
|
// Unjustified Kills display since 10.55
|
||||||
|
msg->getU8();
|
||||||
|
msg->getU8();
|
||||||
|
msg->getU8();
|
||||||
|
msg->getU8();
|
||||||
|
msg->getU8();
|
||||||
|
msg->getU8();
|
||||||
|
msg->getU8();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parsePvpSituations(const InputMessagePtr& msg)
|
||||||
|
{
|
||||||
|
msg->getU8(); // amount of open pvp situations
|
||||||
|
}
|
||||||
|
|
||||||
void ProtocolGame::parsePlayerHelpers(const InputMessagePtr& msg)
|
void ProtocolGame::parsePlayerHelpers(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
uint id = msg->getU32();
|
uint id = msg->getU32();
|
||||||
|
@ -468,6 +512,7 @@ void ProtocolGame::parseChallenge(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
uint timestamp = msg->getU32();
|
uint timestamp = msg->getU32();
|
||||||
uint8 random = msg->getU8();
|
uint8 random = msg->getU8();
|
||||||
|
|
||||||
sendLoginPacket(timestamp, random);
|
sendLoginPacket(timestamp, random);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1038,7 +1083,7 @@ void ProtocolGame::parsePlayerInfo(const InputMessagePtr& msg)
|
||||||
bool premium = msg->getU8(); // premium
|
bool premium = msg->getU8(); // premium
|
||||||
int vocation = msg->getU8(); // vocation
|
int vocation = msg->getU8(); // vocation
|
||||||
if(g_game.getFeature(Otc::GamePremiumExpiration))
|
if(g_game.getFeature(Otc::GamePremiumExpiration))
|
||||||
int premiumEx = msg->getU32(); // premium expiration
|
int premiumEx = msg->getU32(); // premium expiration used for premium advertisement
|
||||||
|
|
||||||
int spellCount = msg->getU16();
|
int spellCount = msg->getU16();
|
||||||
std::vector<int> spells;
|
std::vector<int> spells;
|
||||||
|
@ -1081,6 +1126,10 @@ void ProtocolGame::parsePlayerStats(const InputMessagePtr& msg)
|
||||||
|
|
||||||
double level = msg->getU16();
|
double level = msg->getU16();
|
||||||
double levelPercent = msg->getU8();
|
double levelPercent = msg->getU8();
|
||||||
|
|
||||||
|
if(g_game.getFeature(Otc::GameExperienceBonus))
|
||||||
|
double experienceBonus = msg->getDouble();
|
||||||
|
|
||||||
double mana;
|
double mana;
|
||||||
double maxMana;
|
double maxMana;
|
||||||
|
|
||||||
|
@ -1145,7 +1194,7 @@ void ProtocolGame::parsePlayerSkills(const InputMessagePtr& msg)
|
||||||
|
|
||||||
int baseLevel;
|
int baseLevel;
|
||||||
if(g_game.getFeature(Otc::GameSkillsBase))
|
if(g_game.getFeature(Otc::GameSkillsBase))
|
||||||
if (g_game.getFeature(Otc::GameBaseSkillU16))
|
if(g_game.getFeature(Otc::GameBaseSkillU16))
|
||||||
baseLevel = msg->getU16();
|
baseLevel = msg->getU16();
|
||||||
else
|
else
|
||||||
baseLevel = msg->getU8();
|
baseLevel = msg->getU8();
|
||||||
|
@ -1699,7 +1748,7 @@ void ProtocolGame::parseChangeMapAwareRange(const InputMessagePtr& msg)
|
||||||
void ProtocolGame::parseCreaturesMark(const InputMessagePtr& msg)
|
void ProtocolGame::parseCreaturesMark(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
if (g_game.getClientVersion() >= 1035) {
|
if(g_game.getClientVersion() >= 1035) {
|
||||||
len = 1;
|
len = 1;
|
||||||
} else {
|
} else {
|
||||||
len = msg->getU8();
|
len = msg->getU8();
|
||||||
|
|
|
@ -56,17 +56,20 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
|
||||||
msg->addU16(g_game.getOs());
|
msg->addU16(g_game.getOs());
|
||||||
msg->addU16(g_game.getProtocolVersion());
|
msg->addU16(g_game.getProtocolVersion());
|
||||||
|
|
||||||
if(g_game.getClientVersion() >= 980) {
|
if(g_game.getFeature(Otc::GameClientVersion))
|
||||||
msg->addU32(g_game.getClientVersion());
|
msg->addU32(g_game.getClientVersion());
|
||||||
msg->addU8(0); // preview state
|
|
||||||
}
|
if(g_game.getFeature(Otc::GameContentRevision))
|
||||||
|
msg->addU16(g_things.getContentRevision());
|
||||||
|
|
||||||
|
if(g_game.getFeature(Otc::GamePreviewState))
|
||||||
|
msg->addU8(0);
|
||||||
|
|
||||||
int offset = msg->getMessageSize();
|
int offset = msg->getMessageSize();
|
||||||
|
// first RSA byte must be 0
|
||||||
|
msg->addU8(0);
|
||||||
|
|
||||||
msg->addU8(0); // first RSA byte must be 0
|
if(g_game.getFeature(Otc::GameLoginPacketEncryption)) {
|
||||||
|
|
||||||
if(g_game.getClientVersion() >= 770)
|
|
||||||
{
|
|
||||||
// xtea key
|
// xtea key
|
||||||
generateXteaKey();
|
generateXteaKey();
|
||||||
msg->addU32(m_xteaKey[0]);
|
msg->addU32(m_xteaKey[0]);
|
||||||
|
@ -99,7 +102,7 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
|
||||||
msg->addPaddingBytes(paddingBytes);
|
msg->addPaddingBytes(paddingBytes);
|
||||||
|
|
||||||
// encrypt with RSA
|
// encrypt with RSA
|
||||||
if(g_game.getClientVersion() >= 770)
|
if(g_game.getFeature(Otc::GameLoginPacketEncryption))
|
||||||
msg->encryptRsa();
|
msg->encryptRsa();
|
||||||
|
|
||||||
if(g_game.getFeature(Otc::GameProtocolChecksum))
|
if(g_game.getFeature(Otc::GameProtocolChecksum))
|
||||||
|
@ -107,7 +110,7 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
|
||||||
|
|
||||||
send(msg);
|
send(msg);
|
||||||
|
|
||||||
if(g_game.getClientVersion() >= 770)
|
if(g_game.getFeature(Otc::GameLoginPacketEncryption))
|
||||||
enableXteaEncryption();
|
enableXteaEncryption();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -274,51 +274,60 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
|
||||||
stdext::throw_exception(stdext::format("corrupt data (id: %d, category: %d, count: %d, lastAttr: %d)",
|
stdext::throw_exception(stdext::format("corrupt data (id: %d, category: %d, count: %d, lastAttr: %d)",
|
||||||
m_id, m_category, count, attr));
|
m_id, m_category, count, attr));
|
||||||
|
|
||||||
uint8 width = fin->getU8();
|
uint8 frames = 1;
|
||||||
uint8 height = fin->getU8();
|
if(category == ThingCategoryCreature && g_game.getClientVersion() >= 1057)
|
||||||
m_size = Size(width, height);
|
frames = fin->getU8();
|
||||||
if(width > 1 || height > 1) {
|
|
||||||
m_realSize = fin->getU8();
|
|
||||||
m_exactSize = std::min<int>(m_realSize, std::max<int>(width * 32, height * 32));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_exactSize = 32;
|
|
||||||
|
|
||||||
m_layers = fin->getU8();
|
for(int i = 0; i < frames; ++i) {
|
||||||
m_numPatternX = fin->getU8();
|
uint8 frameGroup = FrameGroupDefault;
|
||||||
m_numPatternY = fin->getU8();
|
if(category == ThingCategoryCreature && g_game.getClientVersion() >= 1057) {
|
||||||
if(g_game.getClientVersion() >= 755)
|
frameGroup = fin->getU8();
|
||||||
m_numPatternZ = fin->getU8();
|
}
|
||||||
else
|
|
||||||
m_numPatternZ = 1;
|
|
||||||
m_animationPhases = fin->getU8();
|
|
||||||
|
|
||||||
if(g_game.getFeature(Otc::GameEnhancedAnimations)) {
|
uint8 width = fin->getU8();
|
||||||
if(m_animationPhases > 1) {
|
uint8 height = fin->getU8();
|
||||||
m_animation.async = fin->getU8() == 0;
|
m_size = Size(width, height);
|
||||||
m_animation.loopCount = fin->get32();
|
if(width > 1 || height > 1) {
|
||||||
m_animation.startIndex = fin->getU8();
|
m_realSize = fin->getU8();
|
||||||
|
m_exactSize = std::min<int>(m_realSize, std::max<int>(width * 32, height * 32));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_exactSize = 32;
|
||||||
|
|
||||||
for(int i = 0; i < m_animationPhases; i++) {
|
m_layers = fin->getU8();
|
||||||
int minDuration = fin->getU32();
|
m_numPatternX = fin->getU8();
|
||||||
int maxDuration = fin->getU32();
|
m_numPatternY = fin->getU8();
|
||||||
|
if(g_game.getClientVersion() >= 755)
|
||||||
|
m_numPatternZ = fin->getU8();
|
||||||
|
else
|
||||||
|
m_numPatternZ = 1;
|
||||||
|
m_animationPhases = fin->getU8();
|
||||||
|
|
||||||
m_animation.frames.push_back(std::make_tuple(minDuration, maxDuration));
|
if(g_game.getFeature(Otc::GameEnhancedAnimations)) {
|
||||||
|
if(m_animationPhases > 1) {
|
||||||
|
m_animation.async = fin->getU8() == 0;
|
||||||
|
m_animation.loopCount = fin->get32();
|
||||||
|
m_animation.startIndex = fin->getU8();
|
||||||
|
|
||||||
|
for (int i = 0; i < m_animationPhases; i++) {
|
||||||
|
int minDuration = fin->getU32();
|
||||||
|
int maxDuration = fin->getU32();
|
||||||
|
|
||||||
|
m_animation.frames.push_back(std::make_tuple(minDuration, maxDuration));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;
|
||||||
|
|
||||||
|
if(totalSprites > 4096)
|
||||||
|
stdext::throw_exception("a thing type has more than 4096 sprites");
|
||||||
|
|
||||||
|
m_spritesIndex.resize(totalSprites);
|
||||||
|
for(int i = 0; i < totalSprites; i++)
|
||||||
|
m_spritesIndex[i] = g_game.getFeature(Otc::GameSpritesU32) ? fin->getU32() : fin->getU16();
|
||||||
}
|
}
|
||||||
|
|
||||||
int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;
|
|
||||||
|
|
||||||
// if(totalSprites == 0)
|
|
||||||
// stdext::throw_exception("a thing type has no sprites");
|
|
||||||
if(totalSprites > 4096)
|
|
||||||
stdext::throw_exception("a thing type has more than 4096 sprites");
|
|
||||||
|
|
||||||
m_spritesIndex.resize(totalSprites);
|
|
||||||
for(int i = 0; i < totalSprites; i++)
|
|
||||||
m_spritesIndex[i] = g_game.getFeature(Otc::GameSpritesU32) ? fin->getU32() : fin->getU16();
|
|
||||||
|
|
||||||
m_textures.resize(m_animationPhases);
|
m_textures.resize(m_animationPhases);
|
||||||
m_texturesFramesRects.resize(m_animationPhases);
|
m_texturesFramesRects.resize(m_animationPhases);
|
||||||
m_texturesFramesOriginRects.resize(m_animationPhases);
|
m_texturesFramesOriginRects.resize(m_animationPhases);
|
||||||
|
|
|
@ -32,6 +32,12 @@
|
||||||
#include <framework/luaengine/luaobject.h>
|
#include <framework/luaengine/luaobject.h>
|
||||||
#include <framework/net/server.h>
|
#include <framework/net/server.h>
|
||||||
|
|
||||||
|
enum FrameGroup : uint8 {
|
||||||
|
FrameGroupIdle = 0,
|
||||||
|
FrameGroupMoving,
|
||||||
|
FrameGroupDefault = FrameGroupIdle
|
||||||
|
};
|
||||||
|
|
||||||
enum ThingCategory : uint8 {
|
enum ThingCategory : uint8 {
|
||||||
ThingCategoryItem = 0,
|
ThingCategoryItem = 0,
|
||||||
ThingCategoryCreature,
|
ThingCategoryCreature,
|
||||||
|
|
|
@ -42,6 +42,7 @@ void ThingTypeManager::init()
|
||||||
m_nullThingType = ThingTypePtr(new ThingType);
|
m_nullThingType = ThingTypePtr(new ThingType);
|
||||||
m_nullItemType = ItemTypePtr(new ItemType);
|
m_nullItemType = ItemTypePtr(new ItemType);
|
||||||
m_datSignature = 0;
|
m_datSignature = 0;
|
||||||
|
m_contentRevision = 0;
|
||||||
m_otbMinorVersion = 0;
|
m_otbMinorVersion = 0;
|
||||||
m_otbMajorVersion = 0;
|
m_otbMajorVersion = 0;
|
||||||
m_datLoaded = false;
|
m_datLoaded = false;
|
||||||
|
@ -100,12 +101,14 @@ bool ThingTypeManager::loadDat(std::string file)
|
||||||
{
|
{
|
||||||
m_datLoaded = false;
|
m_datLoaded = false;
|
||||||
m_datSignature = 0;
|
m_datSignature = 0;
|
||||||
|
m_contentRevision = 0;
|
||||||
try {
|
try {
|
||||||
file = g_resources.guessFilePath(file, "dat");
|
file = g_resources.guessFilePath(file, "dat");
|
||||||
|
|
||||||
FileStreamPtr fin = g_resources.openFile(file);
|
FileStreamPtr fin = g_resources.openFile(file);
|
||||||
|
|
||||||
m_datSignature = fin->getU32();
|
m_datSignature = fin->getU32();
|
||||||
|
m_contentRevision = static_cast<uint16_t>(m_datSignature);
|
||||||
|
|
||||||
for(int category = 0; category < ThingLastCategory; ++category) {
|
for(int category = 0; category < ThingLastCategory; ++category) {
|
||||||
int count = fin->getU16() + 1;
|
int count = fin->getU16() + 1;
|
||||||
|
|
|
@ -66,6 +66,7 @@ public:
|
||||||
uint32 getDatSignature() { return m_datSignature; }
|
uint32 getDatSignature() { return m_datSignature; }
|
||||||
uint32 getOtbMajorVersion() { return m_otbMajorVersion; }
|
uint32 getOtbMajorVersion() { return m_otbMajorVersion; }
|
||||||
uint32 getOtbMinorVersion() { return m_otbMinorVersion; }
|
uint32 getOtbMinorVersion() { return m_otbMinorVersion; }
|
||||||
|
uint16 getContentRevision() { return m_contentRevision; }
|
||||||
|
|
||||||
bool isDatLoaded() { return m_datLoaded; }
|
bool isDatLoaded() { return m_datLoaded; }
|
||||||
bool isXmlLoaded() { return m_xmlLoaded; }
|
bool isXmlLoaded() { return m_xmlLoaded; }
|
||||||
|
@ -89,6 +90,7 @@ private:
|
||||||
uint32 m_otbMinorVersion;
|
uint32 m_otbMinorVersion;
|
||||||
uint32 m_otbMajorVersion;
|
uint32 m_otbMajorVersion;
|
||||||
uint32 m_datSignature;
|
uint32 m_datSignature;
|
||||||
|
uint16 m_contentRevision;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ThingTypeManager g_things;
|
extern ThingTypeManager g_things;
|
||||||
|
|
Loading…
Reference in New Issue