restore outfit colors
* rework sprite manager and ThingType * render colored outfits again compatible with OpenGL 1
This commit is contained in:
parent
fea34a41ea
commit
6495d74edd
1
TODO
1
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
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
PlayerTrade = {}
|
||||
|
||||
-- g_game.inspectTrade(counterOffer, index)
|
||||
-- g_game.acceptTrade()
|
||||
-- g_game.rejectTrade()
|
||||
|
||||
local tradeWindow
|
||||
|
||||
local function createTrade()
|
||||
|
|
|
@ -31,6 +31,7 @@ Image::Image(const Size& size, int bpp, uint8 *pixels)
|
|||
m_size = size;
|
||||
m_bpp = bpp;
|
||||
m_pixels.resize(size.area() * bpp);
|
||||
if(pixels)
|
||||
memcpy(&m_pixels[0], pixels, m_pixels.size());
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
int maskId = getSpriteId(w, h, 1, xPattern, yPattern, zPattern, animationPhase);
|
||||
maskTex = g_sprites.getSpriteTexture(maskId);
|
||||
}
|
||||
//outfitProgram->setTexture(maskTex, 1);
|
||||
if(getLayers() > 1)
|
||||
maskTex = m_type->getSprite(w, h, 1, xPattern, yPattern, zPattern, animationPhase);
|
||||
|
||||
internalDraw(dest + (-Point(w,h)*Otc::TILE_PIXELS)*scaleFactor,
|
||||
scaleFactor, w, h, xPattern, yPattern, zPattern, 0, 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) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
if(id == 0)
|
||||
return nullptr;
|
||||
|
||||
for(int i=1;i<=m_spritesCount;i+=burst)
|
||||
g_eventDispatcher.scheduleEvent(std::bind(preload, i), (i/burst) * interval);
|
||||
}
|
||||
|
||||
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;
|
||||
enum SpriteMask {
|
||||
YellowMask = 0,
|
||||
RedMask,
|
||||
GreenMask,
|
||||
BlueMask,
|
||||
LastMask
|
||||
};
|
||||
|
||||
if(sprIndex >= 0 && sprIndex < (int)sprites.size())
|
||||
return sprites[sprIndex];
|
||||
ThingType();
|
||||
|
||||
return 0;
|
||||
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…
Reference in New Issue