restore outfit colors

* rework sprite manager and ThingType
* render colored outfits again compatible with OpenGL 1
master
Eduardo Bart 12 years ago
parent fea34a41ea
commit 6495d74edd

@ -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

@ -1,9 +1,5 @@
PlayerTrade = {}
-- g_game.inspectTrade(counterOffer, index)
-- g_game.acceptTrade()
-- g_game.rejectTrade()
local tradeWindow
local function createTrade()

@ -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<getPixelCount();p++) {
uint8& r = m_pixels[p*4 + 0];
uint8& g = m_pixels[p*4 + 1];
uint8& b = m_pixels[p*4 + 2];
uint8& a = m_pixels[p*4 + 3];
Color pixelColor(r,g,b,a);
Color writeColor = (pixelColor == maskedColor) ? insideColor : outsideColor;
r = writeColor.r();
g = writeColor.g();
b = writeColor.b();
a = writeColor.a();
}
}

@ -29,13 +29,19 @@
class Image
{
public:
Image(const Size& size, int bpp, uint8 *pixels);
Image(const Size& size, int bpp = 4, uint8 *pixels = nullptr);
static ImagePtr load(const std::string& file);
static ImagePtr loadPNG(const std::string& file);
const std::vector<uint8>& getPixels() { return m_pixels; }
void overwriteMask(const Color& maskedColor, const Color& insideColor = Color::white, const Color& outsideColor = Color::alpha);
std::vector<uint8>& 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:

@ -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

@ -29,6 +29,7 @@ class Texture : public std::enable_shared_from_this<Texture>
{
public:
Texture();
Texture(const ImagePtr& image);
Texture(int width, int height, int channels, uchar* pixels = NULL);
virtual ~Texture();

@ -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

@ -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);
}
}

@ -41,6 +41,8 @@ class Effect;
class Missile;
class AnimatedText;
class StaticText;
class ThingType;
class ThingsType;
typedef std::shared_ptr<MapView> MapViewPtr;
typedef std::shared_ptr<Tile> TilePtr;

@ -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()

@ -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();

@ -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)

@ -22,10 +22,8 @@
#include "spritemanager.h"
#include <framework/core/resourcemanager.h>
#include <framework/core/eventdispatcher.h>
#include <framework/core/filestream.h>
#include <framework/graphics/graphics.h>
#include <framework/thirdparty/apngloader.h>
#include <framework/graphics/image.h>
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;i<start+burst && i<=m_spritesCount;++i) {
loadSpriteTexture(i);
}
};
for(int i=1;i<=m_spritesCount;i+=burst)
g_eventDispatcher.scheduleEvent(std::bind(preload, i), (i/burst) * interval);
}
if(id == 0)
return nullptr;
TexturePtr SpriteManager::loadSpriteTexture(int id)
{
m_spritesFile->seek(((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<uint8> 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;
}

@ -24,40 +24,26 @@
#define SPRITEMANAGER_H
#include <framework/core/declarations.h>
#include <framework/graphics/texture.h>
#include <framework/graphics/declarations.h>
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<false> m_loaded;
uint32 m_signature;
int m_spritesCount;
std::vector<TexturePtr> m_sprites;
TexturePtr m_transparentSprite;
FileStreamPtr m_spritesFile;
};

@ -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);
}

@ -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;
};

@ -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)

@ -25,16 +25,11 @@
#include "declarations.h"
#include <framework/graphics/declarations.h>
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<int, LastDimension> dimensions;
std::vector<int> sprites;
enum Properties {
enum Property {
IsGround = 0,
IsGroundBorder,
IsOnBottom,
@ -86,9 +79,8 @@ struct ThingType
LastProperty,
LastPropertyValue = 255
};
std::array<bool, LastProperty> properties;
enum Parameters {
enum Parameter {
GroundSpeed = 0,
Fluid,
MaxTextLenght,
@ -102,23 +94,49 @@ struct ThingType
Elevation,
LastParameter
};
std::array<int, LastParameter> 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<int, LastDimension> m_dimensions;
std::array<int, LastParameter> m_parameters;
std::array<bool, LastProperty> m_properties;
std::vector<int> m_spritesIndex;
std::vector<TexturePtr> m_sprites;
std::vector<std::array<TexturePtr, LastMask>> m_spritesMask;
friend class ThingsType;
};
typedef std::vector<ThingType> ThingTypeList;

@ -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));

Loading…
Cancel
Save