diff --git a/TODO b/TODO index c2c2e882..512a9c28 100644 --- a/TODO +++ b/TODO @@ -2,7 +2,6 @@ game_shaders (with shader manager) game_map (with save/load/options) game_minimap (with all tibia functionality) -game_playertrade == NOTABLE FEATURES make left panel optional diff --git a/modules/game_playertrade/playertrade.lua b/modules/game_playertrade/playertrade.lua index 0caa937a..d7c4e2a1 100644 --- a/modules/game_playertrade/playertrade.lua +++ b/modules/game_playertrade/playertrade.lua @@ -1,9 +1,5 @@ PlayerTrade = {} --- g_game.inspectTrade(counterOffer, index) --- g_game.acceptTrade() --- g_game.rejectTrade() - local tradeWindow local function createTrade() diff --git a/src/framework/graphics/image.cpp b/src/framework/graphics/image.cpp index 476a56e6..547138ba 100644 --- a/src/framework/graphics/image.cpp +++ b/src/framework/graphics/image.cpp @@ -31,7 +31,8 @@ Image::Image(const Size& size, int bpp, uint8 *pixels) m_size = size; m_bpp = bpp; m_pixels.resize(size.area() * bpp); - memcpy(&m_pixels[0], pixels, m_pixels.size()); + if(pixels) + memcpy(&m_pixels[0], pixels, m_pixels.size()); } ImagePtr Image::load(const std::string& file) @@ -62,3 +63,23 @@ ImagePtr Image::loadPNG(const std::string& file) } return image; } + +void Image::overwriteMask(const Color& maskedColor, const Color& insideColor, const Color& outsideColor) +{ + assert(m_bpp == 4); + + for(int p=0;p& getPixels() { return m_pixels; } + void overwriteMask(const Color& maskedColor, const Color& insideColor = Color::white, const Color& outsideColor = Color::alpha); + + std::vector& getPixels() { return m_pixels; } + uint8* getPixelData() { return &m_pixels[0]; } + int getPixelCount() { return m_size.area(); } const Size& getSize() { return m_size; } + int getWidth() { return m_size.width(); } + int getHeight() { return m_size.height(); } int getBpp() { return m_bpp; } private: diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp index 4ac366ad..4b6f0127 100644 --- a/src/framework/graphics/texture.cpp +++ b/src/framework/graphics/texture.cpp @@ -23,12 +23,18 @@ #include "texture.h" #include "graphics.h" #include "framebuffer.h" +#include "image.h" Texture::Texture() { m_textureId = 0; } +Texture::Texture(const ImagePtr& image) +{ + internalLoadGLTexture(image->getPixelData(), image->getBpp(), image->getWidth(), image->getHeight()); +} + Texture::Texture(int width, int height, int channels, uchar *pixels) { // generate opengl texture diff --git a/src/framework/graphics/texture.h b/src/framework/graphics/texture.h index 26137a0c..30eb759d 100644 --- a/src/framework/graphics/texture.h +++ b/src/framework/graphics/texture.h @@ -29,6 +29,7 @@ class Texture : public std::enable_shared_from_this { public: Texture(); + Texture(const ImagePtr& image); Texture(int width, int height, int channels, uchar* pixels = NULL); virtual ~Texture(); diff --git a/src/otclient/CMakeLists.txt b/src/otclient/CMakeLists.txt index 3bebd598..548ce5be 100644 --- a/src/otclient/CMakeLists.txt +++ b/src/otclient/CMakeLists.txt @@ -28,6 +28,7 @@ SET(otclient_SOURCES ${otclient_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/core/game.cpp ${CMAKE_CURRENT_LIST_DIR}/core/map.cpp ${CMAKE_CURRENT_LIST_DIR}/core/mapview.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/thingtype.cpp ${CMAKE_CURRENT_LIST_DIR}/core/thingstype.cpp ${CMAKE_CURRENT_LIST_DIR}/core/spritemanager.cpp ${CMAKE_CURRENT_LIST_DIR}/core/item.cpp diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index 345d1f8b..ae32a552 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -88,7 +88,6 @@ void Creature::draw(const Point& dest, float scaleFactor, bool animate) void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction) { - g_painter->setColor(Color::white); /* if(!outfitProgram) { outfitProgram = PainterShaderProgramPtr(new PainterShaderProgram); @@ -141,15 +140,32 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani for(int h = 0; h < getDimensionHeight(); h++) { for(int w = 0; w < getDimensionWidth(); w++) { // setup texture outfit mask + /* TexturePtr maskTex; + if(getLayers() > 1) + maskTex = m_type->getSprite(w, h, 1, xPattern, yPattern, zPattern, animationPhase); + + outfitProgram->setTexture(maskTex, 1); + */ + + Point p = dest + (-Point(w,h)*Otc::TILE_PIXELS)*scaleFactor; + m_type->draw(p, scaleFactor, w, h, xPattern, yPattern, zPattern, 0, animationPhase); + if(getLayers() > 1) { - int maskId = getSpriteId(w, h, 1, xPattern, yPattern, zPattern, animationPhase); - maskTex = g_sprites.getSpriteTexture(maskId); + g_painter->setCompositionMode(Painter::CompositionMode_Multiply); + + g_painter->setColor(m_outfit.getHeadColor()); + m_type->drawMask(p, scaleFactor, w, h, xPattern, yPattern, zPattern, 1, animationPhase, ThingType::YellowMask); + g_painter->setColor(m_outfit.getBodyColor()); + m_type->drawMask(p, scaleFactor, w, h, xPattern, yPattern, zPattern, 1, animationPhase, ThingType::RedMask); + g_painter->setColor(m_outfit.getLegsColor()); + m_type->drawMask(p, scaleFactor, w, h, xPattern, yPattern, zPattern, 1, animationPhase, ThingType::GreenMask); + g_painter->setColor(m_outfit.getFeetColor()); + m_type->drawMask(p, scaleFactor, w, h, xPattern, yPattern, zPattern, 1, animationPhase, ThingType::BlueMask); + + g_painter->resetColor(); + g_painter->resetCompositionMode(); } - //outfitProgram->setTexture(maskTex, 1); - - internalDraw(dest + (-Point(w,h)*Otc::TILE_PIXELS)*scaleFactor, - scaleFactor, w, h, xPattern, yPattern, zPattern, 0, animationPhase); } } @@ -178,7 +194,7 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani if(m_outfit.getCategory() == ThingsType::Effect) animationPhase = std::min(animationPhase+1, getAnimationPhases()); - internalDraw(dest, scaleFactor, 0, 0, 0, animationPhase); + m_type->draw(dest, scaleFactor, 0, 0, 0, animationPhase); } } diff --git a/src/otclient/core/declarations.h b/src/otclient/core/declarations.h index 15ccb338..80a5bcbe 100644 --- a/src/otclient/core/declarations.h +++ b/src/otclient/core/declarations.h @@ -41,6 +41,8 @@ class Effect; class Missile; class AnimatedText; class StaticText; +class ThingType; +class ThingsType; typedef std::shared_ptr MapViewPtr; typedef std::shared_ptr TilePtr; diff --git a/src/otclient/core/effect.cpp b/src/otclient/core/effect.cpp index f4493fcf..36ae0459 100644 --- a/src/otclient/core/effect.cpp +++ b/src/otclient/core/effect.cpp @@ -32,7 +32,7 @@ void Effect::draw(const Point& dest, float scaleFactor, bool animate) int animationPhase = 0; if(animate) animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / Otc::EFFECT_TICKS_PER_FRAME), getAnimationPhases() - 1); - internalDraw(dest, scaleFactor, 0, 0, 0, animationPhase); + m_type->draw(dest, scaleFactor, 0, 0, 0, animationPhase); } void Effect::startAnimation() diff --git a/src/otclient/core/item.cpp b/src/otclient/core/item.cpp index abf5a0d6..0d6624ee 100644 --- a/src/otclient/core/item.cpp +++ b/src/otclient/core/item.cpp @@ -181,7 +181,7 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate) */ // now we can draw the item - internalDraw(dest, scaleFactor, xPattern, yPattern, zPattern, animationPhase); + m_type->draw(dest, scaleFactor, xPattern, yPattern, zPattern, animationPhase); // release draw shader g_painter->resetShaderProgram(); diff --git a/src/otclient/core/missile.cpp b/src/otclient/core/missile.cpp index 70ec2cec..bf3c6cae 100644 --- a/src/otclient/core/missile.cpp +++ b/src/otclient/core/missile.cpp @@ -63,7 +63,7 @@ void Missile::draw(const Point& dest, float scaleFactor, bool animate) } float fraction = m_animationTimer.ticksElapsed() / m_duration; - internalDraw(dest + m_delta * fraction * scaleFactor, scaleFactor, xPattern, yPattern, 0, 0); + m_type->draw(dest + m_delta * fraction * scaleFactor, scaleFactor, xPattern, yPattern, 0, 0); } void Missile::setPath(const Position& fromPosition, const Position& toPosition) diff --git a/src/otclient/core/spritemanager.cpp b/src/otclient/core/spritemanager.cpp index c0816cd6..84b14f9a 100644 --- a/src/otclient/core/spritemanager.cpp +++ b/src/otclient/core/spritemanager.cpp @@ -22,10 +22,8 @@ #include "spritemanager.h" #include -#include #include -#include -#include +#include SpriteManager g_sprites; @@ -47,7 +45,6 @@ bool SpriteManager::load(const std::string& file) m_signature = m_spritesFile->getU32(); m_spritesCount = m_spritesFile->getU16(); - m_sprites.resize(m_spritesCount); m_loaded = true; return true; } catch(Exception& e) { @@ -58,35 +55,22 @@ bool SpriteManager::load(const std::string& file) void SpriteManager::unload() { - m_sprites.clear(); m_spritesCount = 0; m_signature = 0; } -void SpriteManager::preloadSprites() +ImagePtr SpriteManager::getSpriteImage(int id) { - // preload every 50 sprites, periodically - const int burst = 50; - const int interval = 10; - auto preload = [this](int start) { - for(int i=start;iseek(((id-1) * 4) + 6); uint32 spriteAddress = m_spritesFile->getU32(); // no sprite? return an empty texture if(spriteAddress == 0) - return g_graphics.getEmptyTexture(); + return nullptr; m_spritesFile->seek(spriteAddress); @@ -97,7 +81,14 @@ TexturePtr SpriteManager::loadSpriteTexture(int id) uint16 pixelDataSize = m_spritesFile->getU16(); - static std::vector pixels(SPRITE_SIZE); + enum { + SPRITE_SIZE = 32, + SPRITE_DATA_SIZE = SPRITE_SIZE*SPRITE_SIZE*4 + }; + + ImagePtr image(new Image(Size(SPRITE_SIZE, SPRITE_SIZE))); + + uint8 *pixels = image->getPixelData(); int writePos = 0; int read = 0; @@ -106,8 +97,10 @@ TexturePtr SpriteManager::loadSpriteTexture(int id) uint16 transparentPixels = m_spritesFile->getU16(); uint16 coloredPixels = m_spritesFile->getU16(); - if(writePos + transparentPixels*4 + coloredPixels*3 >= SPRITE_SIZE) - return g_graphics.getEmptyTexture(); + if(writePos + transparentPixels*4 + coloredPixels*3 >= SPRITE_DATA_SIZE) { + logWarning("corrupt sprite id ", id); + return nullptr; + } for(int i = 0; i < transparentPixels; i++) { pixels[writePos + 0] = 0x00; @@ -130,7 +123,7 @@ TexturePtr SpriteManager::loadSpriteTexture(int id) } // fill remaining pixels with alpha - while(writePos < SPRITE_SIZE) { + while(writePos < SPRITE_DATA_SIZE) { pixels[writePos + 0] = 0x00; pixels[writePos + 1] = 0x00; pixels[writePos + 2] = 0x00; @@ -138,100 +131,6 @@ TexturePtr SpriteManager::loadSpriteTexture(int id) writePos += 4; } - TexturePtr spriteTex(new Texture(32, 32, 4, &pixels[0])); - spriteTex->setSmooth(true); - - if(g_graphics.canUseMipmaps()) - spriteTex->generateSoftwareMipmaps(pixels); - - return spriteTex; + return image; } -TexturePtr& SpriteManager::getSpriteTexture(int id) -{ - if(id == 0) - return g_graphics.getEmptyTexture(); - - assert(id > 0 && id <= m_spritesCount); - - // load sprites on demand - TexturePtr& sprite = m_sprites[id-1]; - if(!sprite) - sprite = loadSpriteTexture(id); - - //TODO: release unused sprites textures after X seconds - // to avoid massive texture allocations - return sprite; -} - -bool SpriteManager::exportSprites() -{ - g_resources.makeDir("sprites"); - std::stringstream ss; - - for(volatile int i = 1; i <= m_spritesCount; i++) { - m_spritesFile->seek(((i-1) * 4) + 6); - - uint32 spriteAddress = m_spritesFile->getU32(); - if(spriteAddress == 0) - continue; - - m_spritesFile->seek(spriteAddress); - - // skip color key - m_spritesFile->getU8(); - m_spritesFile->getU8(); - m_spritesFile->getU8(); - - uint16 pixelDataSize = m_spritesFile->getU16(); - - uchar pixels[SPRITE_SIZE]; - int writePos = 0; - int read = 0; - - // decompress pixels - while(read < pixelDataSize) { - uint16 transparentPixels = m_spritesFile->getU16(); - uint16 coloredPixels = m_spritesFile->getU16(); - - if(writePos + transparentPixels*4 + coloredPixels*3 >= SPRITE_SIZE) - return false; // skip the whole process or just ignore this sprite? - - 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] = m_spritesFile->getU8(); - pixels[writePos + 1] = m_spritesFile->getU8(); - pixels[writePos + 2] = m_spritesFile->getU8(); - pixels[writePos + 3] = 0xFF; - - writePos += 4; - } - - read += 4 + (3 * coloredPixels); - } - - // fill remaining pixels with alpha - while(writePos < SPRITE_SIZE) { - pixels[writePos + 0] = 0x00; - pixels[writePos + 1] = 0x00; - pixels[writePos + 2] = 0x00; - pixels[writePos + 3] = 0x00; - writePos += 4; - } - - // We should get the OTClient and export to that folder... - std::string fileName = Fw::formatString("sprites/%d.png", i); - ss.str(""); - save_png(ss, SPRITE_WIDTH, SPRITE_HEIGHT, SPRITE_CHANNELS, pixels); - g_resources.saveFile(fileName, ss); - } - - return true; -} diff --git a/src/otclient/core/spritemanager.h b/src/otclient/core/spritemanager.h index 34fdc37f..d82a44c7 100644 --- a/src/otclient/core/spritemanager.h +++ b/src/otclient/core/spritemanager.h @@ -24,40 +24,26 @@ #define SPRITEMANAGER_H #include -#include +#include class SpriteManager { - enum { - SPRITE_WIDTH=32, - SPRITE_HEIGHT=32, - SPRITE_CHANNELS=4, - SPRITE_SIZE=SPRITE_WIDTH*SPRITE_HEIGHT*SPRITE_CHANNELS - }; - public: SpriteManager(); bool load(const std::string& file); void unload(); - void preloadSprites(); uint32 getSignature() { return m_signature; } int getSpritesCount() { return m_spritesCount; } - bool exportSprites(); - - TexturePtr& getSpriteTexture(int id); + ImagePtr getSpriteImage(int id); bool isLoaded() { return m_loaded; } private: - TexturePtr loadSpriteTexture(int id); - Boolean m_loaded; uint32 m_signature; int m_spritesCount; - std::vector m_sprites; - TexturePtr m_transparentSprite; FileStreamPtr m_spritesFile; }; diff --git a/src/otclient/core/thing.cpp b/src/otclient/core/thing.cpp index c61da97d..9fb00c54 100644 --- a/src/otclient/core/thing.cpp +++ b/src/otclient/core/thing.cpp @@ -74,23 +74,3 @@ int Thing::getStackpos() return -1; } } - -void Thing::internalDraw(const Point& dest, float scaleFactor, int w, int h, int xPattern, int yPattern, int zPattern, int layer, int animationPhase) -{ - int scaledSize = Otc::TILE_PIXELS * scaleFactor; - - int spriteId = getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animationPhase); - if(spriteId) { - Rect drawRect(dest - getDisplacement()*scaleFactor, Size(scaledSize, scaledSize)); - g_painter->setColor(Color::white); - g_painter->drawTexturedRect(drawRect, g_sprites.getSpriteTexture(spriteId)); - } -} - -void Thing::internalDraw(const Point& dest, float scaleFactor, int xPattern, int yPattern, int zPattern, int animationPhase) -{ - for(int l = 0; l < getLayers(); ++l) - for(int w = 0; w < getDimensionWidth(); ++w) - for(int h = 0; h < getDimensionHeight(); ++h) - internalDraw(dest - Point(w,h)*Otc::TILE_PIXELS*scaleFactor, scaleFactor, w, h, xPattern, yPattern, zPattern, l, animationPhase); -} diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index 4463682d..78daada6 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -65,55 +65,48 @@ public: virtual StaticTextPtr asStaticText() { return nullptr; } // type related - bool isGround() { return m_type->properties[ThingType::IsGround]; } - bool isFullGround() { return m_type->properties[ThingType::IsFullGround]; } - bool isTranslucent() { return m_type->properties[ThingType::IsTranslucent]; } - bool isGroundBorder() { return m_type->properties[ThingType::IsGroundBorder]; } - bool isOnBottom() { return m_type->properties[ThingType::IsOnBottom]; } - bool isOnTop() { return m_type->properties[ThingType::IsOnTop]; } - bool isDontHide() { return m_type->properties[ThingType::DontHide]; } - bool isContainer() { return m_type->properties[ThingType::IsContainer]; } - bool isForceUse() { return m_type->properties[ThingType::IsForceUse]; } - bool isMultiUse() { return m_type->properties[ThingType::IsMultiUse]; } - bool isRotateable() { return m_type->properties[ThingType::IsRotateable]; } - bool isNotMoveable() { return m_type->properties[ThingType::IsNotMovable]; } - bool isNotWalkable() { return m_type->properties[ThingType::NotWalkable]; } - bool isPickupable() { return m_type->properties[ThingType::IsPickupable]; } - bool isNotPathable() { return m_type->properties[ThingType::NotPathable]; } - bool isIgnoreLook() { return m_type->properties[ThingType::IgnoreLook]; } - bool isHangable() { return m_type->properties[ThingType::IsHangable]; } - bool isHookSouth() { return m_type->properties[ThingType::HookSouth]; } - bool isHookEast() { return m_type->properties[ThingType::HookEast]; } - bool isStackable() { return m_type->properties[ThingType::IsStackable]; } - bool isAnimateAlways() { return m_type->properties[ThingType::AnimateAlways]; } - bool isLyingCorpse() { return m_type->properties[ThingType::IsLyingCorpse]; } - bool blocksProjectile() { return m_type->properties[ThingType::BlockProjectile]; } - bool isFluid() { return m_type->properties[ThingType::IsFluid]; } - bool isFluidContainer() { return m_type->properties[ThingType::IsFluidContainer]; } - Size getDimension() { return Size(m_type->dimensions[ThingType::Width], m_type->dimensions[ThingType::Height]); } - int getDimensionWidth() { return m_type->dimensions[ThingType::Width]; } - int getDimensionHeight() { return m_type->dimensions[ThingType::Height]; } - int getExactSize() { return m_type->dimensions[ThingType::ExactSize]; } - Point getDisplacement() { return Point(m_type->parameters[ThingType::DisplacementX], m_type->parameters[ThingType::DisplacementY]); } - int getNumPatternsX() { return m_type->dimensions[ThingType::PatternX]; } - int getNumPatternsY() { return m_type->dimensions[ThingType::PatternY]; } - int getNumPatternsZ() { return m_type->dimensions[ThingType::PatternZ]; } - int getDisplacementX() { return m_type->parameters[ThingType::DisplacementX]; } - int getDisplacementY() { return m_type->parameters[ThingType::DisplacementY]; } - int getLayers() { return m_type->dimensions[ThingType::Layers]; } - int getAnimationPhases() { return m_type->dimensions[ThingType::AnimationPhases]; } - int getGroundSpeed() { return m_type->parameters[ThingType::GroundSpeed]; } - int getElevation() { return m_type->parameters[ThingType::Elevation]; } - int getMinimapColor() { return m_type->parameters[ThingType::MiniMapColor]; } - - int getSpriteId(int w = 0, int h = 0, int layer = 0, - int xPattern = 0, int yPattern = 0, int zPattern = 0, - int animation = 0) { return m_type->getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animation); } + bool isGround() { return m_type->getProperty(ThingType::IsGround); } + bool isFullGround() { return m_type->getProperty(ThingType::IsFullGround); } + bool isTranslucent() { return m_type->getProperty(ThingType::IsTranslucent); } + bool isGroundBorder() { return m_type->getProperty(ThingType::IsGroundBorder); } + bool isOnBottom() { return m_type->getProperty(ThingType::IsOnBottom); } + bool isOnTop() { return m_type->getProperty(ThingType::IsOnTop); } + bool isDontHide() { return m_type->getProperty(ThingType::DontHide); } + bool isContainer() { return m_type->getProperty(ThingType::IsContainer); } + bool isForceUse() { return m_type->getProperty(ThingType::IsForceUse); } + bool isMultiUse() { return m_type->getProperty(ThingType::IsMultiUse); } + bool isRotateable() { return m_type->getProperty(ThingType::IsRotateable); } + bool isNotMoveable() { return m_type->getProperty(ThingType::IsNotMovable); } + bool isNotWalkable() { return m_type->getProperty(ThingType::NotWalkable); } + bool isPickupable() { return m_type->getProperty(ThingType::IsPickupable); } + bool isNotPathable() { return m_type->getProperty(ThingType::NotPathable); } + bool isIgnoreLook() { return m_type->getProperty(ThingType::IgnoreLook); } + bool isHangable() { return m_type->getProperty(ThingType::IsHangable); } + bool isHookSouth() { return m_type->getProperty(ThingType::HookSouth); } + bool isHookEast() { return m_type->getProperty(ThingType::HookEast); } + bool isStackable() { return m_type->getProperty(ThingType::IsStackable); } + bool isAnimateAlways() { return m_type->getProperty(ThingType::AnimateAlways); } + bool isLyingCorpse() { return m_type->getProperty(ThingType::IsLyingCorpse); } + bool blocksProjectile() { return m_type->getProperty(ThingType::BlockProjectile); } + bool isFluid() { return m_type->getProperty(ThingType::IsFluid); } + bool isFluidContainer() { return m_type->getProperty(ThingType::IsFluidContainer); } + Size getDimension() { return Size(m_type->getDimension(ThingType::Width), m_type->getDimension(ThingType::Height)); } + int getDimensionWidth() { return m_type->getDimension(ThingType::Width); } + int getDimensionHeight() { return m_type->getDimension(ThingType::Height); } + int getExactSize() { return m_type->getDimension(ThingType::ExactSize); } + Point getDisplacement() { return Point(m_type->getParameter(ThingType::DisplacementX), m_type->getParameter(ThingType::DisplacementY)); } + int getNumPatternsX() { return m_type->getDimension(ThingType::PatternX); } + int getNumPatternsY() { return m_type->getDimension(ThingType::PatternY); } + int getNumPatternsZ() { return m_type->getDimension(ThingType::PatternZ); } + int getDisplacementX() { return m_type->getParameter(ThingType::DisplacementX); } + int getDisplacementY() { return m_type->getParameter(ThingType::DisplacementY); } + int getLayers() { return m_type->getDimension(ThingType::Layers); } + int getAnimationPhases() { return m_type->getDimension(ThingType::AnimationPhases); } + int getGroundSpeed() { return m_type->getParameter(ThingType::GroundSpeed); } + int getElevation() { return m_type->getParameter(ThingType::Elevation); } + int getMinimapColor() { return m_type->getParameter(ThingType::MiniMapColor); } protected: - void internalDraw(const Point& dest, float scaleFactor, int w, int h, int xPattern, int yPattern, int zPattern, int layer, int animationPhase); - void internalDraw(const Point& dest, float scaleFactor, int xPattern, int yPattern, int zPattern, int animationPhase); - Position m_position; ThingType *m_type; }; diff --git a/src/otclient/core/thingstype.cpp b/src/otclient/core/thingstype.cpp index c9e0c299..a6450a73 100644 --- a/src/otclient/core/thingstype.cpp +++ b/src/otclient/core/thingstype.cpp @@ -71,46 +71,47 @@ void ThingsType::parseThingType(std::stringstream& fin, ThingType& thingType) if(property == ThingType::LastPropertyValue) break; - thingType.properties[property] = true; + thingType.m_properties[property] = true; if(property == ThingType::IsGround) - thingType.parameters[ThingType::GroundSpeed] = Fw::getU16(fin); + thingType.m_parameters[ThingType::GroundSpeed] = Fw::getU16(fin); else if(property == ThingType::IsWritable || property == ThingType::IsWritableOnce) - thingType.parameters[ThingType::MaxTextLenght] = Fw::getU16(fin); + thingType.m_parameters[ThingType::MaxTextLenght] = Fw::getU16(fin); else if(property == ThingType::HasLight) { - thingType.parameters[ThingType::LightLevel] = Fw::getU16(fin); - thingType.parameters[ThingType::LightColor] = Fw::getU16(fin); + thingType.m_parameters[ThingType::LightLevel] = Fw::getU16(fin); + thingType.m_parameters[ThingType::LightColor] = Fw::getU16(fin); } else if(property == ThingType::HasDisplacement) { - thingType.parameters[ThingType::DisplacementX] = Fw::getU16(fin); - thingType.parameters[ThingType::DisplacementY] = Fw::getU16(fin); + thingType.m_parameters[ThingType::DisplacementX] = Fw::getU16(fin); + thingType.m_parameters[ThingType::DisplacementY] = Fw::getU16(fin); } else if(property == ThingType::HasElevation) - thingType.parameters[ThingType::Elevation] = Fw::getU16(fin); + thingType.m_parameters[ThingType::Elevation] = Fw::getU16(fin); else if(property == ThingType::MiniMap) - thingType.parameters[ThingType::MiniMapColor] = Fw::getU16(fin); + thingType.m_parameters[ThingType::MiniMapColor] = Fw::getU16(fin); else if(property == ThingType::LensHelp) - thingType.parameters[ThingType::LensHelpParameter] = Fw::getU16(fin); + thingType.m_parameters[ThingType::LensHelpParameter] = Fw::getU16(fin); else if(property == ThingType::Cloth) - thingType.parameters[ThingType::ClothSlot] = Fw::getU16(fin); + thingType.m_parameters[ThingType::ClothSlot] = Fw::getU16(fin); } int totalSprites = 1; for(int i = 0; i < ThingType::LastDimension; ++i) { - if(i == ThingType::ExactSize && thingType.dimensions[ThingType::Width] <= 1 && thingType.dimensions[ThingType::Height] <= 1) { - thingType.dimensions[i] = 32; + if(i == ThingType::ExactSize && thingType.m_dimensions[ThingType::Width] <= 1 && thingType.m_dimensions[ThingType::Height] <= 1) { + thingType.m_dimensions[i] = 32; continue; } - thingType.dimensions[i] = Fw::getU8(fin); + thingType.m_dimensions[i] = Fw::getU8(fin); if(i != ThingType::ExactSize) - totalSprites *= thingType.dimensions[i]; + totalSprites *= thingType.m_dimensions[i]; } - thingType.sprites.resize(totalSprites); + thingType.m_spritesIndex.resize(totalSprites); + thingType.m_sprites.resize(totalSprites); for(int i = 0; i < totalSprites; i++) - thingType.sprites[i] = Fw::getU16(fin); + thingType.m_spritesIndex[i] = Fw::getU16(fin); } ThingType *ThingsType::getThingType(uint16 id, Categories category) diff --git a/src/otclient/core/thingtype.h b/src/otclient/core/thingtype.h index ee2a6311..6cffe12f 100644 --- a/src/otclient/core/thingtype.h +++ b/src/otclient/core/thingtype.h @@ -25,16 +25,11 @@ #include "declarations.h" +#include + struct ThingType { - ThingType() { - // fill default values - dimensions.fill(0); - properties.fill(false); - parameters.fill(0); - } - - enum Dimensions { + enum Dimension { Width = 0, Height, ExactSize, @@ -45,10 +40,8 @@ struct ThingType AnimationPhases, LastDimension }; - std::array dimensions; - std::vector sprites; - enum Properties { + enum Property { IsGround = 0, IsGroundBorder, IsOnBottom, @@ -86,9 +79,8 @@ struct ThingType LastProperty, LastPropertyValue = 255 }; - std::array properties; - enum Parameters { + enum Parameter { GroundSpeed = 0, Fluid, MaxTextLenght, @@ -102,23 +94,49 @@ struct ThingType Elevation, LastParameter }; - std::array parameters; - - int getSpriteId(int w, int h, int l, int x, int y, int z, int a) - { - int sprIndex = ((((((a % dimensions[ThingType::AnimationPhases]) - * dimensions[ThingType::PatternZ] + z) - * dimensions[ThingType::PatternY] + y) - * dimensions[ThingType::PatternX] + x) - * dimensions[ThingType::Layers] + l) - * dimensions[ThingType::Height] + h) - * dimensions[ThingType::Width] + w; - - if(sprIndex >= 0 && sprIndex < (int)sprites.size()) - return sprites[sprIndex]; - - return 0; + + enum SpriteMask { + YellowMask = 0, + RedMask, + GreenMask, + BlueMask, + LastMask + }; + + ThingType(); + + void draw(const Point& dest, float scaleFactor, int w, int h, int xPattern, int yPattern, int zPattern, int layer, int animationPhase); + void draw(const Point& dest, float scaleFactor, int xPattern, int yPattern, int zPattern, int animationPhase); + void drawMask(const Point& dest, float scaleFactor, int w, int h, int xPattern, int yPattern, int zPattern, int layer, int animationPhase, SpriteMask mask); + + TexturePtr& getSprite(int w, int h, int l, int x, int y, int z, int a); + TexturePtr& getSpriteMask(int w, int h, int l, int x, int y, int z, int a, SpriteMask mask); + + bool getProperty(Property property) { return m_properties[property]; } + int getParameter(Parameter param) { return m_parameters[param]; } + int getDimension(Dimension dimension) { return m_dimensions[dimension]; } + +private: + uint getSpriteIndex(int w, int h, int l, int x, int y, int z, int a) { + uint index = ((((((a % m_dimensions[ThingType::AnimationPhases]) + * m_dimensions[ThingType::PatternZ] + z) + * m_dimensions[ThingType::PatternY] + y) + * m_dimensions[ThingType::PatternX] + x) + * m_dimensions[ThingType::Layers] + l) + * m_dimensions[ThingType::Height] + h) + * m_dimensions[ThingType::Width] + w; + assert(index < m_sprites.size()); + return index; } + + std::array m_dimensions; + std::array m_parameters; + std::array m_properties; + std::vector m_spritesIndex; + std::vector m_sprites; + std::vector> m_spritesMask; + + friend class ThingsType; }; typedef std::vector ThingTypeList; diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index 6290e6b3..265d4742 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -55,10 +55,10 @@ void OTClient::registerLuaFunctions() g_lua.registerStaticClass("g_sprites"); g_lua.bindClassStaticFunction("g_sprites", "load", std::bind(&SpriteManager::load, &g_sprites, std::placeholders::_1)); + g_lua.bindClassStaticFunction("g_sprites", "unload", std::bind(&SpriteManager::unload, &g_sprites)); g_lua.bindClassStaticFunction("g_sprites", "isLoaded", std::bind(&SpriteManager::isLoaded, &g_sprites)); g_lua.bindClassStaticFunction("g_sprites", "getSignature", std::bind(&SpriteManager::getSignature, &g_sprites)); - g_lua.bindClassStaticFunction("g_sprites", "preloadSprites", std::bind(&SpriteManager::preloadSprites, &g_sprites)); - g_lua.bindClassStaticFunction("g_sprites", "export", std::bind(&SpriteManager::exportSprites, &g_sprites)); + g_lua.bindClassStaticFunction("g_sprites", "getSpritesCount", std::bind(&SpriteManager::getSpritesCount, &g_sprites)); g_lua.registerStaticClass("g_map"); g_lua.bindClassStaticFunction("g_map", "isLookPossible", std::bind(&Map::isLookPossible, &g_map, std::placeholders::_1));