Support for client version 7.6
Tell me if there are parts which I should change. - Not everything is tested yet, feel free to report bugs in 7.6 - the data send in between login opcode and account data might not be correct, but I could not find any documents showing the right protocol yet - Hotkeys working
This commit is contained in:
parent
7cf645e715
commit
5843b78e87
|
@ -375,15 +375,41 @@ function doKeyCombo(keyCombo)
|
||||||
modules.game_console.setTextEditText(hotKey.value)
|
modules.game_console.setTextEditText(hotKey.value)
|
||||||
end
|
end
|
||||||
elseif hotKey.useType == HOTKEY_MANAGER_USE then
|
elseif hotKey.useType == HOTKEY_MANAGER_USE then
|
||||||
g_game.useInventoryItem(hotKey.itemId)
|
if g_game.getProtocolVersion() < 780 then
|
||||||
|
local item = g_game.findItemInContainers(hotKey.itemId, -1)
|
||||||
|
if item then
|
||||||
|
g_game.use(item)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
g_game.useInventoryItem(hotKey.itemId)
|
||||||
|
end
|
||||||
elseif hotKey.useType == HOTKEY_MANAGER_USEONSELF then
|
elseif hotKey.useType == HOTKEY_MANAGER_USEONSELF then
|
||||||
g_game.useInventoryItemWith(hotKey.itemId, g_game.getLocalPlayer())
|
if g_game.getProtocolVersion() < 780 then
|
||||||
|
local item = g_game.findItemInContainers(hotKey.itemId, -1)
|
||||||
|
if item then
|
||||||
|
g_game.useWith(item, g_game.getLocalPlayer())
|
||||||
|
end
|
||||||
|
else
|
||||||
|
g_game.useInventoryItemWith(hotKey.itemId, g_game.getLocalPlayer())
|
||||||
|
end
|
||||||
elseif hotKey.useType == HOTKEY_MANAGER_USEONTARGET then
|
elseif hotKey.useType == HOTKEY_MANAGER_USEONTARGET then
|
||||||
local attackingCreature = g_game.getAttackingCreature()
|
local attackingCreature = g_game.getAttackingCreature()
|
||||||
if not attackingCreature then return end
|
if not attackingCreature then return end
|
||||||
g_game.useInventoryItemWith(hotKey.itemId, attackingCreature)
|
if g_game.getProtocolVersion() < 780 then
|
||||||
|
local item = g_game.findItemInContainers(hotKey.itemId, -1)
|
||||||
|
if item then
|
||||||
|
g_game.useWith(item, attackingCreature)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
g_game.useInventoryItemWith(hotKey.itemId, attackingCreature)
|
||||||
|
end
|
||||||
elseif hotKey.useType == HOTKEY_MANAGER_USEWITH then
|
elseif hotKey.useType == HOTKEY_MANAGER_USEWITH then
|
||||||
local item = Item.create(hotKey.itemId)
|
local item = Item.create(hotKey.itemId)
|
||||||
|
if g_game.getProtocolVersion() < 780 then
|
||||||
|
local tmpItem = g_game.findItemInContainers(hotKey.itemId, -1)
|
||||||
|
if not tmpItem then return true end
|
||||||
|
item = tmpItem
|
||||||
|
end
|
||||||
modules.game_interface.startUseWith(item)
|
modules.game_interface.startUseWith(item)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,11 +34,11 @@ end
|
||||||
|
|
||||||
function g_game.getSupportedClients()
|
function g_game.getSupportedClients()
|
||||||
return {
|
return {
|
||||||
810, 811, 840, 842, 850, 853, 854,
|
760, 810, 811, 840, 842, 850, 853,
|
||||||
860, 861, 862, 870, 910, 940, 944,
|
854, 860, 861, 862, 870, 910, 940,
|
||||||
953, 954, 960, 961, 963, 970, 980,
|
944, 953, 954, 960, 961, 963, 970,
|
||||||
981, 982, 983, 984, 985, 986, 1001,
|
980, 981, 982, 983, 984, 985, 986,
|
||||||
1002, 1010
|
1001, 1002, 1010
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -188,5 +188,9 @@ ClientOpcodes = {
|
||||||
ClientMarketCreate = 246, -- 944
|
ClientMarketCreate = 246, -- 944
|
||||||
ClientMarketCancel = 247, -- 944
|
ClientMarketCancel = 247, -- 944
|
||||||
ClientMarketAccept = 248, -- 944
|
ClientMarketAccept = 248, -- 944
|
||||||
ClientAnswerModalDialog = 249 -- 960
|
ClientAnswerModalDialog = 249, -- 960
|
||||||
|
|
||||||
|
-- 760
|
||||||
|
ClientEnterAccount760 = 513,
|
||||||
|
ClientEnterGame760 = 522
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,13 @@ end
|
||||||
|
|
||||||
function ProtocolLogin:sendLoginPacket()
|
function ProtocolLogin:sendLoginPacket()
|
||||||
local msg = OutputMessage.create()
|
local msg = OutputMessage.create()
|
||||||
|
if g_game.getProtocolVersion() == 760 then
|
||||||
msg:addU8(ClientOpcodes.ClientEnterAccount)
|
msg:addU16(ClientOpcodes.ClientEnterAccount760)
|
||||||
msg:addU16(g_game.getOs())
|
else
|
||||||
|
msg:addU8(ClientOpcodes.ClientEnterAccount)
|
||||||
|
msg:addU16(g_game.getOs())
|
||||||
|
end
|
||||||
|
|
||||||
msg:addU16(g_game.getProtocolVersion())
|
msg:addU16(g_game.getProtocolVersion())
|
||||||
|
|
||||||
if g_game.getProtocolVersion() >= 971 then
|
if g_game.getProtocolVersion() >= 971 then
|
||||||
|
@ -49,14 +53,16 @@ function ProtocolLogin:sendLoginPacket()
|
||||||
-- first RSA byte must be 0
|
-- first RSA byte must be 0
|
||||||
msg:addU8(0)
|
msg:addU8(0)
|
||||||
|
|
||||||
-- xtea key
|
if g_game.getProtocolVersion() >= 800 then
|
||||||
self:generateXteaKey()
|
-- xtea key
|
||||||
local xteaKey = self:getXteaKey()
|
self:generateXteaKey()
|
||||||
msg:addU32(xteaKey[1])
|
local xteaKey = self:getXteaKey()
|
||||||
msg:addU32(xteaKey[2])
|
msg:addU32(xteaKey[1])
|
||||||
msg:addU32(xteaKey[3])
|
msg:addU32(xteaKey[2])
|
||||||
msg:addU32(xteaKey[4])
|
msg:addU32(xteaKey[3])
|
||||||
|
msg:addU32(xteaKey[4])
|
||||||
|
end
|
||||||
|
|
||||||
if g_game.getFeature(GameAccountNames) then
|
if g_game.getFeature(GameAccountNames) then
|
||||||
msg:addString(self.accountName)
|
msg:addString(self.accountName)
|
||||||
else
|
else
|
||||||
|
@ -73,14 +79,18 @@ 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)
|
||||||
msg:encryptRsa()
|
if g_game.getProtocolVersion() >= 800 then
|
||||||
|
msg:encryptRsa()
|
||||||
|
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)
|
||||||
self:enableXteaEncryption()
|
if g_game.getProtocolVersion() >= 800 then
|
||||||
|
self:enableXteaEncryption()
|
||||||
|
end
|
||||||
self:recv()
|
self:recv()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -355,6 +355,15 @@ namespace Otc
|
||||||
GameDoubleShopSellAmount = 39,
|
GameDoubleShopSellAmount = 39,
|
||||||
GameContainerPagination = 40,
|
GameContainerPagination = 40,
|
||||||
GameThingMarks = 41,
|
GameThingMarks = 41,
|
||||||
|
|
||||||
|
GameLooktypeU16 = 42,
|
||||||
|
GamePlayerStamina = 43,
|
||||||
|
GamePlayerAddons = 44,
|
||||||
|
GameMessageStatments = 45,
|
||||||
|
GameMessageLevel = 46,
|
||||||
|
GameNewFluids = 47,
|
||||||
|
GamePlayerStateU16 = 48,
|
||||||
|
|
||||||
// 51-100 reserved to be defined in lua
|
// 51-100 reserved to be defined in lua
|
||||||
LastGameFeature = 101
|
LastGameFeature = 101
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,6 +59,14 @@ void Container::onAddItem(const ItemPtr& item)
|
||||||
callLuaField("onAddItem", 0, item);
|
callLuaField("onAddItem", 0, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemPtr Container::findItemById(uint itemId, int subType)
|
||||||
|
{
|
||||||
|
for(const ItemPtr item : m_items)
|
||||||
|
if(item->getId() == itemId && (subType == -1 || item->getSubType() == subType))
|
||||||
|
return item;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void Container::onAddItems(const std::vector<ItemPtr>& items)
|
void Container::onAddItems(const std::vector<ItemPtr>& items)
|
||||||
{
|
{
|
||||||
for(const ItemPtr& item : items)
|
for(const ItemPtr& item : items)
|
||||||
|
|
|
@ -45,6 +45,7 @@ public:
|
||||||
std::string getName() { return m_name; }
|
std::string getName() { return m_name; }
|
||||||
bool hasParent() { return m_hasParent; }
|
bool hasParent() { return m_hasParent; }
|
||||||
bool isClosed() { return m_closed; }
|
bool isClosed() { return m_closed; }
|
||||||
|
ItemPtr findItemById(uint itemId, int subType);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onOpen(const ContainerPtr& previousContainer);
|
void onOpen(const ContainerPtr& previousContainer);
|
||||||
|
|
|
@ -884,7 +884,7 @@ void Game::useWith(const ItemPtr& item, const ThingPtr& toThing)
|
||||||
if(!pos.isValid()) // virtual item
|
if(!pos.isValid()) // virtual item
|
||||||
pos = Position(0xFFFF, 0, 0); // means that is a item in inventory
|
pos = Position(0xFFFF, 0, 0); // means that is a item in inventory
|
||||||
|
|
||||||
if(toThing->isCreature())
|
if(toThing->isCreature() && g_game.getProtocolVersion() >= 780)
|
||||||
m_protocolGame->sendUseOnCreature(pos, item->getId(), item->getStackPos(), toThing->getId());
|
m_protocolGame->sendUseOnCreature(pos, item->getId(), item->getStackPos(), toThing->getId());
|
||||||
else
|
else
|
||||||
m_protocolGame->sendUseItemWith(pos, item->getId(), item->getStackPos(), toThing->getPosition(), toThing->getId(), toThing->getStackPos());
|
m_protocolGame->sendUseItemWith(pos, item->getId(), item->getStackPos(), toThing->getPosition(), toThing->getId(), toThing->getStackPos());
|
||||||
|
@ -903,6 +903,20 @@ void Game::useInventoryItemWith(int itemId, const ThingPtr& toThing)
|
||||||
m_protocolGame->sendUseItemWith(pos, itemId, 0, toThing->getPosition(), toThing->getId(), toThing->getStackPos());
|
m_protocolGame->sendUseItemWith(pos, itemId, 0, toThing->getPosition(), toThing->getId(), toThing->getStackPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemPtr Game::findItemInContainers(uint itemId, int subType)
|
||||||
|
{
|
||||||
|
for(auto& it : m_containers) {
|
||||||
|
const ContainerPtr& container = it.second;
|
||||||
|
|
||||||
|
if(container) {
|
||||||
|
ItemPtr item = container->findItemById(itemId, subType);
|
||||||
|
if(item != nullptr)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
int Game::open(const ItemPtr& item, const ContainerPtr& previousContainer)
|
int Game::open(const ItemPtr& item, const ContainerPtr& previousContainer)
|
||||||
{
|
{
|
||||||
if(!canPerformGameAction() || !item)
|
if(!canPerformGameAction() || !item)
|
||||||
|
@ -1400,19 +1414,31 @@ 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 < 810 || version > 1010))
|
if(version != 0 && version != 760 && (version < 810 || version > 1010))
|
||||||
stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
|
stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
|
||||||
|
|
||||||
m_features.reset();
|
m_features.reset();
|
||||||
enableFeature(Otc::GameFormatCreatureName);
|
enableFeature(Otc::GameFormatCreatureName);
|
||||||
|
|
||||||
|
|
||||||
|
if(version >= 780)
|
||||||
|
{
|
||||||
|
enableFeature(Otc::GamePlayerAddons);
|
||||||
|
enableFeature(Otc::GamePlayerStamina);
|
||||||
|
enableFeature(Otc::GameNewFluids);
|
||||||
|
enableFeature(Otc::GameMessageLevel);
|
||||||
|
enableFeature(Otc::GameMessageStatments);
|
||||||
|
enableFeature(Otc::GamePlayerStateU16);
|
||||||
|
enableFeature(Otc::GameLooktypeU16);
|
||||||
|
}
|
||||||
|
|
||||||
if(version >= 840) {
|
if(version >= 840) {
|
||||||
enableFeature(Otc::GameProtocolChecksum);
|
enableFeature(Otc::GameProtocolChecksum);
|
||||||
enableFeature(Otc::GameChallengeOnLogin);
|
enableFeature(Otc::GameChallengeOnLogin);
|
||||||
enableFeature(Otc::GameAccountNames);
|
enableFeature(Otc::GameAccountNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(version <= 854) {
|
if(version >= 780 && version <= 854) { // 780 might not be accurate
|
||||||
enableFeature(Otc::GameChargeableItems);
|
enableFeature(Otc::GameChargeableItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1487,7 +1513,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 < 810 || version > 1010))
|
if(version != 0 && version != 760 && (version < 810 || version > 1010))
|
||||||
stdext::throw_exception(stdext::format("Client version %d not supported", version));
|
stdext::throw_exception(stdext::format("Client version %d not supported", version));
|
||||||
|
|
||||||
m_clientVersion = version;
|
m_clientVersion = version;
|
||||||
|
|
|
@ -158,6 +158,7 @@ public:
|
||||||
void useWith(const ItemPtr& fromThing, const ThingPtr& toThing);
|
void useWith(const ItemPtr& fromThing, const ThingPtr& toThing);
|
||||||
void useInventoryItem(int itemId);
|
void useInventoryItem(int itemId);
|
||||||
void useInventoryItemWith(int itemId, const ThingPtr& toThing);
|
void useInventoryItemWith(int itemId, const ThingPtr& toThing);
|
||||||
|
ItemPtr findItemInContainers(uint itemId, int subType);
|
||||||
|
|
||||||
// container related
|
// container related
|
||||||
int open(const ItemPtr& item, const ContainerPtr& previousContainer);
|
int open(const ItemPtr& item, const ContainerPtr& previousContainer);
|
||||||
|
|
|
@ -288,65 +288,68 @@ void Item::calculatePatterns(int& xPattern, int& yPattern, int& zPattern)
|
||||||
}
|
}
|
||||||
} else if(isSplash() || isFluidContainer()) {
|
} else if(isSplash() || isFluidContainer()) {
|
||||||
int color = Otc::FluidTransparent;
|
int color = Otc::FluidTransparent;
|
||||||
switch(m_countOrSubType) {
|
if(g_game.getFeature(Otc::GameNewFluids)) {
|
||||||
case Otc::FluidNone:
|
switch(m_countOrSubType) {
|
||||||
color = Otc::FluidTransparent;
|
case Otc::FluidNone:
|
||||||
break;
|
color = Otc::FluidTransparent;
|
||||||
case Otc::FluidWater:
|
break;
|
||||||
color = Otc::FluidBlue;
|
case Otc::FluidWater:
|
||||||
break;
|
color = Otc::FluidBlue;
|
||||||
case Otc::FluidMana:
|
break;
|
||||||
color = Otc::FluidPurple;
|
case Otc::FluidMana:
|
||||||
break;
|
color = Otc::FluidPurple;
|
||||||
case Otc::FluidBeer:
|
break;
|
||||||
color = Otc::FluidBrown;
|
case Otc::FluidBeer:
|
||||||
break;
|
color = Otc::FluidBrown;
|
||||||
case Otc::FluidOil:
|
break;
|
||||||
color = Otc::FluidBrown;
|
case Otc::FluidOil:
|
||||||
break;
|
color = Otc::FluidBrown;
|
||||||
case Otc::FluidBlood:
|
break;
|
||||||
color = Otc::FluidRed;
|
case Otc::FluidBlood:
|
||||||
break;
|
color = Otc::FluidRed;
|
||||||
case Otc::FluidSlime:
|
break;
|
||||||
color = Otc::FluidGreen;
|
case Otc::FluidSlime:
|
||||||
break;
|
color = Otc::FluidGreen;
|
||||||
case Otc::FluidMud:
|
break;
|
||||||
color = Otc::FluidBrown;
|
case Otc::FluidMud:
|
||||||
break;
|
color = Otc::FluidBrown;
|
||||||
case Otc::FluidLemonade:
|
break;
|
||||||
color = Otc::FluidYellow;
|
case Otc::FluidLemonade:
|
||||||
break;
|
color = Otc::FluidYellow;
|
||||||
case Otc::FluidMilk:
|
break;
|
||||||
color = Otc::FluidWhite;
|
case Otc::FluidMilk:
|
||||||
break;
|
color = Otc::FluidWhite;
|
||||||
case Otc::FluidWine:
|
break;
|
||||||
color = Otc::FluidPurple;
|
case Otc::FluidWine:
|
||||||
break;
|
color = Otc::FluidPurple;
|
||||||
case Otc::FluidHealth:
|
break;
|
||||||
color = Otc::FluidRed;
|
case Otc::FluidHealth:
|
||||||
break;
|
color = Otc::FluidRed;
|
||||||
case Otc::FluidUrine:
|
break;
|
||||||
color = Otc::FluidYellow;
|
case Otc::FluidUrine:
|
||||||
break;
|
color = Otc::FluidYellow;
|
||||||
case Otc::FluidRum:
|
break;
|
||||||
color = Otc::FluidBrown;
|
case Otc::FluidRum:
|
||||||
break;
|
color = Otc::FluidBrown;
|
||||||
case Otc::FluidFruidJuice:
|
break;
|
||||||
color = Otc::FluidYellow;
|
case Otc::FluidFruidJuice:
|
||||||
break;
|
color = Otc::FluidYellow;
|
||||||
case Otc::FluidCoconutMilk:
|
break;
|
||||||
color = Otc::FluidWhite;
|
case Otc::FluidCoconutMilk:
|
||||||
break;
|
color = Otc::FluidWhite;
|
||||||
case Otc::FluidTea:
|
break;
|
||||||
color = Otc::FluidBrown;
|
case Otc::FluidTea:
|
||||||
break;
|
color = Otc::FluidBrown;
|
||||||
case Otc::FluidMead:
|
break;
|
||||||
color = Otc::FluidBrown;
|
case Otc::FluidMead:
|
||||||
break;
|
color = Otc::FluidBrown;
|
||||||
default:
|
break;
|
||||||
color = Otc::FluidTransparent;
|
default:
|
||||||
break;
|
color = Otc::FluidTransparent;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
color = m_countOrSubType;
|
||||||
|
|
||||||
xPattern = (color % 4) % getNumPatternX();
|
xPattern = (color % 4) % getNumPatternX();
|
||||||
yPattern = (color / 4) % getNumPatternY();
|
yPattern = (color / 4) % getNumPatternY();
|
||||||
|
|
|
@ -184,6 +184,7 @@ void Client::registerLuaFunctions()
|
||||||
g_lua.bindSingletonFunction("g_game", "useWith", &Game::useWith, &g_game);
|
g_lua.bindSingletonFunction("g_game", "useWith", &Game::useWith, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "useInventoryItem", &Game::useInventoryItem, &g_game);
|
g_lua.bindSingletonFunction("g_game", "useInventoryItem", &Game::useInventoryItem, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "useInventoryItemWith", &Game::useInventoryItemWith, &g_game);
|
g_lua.bindSingletonFunction("g_game", "useInventoryItemWith", &Game::useInventoryItemWith, &g_game);
|
||||||
|
g_lua.bindSingletonFunction("g_game", "findItemInContainers", &Game::findItemInContainers, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "open", &Game::open, &g_game);
|
g_lua.bindSingletonFunction("g_game", "open", &Game::open, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "openParent", &Game::openParent, &g_game);
|
g_lua.bindSingletonFunction("g_game", "openParent", &Game::openParent, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "close", &Game::close, &g_game);
|
g_lua.bindSingletonFunction("g_game", "close", &Game::close, &g_game);
|
||||||
|
|
|
@ -87,7 +87,7 @@ void buildMessageModesMap(int version) {
|
||||||
messageModesMap[Otc::MessageLook] = 25;
|
messageModesMap[Otc::MessageLook] = 25;
|
||||||
messageModesMap[Otc::MessageFailure] = 26;
|
messageModesMap[Otc::MessageFailure] = 26;
|
||||||
messageModesMap[Otc::MessageBlue] = 27;
|
messageModesMap[Otc::MessageBlue] = 27;
|
||||||
} else if(version >= 810) {
|
} else if(version >= 760) {
|
||||||
messageModesMap[Otc::MessageNone] = 0;
|
messageModesMap[Otc::MessageNone] = 0;
|
||||||
messageModesMap[Otc::MessageSay] = 1;
|
messageModesMap[Otc::MessageSay] = 1;
|
||||||
messageModesMap[Otc::MessageWhisper] = 2;
|
messageModesMap[Otc::MessageWhisper] = 2;
|
||||||
|
|
|
@ -1038,7 +1038,9 @@ void ProtocolGame::parsePlayerStats(const InputMessagePtr& msg)
|
||||||
|
|
||||||
double magicLevelPercent = msg->getU8();
|
double magicLevelPercent = msg->getU8();
|
||||||
double soul = msg->getU8();
|
double soul = msg->getU8();
|
||||||
double stamina = msg->getU16();
|
double stamina = 0;
|
||||||
|
if(g_game.getFeature(Otc::GamePlayerStamina))
|
||||||
|
stamina = msg->getU16();
|
||||||
|
|
||||||
double baseSpeed = 0;
|
double baseSpeed = 0;
|
||||||
if(g_game.getFeature(Otc::GameSkillsBase))
|
if(g_game.getFeature(Otc::GameSkillsBase))
|
||||||
|
@ -1092,7 +1094,12 @@ void ProtocolGame::parsePlayerSkills(const InputMessagePtr& msg)
|
||||||
|
|
||||||
void ProtocolGame::parsePlayerState(const InputMessagePtr& msg)
|
void ProtocolGame::parsePlayerState(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
int states = msg->getU16();
|
int states;
|
||||||
|
if(g_game.getFeature(Otc::GamePlayerStateU16))
|
||||||
|
states = msg->getU16();
|
||||||
|
else
|
||||||
|
states = msg->getU8();
|
||||||
|
|
||||||
m_localPlayer->setStates(states);
|
m_localPlayer->setStates(states);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1130,10 +1137,15 @@ void ProtocolGame::parseMultiUseCooldown(const InputMessagePtr& msg)
|
||||||
|
|
||||||
void ProtocolGame::parseTalk(const InputMessagePtr& msg)
|
void ProtocolGame::parseTalk(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
msg->getU32(); // channel statement guid
|
if(g_game.getFeature(Otc::GameMessageStatments))
|
||||||
|
msg->getU32(); // channel statement guid
|
||||||
|
|
||||||
std::string name = g_game.formatCreatureName(msg->getString());
|
std::string name = g_game.formatCreatureName(msg->getString());
|
||||||
int level = msg->getU16();
|
|
||||||
|
int level = 0;
|
||||||
|
if(g_game.getFeature(Otc::GameMessageLevel))
|
||||||
|
level = msg->getU16();
|
||||||
|
|
||||||
Otc::MessageMode mode = Proto::translateMessageModeFromServer(msg->getU8());
|
Otc::MessageMode mode = Proto::translateMessageModeFromServer(msg->getU8());
|
||||||
int channelId = 0;
|
int channelId = 0;
|
||||||
Position pos;
|
Position pos;
|
||||||
|
@ -1380,15 +1392,23 @@ void ProtocolGame::parseFloorChangeDown(const InputMessagePtr& msg)
|
||||||
void ProtocolGame::parseOpenOutfitWindow(const InputMessagePtr& msg)
|
void ProtocolGame::parseOpenOutfitWindow(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
Outfit currentOutfit = getOutfit(msg);
|
Outfit currentOutfit = getOutfit(msg);
|
||||||
|
|
||||||
std::vector<std::tuple<int, std::string, int> > outfitList;
|
std::vector<std::tuple<int, std::string, int> > outfitList;
|
||||||
int outfitCount = msg->getU8();
|
|
||||||
for(int i = 0; i < outfitCount; i++) {
|
|
||||||
int outfitId = msg->getU16();
|
|
||||||
std::string outfitName = msg->getString();
|
|
||||||
int outfitAddons = msg->getU8();
|
|
||||||
|
|
||||||
outfitList.push_back(std::make_tuple(outfitId, outfitName, outfitAddons));
|
if(g_game.getProtocolVersion() < 780) {
|
||||||
|
int outfitStart = msg->getU8();
|
||||||
|
int outfitEnd = msg->getU8();
|
||||||
|
for(int i = outfitStart; i <= outfitEnd; i++)
|
||||||
|
outfitList.push_back(std::make_tuple(i, "", 0));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int outfitCount = msg->getU8();
|
||||||
|
for(int i = 0; i < outfitCount; i++) {
|
||||||
|
int outfitId = msg->getU16();
|
||||||
|
std::string outfitName = msg->getString();
|
||||||
|
int outfitAddons = msg->getU8();
|
||||||
|
|
||||||
|
outfitList.push_back(std::make_tuple(outfitId, outfitName, outfitAddons));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::tuple<int, std::string> > mountList;
|
std::vector<std::tuple<int, std::string> > mountList;
|
||||||
|
@ -1665,14 +1685,21 @@ Outfit ProtocolGame::getOutfit(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
Outfit outfit;
|
Outfit outfit;
|
||||||
|
|
||||||
int lookType = msg->getU16();
|
int lookType;
|
||||||
|
if(g_game.getFeature(Otc::GameLooktypeU16))
|
||||||
|
lookType = msg->getU16();
|
||||||
|
else
|
||||||
|
lookType = msg->getU8();
|
||||||
|
|
||||||
if(lookType != 0) {
|
if(lookType != 0) {
|
||||||
outfit.setCategory(ThingCategoryCreature);
|
outfit.setCategory(ThingCategoryCreature);
|
||||||
int head = msg->getU8();
|
int head = msg->getU8();
|
||||||
int body = msg->getU8();
|
int body = msg->getU8();
|
||||||
int legs = msg->getU8();
|
int legs = msg->getU8();
|
||||||
int feet = msg->getU8();
|
int feet = msg->getU8();
|
||||||
int addons = msg->getU8();
|
int addons = 0;
|
||||||
|
if(g_game.getFeature(Otc::GamePlayerAddons))
|
||||||
|
addons = msg->getU8();
|
||||||
|
|
||||||
if(!g_things.isValidDatId(lookType, ThingCategoryCreature)) {
|
if(!g_things.isValidDatId(lookType, ThingCategoryCreature)) {
|
||||||
g_logger.traceError(stdext::format("invalid outfit looktype %d", lookType));
|
g_logger.traceError(stdext::format("invalid outfit looktype %d", lookType));
|
||||||
|
|
|
@ -52,8 +52,16 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
|
||||||
{
|
{
|
||||||
OutputMessagePtr msg(new OutputMessage);
|
OutputMessagePtr msg(new OutputMessage);
|
||||||
|
|
||||||
msg->addU8(Proto::ClientPendingGame);
|
if(g_game.getProtocolVersion() == 760)
|
||||||
msg->addU16(g_game.getOs());
|
{
|
||||||
|
msg->addU16(0x20A);
|
||||||
|
msg->addU8(g_game.getOs());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg->addU8(Proto::ClientPendingGame);
|
||||||
|
msg->addU16(g_game.getOs());
|
||||||
|
}
|
||||||
msg->addU16(g_game.getProtocolVersion());
|
msg->addU16(g_game.getProtocolVersion());
|
||||||
|
|
||||||
if(g_game.getProtocolVersion() >= 971) {
|
if(g_game.getProtocolVersion() >= 971) {
|
||||||
|
@ -65,13 +73,16 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
|
||||||
|
|
||||||
msg->addU8(0); // first RSA byte must be 0
|
msg->addU8(0); // first RSA byte must be 0
|
||||||
|
|
||||||
// xtea key
|
if(g_game.getProtocolVersion() >= 800)
|
||||||
generateXteaKey();
|
{
|
||||||
msg->addU32(m_xteaKey[0]);
|
// xtea key
|
||||||
msg->addU32(m_xteaKey[1]);
|
generateXteaKey();
|
||||||
msg->addU32(m_xteaKey[2]);
|
msg->addU32(m_xteaKey[0]);
|
||||||
msg->addU32(m_xteaKey[3]);
|
msg->addU32(m_xteaKey[1]);
|
||||||
msg->addU8(0); // is gm set?
|
msg->addU32(m_xteaKey[2]);
|
||||||
|
msg->addU32(m_xteaKey[3]);
|
||||||
|
msg->addU8(0); // is gm set?
|
||||||
|
}
|
||||||
|
|
||||||
if(g_game.getFeature(Otc::GameAccountNames))
|
if(g_game.getFeature(Otc::GameAccountNames))
|
||||||
msg->addString(m_accountName);
|
msg->addString(m_accountName);
|
||||||
|
@ -96,14 +107,16 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
|
||||||
msg->addPaddingBytes(paddingBytes);
|
msg->addPaddingBytes(paddingBytes);
|
||||||
|
|
||||||
// encrypt with RSA
|
// encrypt with RSA
|
||||||
msg->encryptRsa();
|
if(g_game.getProtocolVersion() >= 800)
|
||||||
|
msg->encryptRsa();
|
||||||
|
|
||||||
if(g_game.getFeature(Otc::GameProtocolChecksum))
|
if(g_game.getFeature(Otc::GameProtocolChecksum))
|
||||||
enableChecksum();
|
enableChecksum();
|
||||||
|
|
||||||
send(msg);
|
send(msg);
|
||||||
|
|
||||||
enableXteaEncryption();
|
if(g_game.getProtocolVersion() >= 800)
|
||||||
|
enableXteaEncryption();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolGame::sendEnterGame()
|
void ProtocolGame::sendEnterGame()
|
||||||
|
|
Loading…
Reference in New Issue