mirror of
https://github.com/edubart/otclient.git
synced 2025-10-14 11:34:54 +02:00
Multi-protocol
Lots of chagnes to add multi protocol flexibility, not really completed yet, still have to rework text messages opcodes and other stuff, so this still a working in progress feature * Rework dat reader, the dat reader can now * dinamically detect dat version * Split game into gamelib and game_interface * Lots of other minor changes
This commit is contained in:
@@ -141,3 +141,14 @@ void Application::close()
|
||||
if(!g_lua.callGlobalField<bool>("g_app", "onClose"))
|
||||
exit();
|
||||
}
|
||||
|
||||
std::string Application::getOs()
|
||||
{
|
||||
#if defined(WIN32)
|
||||
return "windows";
|
||||
#elif defined(__APPLE__)
|
||||
return "mac";
|
||||
#else
|
||||
return "linux";
|
||||
#endif
|
||||
}
|
||||
|
@@ -58,6 +58,7 @@ public:
|
||||
std::string getBuildCommit() { return BUILD_COMMIT; }
|
||||
std::string getBuildType() { return BUILD_TYPE; }
|
||||
std::string getBuildArch() { return BUILD_ARCH; }
|
||||
std::string getOs();
|
||||
std::string getStartupOptions() { return m_startupOptions; }
|
||||
|
||||
protected:
|
||||
|
@@ -22,22 +22,25 @@
|
||||
|
||||
#include <framework/core/application.h>
|
||||
#include <framework/luaengine/luainterface.h>
|
||||
#include <framework/graphics/fontmanager.h>
|
||||
#include <framework/ui/ui.h>
|
||||
#include <framework/net/protocol.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/core/configmanager.h>
|
||||
#include <framework/otml/otml.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/platform/platformwindow.h>
|
||||
#include <framework/core/modulemanager.h>
|
||||
#include <framework/core/module.h>
|
||||
#include <framework/sound/soundmanager.h>
|
||||
#include <framework/util/crypt.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/graphics/particlemanager.h>
|
||||
#include <framework/graphics/texturemanager.h>
|
||||
|
||||
#ifdef FW_GRAPHICS
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/platform/platformwindow.h>
|
||||
#include <framework/graphics/particlemanager.h>
|
||||
#include <framework/graphics/fontmanager.h>
|
||||
#include <framework/ui/ui.h>
|
||||
#endif
|
||||
|
||||
void Application::registerLuaFunctions()
|
||||
{
|
||||
// conversion globals
|
||||
@@ -67,6 +70,7 @@ void Application::registerLuaFunctions()
|
||||
g_lua.bindSingletonFunction("g_app", "getBuildCommit", &Application::getBuildCommit, static_cast<Application*>(&g_app));
|
||||
g_lua.bindSingletonFunction("g_app", "getBuildType", &Application::getBuildType, static_cast<Application*>(&g_app));
|
||||
g_lua.bindSingletonFunction("g_app", "getBuildArch", &Application::getBuildArch, static_cast<Application*>(&g_app));
|
||||
g_lua.bindSingletonFunction("g_app", "getOs", &Application::getOs, static_cast<Application*>(&g_app));
|
||||
g_lua.bindSingletonFunction("g_app", "exit", &Application::exit, static_cast<Application*>(&g_app));
|
||||
|
||||
// Crypt
|
||||
@@ -644,7 +648,7 @@ void Application::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<InputMessage>("peekU16", &InputMessage::peekU16);
|
||||
g_lua.bindClassMemberFunction<InputMessage>("peekU32", &InputMessage::peekU32);
|
||||
g_lua.bindClassMemberFunction<InputMessage>("peekU64", &InputMessage::peekU64);
|
||||
g_lua.bindClassMemberFunction<InputMessage>("decryptRSA", &InputMessage::decryptRSA);
|
||||
g_lua.bindClassMemberFunction<InputMessage>("decryptRsa", &InputMessage::decryptRsa);
|
||||
g_lua.bindClassMemberFunction<InputMessage>("getReadSize", &InputMessage::getReadSize);
|
||||
g_lua.bindClassMemberFunction<InputMessage>("getUnreadSize", &InputMessage::getUnreadSize);
|
||||
g_lua.bindClassMemberFunction<InputMessage>("getMessageSize", &InputMessage::getMessageSize);
|
||||
@@ -661,7 +665,7 @@ void Application::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<OutputMessage>("addU64", &OutputMessage::addU64);
|
||||
g_lua.bindClassMemberFunction<OutputMessage>("addString", &OutputMessage::addString);
|
||||
g_lua.bindClassMemberFunction<OutputMessage>("addPaddingBytes", &OutputMessage::addPaddingBytes);
|
||||
g_lua.bindClassMemberFunction<OutputMessage>("encryptRSA", &OutputMessage::encryptRSA);
|
||||
g_lua.bindClassMemberFunction<OutputMessage>("encryptRsa", &OutputMessage::encryptRsa);
|
||||
g_lua.bindClassMemberFunction<OutputMessage>("getMessageSize", &OutputMessage::getMessageSize);
|
||||
#endif
|
||||
|
||||
|
@@ -86,7 +86,7 @@ std::string InputMessage::getString()
|
||||
return std::string(v, stringLength);
|
||||
}
|
||||
|
||||
void InputMessage::decryptRSA(int size, const std::string& p, const std::string& q, const std::string& d)
|
||||
void InputMessage::decryptRsa(int size, const std::string& p, const std::string& q, const std::string& d)
|
||||
{
|
||||
checkRead(size);
|
||||
RSA::decrypt((char*)m_buffer + m_readPos, size, p.c_str(), q.c_str(), d.c_str());
|
||||
|
@@ -40,6 +40,7 @@ public:
|
||||
void setBuffer(const std::string& buffer);
|
||||
|
||||
void skipBytes(uint16 bytes) { m_readPos += bytes; }
|
||||
void setReadPos(uint16 readPos) { m_readPos = readPos; }
|
||||
uint8 getU8();
|
||||
uint16 getU16();
|
||||
uint32 getU32();
|
||||
@@ -51,9 +52,10 @@ public:
|
||||
uint32 peekU32() { uint32 v = getU32(); m_readPos-=4; return v; }
|
||||
uint64 peekU64() { uint64 v = getU64(); m_readPos-=8; return v; }
|
||||
|
||||
void decryptRSA(int size, const std::string& p, const std::string& q, const std::string& d);
|
||||
void decryptRsa(int size, const std::string& p, const std::string& q, const std::string& d);
|
||||
|
||||
int getReadSize() { return m_readPos - m_headerPos; }
|
||||
int getReadPos() { return m_readPos; }
|
||||
int getUnreadSize() { return m_messageSize - (m_readPos - m_headerPos); }
|
||||
uint16 getMessageSize() { return m_messageSize; }
|
||||
|
||||
|
@@ -89,7 +89,7 @@ void OutputMessage::addPaddingBytes(int bytes, uint8 byte)
|
||||
m_messageSize += bytes;
|
||||
}
|
||||
|
||||
void OutputMessage::encryptRSA(int size, const std::string& key)
|
||||
void OutputMessage::encryptRsa(int size, const std::string& key)
|
||||
{
|
||||
if(m_messageSize < size)
|
||||
throw stdext::exception("insufficient bytes in buffer to encrypt");
|
||||
|
@@ -49,7 +49,7 @@ public:
|
||||
void addString(const std::string& buffer);
|
||||
void addPaddingBytes(int bytes, uint8 byte = 0);
|
||||
|
||||
void encryptRSA(int size, const std::string& key);
|
||||
void encryptRsa(int size, const std::string& key);
|
||||
|
||||
uint16 getMessageSize() { return m_messageSize; }
|
||||
|
||||
|
@@ -286,31 +286,27 @@ namespace Otc
|
||||
};
|
||||
|
||||
enum GameFeature {
|
||||
GameExtendedOpcode = 0,
|
||||
GameProtocolChecksum,
|
||||
GameAccountNames,
|
||||
GameChallangeOnLogin,
|
||||
GameStackposOnTileAddThing,
|
||||
GamePenalityOnDeath,
|
||||
GameNameOnNpcTrade,
|
||||
GameDoubleFreeCapacity,
|
||||
GameDoubleExperience,
|
||||
GameTotalCapacity,
|
||||
GameSkillsBase,
|
||||
GameAdditionalPlayerStats,
|
||||
GameIdOnCancelAttack,
|
||||
GameChannelPlayerList,
|
||||
GamePlayerMounts,
|
||||
GameEnvironmentEffect,
|
||||
GameCreatureType,
|
||||
GameCreatureAdditionalInfo,
|
||||
GameCreaturePassableInfo,
|
||||
GameItemAnimationPhase,
|
||||
GameTrucatedPingOpcode,
|
||||
GameReverseCreatureStack,
|
||||
GameMagicEffectU16,
|
||||
GamePlayerMarket,
|
||||
LastGameFeature
|
||||
// 1-50 defined in c++
|
||||
GameProtocolChecksum = 1,
|
||||
GameAccountNames = 2,
|
||||
GameChallangeOnLogin = 3,
|
||||
GamePenalityOnDeath = 5,
|
||||
GameNameOnNpcTrade = 6,
|
||||
GameDoubleFreeCapacity = 7,
|
||||
GameDoubleExperience = 8,
|
||||
GameTotalCapacity = 9,
|
||||
GameSkillsBase = 10,
|
||||
GamePlayerRegenerationTime = 11,
|
||||
GameChannelPlayerList = 13,
|
||||
GamePlayerMounts = 14,
|
||||
GameEnvironmentEffect = 15,
|
||||
GameCreatureEmblems = 17,
|
||||
GameItemAnimationPhase = 19,
|
||||
GameMagicEffectU16 = 22,
|
||||
GamePlayerMarket = 23,
|
||||
// 23-50 unused yet
|
||||
// 51-100 reserved to be defined in lua
|
||||
LastGameFeature = 101
|
||||
};
|
||||
|
||||
enum PathFindResult {
|
||||
|
@@ -461,6 +461,8 @@ void Creature::setDirection(Otc::Direction direction)
|
||||
|
||||
void Creature::setOutfit(const Outfit& outfit)
|
||||
{
|
||||
if(!g_things.isValidDatId(outfit.getId(), DatCreatureCategory))
|
||||
return;
|
||||
m_walkAnimationPhase = 0; // might happen when player is walking and outfit is changed.
|
||||
m_outfit = outfit;
|
||||
}
|
||||
|
@@ -46,6 +46,8 @@ void Effect::startAnimation()
|
||||
|
||||
void Effect::setId(uint32 id)
|
||||
{
|
||||
if(!g_things.isValidDatId(id, DatEffectCategory))
|
||||
id = 0;
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
|
@@ -38,7 +38,7 @@ Game g_game;
|
||||
Game::Game()
|
||||
{
|
||||
resetGameStates();
|
||||
setClientVersion(860);
|
||||
m_protocolVersion = 0;
|
||||
}
|
||||
|
||||
void Game::resetGameStates()
|
||||
@@ -416,10 +416,11 @@ void Game::processWalkCancel(Otc::Direction direction)
|
||||
|
||||
void Game::loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName)
|
||||
{
|
||||
if(m_protocolGame || isOnline()) {
|
||||
g_logger.traceError("unable to login into a world while already online or logging");
|
||||
return;
|
||||
}
|
||||
if(m_protocolGame || isOnline())
|
||||
stdext::throw_exception("Unable to login into a world while already online or logging.");
|
||||
|
||||
if(m_protocolVersion == 0)
|
||||
stdext::throw_exception("Must set a valid game protocol version before logging.");
|
||||
|
||||
m_protocolGame = ProtocolGamePtr(new ProtocolGame);
|
||||
m_protocolGame->login(account, password, worldHost, (uint16)worldPort, characterName);
|
||||
@@ -1090,61 +1091,48 @@ bool Game::canPerformGameAction()
|
||||
return m_localPlayer && !m_dead && m_protocolGame && m_protocolGame->isConnected() && checkBotProtection();
|
||||
}
|
||||
|
||||
void Game::setClientVersion(int clientVersion)
|
||||
void Game::setProtocolVersion(int version)
|
||||
{
|
||||
if(isOnline()) {
|
||||
g_logger.error("Unable to change client version while online");
|
||||
return;
|
||||
}
|
||||
if(isOnline())
|
||||
stdext::throw_exception("Unable to change client version while online");
|
||||
|
||||
//TODO: check supported versions
|
||||
if(version < 810 || version > 960)
|
||||
stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
|
||||
|
||||
m_features.reset();
|
||||
|
||||
if(clientVersion >= 854) {
|
||||
if(version >= 854) {
|
||||
enableFeature(Otc::GameProtocolChecksum);
|
||||
enableFeature(Otc::GameAccountNames);
|
||||
enableFeature(Otc::GameChallangeOnLogin);
|
||||
enableFeature(Otc::GameStackposOnTileAddThing);
|
||||
enableFeature(Otc::GameDoubleFreeCapacity);
|
||||
enableFeature(Otc::GameCreatureAdditionalInfo);
|
||||
enableFeature(Otc::GameReverseCreatureStack);
|
||||
enableFeature(Otc::GameCreatureEmblems);
|
||||
}
|
||||
|
||||
if(clientVersion >= 860) {
|
||||
enableFeature(Otc::GameIdOnCancelAttack);
|
||||
}
|
||||
|
||||
if(clientVersion >= 862) {
|
||||
if(version >= 862) {
|
||||
enableFeature(Otc::GamePenalityOnDeath);
|
||||
}
|
||||
|
||||
if(clientVersion >= 870) {
|
||||
if(version >= 870) {
|
||||
enableFeature(Otc::GameDoubleExperience);
|
||||
enableFeature(Otc::GamePlayerMounts);
|
||||
}
|
||||
|
||||
if(clientVersion >= 910) {
|
||||
if(version >= 910) {
|
||||
enableFeature(Otc::GameNameOnNpcTrade);
|
||||
enableFeature(Otc::GameTotalCapacity);
|
||||
enableFeature(Otc::GameSkillsBase);
|
||||
enableFeature(Otc::GameAdditionalPlayerStats);
|
||||
enableFeature(Otc::GamePlayerRegenerationTime);
|
||||
enableFeature(Otc::GameChannelPlayerList);
|
||||
enableFeature(Otc::GameEnvironmentEffect);
|
||||
enableFeature(Otc::GameCreatureType);
|
||||
enableFeature(Otc::GameItemAnimationPhase);
|
||||
}
|
||||
|
||||
if(clientVersion >= 940) {
|
||||
if(version >= 940) {
|
||||
enableFeature(Otc::GamePlayerMarket);
|
||||
}
|
||||
|
||||
if(clientVersion >= 953) {
|
||||
enableFeature(Otc::GameCreaturePassableInfo);
|
||||
enableFeature(Otc::GameTrucatedPingOpcode);
|
||||
}
|
||||
|
||||
m_clientVersion = clientVersion;
|
||||
m_protocolVersion = version;
|
||||
}
|
||||
|
||||
void Game::setAttackingCreature(const CreaturePtr& creature)
|
||||
|
@@ -232,8 +232,8 @@ public:
|
||||
void setFeature(Otc::GameFeature feature) { m_features.set(feature, false); }
|
||||
bool getFeature(Otc::GameFeature feature) { return m_features.test(feature); }
|
||||
|
||||
void setClientVersion(int clientVersion);
|
||||
int getClientVersion() { return m_clientVersion; }
|
||||
void setProtocolVersion(int version);
|
||||
int getProtocolVersion() { return m_protocolVersion; }
|
||||
|
||||
void setRSA(const std::string& rsa);
|
||||
std::string getRSA() { return m_rsa; }
|
||||
@@ -256,7 +256,6 @@ public:
|
||||
int getServerBeat() { return m_serverBeat; }
|
||||
LocalPlayerPtr getLocalPlayer() { return m_localPlayer; }
|
||||
ProtocolGamePtr getProtocolGame() { return m_protocolGame; }
|
||||
int getProtocolVersion() { return PROTOCOL; }
|
||||
std::string getCharacterName() { return m_characterName; }
|
||||
std::string getWorldName() { return m_worldName; }
|
||||
std::vector<uint8> getGMActions() { return m_gmActions; }
|
||||
@@ -288,7 +287,7 @@ private:
|
||||
std::string m_characterName;
|
||||
std::string m_worldName;
|
||||
std::bitset<Otc::LastGameFeature> m_features;
|
||||
int m_clientVersion;
|
||||
int m_protocolVersion;
|
||||
std::string m_rsa;
|
||||
};
|
||||
|
||||
|
@@ -101,7 +101,7 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate)
|
||||
else if(tile->mustHookEast())
|
||||
xPattern = getNumPatternX() >= 3 ? 2 : 0;
|
||||
}
|
||||
} else if(isFluid() || isFluidContainer()) {
|
||||
} else if(isSplash() || isFluidContainer()) {
|
||||
int color = Otc::FluidTransparent;
|
||||
switch(m_countOrSubType) {
|
||||
case Otc::FluidNone:
|
||||
@@ -176,15 +176,20 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate)
|
||||
|
||||
void Item::setId(uint32 id)
|
||||
{
|
||||
m_otbId = g_things.findOtbForClientId(id)->getServerId();
|
||||
if(!g_things.isValidDatId(id, DatItemCategory))
|
||||
id = 0;
|
||||
//m_otbId = g_things.findOtbForClientId(id)->getServerId();
|
||||
m_id = id;
|
||||
m_otbId = 0;
|
||||
}
|
||||
|
||||
void Item::setOtbId(uint16 id)
|
||||
{
|
||||
if(!g_things.isValidOtbId(id))
|
||||
id = 0;
|
||||
auto otbType = g_things.getOtbType(id);
|
||||
m_otbId = id;
|
||||
m_id = otbType->getClientId();
|
||||
m_otbId = id;
|
||||
}
|
||||
|
||||
bool Item::isValid()
|
||||
|
@@ -190,10 +190,10 @@ void OTClient::registerLuaFunctions()
|
||||
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", "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);
|
||||
g_lua.bindSingletonFunction("g_game", "getClientVersion", &Game::getClientVersion, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getFeature", &Game::getFeature, &g_game);
|
||||
|
||||
g_lua.registerSingletonClass("g_shaders");
|
||||
|
@@ -467,7 +467,7 @@ bool Map::loadOtcm(const std::string& fileName)
|
||||
uint8 countOrSubType = fin->getU8();
|
||||
|
||||
ItemPtr item = Item::create(id);
|
||||
if(item->isStackable() || item->isFluidContainer() || item->isFluid())
|
||||
if(item->isStackable() || item->isFluidContainer() || item->isSplash() || item->isChargeable())
|
||||
item->setCountOrSubType(countOrSubType);
|
||||
|
||||
if(item->isValid())
|
||||
|
@@ -83,6 +83,8 @@ void Missile::setPath(const Position& fromPosition, const Position& toPosition)
|
||||
|
||||
void Missile::setId(uint32 id)
|
||||
{
|
||||
if(!g_things.isValidDatId(id, DatMissileCategory))
|
||||
id = 0;
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
|
@@ -25,7 +25,7 @@
|
||||
Outfit::Outfit()
|
||||
{
|
||||
m_category = DatCreatureCategory;
|
||||
m_id = 1;
|
||||
m_id = 0;
|
||||
resetClothes();
|
||||
}
|
||||
|
||||
|
@@ -25,49 +25,7 @@
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#if !(PROTOCOL == 810) && \
|
||||
!(PROTOCOL == 854) && \
|
||||
!(PROTOCOL >= 860 && PROTOCOL <= 862) && \
|
||||
!(PROTOCOL >= 870 && PROTOCOL <= 871) && \
|
||||
!(PROTOCOL >= 910 && PROTOCOL <= 953)
|
||||
#error "the supplied protocol version is not supported"
|
||||
#endif
|
||||
|
||||
namespace Proto {
|
||||
#ifdef CIPSOFT_RSA
|
||||
constexpr const char* RSA = "1321277432058722840622950990822933849527763264961655079678763618"
|
||||
"4334395343554449668205332383339435179772895415509701210392836078"
|
||||
"6959821132214473291575712138800495033169914814069637740318278150"
|
||||
"2907336840325241747827401343576296990629870233111328210165697754"
|
||||
"88792221429527047321331896351555606801473202394175817";
|
||||
#else
|
||||
constexpr const char* RSA = "1091201329673994292788609605089955415282375029027981291234687579"
|
||||
"3726629149257644633073969600111060390723088861007265581882535850"
|
||||
"3429057592827629436413108566029093628212635953836686562675849720"
|
||||
"6207862794310902180176810615217550567108238764764442605581471797"
|
||||
"07119674283982419152118103759076030616683978566631413";
|
||||
#endif
|
||||
|
||||
constexpr int PicSignature = 0x4F8C231A; // 953 pic signature
|
||||
constexpr int ClientVersion = PROTOCOL;
|
||||
|
||||
enum OsTypes {
|
||||
OsLinux = 1,
|
||||
OsWindows = 2,
|
||||
OsFlash = 3,
|
||||
OsOtclientLinux = 10,
|
||||
OsOtclientWindows = 11,
|
||||
OsOtclientMac = 12
|
||||
};
|
||||
|
||||
#ifdef OSTYPE
|
||||
constexpr int ClientOs = OSTYPE;
|
||||
#elif defined WIN32
|
||||
constexpr int ClientOs = OsOtclientWindows;
|
||||
#else
|
||||
constexpr int ClientOs = OsOtclientLinux;
|
||||
#endif
|
||||
|
||||
enum LoginServerOpts {
|
||||
LoginServerError = 10,
|
||||
LoginServerMotd = 20,
|
||||
|
@@ -43,8 +43,11 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
||||
opcode = msg->getU8();
|
||||
|
||||
// try to parse in lua first
|
||||
int readPos = msg->getReadPos();
|
||||
if(callLuaField<bool>("onOpcode", opcode, msg))
|
||||
continue;
|
||||
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");
|
||||
@@ -66,16 +69,12 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
||||
parseLoginWait(msg);
|
||||
break;
|
||||
case Proto::GameServerPing:
|
||||
if(g_game.getFeature(Otc::GameTrucatedPingOpcode))
|
||||
parsePingBack(msg);
|
||||
else
|
||||
parsePing(msg);
|
||||
break;
|
||||
case Proto::GameServerPingBack:
|
||||
if(g_game.getFeature(Otc::GameTrucatedPingOpcode))
|
||||
parsePing(msg);
|
||||
else
|
||||
if((opcode == Proto::GameServerPing && g_game.getProtocolVersion() >= 953) ||
|
||||
(opcode == Proto::GameServerPingBack && g_game.getProtocolVersion() < 953))
|
||||
parsePingBack(msg);
|
||||
else
|
||||
parsePing(msg);
|
||||
break;
|
||||
case Proto::GameServerChallange:
|
||||
parseChallange(msg);
|
||||
@@ -334,9 +333,9 @@ void ProtocolGame::parseGMActions(const InputMessagePtr& msg)
|
||||
|
||||
int numViolationReasons;
|
||||
|
||||
if(g_game.getClientVersion() >= 860)
|
||||
if(g_game.getProtocolVersion() >= 860)
|
||||
numViolationReasons = 20;
|
||||
else if(g_game.getClientVersion() >= 854)
|
||||
else if(g_game.getProtocolVersion() >= 854)
|
||||
numViolationReasons = 19;
|
||||
else
|
||||
numViolationReasons = 32;
|
||||
@@ -454,7 +453,7 @@ void ProtocolGame::parseTileAddThing(const InputMessagePtr& msg)
|
||||
Position pos = getPosition(msg);
|
||||
int stackPos = -1;
|
||||
|
||||
if(g_game.getFeature(Otc::GameStackposOnTileAddThing))
|
||||
if(g_game.getProtocolVersion() >= 854)
|
||||
stackPos = msg->getU8();
|
||||
|
||||
ThingPtr thing = getThing(msg);
|
||||
@@ -508,7 +507,7 @@ void ProtocolGame::parseCreatureMove(const InputMessagePtr& msg)
|
||||
int stackPos = -2;
|
||||
|
||||
// older protocols stores creatures in reverse order
|
||||
if(!g_game.getFeature(Otc::GameReverseCreatureStack))
|
||||
if(!g_game.getProtocolVersion() >= 854)
|
||||
stackPos = -1;
|
||||
|
||||
g_map.addThing(thing, newPos, stackPos);
|
||||
@@ -884,12 +883,11 @@ void ProtocolGame::parsePlayerStats(const InputMessagePtr& msg)
|
||||
m_localPlayer->setStamina(stamina);
|
||||
m_localPlayer->setSoul(soul);
|
||||
|
||||
if(g_game.getFeature(Otc::GameAdditionalPlayerStats)) {
|
||||
int speed = msg->getU16();
|
||||
msg->getU16(); // regeneration time
|
||||
if(g_game.getProtocolVersion() >= 910)
|
||||
m_localPlayer->setSpeed(msg->getU16());
|
||||
|
||||
m_localPlayer->setSpeed(speed);
|
||||
}
|
||||
if(g_game.getFeature(Otc::GamePlayerRegenerationTime))
|
||||
msg->getU16(); // regeneration time
|
||||
}
|
||||
|
||||
void ProtocolGame::parsePlayerSkills(const InputMessagePtr& msg)
|
||||
@@ -913,7 +911,7 @@ void ProtocolGame::parsePlayerState(const InputMessagePtr& msg)
|
||||
|
||||
void ProtocolGame::parsePlayerCancelAttack(const InputMessagePtr& msg)
|
||||
{
|
||||
if(g_game.getFeature(Otc::GameIdOnCancelAttack))
|
||||
if(g_game.getProtocolVersion() >= 860)
|
||||
msg->getU32(); // unknown
|
||||
|
||||
g_game.processAttackCancel();
|
||||
@@ -1389,7 +1387,7 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
||||
uint id = msg->getU32();
|
||||
|
||||
int creatureType;
|
||||
if(g_game.getFeature(Otc::GameCreatureType))
|
||||
if(g_game.getProtocolVersion() >= 910)
|
||||
creatureType = msg->getU8();
|
||||
else {
|
||||
if(id >= Proto::PlayerStartId && id < Proto::PlayerEndId)
|
||||
@@ -1441,12 +1439,11 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
||||
int emblem = -1;
|
||||
bool passable = false;
|
||||
|
||||
if(g_game.getFeature(Otc::GameCreatureAdditionalInfo)) {
|
||||
if(!known)
|
||||
emblem = msg->getU8();
|
||||
if(g_game.getFeature(Otc::GameCreatureEmblems) && !known)
|
||||
emblem = msg->getU8();
|
||||
|
||||
if(g_game.getProtocolVersion() >= 854)
|
||||
passable = (msg->getU8() == 0);
|
||||
}
|
||||
|
||||
if(creature) {
|
||||
creature->setHealthPercent(healthPercent);
|
||||
@@ -1474,7 +1471,7 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
||||
if(creature)
|
||||
creature->turn(direction);
|
||||
|
||||
if(g_game.getFeature(Otc::GameCreaturePassableInfo)) {
|
||||
if(g_game.getProtocolVersion() >= 953) {
|
||||
bool passable = msg->getU8();
|
||||
|
||||
if(creature)
|
||||
@@ -1497,7 +1494,7 @@ ItemPtr ProtocolGame::getItem(const InputMessagePtr& msg, int id)
|
||||
if(item->getId() == 0)
|
||||
stdext::throw_exception("unable to create item with invalid id 0");
|
||||
|
||||
if(item->isStackable() || item->isFluidContainer() || item->isFluid())
|
||||
if(item->isStackable() || item->isFluidContainer() || item->isSplash() || item->isChargeable())
|
||||
item->setCountOrSubType(msg->getU8());
|
||||
|
||||
if(g_game.getFeature(Otc::GameItemAnimationPhase)) {
|
||||
|
@@ -49,8 +49,9 @@ void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRando
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
|
||||
msg->addU8(Proto::ClientEnterGame);
|
||||
msg->addU16(Proto::ClientOs);
|
||||
msg->addU16(g_game.getClientVersion());
|
||||
|
||||
msg->addU16(g_lua.callGlobalField<int>("g_game", "getOs"));
|
||||
msg->addU16(g_game.getProtocolVersion());
|
||||
|
||||
int paddingBytes = 128;
|
||||
msg->addU8(0); // first RSA byte must be 0
|
||||
@@ -90,7 +91,7 @@ void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRando
|
||||
msg->addPaddingBytes(paddingBytes);
|
||||
|
||||
// encrypt with RSA
|
||||
msg->encryptRSA(128, Proto::RSA);
|
||||
msg->encryptRsa(128, g_lua.callGlobalField<std::string>("g_game", "getRsa"));
|
||||
|
||||
send(msg);
|
||||
|
||||
@@ -570,9 +571,10 @@ void ProtocolGame::sendShareExperience(bool active, int unknown)
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientShareExperience);
|
||||
msg->addU8(active ? 0x01 : 0x00);
|
||||
#if PROTOCOL<910
|
||||
msg->addU8(unknown);
|
||||
#endif
|
||||
|
||||
if(g_game.getProtocolVersion() < 910)
|
||||
msg->addU8(unknown);
|
||||
|
||||
send(msg);
|
||||
}
|
||||
|
||||
|
@@ -28,12 +28,6 @@
|
||||
#include "thingtypemanager.h"
|
||||
#include <framework/luaengine/luaobject.h>
|
||||
|
||||
struct Light
|
||||
{
|
||||
uint8 intensity;
|
||||
uint8 color;
|
||||
};
|
||||
|
||||
// @bindclass
|
||||
#pragma pack(push,1) // disable memory alignment
|
||||
class Thing : public LuaObject
|
||||
@@ -95,8 +89,7 @@ public:
|
||||
int getAnimationPhases() { return rawGetDatType()->getAnimationPhases(); }
|
||||
int getGroundSpeed() { return rawGetDatType()->getGroundSpeed(); }
|
||||
int getMaxTextLength() { return rawGetDatType()->getMaxTextLength(); }
|
||||
int getLightLevel() { return rawGetDatType()->getLightLevel(); }
|
||||
int getLightColor() { return rawGetDatType()->getLightColor(); }
|
||||
Light getLight() { return rawGetDatType()->getLight(); }
|
||||
int getMinimapColor() { return rawGetDatType()->getMinimapColor(); }
|
||||
int getLensHelp() { return rawGetDatType()->getLensHelp(); }
|
||||
int getClothSlot() { return rawGetDatType()->getClothSlot(); }
|
||||
@@ -110,9 +103,10 @@ public:
|
||||
bool isForceUse() { return rawGetDatType()->isForceUse(); }
|
||||
bool isMultiUse() { return rawGetDatType()->isMultiUse(); }
|
||||
bool isWritable() { return rawGetDatType()->isWritable(); }
|
||||
bool isChargeable() { return rawGetDatType()->isChargeable(); }
|
||||
bool isWritableOnce() { return rawGetDatType()->isWritableOnce(); }
|
||||
bool isFluidContainer() { return rawGetDatType()->isFluidContainer(); }
|
||||
bool isFluid() { return rawGetDatType()->isFluid(); }
|
||||
bool isSplash() { return rawGetDatType()->isSplash(); }
|
||||
bool isNotWalkable() { return rawGetDatType()->isNotWalkable(); }
|
||||
bool isNotMoveable() { return rawGetDatType()->isNotMoveable(); }
|
||||
bool blockProjectile() { return rawGetDatType()->blockProjectile(); }
|
||||
@@ -134,6 +128,7 @@ public:
|
||||
bool isFullGround() { return rawGetDatType()->isFullGround(); }
|
||||
bool isIgnoreLook() { return rawGetDatType()->isIgnoreLook(); }
|
||||
bool isCloth() { return rawGetDatType()->isCloth(); }
|
||||
MarketData getMarketData() { return rawGetDatType()->getMarketData(); }
|
||||
|
||||
protected:
|
||||
Position m_position;
|
||||
|
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "thingtypedat.h"
|
||||
#include "spritemanager.h"
|
||||
#include "game.h"
|
||||
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/texture.h>
|
||||
@@ -33,20 +34,11 @@ ThingTypeDat::ThingTypeDat()
|
||||
{
|
||||
m_category = DatInvalidCategory;
|
||||
m_id = 0;
|
||||
m_null = true;
|
||||
m_exactSize = 0;
|
||||
m_layers = 0;
|
||||
m_numPatternX = 0;
|
||||
m_numPatternY = 0;
|
||||
m_numPatternZ = 0;
|
||||
m_numPatternX = m_numPatternY = m_numPatternZ = 0;
|
||||
m_animationPhases = 0;
|
||||
m_groundSpeed = 0;
|
||||
m_maxTextLenght = 0;
|
||||
m_lightLevel = 0;
|
||||
m_lightColor = 0;
|
||||
m_miniMapColor = 0;
|
||||
m_lensHelp = 0;
|
||||
m_clothSlot = 0;
|
||||
m_elevation = 0;
|
||||
m_layers = 0;
|
||||
}
|
||||
|
||||
void ThingTypeDat::unserialize(uint16 clientId, DatCategory category, const FileStreamPtr& fin)
|
||||
@@ -55,136 +47,68 @@ void ThingTypeDat::unserialize(uint16 clientId, DatCategory category, const File
|
||||
m_id = clientId;
|
||||
m_category = category;
|
||||
|
||||
|
||||
static int datVersion;
|
||||
if(clientId == 100 && category == DatItemCategory)
|
||||
datVersion = 2;
|
||||
|
||||
bool done = false;
|
||||
for(int i = 0 ; i < DatLastAttrib;++i) {
|
||||
int property = fin->getU8();
|
||||
if(property == DatLastAttrib) {
|
||||
int attrib = fin->getU8();
|
||||
if(attrib == DatLastAttrib) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(property) {
|
||||
case DatAttribIsGround:
|
||||
m_isGround = true;
|
||||
m_groundSpeed = fin->getU16();
|
||||
if(m_groundSpeed == 0)
|
||||
m_groundSpeed = 100;
|
||||
// hacky way to detect if is older dat version or not
|
||||
if(clientId == 100 && category == DatItemCategory && datVersion != 1 &&
|
||||
(attrib == DatAttribNotPathable || attrib == DatAttribDontHide || attrib == DatAttribIgnoreLook)) {
|
||||
datVersion = 1;
|
||||
}
|
||||
if(datVersion <= 1) {
|
||||
if(attrib == DatAttribWritable) {
|
||||
m_attribs.set(DatAttribChargeable, true);
|
||||
continue;
|
||||
} else if(attrib > DatAttribWritable)
|
||||
attrib -= 1;
|
||||
}
|
||||
|
||||
switch(attrib) {
|
||||
case DatAttribDisplacement: {
|
||||
m_displacement.x = fin->getU16();
|
||||
m_displacement.y = fin->getU16();
|
||||
m_attribs.set(attrib, true);
|
||||
break;
|
||||
case DatAttribIsGroundBorder:
|
||||
m_isGroundBorder = true;
|
||||
}
|
||||
case DatAttribLight: {
|
||||
Light light;
|
||||
light.intensity = fin->getU16();
|
||||
light.color = fin->getU16();
|
||||
m_attribs.set(attrib, light);
|
||||
break;
|
||||
case DatAttribIsOnBottom:
|
||||
m_isOnBottom = true;
|
||||
break;
|
||||
case DatAttribIsOnTop:
|
||||
m_isOnTop = true;
|
||||
break;
|
||||
case DatAttribIsContainer:
|
||||
m_isContainer = true;
|
||||
break;
|
||||
case DatAttribIsStackable:
|
||||
m_isStackable = true;
|
||||
break;
|
||||
case DatAttribIsForceUse:
|
||||
m_isForceUse = true;
|
||||
break;
|
||||
case DatAttribIsMultiUse:
|
||||
m_isMultiUse = true;
|
||||
break;
|
||||
case DatAttribIsWritable:
|
||||
m_isWritable = true;
|
||||
m_maxTextLenght = fin->getU16();
|
||||
break;
|
||||
case DatAttribIsWritableOnce:
|
||||
m_isWritableOnce = true;
|
||||
m_maxTextLenght = fin->getU16();
|
||||
break;
|
||||
case DatAttribIsFluidContainer:
|
||||
m_isFluidContainer = true;
|
||||
break;
|
||||
case DatAttribIsFluid:
|
||||
m_isFluid = true;
|
||||
break;
|
||||
case DatAttribIsNotWalkable:
|
||||
m_isNotWalkable = true;
|
||||
break;
|
||||
case DatAttribIsNotMoveable:
|
||||
m_isNotMoveable = true;
|
||||
break;
|
||||
case DatAttribBlockProjectile:
|
||||
m_blockProjectile = true;
|
||||
break;
|
||||
case DatAttribIsNotPathable:
|
||||
m_isNotPathable = true;
|
||||
break;
|
||||
case DatAttribIsPickupable:
|
||||
m_isPickupable = true;
|
||||
break;
|
||||
case DatAttribIsHangable:
|
||||
m_isHangable = true;
|
||||
break;
|
||||
case DatAttribHookSouth:
|
||||
m_isHookSouth = true;
|
||||
break;
|
||||
case DatAttribHookEast:
|
||||
m_isHookEast = true;
|
||||
break;
|
||||
case DatAttribIsRotateable:
|
||||
m_isRotateable = true;
|
||||
break;
|
||||
case DatAttribHasLight:
|
||||
m_hasLight = true;
|
||||
m_lightLevel = fin->getU16();
|
||||
m_lightColor = fin->getU16();
|
||||
break;
|
||||
case DatAttribDontHide:
|
||||
m_isDontHide = true;
|
||||
break;
|
||||
case DatAttribIsTranslucent:
|
||||
m_isTranslucent = true;
|
||||
break;
|
||||
case DatAttribHasDisplacement:
|
||||
m_hasDisplacement = true;
|
||||
m_displacement = Point(fin->getU16(), fin->getU16());
|
||||
break;
|
||||
case DatAttribHasElevation:
|
||||
m_hasElevation = true;
|
||||
m_elevation = fin->getU16();
|
||||
break;
|
||||
case DatAttribIsLyingCorpse:
|
||||
m_isLyingCorpse = true;
|
||||
break;
|
||||
case DatAttribAnimateAlways:
|
||||
m_isAnimateAlways = true;
|
||||
}
|
||||
case DatAttribMarket: {
|
||||
MarketData market;
|
||||
market.category = fin->getU16();
|
||||
market.showAs = fin->getU16();
|
||||
market.tradeAs = fin->getU16();
|
||||
market.name = fin->getString();
|
||||
market.restrictProfession = fin->getU16();
|
||||
market.requiredLevel = fin->getU16();
|
||||
m_attribs.set(attrib, market);
|
||||
break;
|
||||
}
|
||||
case DatAttribGround:
|
||||
case DatAttribWritable:
|
||||
case DatAttribWritableOnce:
|
||||
case DatAttribElevation:
|
||||
case DatAttribMiniMapColor:
|
||||
m_miniMapColor = true;
|
||||
m_miniMapColor = fin->getU16();
|
||||
break;
|
||||
case DatAttribLensHelp:
|
||||
m_lensHelp = true;
|
||||
m_lensHelp = fin->getU16();
|
||||
break;
|
||||
case DatAttribIsFullGround:
|
||||
m_isFullGround = true;
|
||||
break;
|
||||
case DatAttribIgnoreLook:
|
||||
m_isIgnoreLook = true;
|
||||
break;
|
||||
case DatAttribCloth:
|
||||
m_isCloth = true;
|
||||
m_clothSlot = fin->getU16();
|
||||
break;
|
||||
case DatAttribMarket:
|
||||
fin->getU16(); // category
|
||||
fin->getU16(); // trade as
|
||||
fin->getU16(); // show as
|
||||
fin->getString(); // name
|
||||
fin->getU16(); // restrict profession
|
||||
fin->getU16(); // level
|
||||
case DatAttribLensHelp:
|
||||
m_attribs.set(attrib, fin->getU16());
|
||||
break;
|
||||
default:
|
||||
stdext::throw_exception("corrupt data, invalid type attribute");
|
||||
m_attribs.set(attrib, true);
|
||||
break;
|
||||
};
|
||||
}
|
||||
@@ -192,40 +116,18 @@ void ThingTypeDat::unserialize(uint16 clientId, DatCategory category, const File
|
||||
if(!done)
|
||||
stdext::throw_exception("corrupt data");
|
||||
|
||||
int totalSprites = 1;
|
||||
for(int i = 0; i < DatLastDimension; ++i) {
|
||||
switch(i) {
|
||||
case DatWidth:
|
||||
m_size.setWidth(fin->getU8());
|
||||
break;
|
||||
case DatHeight:
|
||||
m_size.setHeight(fin->getU8());
|
||||
break;
|
||||
case DatExactSize:
|
||||
if(m_size.width() <= 1 && m_size.height() <= 1)
|
||||
m_exactSize = 32;
|
||||
else
|
||||
m_exactSize = std::min((int)fin->getU8(), std::max(m_size.width() * 32, m_size.height() * 32));
|
||||
break;
|
||||
case DatLayers:
|
||||
m_layers = fin->getU8();
|
||||
break;
|
||||
case DatPatternX:
|
||||
m_numPatternX = fin->getU8();
|
||||
break;
|
||||
case DatPatternY:
|
||||
m_numPatternY = fin->getU8();
|
||||
break;
|
||||
case DatPatternZ:
|
||||
m_numPatternZ = fin->getU8();
|
||||
break;
|
||||
case DatAnimationPhases:
|
||||
m_animationPhases = fin->getU8();
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint8 width = fin->getU8();
|
||||
uint8 height = fin->getU8();
|
||||
m_size = Size(width, height);
|
||||
m_exactSize = (width > 1 || height > 1) ? std::min((int)fin->getU8(), std::max(width * 32, height * 32)) : 32;
|
||||
m_layers = fin->getU8();
|
||||
m_numPatternX = fin->getU8();
|
||||
m_numPatternY = fin->getU8();
|
||||
m_numPatternZ = fin->getU8();
|
||||
m_animationPhases = fin->getU8();
|
||||
|
||||
int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;
|
||||
|
||||
totalSprites = m_size.width() * m_size.height() * 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)
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include <framework/graphics/coordsbuffer.h>
|
||||
#include <framework/luaengine/luaobject.h>
|
||||
#include <framework/net/server.h>
|
||||
#include <framework/util/attribstorage.h>
|
||||
|
||||
enum DatCategory {
|
||||
DatItemCategory = 0,
|
||||
@@ -48,53 +49,59 @@ enum DatSpriteMask {
|
||||
};
|
||||
|
||||
enum DatAttrib {
|
||||
DatAttribIsGround = 0,
|
||||
DatAttribIsGroundBorder,
|
||||
DatAttribIsOnBottom,
|
||||
DatAttribIsOnTop,
|
||||
DatAttribIsContainer,
|
||||
DatAttribIsStackable,
|
||||
DatAttribIsForceUse,
|
||||
DatAttribIsMultiUse,
|
||||
DatAttribIsWritable,
|
||||
DatAttribIsWritableOnce,
|
||||
DatAttribIsFluidContainer,
|
||||
DatAttribIsFluid,
|
||||
DatAttribIsNotWalkable,
|
||||
DatAttribIsNotMoveable,
|
||||
DatAttribGround = 0,
|
||||
DatAttribGroundBorder,
|
||||
DatAttribOnBottom,
|
||||
DatAttribOnTop,
|
||||
DatAttribContainer,
|
||||
DatAttribStackable,
|
||||
DatAttribForceUse,
|
||||
DatAttribMultiUse,
|
||||
//DatAttribRune
|
||||
DatAttribWritable,
|
||||
DatAttribWritableOnce,
|
||||
DatAttribFluidContainer,
|
||||
DatAttribSplash,
|
||||
DatAttribNotWalkable,
|
||||
DatAttribNotMoveable,
|
||||
DatAttribBlockProjectile,
|
||||
DatAttribIsNotPathable,
|
||||
DatAttribIsPickupable,
|
||||
DatAttribIsHangable,
|
||||
DatAttribNotPathable,
|
||||
DatAttribPickupable,
|
||||
DatAttribHangable,
|
||||
DatAttribHookSouth,
|
||||
DatAttribHookEast,
|
||||
DatAttribIsRotateable,
|
||||
DatAttribHasLight,
|
||||
DatAttribRotateable,
|
||||
DatAttribLight,
|
||||
DatAttribDontHide,
|
||||
DatAttribIsTranslucent,
|
||||
DatAttribHasDisplacement,
|
||||
DatAttribHasElevation,
|
||||
DatAttribIsLyingCorpse,
|
||||
DatAttribTranslucent,
|
||||
DatAttribDisplacement,
|
||||
DatAttribElevation,
|
||||
DatAttribLyingCorpse,
|
||||
DatAttribAnimateAlways,
|
||||
DatAttribMiniMapColor,
|
||||
DatAttribLensHelp,
|
||||
DatAttribIsFullGround,
|
||||
DatAttribFullGround,
|
||||
DatAttribIgnoreLook,
|
||||
DatAttribCloth,
|
||||
DatAttribMarket,
|
||||
DatLastAttrib = 255
|
||||
DatLastAttrib = 255,
|
||||
|
||||
// legacy attribs
|
||||
DatAttribChargeable = 254
|
||||
};
|
||||
|
||||
enum DatDimension {
|
||||
DatWidth = 0,
|
||||
DatHeight,
|
||||
DatExactSize,
|
||||
DatLayers,
|
||||
DatPatternX,
|
||||
DatPatternY,
|
||||
DatPatternZ,
|
||||
DatAnimationPhases,
|
||||
DatLastDimension
|
||||
struct MarketData {
|
||||
std::string name;
|
||||
int category;
|
||||
uint16 requiredLevel;
|
||||
uint16 restrictProfession;
|
||||
uint16 showAs;
|
||||
uint16 tradeAs;
|
||||
};
|
||||
|
||||
struct Light {
|
||||
uint8 intensity;
|
||||
uint8 color;
|
||||
};
|
||||
|
||||
class ThingTypeDat : public LuaObject
|
||||
@@ -113,56 +120,58 @@ public:
|
||||
Size getSize() { return m_size; }
|
||||
int getWidth() { return m_size.width(); }
|
||||
int getHeight() { return m_size.height(); }
|
||||
Point getDisplacement() { return m_displacement; }
|
||||
int getDisplacementX() { return m_displacement.x; }
|
||||
int getDisplacementY() { return m_displacement.y; }
|
||||
int getExactSize() { return m_exactSize; }
|
||||
int getLayers() { return m_layers; }
|
||||
int getNumPatternX() { return m_numPatternX; }
|
||||
int getNumPatternY() { return m_numPatternY; }
|
||||
int getNumPatternZ() { return m_numPatternZ; }
|
||||
int getAnimationPhases() { return m_animationPhases; }
|
||||
int getGroundSpeed() { return m_groundSpeed; }
|
||||
int getMaxTextLength() { return m_maxTextLenght; }
|
||||
int getLightLevel() { return m_lightLevel; }
|
||||
int getLightColor() { return m_lightColor; }
|
||||
int getMinimapColor() { return m_miniMapColor; }
|
||||
int getLensHelp() { return m_lensHelp; }
|
||||
int getClothSlot() { return m_clothSlot; }
|
||||
int getElevation() { return m_elevation; }
|
||||
bool isGround() { return m_isGround; }
|
||||
bool isGroundBorder() { return m_isGroundBorder; }
|
||||
bool isOnBottom() { return m_isOnBottom; }
|
||||
bool isOnTop() { return m_isOnTop; }
|
||||
bool isContainer() { return m_isContainer; }
|
||||
bool isStackable() { return m_isStackable; }
|
||||
bool isForceUse() { return m_isForceUse; }
|
||||
bool isMultiUse() { return m_isMultiUse; }
|
||||
bool isWritable() { return m_isWritable; }
|
||||
bool isWritableOnce() { return m_isWritableOnce; }
|
||||
bool isFluidContainer() { return m_isFluidContainer; }
|
||||
bool isFluid() { return m_isFluid; }
|
||||
bool isNotWalkable() { return m_isNotWalkable; }
|
||||
bool isNotMoveable() { return m_isNotMoveable; }
|
||||
bool blockProjectile() { return m_blockProjectile; }
|
||||
bool isNotPathable() { return m_isNotPathable; }
|
||||
bool isPickupable() { return m_isPickupable; }
|
||||
bool isHangable() { return m_isHangable; }
|
||||
bool isHookSouth() { return m_isHookSouth; }
|
||||
bool isHookEast() { return m_isHookEast; }
|
||||
bool isRotateable() { return m_isRotateable; }
|
||||
bool hasLight() { return m_hasLight; }
|
||||
bool isDontHide() { return m_isDontHide; }
|
||||
bool isTranslucent() { return m_isTranslucent; }
|
||||
bool hasDisplacement() { return m_hasDisplacement; }
|
||||
bool hasElevation() { return m_hasElevation; }
|
||||
bool isLyingCorpse() { return m_isLyingCorpse; }
|
||||
bool isAnimateAlways() { return m_isAnimateAlways; }
|
||||
bool hasMiniMapColor() { return m_hasMiniMapColor; }
|
||||
bool hasLensHelp() { return m_hasLensHelp; }
|
||||
bool isFullGround() { return m_isFullGround; }
|
||||
bool isIgnoreLook() { return m_isIgnoreLook; }
|
||||
bool isCloth() { return m_isCloth; }
|
||||
Point getDisplacement() { return m_displacement; }
|
||||
int getDisplacementX() { return getDisplacement().x; }
|
||||
int getDisplacementY() { return getDisplacement().y; }
|
||||
|
||||
int getGroundSpeed() { return m_attribs.get<uint16>(DatAttribGround); }
|
||||
int getMaxTextLength() { return m_attribs.has(DatAttribWritableOnce) ? m_attribs.get<uint16>(DatAttribWritableOnce) : m_attribs.get<uint16>(DatAttribWritable); }
|
||||
Light getLight() { return m_attribs.get<Light>(DatAttribLight); }
|
||||
int getMinimapColor() { return m_attribs.get<uint16>(DatAttribMiniMapColor); }
|
||||
int getLensHelp() { return m_attribs.get<uint16>(DatAttribLensHelp); }
|
||||
int getClothSlot() { return m_attribs.get<uint16>(DatAttribCloth); }
|
||||
int getElevation() { return m_attribs.get<uint16>(DatAttribElevation); }
|
||||
MarketData getMarketData() { return m_attribs.get<MarketData>(DatAttribMarket); }
|
||||
bool isGround() { return m_attribs.has(DatAttribGround); }
|
||||
bool isGroundBorder() { return m_attribs.has(DatAttribGroundBorder); }
|
||||
bool isOnBottom() { return m_attribs.has(DatAttribOnBottom); }
|
||||
bool isOnTop() { return m_attribs.has(DatAttribOnTop); }
|
||||
bool isContainer() { return m_attribs.has(DatAttribContainer); }
|
||||
bool isStackable() { return m_attribs.has(DatAttribStackable); }
|
||||
bool isForceUse() { return m_attribs.has(DatAttribForceUse); }
|
||||
bool isMultiUse() { return m_attribs.has(DatAttribMultiUse); }
|
||||
bool isWritable() { return m_attribs.has(DatAttribWritable); }
|
||||
bool isChargeable() { return m_attribs.has(DatAttribChargeable); }
|
||||
bool isWritableOnce() { return m_attribs.has(DatAttribWritableOnce); }
|
||||
bool isFluidContainer() { return m_attribs.has(DatAttribFluidContainer); }
|
||||
bool isSplash() { return m_attribs.has(DatAttribSplash); }
|
||||
bool isNotWalkable() { return m_attribs.has(DatAttribNotWalkable); }
|
||||
bool isNotMoveable() { return m_attribs.has(DatAttribNotMoveable); }
|
||||
bool blockProjectile() { return m_attribs.has(DatAttribBlockProjectile); }
|
||||
bool isNotPathable() { return m_attribs.has(DatAttribNotPathable); }
|
||||
bool isPickupable() { return m_attribs.has(DatAttribPickupable); }
|
||||
bool isHangable() { return m_attribs.has(DatAttribHangable); }
|
||||
bool isHookSouth() { return m_attribs.has(DatAttribHookSouth); }
|
||||
bool isHookEast() { return m_attribs.has(DatAttribHookEast); }
|
||||
bool isRotateable() { return m_attribs.has(DatAttribRotateable); }
|
||||
bool hasLight() { return m_attribs.has(DatAttribLight); }
|
||||
bool isDontHide() { return m_attribs.has(DatAttribDontHide); }
|
||||
bool isTranslucent() { return m_attribs.has(DatAttribTranslucent); }
|
||||
bool hasDisplacement() { return m_attribs.has(DatAttribDisplacement); }
|
||||
bool hasElevation() { return m_attribs.has(DatAttribElevation); }
|
||||
bool isLyingCorpse() { return m_attribs.has(DatAttribLyingCorpse); }
|
||||
bool isAnimateAlways() { return m_attribs.has(DatAttribAnimateAlways); }
|
||||
bool hasMiniMapColor() { return m_attribs.has(DatAttribMiniMapColor); }
|
||||
bool hasLensHelp() { return m_attribs.has(DatAttribLensHelp); }
|
||||
bool isFullGround() { return m_attribs.has(DatAttribFullGround); }
|
||||
bool isIgnoreLook() { return m_attribs.has(DatAttribIgnoreLook); }
|
||||
bool isCloth() { return m_attribs.has(DatAttribCloth); }
|
||||
|
||||
private:
|
||||
const TexturePtr& getTexture(int animationPhase);
|
||||
@@ -172,64 +181,21 @@ private:
|
||||
|
||||
DatCategory m_category;
|
||||
uint16 m_id;
|
||||
Boolean<true> m_null;
|
||||
bool m_null;
|
||||
AttribStorage m_attribs;
|
||||
|
||||
Size m_size;
|
||||
Point m_displacement;
|
||||
int m_exactSize;
|
||||
int m_numPatternX, m_numPatternY, m_numPatternZ;
|
||||
int m_animationPhases;
|
||||
int m_layers;
|
||||
|
||||
std::vector<int> m_spritesIndex;
|
||||
std::vector<TexturePtr> m_textures;
|
||||
std::vector<std::vector<Rect>> m_texturesFramesRects;
|
||||
std::vector<std::vector<Rect>> m_texturesFramesOriginRects;
|
||||
std::vector<std::vector<Point>> m_texturesFramesOffsets;
|
||||
|
||||
// dat stuff
|
||||
Size m_size;
|
||||
Point m_displacement;
|
||||
int m_exactSize;
|
||||
int m_layers;
|
||||
int m_numPatternX;
|
||||
int m_numPatternY;
|
||||
int m_numPatternZ;
|
||||
int m_animationPhases;
|
||||
int m_groundSpeed;
|
||||
int m_maxTextLenght;
|
||||
int m_lightLevel;
|
||||
int m_lightColor;
|
||||
int m_miniMapColor;
|
||||
int m_lensHelp;
|
||||
int m_clothSlot;
|
||||
int m_elevation;
|
||||
Boolean<false> m_isGround;
|
||||
Boolean<false> m_isGroundBorder;
|
||||
Boolean<false> m_isOnBottom;
|
||||
Boolean<false> m_isOnTop;
|
||||
Boolean<false> m_isContainer;
|
||||
Boolean<false> m_isStackable;
|
||||
Boolean<false> m_isForceUse;
|
||||
Boolean<false> m_isMultiUse;
|
||||
Boolean<false> m_isWritable;
|
||||
Boolean<false> m_isWritableOnce;
|
||||
Boolean<false> m_isFluidContainer;
|
||||
Boolean<false> m_isFluid;
|
||||
Boolean<false> m_isNotWalkable;
|
||||
Boolean<false> m_isNotMoveable;
|
||||
Boolean<false> m_blockProjectile;
|
||||
Boolean<false> m_isNotPathable;
|
||||
Boolean<false> m_isPickupable;
|
||||
Boolean<false> m_isHangable;
|
||||
Boolean<false> m_isHookSouth;
|
||||
Boolean<false> m_isHookEast;
|
||||
Boolean<false> m_isRotateable;
|
||||
Boolean<false> m_hasLight;
|
||||
Boolean<false> m_isDontHide;
|
||||
Boolean<false> m_isTranslucent;
|
||||
Boolean<false> m_hasDisplacement;
|
||||
Boolean<false> m_hasElevation;
|
||||
Boolean<false> m_isLyingCorpse;
|
||||
Boolean<false> m_isAnimateAlways;
|
||||
Boolean<false> m_hasMiniMapColor;
|
||||
Boolean<false> m_hasLensHelp;
|
||||
Boolean<false> m_isFullGround;
|
||||
Boolean<false> m_isIgnoreLook;
|
||||
Boolean<false> m_isCloth;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -367,7 +367,7 @@ ThingPtr Tile::getTopMultiUseThing()
|
||||
for(uint i = 0; i < m_things.size(); ++i) {
|
||||
ThingPtr thing = m_things[i];
|
||||
if(thing->isForceUse() || (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop())) {
|
||||
if(i > 0 && thing->isFluid())
|
||||
if(i > 0 && thing->isSplash())
|
||||
return m_things[i-1];
|
||||
return thing;
|
||||
}
|
||||
|
@@ -58,7 +58,7 @@ void UIItem::drawSelf(Fw::DrawPane drawPane)
|
||||
g_painter->setColor(Color::white);
|
||||
m_item->draw(dest, scaleFactor, true);
|
||||
|
||||
if(m_font && m_item->isStackable() && m_item->getCount() > 1) {
|
||||
if(m_font && (m_item->isStackable() || m_item->isChargeable()) && m_item->getCount() > 1) {
|
||||
std::string count = stdext::to_string(m_item->getCount());
|
||||
g_painter->setColor(Color(231, 231, 231));
|
||||
m_font->drawText(count, Rect(m_rect.topLeft(), m_rect.bottomRight() - Point(3, 0)), Fw::AlignBottomRight);
|
||||
|
Reference in New Issue
Block a user