diff --git a/CMakeLists.txt b/CMakeLists.txt index 5db31f5b..2f41c782 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,7 @@ SET(SOURCES src/otclient/core/thing.cpp src/otclient/core/creature.cpp src/otclient/core/effect.cpp + src/otclient/core/localplayer.cpp # otclient net src/otclient/net/protocollogin.cpp diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp index 589386d1..0f284e8f 100644 --- a/src/framework/graphics/graphics.cpp +++ b/src/framework/graphics/graphics.cpp @@ -121,7 +121,6 @@ void Graphics::drawTexturedRect(const Rect& screenCoords, int bottom = screenCoords.bottom() + 1; int top = screenCoords.top(); int left = screenCoords.left(); - const Size& textureSize = texture->getGlSize(); float textureRight; float textureBottom; @@ -134,6 +133,7 @@ void Graphics::drawTexturedRect(const Rect& screenCoords, textureTop = 0.0f; textureLeft = 0.0f; } else { + const Size& textureSize = texture->getGlSize(); textureRight = (float)(textureCoords.right() + 1) / textureSize.width(); textureBottom = (float)(textureCoords.bottom() + 1) / textureSize.height(); textureTop = (float)textureCoords.top() / textureSize.height(); @@ -152,7 +152,6 @@ void Graphics::drawTexturedRect(const Rect& screenCoords, if(!m_drawing) glEnd(); - } void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords, diff --git a/src/otclient/core/const.h b/src/otclient/core/const.h index a72494db..e51eed38 100644 --- a/src/otclient/core/const.h +++ b/src/otclient/core/const.h @@ -19,4 +19,11 @@ enum ThingAttributesGroup { THING_GROUP_LAST }; +enum ThingType { + THING_ITEM, + THING_CREATURE, + THING_EFFECT, + THING_SHOT +}; + #endif diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index b7a2a6e3..2c3c3405 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -8,27 +8,10 @@ #include #include - - - - - -// OW BART TEM COMO USAR 2 FRAMEBUFFER? -// SERIA O IDEAL PARA DESENHAR A COR DOS BONEQUIN. - - - - - - -Creature::Creature() +Creature::Creature() : Thing(THING_CREATURE) { - m_type = Thing::TYPE_CREATURE; -} - -const ThingAttributes& Creature::getAttributes() -{ - return g_dat.getCreatureAttributes(m_outfit.type); + m_healthPercent = 0; + m_direction = DIRECTION_SOUTH; } void Creature::draw(int x, int y) @@ -62,3 +45,8 @@ void Creature::draw(int x, int y) //} //glPopAttrib(); } + +const ThingAttributes& Creature::getAttributes() +{ + return g_dat.getCreatureAttributes(m_outfit.type); +} diff --git a/src/otclient/core/creature.h b/src/otclient/core/creature.h index 499bff7b..d7b1afe1 100644 --- a/src/otclient/core/creature.h +++ b/src/otclient/core/creature.h @@ -3,8 +3,7 @@ #include "thing.h" -struct Outfit -{ +struct Outfit { uint16 type; uint8 head; uint8 body; @@ -17,31 +16,28 @@ class Creature : public Thing { public: Creature(); + virtual ~Creature() { } - virtual const ThingAttributes& getAttributes(); - void draw(int x, int y); + virtual void draw(int x, int y); void setName(const std::string& name) { m_name = name; } - std::string getName() { return m_name; } - void setHealthPercent(uint8 healthPercent) { m_healthPercent = healthPercent; } - uint8 getHealthPercent() { return m_healthPercent; } - void setDirection(Direction direction) { m_direction = direction; } + void setOutfit(const Outfit& outfit) { m_outfit = outfit; } Direction getDirection() { return m_direction; } - void setOutfit(const Outfit& outfit) { m_outfit = outfit; } Outfit getOutfit() { return m_outfit; } + std::string getName() { return m_name; } + uint8 getHealthPercent() { return m_healthPercent; } + const ThingAttributes& getAttributes(); - virtual Creature *getCreature() { return this; } - virtual const Creature *getCreature() const { return this; } + CreaturePtr asCreature() { return std::static_pointer_cast(shared_from_this()); } private: std::string m_name; uint8 m_healthPercent; Direction m_direction; Outfit m_outfit; - }; -#endif // CREATURE_H +#endif diff --git a/src/otclient/core/datmanager.cpp b/src/otclient/core/datmanager.cpp new file mode 100644 index 00000000..16386967 --- /dev/null +++ b/src/otclient/core/datmanager.cpp @@ -0,0 +1,209 @@ +#include "datmanager.h" +#include "spritemanager.h" +#include + +DatManager g_dat; + +bool DatManager::load(const std::string& filename) +{ + try { + std::stringstream fin; + g_resources.loadFile(filename, fin); + + m_signature = fw::getu32(fin); + int numItems = fw::getu16(fin); + int numCreatures = fw::getu16(fin); + int numEffects = fw::getu16(fin); + int numShots = fw::getu16(fin); + + m_itemsAttributes.resize(numItems); + for(int id = 100; id <= numItems; ++id) + parseThingAttributes(fin, m_itemsAttributes[id - 100]); + + m_creaturesAttributes.resize(numItems); + for(int id = 1; id < numCreatures; ++id) + parseThingAttributes(fin, m_creaturesAttributes[id - 1]); + + m_effectsAttributes.resize(numItems); + for(int id = 100; id < numEffects; ++id) + parseThingAttributes(fin, m_effectsAttributes[id - 100]); + + m_shotsAttributes.resize(numItems); + for(int id = 1; id < numShots; ++id) + parseThingAttributes(fin, m_shotsAttributes[id - 1]); + + return true; + } catch(std::exception& e) { + logError(e.what()); + return false; + } +} + +void DatManager::unload() +{ + m_itemsAttributes.clear(); + m_creaturesAttributes.clear(); + m_effectsAttributes.clear(); + m_shotsAttributes.clear(); +} + +void DatManager::parseThingAttributes(std::stringstream& fin, ThingAttributes& thingAttributes) +{ + assert(fin.good()); + + while(true) { + uint8 opt; + fin.read((char*)&opt, 1); + + if(opt == 0xFF) + break; + + parseThingAttributesOpt(fin, thingAttributes, opt); + } + + thingAttributes.width = fw::getu8(fin); + thingAttributes.height = fw::getu8(fin); + if(thingAttributes.width > 1 || thingAttributes.height > 1) + fw::getu8(fin); // ?? + + thingAttributes.blendframes = fw::getu8(fin); + thingAttributes.xdiv = fw::getu8(fin); + thingAttributes.ydiv = fw::getu8(fin); + thingAttributes.zdiv = fw::getu8(fin); + thingAttributes.animcount = fw::getu8(fin); + + int totalSprites = thingAttributes.width + * thingAttributes.height + * thingAttributes.blendframes + * thingAttributes.xdiv + * thingAttributes.ydiv + * thingAttributes.zdiv + * thingAttributes.animcount; + + thingAttributes.sprites.resize(totalSprites); + for(uint16 i = 0; i < totalSprites; i++) + thingAttributes.sprites[i] = fw::getu16(fin); +} + +void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes& thingAttributes, uint8 opt) +{ + uint8 read_byte; + uint16 read_short; + switch(opt) { + case 0x00: // Ground tile + fin.read((char*)&thingAttributes.speed, 2); + thingAttributes.group = THING_GROUP_GROUND; + break; + case 0x01: // All OnTop + thingAttributes.alwaysOnTop = true; + thingAttributes.alwaysOnTopOrder = 1; + break; + case 0x02: // Can walk trough (open doors, arces, bug pen fence) + thingAttributes.alwaysOnTop = true; + thingAttributes.alwaysOnTopOrder = 2; + break; + case 0x03: // Can walk trough (arces) + thingAttributes.alwaysOnTop = true; + thingAttributes.alwaysOnTopOrder = 3; + break; + case 0x04: // Container + thingAttributes.group = THING_GROUP_CONTAINER; + break; + case 0x05: // Stackable + thingAttributes.stackable = true; + break; + case 0x06: // Unknown + break; + case 0x07: // Useable + thingAttributes.useable = true; + break; + case 0x08: // Writtable + thingAttributes.group = THING_GROUP_WRITEABLE; + thingAttributes.readable = true; + fin.read((char*)&thingAttributes.subParam07, 2); + break; + case 0x09: // Writtable once + // Writtable objects that can't be edited by players + thingAttributes.readable = true; + fin.read((char*)&thingAttributes.subParam08, 2); + break; + case 0x0A: // Fluid containers + fin.read((char*)&read_byte, 1); + thingAttributes.group = THING_GROUP_FLUID; + break; + case 0x0B: // Splashes + thingAttributes.group = THING_GROUP_SPLASH; + break; + case 0x0C: // Blocks solid objects (creatures, walls etc) + thingAttributes.blockSolid = true; + break; + case 0x0D: // Not moveable + thingAttributes.moveable = false; + break; + case 0x0E: // Blocks missiles (walls, magic wall etc) + thingAttributes.blockProjectile = true; + break; + case 0x0F: // Blocks pathfind algorithms (monsters) + thingAttributes.blockPathFind = true; + break; + case 0x10: // Blocks monster movement (flowers, parcels etc) + thingAttributes.pickupable = true; + break; + case 0x11: // Hangable objects (wallpaper etc) + thingAttributes.isHangable = true; + break; + case 0x12: // Horizontal wall + thingAttributes.isHorizontal = true; + break; + case 0x13: // Vertical wall + thingAttributes.isVertical = true; + break; + case 0x14: // Rotable + thingAttributes.rotable = true; + break; + case 0x15: // Light info + fin.read((char*)&thingAttributes.lightLevel, 2); + fin.read((char*)&thingAttributes.lightColor, 2); + break; + case 0x16: + break; + case 0x17: // Changes floor + break; + case 0x18: // Thing must be drawed with offset + thingAttributes.hasHeight = true; + fin.read((char*)&thingAttributes.xOffset, 1); + fin.read((char*)&thingAttributes.yOffset, 1); + + fin.read((char*)&read_short, 2); + break; + case 0x19: // pixels characters height + + fin.read((char*)&thingAttributes.xOffset, 1); + fin.read((char*)&thingAttributes.yOffset, 1); + //logDebug((int)thingAttributes.xOffset, " ", (int)thingAttributes.yOffset); + break; + case 0x1A: + //thingAttributes.hasHeight = true; + break; + case 0x1B: + break; + case 0x1C: // Minimap color + fin.read((char*)&thingAttributes.miniMapColor, 2); + thingAttributes.hasMiniMapColor = true; + break; + case 0x1D: // Unknown + fin.read((char*)&read_short, 2); + if(read_short == 1112) + thingAttributes.readable = true; + break; + case 0x1E: + break; + case 0x1F: + thingAttributes.lookThrough = true; + break; + case 0x20: + break; + default: + throw std::logic_error(fw::mkstr("ERROR: unknown .dat byte code: 0x", std::hex, (int)opt)); + } +} diff --git a/src/otclient/core/datmanager.h b/src/otclient/core/datmanager.h new file mode 100644 index 00000000..89f60301 --- /dev/null +++ b/src/otclient/core/datmanager.h @@ -0,0 +1,34 @@ +#ifndef DATMANAGER_H +#define DATMANAGER_H + +#include +#include "thing.h" + +class DatManager +{ +public: + bool load(const std::string& filename); + void unload(); + + void parseThingAttributes(std::stringstream& fin, ThingAttributes& thingAttributes); + void parseThingAttributesOpt(std::stringstream& fin, ThingAttributes& thingAttributes, uint8 opt); + + const ThingAttributes& getItemAttributes(uint16 id) { return m_itemsAttributes[id - 100]; } + const ThingAttributes& getCreatureAttributes(uint16 id) { return m_creaturesAttributes[id - 1]; } + const ThingAttributes& getEffectAttributes(uint16 id) { return m_effectsAttributes[id - 100]; } + const ThingAttributes& getShotAttributes(uint16 id) { return m_shotsAttributes[id - 1]; } + + uint32 getSignature() { return m_signature; } + +private: + uint32 m_signature; + + std::vector m_itemsAttributes; + std::vector m_creaturesAttributes; + std::vector m_effectsAttributes; + std::vector m_shotsAttributes; +}; + +extern DatManager g_dat; + +#endif diff --git a/src/otclient/core/declarations.h b/src/otclient/core/declarations.h index 6a1c6878..3b227c5f 100644 --- a/src/otclient/core/declarations.h +++ b/src/otclient/core/declarations.h @@ -4,18 +4,20 @@ #include #include "const.h" +class Tile; class Thing; class Item; -class Tile; class Creature; -class Player; class Effect; +class Player; +class LocalPlayer; +typedef std::shared_ptr TilePtr; typedef std::shared_ptr ThingPtr; typedef std::shared_ptr ItemPtr; -typedef std::shared_ptr TilePtr; typedef std::shared_ptr CreaturePtr; -typedef std::shared_ptr PlayerPtr; typedef std::shared_ptr EffectPtr; +typedef std::shared_ptr PlayerPtr; +typedef std::shared_ptr LocalPlayerPtr; #endif diff --git a/src/otclient/core/effect.cpp b/src/otclient/core/effect.cpp index b12848a5..6ce97939 100644 --- a/src/otclient/core/effect.cpp +++ b/src/otclient/core/effect.cpp @@ -1,14 +1,8 @@ #include "effect.h" #include "datmanager.h" -Effect::Effect() +Effect::Effect() : Thing(THING_EFFECT) { - m_type = Thing::TYPE_EFFECT; -} - -const ThingAttributes& Effect::getAttributes() -{ - return g_dat.getEffectAttributes(m_id); } void Effect::draw(int x, int y) @@ -16,3 +10,8 @@ void Effect::draw(int x, int y) int anim = 0; internalDraw(x, y, 0, 0, 0, 0, anim); } + +const ThingAttributes& Effect::getAttributes() +{ + return g_dat.getEffectAttributes(m_id); +} diff --git a/src/otclient/core/effect.h b/src/otclient/core/effect.h index 1559b796..4b2a6fbb 100644 --- a/src/otclient/core/effect.h +++ b/src/otclient/core/effect.h @@ -4,16 +4,16 @@ #include #include "thing.h" - class Effect : public Thing { public: Effect(); - virtual const ThingAttributes& getAttributes(); void draw(int x, int y); -private: + const ThingAttributes& getAttributes(); + + virtual EffectPtr asEffect() { return std::static_pointer_cast(shared_from_this()); } }; -#endif // EFFECT_H +#endif diff --git a/src/otclient/core/game.cpp b/src/otclient/core/game.cpp index d3968153..21c1245b 100644 --- a/src/otclient/core/game.cpp +++ b/src/otclient/core/game.cpp @@ -1,4 +1,5 @@ #include "game.h" +#include "localplayer.h" Game g_game; @@ -6,3 +7,15 @@ Game::Game() { m_online = false; } + +void Game::onLogin() +{ + m_localPlayer = LocalPlayerPtr(new LocalPlayer); + m_online = true; +} + +void Game::onLogout() +{ + m_localPlayer.reset(); + m_online = false; +} diff --git a/src/otclient/core/game.h b/src/otclient/core/game.h index 527ef3c9..ffec50fe 100644 --- a/src/otclient/core/game.h +++ b/src/otclient/core/game.h @@ -1,33 +1,30 @@ #ifndef GAME_H #define GAME_H -#include -#include "map.h" -#include "player.h" -#include +#include "declarations.h" +#include class Game { public: Game(); + void onLogin(); + void onLogout(); + void setProtocol(ProtocolGamePtr protocolGame) { m_protocolGame = protocolGame; } - ProtocolGamePtr getProtocol() { return m_protocolGame; } - Map *getMap() { return &m_map; } - Player *getPlayer() { return &m_player; } + bool isOnline() { return m_online; } - void setOnline(bool online) { m_online = online; } - bool getOnline() { return m_online; } + ProtocolGamePtr getProtocol() { return m_protocolGame; } + LocalPlayerPtr getLocalPlayer() { return m_localPlayer; } private: - Map m_map; - Player m_player; + LocalPlayerPtr m_localPlayer; ProtocolGamePtr m_protocolGame; bool m_online; - }; extern Game g_game; -#endif // GAME_H +#endif diff --git a/src/otclient/core/item.cpp b/src/otclient/core/item.cpp index e0775f87..09c651b9 100644 --- a/src/otclient/core/item.cpp +++ b/src/otclient/core/item.cpp @@ -4,19 +4,14 @@ #include #include "thing.h" -Item::Item() +Item::Item() : Thing(THING_ITEM) { - m_type = Thing::TYPE_ITEM; -} - -const ThingAttributes& Item::getAttributes() -{ - return g_dat.getItemAttributes(m_id); + m_count = 0; } void Item::draw(int x, int y) { - auto attributes = g_dat.getItemAttributes(m_id); + const ThingAttributes& attributes = g_dat.getItemAttributes(m_id); int xdiv = 0, ydiv = 0, zdiv = 0, anim = 0; @@ -33,3 +28,8 @@ void Item::draw(int x, int y) for(int b = 0; b < attributes.blendframes; b++) internalDraw(x, y, b, xdiv, ydiv, zdiv, anim); } + +const ThingAttributes& Item::getAttributes() +{ + return g_dat.getItemAttributes(m_id); +} diff --git a/src/otclient/core/item.h b/src/otclient/core/item.h index fb90c7ea..70609925 100644 --- a/src/otclient/core/item.h +++ b/src/otclient/core/item.h @@ -9,16 +9,17 @@ class Item : public Thing public: Item(); - virtual const ThingAttributes& getAttributes(); void draw(int x, int y); void setCount(uint8 count) { m_count = count; } - virtual Item* getItem() { return this; } - virtual const Item* getItem() const { return this; } + int getCount() { return m_count; } + const ThingAttributes& getAttributes(); + + ItemPtr asItem() { return std::static_pointer_cast(shared_from_this()); } private: uint8 m_count; }; -#endif // ITEM_H +#endif diff --git a/src/otclient/core/localplayer.cpp b/src/otclient/core/localplayer.cpp new file mode 100644 index 00000000..4924438f --- /dev/null +++ b/src/otclient/core/localplayer.cpp @@ -0,0 +1,2 @@ +#include "localplayer.h" + diff --git a/src/otclient/core/localplayer.h b/src/otclient/core/localplayer.h new file mode 100644 index 00000000..ba63acd7 --- /dev/null +++ b/src/otclient/core/localplayer.h @@ -0,0 +1,24 @@ +#ifndef LOCALPLAYER_H +#define LOCALPLAYER_H + +#include "player.h" + +class LocalPlayer : public Player +{ +public: + LocalPlayer() { } + + void setDrawSpeed(uint16 drawSpeed) { m_drawSpeed = drawSpeed; } + uint16 getDrawSpeed() { return m_drawSpeed; } + + void setCanReportBugs(uint8 canReportBugs) { m_canReportBugs = (canReportBugs != 0); } + bool getCanReportBugs() { return m_canReportBugs; } + + LocalPlayerPtr asLocalPlayer() { return std::static_pointer_cast(shared_from_this()); } + +private: + uint16 m_drawSpeed; + bool m_canReportBugs; +}; + +#endif diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 818224ea..a2cde7fa 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -1,8 +1,11 @@ #include "map.h" #include "game.h" +#include "localplayer.h" #include #include +Map g_map; + void Map::draw(int x, int y) { if(!m_framebuffer) @@ -11,17 +14,17 @@ void Map::draw(int x, int y) g_graphics.bindColor(Color::white); m_framebuffer->bind(); - Position *playerPos = g_game.getPlayer()->getPosition(); + Position playerPos = g_game.getLocalPlayer()->getPosition(); // player is above 7 - if(playerPos->z <= 7) { + if(playerPos.z <= 7) { // player pos it 8-6. check if we can draw upper floors. bool draw = true; for(int jz = 6; jz >= 0; --jz) { - Position coverPos = Position(playerPos->x-(6-jz), playerPos->y-(6-jz), jz); + Position coverPos = Position(playerPos.x-(6-jz), playerPos.y-(6-jz), jz); if(m_tiles[coverPos]) { - if(m_tiles[coverPos]->getStackSize() > 0 && jz < playerPos->z) { + if(m_tiles[coverPos]->getStackSize() > 0 && jz < playerPos.z) { draw = false; } } @@ -32,8 +35,8 @@ void Map::draw(int x, int y) // +1 in draws cause 64x64 items may affect view. for(int ix = -7; ix < + 8+7; ++ix) { for(int iy = -5; iy < + 6+7; ++iy) { - Position itemPos = Position(playerPos->x + ix, playerPos->y + iy, iz); - //Position drawPos = Position(ix + 8, iy - playerPos->y + 6, iz); + Position itemPos = Position(playerPos.x + ix, playerPos.y + iy, iz); + //Position drawPos = Position(ix + 8, iy - playerPos.y + 6, iz); //logDebug("x: ", relativePos.x, " y: ", relativePos.y, " z: ", (int)relativePos.z); if(m_tiles[itemPos]) m_tiles[itemPos]->draw((ix + 7 - (7-iz))*32, (iy + 5 - (7-iz))*32); @@ -48,8 +51,8 @@ void Map::draw(int x, int y) // draw effects for(auto it = m_effects.begin(), end = m_effects.end(); it != end; ++it) { - Position *effectPos = (*it)->getPosition(); - (*it)->draw((effectPos->x - playerPos->x + 7) * 32, (effectPos->y - playerPos->y + 5) * 32); + Position effectPos = (*it)->getPosition(); + (*it)->draw((effectPos.x - playerPos.x + 7) * 32, (effectPos.y - playerPos.y + 5) * 32); } // debug draws @@ -61,14 +64,14 @@ void Map::draw(int x, int y) void Map::addThing(ThingPtr thing, uint8 stackpos) { - if(thing->getType() == Thing::TYPE_ITEM || thing->getType() == Thing::TYPE_CREATURE) { - if(!m_tiles[*thing->getPosition()]) { - m_tiles[*thing->getPosition()] = TilePtr(new Tile()); + if(thing->asItem() || thing->asCreature()) { + if(!m_tiles[thing->getPosition()]) { + m_tiles[thing->getPosition()] = TilePtr(new Tile()); } - m_tiles[*thing->getPosition()]->addThing(thing, stackpos); + m_tiles[thing->getPosition()]->addThing(thing, stackpos); } - else if(thing->getType() == Thing::TYPE_EFFECT) { + else if(thing->asEffect()) { m_effects.push_back(thing); } } diff --git a/src/otclient/core/map.h b/src/otclient/core/map.h index 90a6f854..ece6fda0 100644 --- a/src/otclient/core/map.h +++ b/src/otclient/core/map.h @@ -25,4 +25,6 @@ private: FrameBufferPtr m_framebuffer; }; +extern Map g_map; + #endif diff --git a/src/otclient/core/player.h b/src/otclient/core/player.h index b2aff45e..96ffd4a1 100644 --- a/src/otclient/core/player.h +++ b/src/otclient/core/player.h @@ -6,17 +6,10 @@ class Player : public Creature { public: - void setDrawSpeed(uint16 drawSpeed) { m_drawSpeed = drawSpeed; } - uint16 getDrawSpeed() { return m_drawSpeed; } - - void setCanReportBugs(uint8 canReportBugs) { m_canReportBugs = (canReportBugs != 0); } - bool getCanReportBugs() { return m_canReportBugs; } - -private: - - uint16 m_drawSpeed; - bool m_canReportBugs; + Player() { } + virtual ~Player() { } + PlayerPtr asPlayer() { return std::static_pointer_cast(shared_from_this()); } }; #endif diff --git a/src/otclient/core/spritemanager.cpp b/src/otclient/core/spritemanager.cpp new file mode 100644 index 00000000..5b5b8aec --- /dev/null +++ b/src/otclient/core/spritemanager.cpp @@ -0,0 +1,109 @@ +#include "spritemanager.h" +#include +#include + +SpriteManager g_sprites; + +SpriteManager::SpriteManager() +{ + m_spritesCount = 0; + m_signature = 0; +} + +bool SpriteManager::load(const std::string &filename) +{ + g_resources.loadFile(filename, m_fin); + m_signature = fw::getu32(m_fin); + m_spritesCount = fw::getu16(m_fin); + m_sprites.resize(m_spritesCount); + return true; +} + +void SpriteManager::unload() +{ + m_sprites.clear(); + m_spritesCount = 0; + m_signature = 0; +} + +TexturePtr SpriteManager::loadSprite(int id) +{ + m_fin.seekg(((id-1) * 4) + 6, std::ios_base::beg); + + uint32 spriteAddress = fw::getu32(m_fin); + + // no sprite? return an empty texture + if(spriteAddress == 0) + return g_graphics.getEmptyTexture(); + + m_fin.seekg(spriteAddress, std::ios_base::beg); + assert(m_fin.good()); + + // skip color key + fw::getu8(m_fin); + fw::getu8(m_fin); + fw::getu8(m_fin); + + uint16 pixelDataSize = fw::getu16(m_fin); + + uchar pixels[4096]; + int writePos = 0; + int read = 0; + + // decompress pixels + while(read < pixelDataSize) { + uint16 transparentPixels, coloredPixels; + m_fin.read((char*)&transparentPixels, 2); + m_fin.read((char*)&coloredPixels, 2); + + for(int i = 0; i < transparentPixels; i++) { + pixels[writePos + 0] = 0x00; + pixels[writePos + 1] = 0x00; + pixels[writePos + 2] = 0x00; + pixels[writePos + 3] = 0x00; + writePos += 4; + } + + for(int i = 0; i < coloredPixels; i++) { + pixels[writePos + 0] = fw::getu8(m_fin); + pixels[writePos + 1] = fw::getu8(m_fin); + pixels[writePos + 2] = fw::getu8(m_fin); + pixels[writePos + 3] = 0xFF; + + writePos += 4; + } + + read += 4 + (3 * coloredPixels); + } + + // fill remaining pixels with alpha + while(writePos < 4096) { + pixels[writePos + 0] = 0x00; + pixels[writePos + 1] = 0x00; + pixels[writePos + 2] = 0x00; + pixels[writePos + 3] = 0x00; + writePos += 4; + } + + return TexturePtr(new Texture(32, 32, 4, pixels)); +} + +TexturePtr SpriteManager::getSpriteTexture(int id) +{ + if(id == 0) + return g_graphics.getEmptyTexture(); + + assert(id <= m_spritesCount); + + // load sprites on demand + TexturePtr texture = m_sprites[id-1]; + if(!texture) { + texture = loadSprite(id); + m_sprites[id-1] = texture; + } + + //TODO: release unused sprites textures after X seconds + // to avoid massive texture allocations + + return texture; +} diff --git a/src/otclient/core/spritemanager.h b/src/otclient/core/spritemanager.h new file mode 100644 index 00000000..0d5692d0 --- /dev/null +++ b/src/otclient/core/spritemanager.h @@ -0,0 +1,31 @@ +#ifndef SPRITEMANAGER_H +#define SPRITEMANAGER_H + +#include +#include + +class SpriteManager +{ +public: + SpriteManager(); + + bool load(const std::string& filename); + void unload(); + + uint32 getSignature() { return m_signature; } + int getSpritesCount() { return m_spritesCount; } + TexturePtr getSpriteTexture(int id); + +private: + TexturePtr loadSprite(int id); + + uint32 m_signature; + uint16 m_spritesCount; + std::stringstream m_fin; + std::vector m_sprites; + TexturePtr m_transparentSprite; +}; + +extern SpriteManager g_sprites; + +#endif diff --git a/src/otclient/core/thing.cpp b/src/otclient/core/thing.cpp index f930983b..bb352ed5 100644 --- a/src/otclient/core/thing.cpp +++ b/src/otclient/core/thing.cpp @@ -2,48 +2,6 @@ #include "spritemanager.h" #include -ThingAttributes::ThingAttributes() -{ - group = THING_GROUP_NONE; - blockSolid = false; - hasHeight = false; - blockPathFind = false; - blockProjectile = false; - alwaysOnTop = false; - alwaysOnTopOrder = 0; - stackable = false; - useable = false; - moveable = true; - pickupable = false; - rotable = false; - readable = false; - lookThrough = false; - speed = 0; - lightLevel = 0; - lightColor = 0; - isVertical = false; - isHorizontal = false; - isHangable = false; - miniMapColor = 0; - hasMiniMapColor = false; - subParam07 = 0; - subParam08 = 0; - width = 0; - height = 0; - blendframes = 0; - xdiv = 0; - ydiv = 0; - zdiv = 0; - animcount = 0; - xOffset = 0; - yOffset = 0; -} - -Thing::Thing() -{ - m_type = TYPE_NONE; -} - void Thing::internalDraw(int x, int y, int blendframes, int xdiv, int ydiv, int zdiv, int anim) { const ThingAttributes& attributes = getAttributes(); @@ -63,16 +21,11 @@ void Thing::internalDraw(int x, int y, int blendframes, int xdiv, int ydiv, int continue; TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); - if(spriteTex->isEmpty()) - continue; - - int offsetX = 0, offsetY = 0; - if(attributes.hasHeight) { - offsetX = attributes.xOffset; - offsetY = attributes.xOffset; // << look to xoffset - } + Rect drawRect((x - xi*32) - attributes.xOffset, + (y - yi*32) - attributes.yOffset, + 32, 32); - g_graphics.drawTexturedRect(Rect((x - xi*32) - offsetX, (y - yi*32) - offsetY, 32, 32), spriteTex, Rect(0, 0, 32, 32)); + g_graphics.drawTexturedRect(drawRect, spriteTex); } } } diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index 073ca889..33433ef0 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -1,58 +1,39 @@ #ifndef THING_H #define THING_H -#include #include "declarations.h" +#include "thingattributes.h" +#include -struct ThingAttributes -{ - ThingAttributes(); - - bool stackable, alwaysOnTop, useable, readable, moveable, blockSolid, blockProjectile, blockPathFind, pickupable, - isHangable, isHorizontal, isVertical, rotable, hasHeight, lookThrough, hasMiniMapColor; - uint8 alwaysOnTopOrder, width, height, blendframes, xdiv, ydiv, zdiv, animcount, xOffset, yOffset; - uint16 speed, subParam07, subParam08, lightLevel, lightColor, miniMapColor; - std::vector sprites; - ThingAttributesGroup group; -}; - -class Thing +class Thing : public LuaObject { public: - Thing(); + Thing(ThingType type) : m_id(0), m_type(type) { } + virtual ~Thing() { } - enum Type { - TYPE_NONE, - TYPE_ITEM, - TYPE_CREATURE, - TYPE_EFFECT, - TYPE_SHOT - }; + virtual void draw(int x, int y) = 0; void setId(uint32 id) { m_id = id; } - uint32 getId() { return m_id; } - - void setType(Type type) { m_type = type; } - Type getType() const { return m_type; } - void setPosition(const Position& position) { m_position = position; } - Position *getPosition() { return &m_position; } - virtual void draw(int, int) {} + uint32 getId() const { return m_id; } + ThingType getType() const { return m_type; } + Position getPosition() const { return m_position; } virtual const ThingAttributes& getAttributes() = 0; - virtual Item* getItem() { return NULL; } - virtual const Item *getItem() const { return NULL; } - virtual Creature *getCreature() { return NULL; } - virtual const Creature *getCreature() const { return NULL; } + ThingPtr asThing() { return std::static_pointer_cast(shared_from_this()); } + virtual ItemPtr asItem() { return nullptr; } + virtual CreaturePtr asCreature() { return nullptr; } + virtual EffectPtr asEffect() { return nullptr; } + virtual PlayerPtr asPlayer() { return nullptr; } + virtual LocalPlayerPtr asLocalPlayer() { return nullptr; } protected: void internalDraw(int x, int y, int blendframes, int xdiv, int ydiv, int zdiv, int anim); uint32 m_id; - Type m_type; + ThingType m_type; Position m_position; - }; #endif diff --git a/src/otclient/core/thingattributes.h b/src/otclient/core/thingattributes.h new file mode 100644 index 00000000..4ffe7fd7 --- /dev/null +++ b/src/otclient/core/thingattributes.h @@ -0,0 +1,52 @@ +#ifndef THINGATTRIBUTES_H +#define THINGATTRIBUTES_H + +#include "declarations.h" + +struct ThingAttributes +{ + ThingAttributes() { + group = THING_GROUP_NONE; + blockSolid = false; + hasHeight = false; + blockPathFind = false; + blockProjectile = false; + alwaysOnTop = false; + alwaysOnTopOrder = 0; + stackable = false; + useable = false; + moveable = true; + pickupable = false; + rotable = false; + readable = false; + lookThrough = false; + speed = 0; + lightLevel = 0; + lightColor = 0; + isVertical = false; + isHorizontal = false; + isHangable = false; + miniMapColor = 0; + hasMiniMapColor = false; + subParam07 = 0; + subParam08 = 0; + width = 0; + height = 0; + blendframes = 0; + xdiv = 0; + ydiv = 0; + zdiv = 0; + animcount = 0; + xOffset = 0; + yOffset = 0; + } + + bool stackable, alwaysOnTop, useable, readable, moveable, blockSolid, blockProjectile, blockPathFind, pickupable, + isHangable, isHorizontal, isVertical, rotable, hasHeight, lookThrough, hasMiniMapColor; + uint8 alwaysOnTopOrder, width, height, blendframes, xdiv, ydiv, zdiv, animcount, xOffset, yOffset; + uint16 speed, subParam07, subParam08, lightLevel, lightColor, miniMapColor; + std::vector sprites; + ThingAttributesGroup group; +}; + +#endif diff --git a/src/otclient/core/tile.cpp b/src/otclient/core/tile.cpp index dec85633..ab7ee261 100644 --- a/src/otclient/core/tile.cpp +++ b/src/otclient/core/tile.cpp @@ -4,7 +4,6 @@ Tile::Tile() { - } void Tile::addThing(ThingPtr thing, uint8 stackpos) @@ -13,7 +12,7 @@ void Tile::addThing(ThingPtr thing, uint8 stackpos) return; const ThingAttributes& thingAttributes = thing->getAttributes(); - if(thing->getType() == Thing::TYPE_ITEM) { + if(thing->asItem()) { if(thingAttributes.group == THING_GROUP_GROUND) m_ground = thing; else { @@ -22,7 +21,7 @@ void Tile::addThing(ThingPtr thing, uint8 stackpos) else m_itemsBot.push_back(thing); } - } else if(thing->getType() == Thing::TYPE_CREATURE) { + } else if(thing->asCreature()) { m_creatures.push_back(thing); } } diff --git a/src/otclient/core/tile.h b/src/otclient/core/tile.h index 3941d193..6b4b5bbe 100644 --- a/src/otclient/core/tile.h +++ b/src/otclient/core/tile.h @@ -1,9 +1,10 @@ #ifndef TILE_H #define TILE_H -#include "thing.h" +#include "declarations.h" +#include -class Tile +class Tile : public LuaObject { public: Tile(); diff --git a/src/otclient/net/protocolgame.h b/src/otclient/net/protocolgame.h index b4faa949..9bcd475e 100644 --- a/src/otclient/net/protocolgame.h +++ b/src/otclient/net/protocolgame.h @@ -20,7 +20,6 @@ public: void onConnect(); void onRecv(InputMessage& inputMessage); - // Send Messages void sendLogout(); void sendPing(); void sendWalkNorth(); @@ -108,13 +107,18 @@ private: void setMapDescription(InputMessage& msg, int32 x, int32 y, int32 z, int32 width, int32 height); void setFloorDescription(InputMessage& msg, int32 x, int32 y, int32 z, int32 width, int32 height, int32 offset, int32* skipTiles); void setTileDescription(InputMessage& msg, Position position); + + Outfit internalGetOutfit(InputMessage& msg); ThingPtr internalGetThing(InputMessage& msg); - Outfit internalCreatureOutfit(InputMessage& msg); ItemPtr internalGetItem(InputMessage& msg, uint16 id); Position parsePosition(InputMessage& msg); - std::string m_accountName, m_accountPassword, m_characterName; +private: + std::string m_accountName; + std::string m_accountPassword; + std::string m_characterName; + LocalPlayerPtr m_localPlayer; }; -#endif // PROTOCOLGAME_H +#endif diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index 04f4b9b2..5a1ef210 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -1,6 +1,6 @@ #include "protocolgame.h" -#include +#include #include #include #include @@ -10,9 +10,6 @@ void ProtocolGame::parseMessage(InputMessage& msg) { while(!msg.end()) { uint8 opt = msg.getU8(); - - dump << "Protocol opt: " << std::hex << (int)opt << std::dec; - switch(opt) { case 0x0A: parsePlayerLogin(msg); @@ -225,23 +222,25 @@ void ProtocolGame::parseMessage(InputMessage& msg) parseQuestPartList(msg); break; default: - logDebug("UNKNOWN PACKET BYTE.", opt); - //skipPacket = true; + logError("UNKNOWN PACKET OPT BYTE: 0x", std::hex, opt); break; } } - recv(); } void ProtocolGame::parsePlayerLogin(InputMessage& msg) { - Player *player = g_game.getPlayer(); - player->setId(msg.getU32()); - player->setDrawSpeed(msg.getU16()); - player->setCanReportBugs(msg.getU8()); + int playerId = msg.getU32(); + int playerDrawSpeed = msg.getU16(); + int playerCanReportBugs = msg.getU8(); - g_game.setOnline(true); + g_game.onLogin(); + + m_localPlayer = g_game.getLocalPlayer(); + m_localPlayer->setId(playerId); + m_localPlayer->setDrawSpeed(playerDrawSpeed); + m_localPlayer->setCanReportBugs(playerCanReportBugs); } void ProtocolGame::parseGMActions(InputMessage& msg) @@ -284,37 +283,41 @@ void ProtocolGame::parseCanReportBugs(InputMessage& msg) void ProtocolGame::parseMapDescription(InputMessage& msg) { - Player *player = g_game.getPlayer(); - player->setPosition(parsePosition(msg)); - setMapDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, player->getPosition()->z, 18, 14); + Position pos = parsePosition(msg); + setMapDescription(msg, pos.x - 8, pos.y - 6, pos.z, 18, 14); + m_localPlayer->setPosition(pos); } void ProtocolGame::parseMoveNorth(InputMessage& msg) { - Player *player = g_game.getPlayer(); - player->getPosition()->y--; - setMapDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, player->getPosition()->z, 18, 1); + Position pos = m_localPlayer->getPosition(); + pos.y--; + setMapDescription(msg, pos.x - 8, pos.y - 6, pos.z, 18, 1); + m_localPlayer->setPosition(pos); } void ProtocolGame::parseMoveEast(InputMessage& msg) { - Player *player = g_game.getPlayer(); - player->getPosition()->x++; - setMapDescription(msg, player->getPosition()->x + 9, player->getPosition()->y - 6, player->getPosition()->z, 1, 14); + Position pos = m_localPlayer->getPosition(); + pos.x++; + setMapDescription(msg, pos.x + 9, pos.y - 6, pos.z, 1, 14); + m_localPlayer->setPosition(pos); } void ProtocolGame::parseMoveSouth(InputMessage& msg) { - Player *player = g_game.getPlayer(); - player->getPosition()->y++; - setMapDescription(msg, player->getPosition()->x - 8, player->getPosition()->y + 7, player->getPosition()->z, 18, 1); + Position pos = m_localPlayer->getPosition(); + pos.y++; + setMapDescription(msg, pos.x - 8, pos.y + 7, pos.z, 18, 1); + m_localPlayer->setPosition(pos); } void ProtocolGame::parseMoveWest(InputMessage& msg) { - Player *player = g_game.getPlayer(); - player->getPosition()->x--; - setMapDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, player->getPosition()->z, 1, 14); + Position pos = m_localPlayer->getPosition(); + pos.x--; + setMapDescription(msg, pos.x - 8, pos.y - 6, pos.z, 1, 14); + m_localPlayer->setPosition(pos); } void ProtocolGame::parseUpdateTile(InputMessage& msg) @@ -466,7 +469,7 @@ void ProtocolGame::parseMagicEffect(InputMessage& msg) effect->setPosition(parsePosition(msg)); effect->setId(msg.getU8()); - g_game.getMap()->addThing(effect); + g_map.addThing(effect); } void ProtocolGame::parseAnimatedText(InputMessage& msg) @@ -505,7 +508,7 @@ void ProtocolGame::parseCreatureLight(InputMessage& msg) void ProtocolGame::parseCreatureOutfit(InputMessage& msg) { msg.getU32(); // creature id - internalCreatureOutfit(msg); + internalGetOutfit(msg); } void ProtocolGame::parseCreatureSpeed(InputMessage& msg) @@ -698,41 +701,45 @@ void ProtocolGame::parseCancelWalk(InputMessage& msg) void ProtocolGame::parseFloorChangeUp(InputMessage& msg) { - Player *player = g_game.getPlayer(); - player->getPosition()->z--; + Position pos = m_localPlayer->getPosition(); + pos.z--; int32 skip = 0; - if(player->getPosition()->z == 7) + if(m_localPlayer->getPosition().z == 7) for(int32 i = 5; i >= 0; i--) - setFloorDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, i, 18, 14, 8 - i, &skip); - else if(player->getPosition()->z > 7) - setFloorDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, player->getPosition()->z - 2, 18, 14, 3, &skip); + setFloorDescription(msg, pos.x - 8, pos.y - 6, i, 18, 14, 8 - i, &skip); + else if(m_localPlayer->getPosition().z > 7) + setFloorDescription(msg, pos.x - 8, pos.y - 6, pos.z - 2, 18, 14, 3, &skip); + + pos.x++; + pos.y++; - player->getPosition()->x++; - player->getPosition()->y++; + m_localPlayer->setPosition(pos); } void ProtocolGame::parseFloorChangeDown(InputMessage& msg) { - Player *player = g_game.getPlayer(); - player->getPosition()->z++; + Position pos = m_localPlayer->getPosition(); + pos.z++; - int32 skip = 0; - if(player->getPosition()->z == 8) { - int32 j, i; - for(i = player->getPosition()->z, j = -1; i < (int32)player->getPosition()->z + 3; ++i, --j) - setFloorDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, i, 18, 14, j, &skip); + int skip = 0; + if(pos.z == 8) { + int j, i; + for(i = pos.z, j = -1; i < pos.z + 3; ++i, --j) + setFloorDescription(msg, pos.x - 8, pos.y - 6, i, 18, 14, j, &skip); } - else if(player->getPosition()->z > 8 && player->getPosition()->z < 14) - setFloorDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, player->getPosition()->z + 2, 18, 14, -3, &skip); + else if(pos.z > 8 && pos.z < 14) + setFloorDescription(msg, pos.x - 8, pos.y - 6, pos.z + 2, 18, 14, -3, &skip); - player->getPosition()->x--; - player->getPosition()->y--; + pos.x--; + pos.y--; + + m_localPlayer->setPosition(pos); } void ProtocolGame::parseOutfitWindow(InputMessage& msg) { - internalCreatureOutfit(msg); + internalGetOutfit(msg); uint8 outfitCount = msg.getU8(); for(int i = 0; i < outfitCount; i++) { @@ -852,11 +859,30 @@ void ProtocolGame::setTileDescription(InputMessage& msg, Position position) ThingPtr thing = internalGetThing(msg); if(thing) thing->setPosition(position); - g_game.getMap()->addThing(thing, stackpos); + g_map.addThing(thing, stackpos); } } } +Outfit ProtocolGame::internalGetOutfit(InputMessage& msg) +{ + Outfit outfit; + + outfit.type = msg.getU16(); // looktype + if(outfit.type != 0) { + outfit.head = msg.getU8(); + outfit.body = msg.getU8(); + outfit.legs = msg.getU8(); + outfit.feet = msg.getU8(); + outfit.addons = msg.getU8(); + } + else { + outfit.type = msg.getU16(); + } + + return outfit; +} + ThingPtr ProtocolGame::internalGetThing(InputMessage& msg) { ThingPtr thing; @@ -876,7 +902,7 @@ ThingPtr ProtocolGame::internalGetThing(InputMessage& msg) creature->setHealthPercent(msg.getU8()); creature->setDirection((Direction)msg.getU8()); - creature->setOutfit(internalCreatureOutfit(msg)); + creature->setOutfit(internalGetOutfit(msg)); msg.getU8(); // light level msg.getU8(); // light color msg.getU16(); // speed @@ -899,25 +925,6 @@ ThingPtr ProtocolGame::internalGetThing(InputMessage& msg) return thing; } -Outfit ProtocolGame::internalCreatureOutfit(InputMessage& msg) -{ - Outfit outfit; - - outfit.type = msg.getU16(); // looktype - if(outfit.type != 0) { - outfit.head = msg.getU8(); - outfit.body = msg.getU8(); - outfit.legs = msg.getU8(); - outfit.feet = msg.getU8(); - outfit.addons = msg.getU8(); - } - else { - outfit.type = msg.getU16(); - } - - return outfit; -} - ItemPtr ProtocolGame::internalGetItem(InputMessage& msg, uint16 id) { ItemPtr item = ItemPtr(new Item()); diff --git a/src/otclient/otclient.cpp b/src/otclient/otclient.cpp index ab5b7aa3..60d4bc9e 100644 --- a/src/otclient/otclient.cpp +++ b/src/otclient/otclient.cpp @@ -200,8 +200,8 @@ void OTClient::poll() void OTClient::render() { //TODO: UIMap for map drawing - if(g_game.getOnline()) - g_game.getMap()->draw(0, 0); + if(g_game.isOnline()) + g_map.draw(0, 0); // everything is rendered by UI components g_ui.render();