rework on dat and spr loader

This commit is contained in:
Eduardo Bart 2011-08-15 16:15:49 -03:00
parent b21ccd16f9
commit 2e1a96c2df
43 changed files with 191 additions and 581 deletions

1
.gitignore vendored
View File

@ -10,4 +10,5 @@ otclient.exe
.kdev*
otclient.kdev4
CMakeLists.txt.user
callgrind.out.*
!.gitignore

View File

@ -1,2 +1,3 @@
Programming
Developers
edubart - leader developer <edub4rt@gmail.com>
baxnie - developer <henrique_santiago93@hotmail.com>

View File

@ -58,8 +58,8 @@ SET(SOURCES
# otclient core
src/otclient/core/game.cpp
src/otclient/core/map.cpp
src/otclient/core/tibiadat.cpp
src/otclient/core/tibiaspr.cpp
src/otclient/core/datmanager.cpp
src/otclient/core/spritemanager.cpp
src/otclient/core/item.cpp
src/otclient/core/tile.cpp
src/otclient/core/thing.cpp

View File

@ -1,6 +1,6 @@
Button < UIButton
font: helvetica-11px-bold
font-color: 240 173 77
font-color: #f0ad4dff
size: 106 24
border-image:
source: /core_ui/images/button.png

View File

@ -6,7 +6,7 @@ FlatPanel < Panel
border: 4
RoundedPanel < Panel
color: 255 255 255 192
color: #ffffffc0
border-image:
source: /core_ui/images/panel_rounded.png
border: 4

View File

@ -2,7 +2,7 @@ GFX = { }
function GFX.fadeIn(widget, time, elapsed)
if not elapsed then elapsed = 0 end
if not time then time = 750 end
if not time then time = 250 end
widget.opacity = math.min((255*elapsed)/time, 255)
if elapsed < time then
scheduleEvent(function()
@ -13,7 +13,7 @@ end
function GFX.fadeOut(widget, time, elapsed)
if not elapsed then elapsed = 0 end
if not time then time = 750 end
if not time then time = 250 end
widget.opacity = (255*(time - elapsed))/time
if elapsed < time then
scheduleEvent(function()

View File

@ -89,10 +89,9 @@ void ResourceManager::loadFile(const std::string& fileName, std::iostream& out)
} else {
int fileSize = PHYSFS_fileLength(file);
if(fileSize > 0) {
char* buffer = new char[fileSize];
PHYSFS_read(file, (void*)buffer, 1, fileSize);
out.write(buffer, fileSize);
delete[] buffer;
std::vector<char> buffer(fileSize);
PHYSFS_read(file, (void*)&buffer[0], 1, fileSize);
out.write(&buffer[0], fileSize);
} else
out.clear(std::ios::eofbit);
PHYSFS_close(file);
@ -124,10 +123,9 @@ bool ResourceManager::saveFile(const std::string& fileName, std::istream& in)
in.seekg(0, std::ios::end);
std::streampos size = in.tellg();
in.seekg(0, std::ios::beg);
char* buffer = new char[size];
in.read(buffer, size);
bool ret = saveFile(fileName, (const uchar*)buffer, size);
delete[] buffer;
std::vector<char> buffer(size);
in.read(&buffer[0], size);
bool ret = saveFile(fileName, (const uchar*)&buffer[0], size);
in.seekg(oldPos, std::ios::beg);
return ret;
}
@ -145,10 +143,10 @@ bool ResourceManager::deleteFile(const std::string& fileName)
std::list<std::string> ResourceManager::listDirectoryFiles(const std::string& directoryPath)
{
std::list<std::string> files;
char** rc = PHYSFS_enumerateFiles(resolvePath(directoryPath).c_str());
auto rc = PHYSFS_enumerateFiles(resolvePath(directoryPath).c_str());
for(char** i = rc; *i != NULL; i++)
files.push_back(*i);
for(int i = 0; rc[i] != NULL; i++)
files.push_back(rc[i]);
PHYSFS_freeList(rc);
return files;

View File

@ -29,6 +29,7 @@
#include <typeinfo>
#include <array>
#include <iomanip>
#include <unordered_map>
// boost utilities
#include <boost/algorithm/string.hpp>

View File

@ -12,8 +12,8 @@ AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFra
{
m_size.setSize(width, height);
m_framesTextureId = new uint[numFrames];
m_framesDelay = new int[numFrames];
m_framesTextureId.resize(numFrames);
m_framesDelay.resize(numFrames);
for(int i=0;i<numFrames;++i) {
uchar *framePixels = framesPixels + (i*height*width* channels);
@ -29,9 +29,8 @@ AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFra
AnimatedTexture::~AnimatedTexture()
{
glDeleteTextures(m_numFrames, m_framesTextureId);
delete[] m_framesTextureId;
delete[] m_framesDelay;
assert(!g_graphics.isDrawing());
glDeleteTextures(m_numFrames, &m_framesTextureId[0]);
m_textureId = 0;
}

View File

@ -7,14 +7,14 @@ class AnimatedTexture : public Texture
{
public:
AnimatedTexture(int width, int height, int channels, int numFrames, uchar *framesPixels, int *framesDelay);
~AnimatedTexture();
virtual ~AnimatedTexture();
void enableBilinearFilter();
void processAnimation();
private:
uint *m_framesTextureId;
int *m_framesDelay;
std::vector<uint> m_framesTextureId;
std::vector<int> m_framesDelay;
int m_numFrames;
int m_currentFrame;
int m_lastAnimCheckTicks;

View File

@ -224,7 +224,7 @@ Size Font::calculateTextRectSize(const std::string& text)
void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize)
{
int numHorizontalGlyphs = m_texture->getSize().width() / glyphSize.width();
uchar *texturePixels = m_texture->getPixels();
auto texturePixels = m_texture->getPixels();
// small AI to auto calculate pixels widths
for(int glyph = m_firstGlyph; glyph< 256; ++glyph) {
@ -256,6 +256,4 @@ void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize)
// store glyph size
m_glyphsSize[glyph].setSize(width, m_glyphHeight);
}
delete[] texturePixels;
}

View File

@ -26,13 +26,16 @@ void Graphics::init()
logInfo("OpenGL ", glGetString(GL_VERSION));
m_drawing = false;
bindColor(Color::white);
m_opacity = 255;
m_emptyTexture = TexturePtr(new Texture);
bindColor(Color::white);
}
void Graphics::terminate()
{
g_fonts.releaseFonts();
m_emptyTexture.reset();
}
bool Graphics::isExtensionSupported(const char *extension)
@ -110,7 +113,7 @@ void Graphics::drawTexturedRect(const Rect& screenCoords,
const TexturePtr& texture,
const Rect& textureCoords)
{
if(screenCoords.isEmpty())
if(screenCoords.isEmpty() || texture->getId() == 0)
return;
// rect correction for opengl
@ -156,7 +159,7 @@ void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords,
const TexturePtr& texture,
const Rect& textureCoords)
{
if(screenCoords.isEmpty() || textureCoords.isEmpty())
if(screenCoords.isEmpty() || texture->getId() == 0 || textureCoords.isEmpty())
return;
if(!m_drawing) {

View File

@ -50,14 +50,17 @@ public:
void startDrawing();
void stopDrawing();
bool isDrawing() const { return m_drawing; }
int getOpacity() const { return m_opacity; }
void setOpacity(int opacity) { m_opacity = opacity; }
TexturePtr getEmptyTexture() { return m_emptyTexture; }
private:
bool m_drawing;
int m_opacity;
Size m_screenSize;
TexturePtr m_emptyTexture;
};
extern Graphics g_graphics;

View File

@ -3,14 +3,29 @@
#include <GL/gl.h>
Texture::Texture()
{
m_textureId = 0;
}
Texture::Texture(int width, int height, int channels, uchar *pixels)
{
// generate opengl texture
m_textureId = internalLoadGLTexture(pixels, channels, width, height);
}
Texture::~Texture()
{
assert(!g_graphics.isDrawing());
// free texture from gl memory
if(m_textureId > 0)
glDeleteTextures(1, &m_textureId);
}
uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int height)
{
assert(!g_graphics.isDrawing());
m_size.setSize(width, height);
// gets max texture size supported by the driver
@ -30,7 +45,8 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
bool mustFree = false;
std::vector<uchar> tmp;
// old opengl drivers only accept power of two dimensions
if(!g_graphics.isExtensionSupported("GL_ARB_texture_non_power_of_two") && pixels) {
@ -43,15 +59,13 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
glHeight = glHeight << 1;
if(m_size != m_glSize) {
uchar *tmp = new uchar[glHeight*glWidth*channels];
memset(tmp, 0, glHeight*glWidth*channels);
tmp.resize(glHeight*glWidth*channels, 0);
if(pixels)
for(int y=0; y<height; ++y)
for(int x=0; x<width; ++x)
for(int i=0; i<channels; ++i)
tmp[y*glWidth*channels+x*channels+i] = pixels[y*width*channels+x*channels+i];
pixels = tmp;
mustFree = true;
pixels = &tmp[0];
}
m_glSize.setSize(glWidth, glHeight);
@ -86,19 +100,9 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
if(mustFree)
delete[] pixels;
return id;
}
Texture::~Texture()
{
// free texture from gl memory
if(m_textureId)
glDeleteTextures(1, &m_textureId);
}
void Texture::enableBilinearFilter()
{
// enable smooth texture
@ -107,12 +111,12 @@ void Texture::enableBilinearFilter()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
uchar* Texture::getPixels()
std::vector<uint8> Texture::getPixels()
{
// copy pixels from opengl memory
uchar* pixels = new uchar[m_glSize.area()*4];
std::vector<uint8> pixels(m_glSize.area()*4, 0);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
// convert pixels to the real texture size
if(m_size != m_glSize)

View File

@ -7,6 +7,7 @@ class Texture : public std::enable_shared_from_this<Texture>
{
public:
/// Create a texture, width and height must be a multiple of 2
Texture();
Texture(int width, int height, int channels, uchar* pixels = NULL);
virtual ~Texture();
@ -17,15 +18,16 @@ public:
virtual uint getId() const { return m_textureId; }
/// Copy pixels from OpenGL texture
uchar* getPixels();
std::vector<uint8> getPixels();
int getWidth() const { return m_size.width(); }
int getHeight() const { return m_size.height(); }
const Size getSize() const { return m_size; }
const Size& getGlSize() const { return m_glSize; }
bool isEmpty() const { return m_textureId == 0; }
protected:
Texture() { }
uint internalLoadGLTexture(uchar* pixels, int channels, int w, int h);
uint m_textureId;

View File

@ -23,25 +23,6 @@ Rsa::~Rsa()
mpz_clear(m_mod);
}
bool Rsa::setKey(const std::string& file)
{
//loads p,q and d from a file
FILE* f = fopen(file.c_str(), "r");
if(!f){
return false;
}
char p[512];
char q[512];
char d[512];
delete fgets(p, 512, f);
delete fgets(q, 512, f);
delete fgets(d, 512, f);
setKey(p, q, d);
return true;
}
void Rsa::setKey(const char* p, const char* q, const char* d)
{
mpz_set_str(m_p, p, 10);

View File

@ -9,8 +9,8 @@ class Rsa
public:
Rsa();
~Rsa();
void setKey(const char* p, const char* q, const char* d);
bool setKey(const std::string& file);
bool decrypt(char* msg, int32_t size);
static bool encrypt(char* msg, int32_t size, const char* key);
@ -20,6 +20,4 @@ protected:
mpz_t m_p, m_q, m_u, m_d, m_dp, m_dq, m_mod;
};
typedef std::shared_ptr<Rsa> RsaPtr;
#endif //RSA_H
#endif

View File

@ -151,7 +151,7 @@ enum InputKeyCode {
KC_MEDIASELECT = 0xED // Media Select
};
enum InputEventType {
enum PlatformEventType {
EventNone = 0,
EventMouseAction = 1,
EventKeyboardAction = 2,
@ -175,7 +175,7 @@ enum InputEventType {
EventMouseWheelDown = EventMouseAction | EventMouseWheel | EventDown
};
struct InputEvent {
struct PlatformEvent {
int type;
Point mousePos;
Point mouseMoved;

View File

@ -11,7 +11,7 @@ public:
/// Fired when user resize the window
virtual void onResize(const Size& size) = 0;
/// Fired when user press a key or move the mouse
virtual void onInputEvent(const InputEvent& event) = 0;
virtual void onPlatformEvent(const PlatformEvent& event) = 0;
};
#endif

View File

@ -260,7 +260,7 @@ void Platform::terminate()
void Platform::poll()
{
XEvent event, peekevent;
static InputEvent inputEvent;
static PlatformEvent inputEvent;
while(XPending(x11.display) > 0) {
XNextEvent(x11.display, &event);
@ -335,7 +335,7 @@ void Platform::poll()
inputEvent.type = EventTextEnter;
inputEvent.keychar = buf[0];
inputEvent.keycode = KC_UNKNOWN;
m_listener->onInputEvent(inputEvent);
m_listener->onPlatformEvent(inputEvent);
}
}
@ -348,7 +348,7 @@ void Platform::poll()
inputEvent.keycode = x11.keyMap[keysym];
inputEvent.type = (event.type == KeyPress) ? EventKeyDown : EventKeyUp;
inputEvent.keychar = (len > 0) ? buf[0] : 0;
m_listener->onInputEvent(inputEvent);
m_listener->onPlatformEvent(inputEvent);
}
break;
}
@ -371,7 +371,7 @@ void Platform::poll()
inputEvent.type = EventMouseWheelDown;
break;
}
m_listener->onInputEvent(inputEvent);
m_listener->onPlatformEvent(inputEvent);
break;
case MotionNotify:
@ -380,7 +380,7 @@ void Platform::poll()
Point newMousePos(event.xbutton.x, event.xbutton.y);
inputEvent.mouseMoved = newMousePos - inputEvent.mousePos;
inputEvent.mousePos = newMousePos;
m_listener->onInputEvent(inputEvent);
m_listener->onPlatformEvent(inputEvent);
break;
}

View File

@ -37,7 +37,7 @@ void UIManager::resize(const Size& size)
m_rootWidget->resize(size);
}
void UIManager::inputEvent(const InputEvent& event)
void UIManager::inputEvent(const PlatformEvent& event)
{
// translate input event to ui events
if(m_rootWidget) {

View File

@ -13,7 +13,7 @@ public:
void render();
void resize(const Size& size);
void inputEvent(const InputEvent& event);
void inputEvent(const PlatformEvent& event);
bool importStyles(const std::string& file);
void importStyleFromOTML(const OTMLNodePtr& styleNode);

View File

@ -26,6 +26,7 @@ public:
void setGreen(uint8 g) { color = ((g & 0xff)<<8) | (color & 0xffff00ff); }
void setRed(uint8 r) { color = (r & 0xff) | (color & 0xffffff00); }
void setRGBA(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) { color = ((a & 0xff)<<24) | ((b & 0xff)<<16) | ((g & 0xff)<<8) | (r & 0xff); }
void setABGR(uint32 abgr) { color = ((abgr>>24) & 0xff) | ((abgr>>16) & 0xff) << 8 | ((abgr>>8) & 0xff) << 16 | (abgr & 0xff) << 24; }
void setRGBA(uint32 rgba) { color = rgba; }
Color& operator=(const Color& other) { color = other.color; return *this; }
@ -47,17 +48,26 @@ private:
inline std::ostream& operator<<(std::ostream& out, const Color& color)
{
out << (int)color.r() << " "<< (int)color.g() << " "<< (int)color.b() << " " << (int)color.a();
using namespace std;
out << "#" << hex << setfill('0')
<< setw(2) << (int)color.r()
<< setw(2) << (int)color.g()
<< setw(2) << (int)color.b()
<< setw(2) << (int)color.a();
out << dec << setfill(' ');
return out;
}
inline std::istream& operator>>(std::istream& in, Color& color)
{
int r, g, b, a = 255;
in >> r >> g >> b;
if(!in.eof())
in >> a;
color.setRGBA(r, g, b, a);
using namespace std;
if(in.get() == '#') {
uint32 tmp;
in >> hex >> tmp;
color.setABGR(tmp);
in >> dec;
}
return in;
}

View File

@ -10,6 +10,25 @@
namespace fw {
// read utilities for istream
inline uint8 getu8(std::istream& in) {
uint8 tmp;
in.read((char*)&tmp, 1);
return tmp;
}
inline uint16 getu16(std::istream& in) {
uint16 tmp;
in.read((char*)&tmp, 2);
return tmp;
}
inline uint32 getu32(std::istream& in) {
uint32 tmp;
in.read((char*)&tmp, 4);
return tmp;
}
/// Fill an ostream by concatenating args
/// Usage:
/// fw::fill_ostream(stream, a1, a2, ..., aN);

View File

@ -1,5 +1,5 @@
#include "creature.h"
#include "tibiadat.h"
#include "datmanager.h"
#include <framework/graphics/graphics.h>
#include <framework/graphics/framebuffer.h>
#include "game.h"
@ -26,9 +26,9 @@ Creature::Creature()
m_type = Thing::TYPE_CREATURE;
}
ThingAttributes *Creature::getAttributes()
const ThingAttributes& Creature::getAttributes()
{
return g_tibiaDat.getCreatureAttributes(m_outfit.type);
return g_dat.getCreatureAttributes(m_outfit.type);
}
void Creature::draw(int x, int y)

View File

@ -18,7 +18,7 @@ class Creature : public Thing
public:
Creature();
virtual ThingAttributes *getAttributes();
virtual const ThingAttributes& getAttributes();
void draw(int x, int y);
void setName(const std::string& name) { m_name = name; }

View File

@ -1,14 +1,14 @@
#include "effect.h"
#include "tibiadat.h"
#include "datmanager.h"
Effect::Effect()
{
m_type = Thing::TYPE_EFFECT;
}
ThingAttributes *Effect::getAttributes()
const ThingAttributes& Effect::getAttributes()
{
return g_tibiaDat.getEffectAttributes(m_id);
return g_dat.getEffectAttributes(m_id);
}
void Effect::draw(int x, int y)

View File

@ -10,7 +10,7 @@ class Effect : public Thing
public:
Effect();
virtual ThingAttributes *getAttributes();
virtual const ThingAttributes& getAttributes();
void draw(int x, int y);
private:

View File

@ -1,6 +1,6 @@
#include "item.h"
#include "tibiadat.h"
#include "tibiaspr.h"
#include "datmanager.h"
#include "spritemanager.h"
#include <framework/graphics/graphics.h>
#include "thing.h"
@ -9,27 +9,27 @@ Item::Item()
m_type = Thing::TYPE_ITEM;
}
ThingAttributes *Item::getAttributes()
const ThingAttributes& Item::getAttributes()
{
return g_tibiaDat.getItemAttributes(m_id);
return g_dat.getItemAttributes(m_id);
}
void Item::draw(int x, int y)
{
ThingAttributes *itemAttributes = getAttributes();
auto attributes = g_dat.getItemAttributes(m_id);
int xdiv = 0, ydiv = 0, zdiv = 0, anim = 0;
if(itemAttributes->group == THING_GROUP_SPLASH || itemAttributes->group == THING_GROUP_FLUID || itemAttributes->stackable) {
if(attributes.group == THING_GROUP_SPLASH || attributes.group == THING_GROUP_FLUID || attributes.stackable) {
//cDivX = subType % itemAttributes->xdiv;
//cDivY = subType / itemAttributes->xdiv;
}
else if(!itemAttributes->moveable) {
xdiv = m_position.x % itemAttributes->xdiv;
ydiv = m_position.y % itemAttributes->ydiv;
zdiv = m_position.z % itemAttributes->zdiv;
else if(!attributes.moveable) {
xdiv = m_position.x % attributes.xdiv;
ydiv = m_position.y % attributes.ydiv;
zdiv = m_position.z % attributes.zdiv;
}
for(int b = 0; b < itemAttributes->blendframes; b++)
for(int b = 0; b < attributes.blendframes; b++)
internalDraw(x, y, b, xdiv, ydiv, zdiv, anim);
}

View File

@ -9,7 +9,7 @@ class Item : public Thing
public:
Item();
virtual ThingAttributes *getAttributes();
virtual const ThingAttributes& getAttributes();
void draw(int x, int y);
void setCount(uint8 count) { m_count = count; }

View File

@ -4,7 +4,6 @@
#include "tile.h"
#include "effect.h"
#include <framework/graphics/declarations.h>
#include <unordered_map>
struct MapPositionHasher : std::unary_function<Position, std::size_t> {
std::size_t operator()(const Position& pos) const {

View File

@ -1,5 +1,5 @@
#include "thing.h"
#include "tibiaspr.h"
#include "spritemanager.h"
#include <framework/graphics/graphics.h>
ThingAttributes::ThingAttributes()
@ -28,7 +28,6 @@ ThingAttributes::ThingAttributes()
hasMiniMapColor = false;
subParam07 = 0;
subParam08 = 0;
sprites = NULL;
width = 0;
height = 0;
blendframes = 0;
@ -40,12 +39,6 @@ ThingAttributes::ThingAttributes()
yOffset = 0;
}
ThingAttributes::~ThingAttributes()
{
if(sprites)
delete []sprites;
}
Thing::Thing()
{
m_type = TYPE_NONE;
@ -53,31 +46,33 @@ Thing::Thing()
void Thing::internalDraw(int x, int y, int blendframes, int xdiv, int ydiv, int zdiv, int anim)
{
ThingAttributes *thingAttributes = getAttributes();
if(!thingAttributes)
return;
const ThingAttributes& attributes = getAttributes();
for(int yi = 0; yi < thingAttributes->height; yi++) {
for(int xi = 0; xi < thingAttributes->width; xi++) {
uint16 sprIndex = xi +
yi * thingAttributes->width +
blendframes * thingAttributes->width * thingAttributes->height +
xdiv * thingAttributes->width * thingAttributes->height * thingAttributes->blendframes +
ydiv * thingAttributes->width * thingAttributes->height * thingAttributes->blendframes * thingAttributes->xdiv +
zdiv * thingAttributes->width * thingAttributes->height * thingAttributes->blendframes * thingAttributes->xdiv * thingAttributes->ydiv +
anim * thingAttributes->width * thingAttributes->height * thingAttributes->blendframes * thingAttributes->xdiv * thingAttributes->ydiv * thingAttributes->zdiv;
uint16 itemId = thingAttributes->sprites[sprIndex];
if(itemId == 0xFFFF)
for(int yi = 0; yi < attributes.height; yi++) {
for(int xi = 0; xi < attributes.width; xi++) {
int sprIndex = xi +
yi * attributes.width +
blendframes * attributes.width * attributes.height +
xdiv * attributes.width * attributes.height * attributes.blendframes +
ydiv * attributes.width * attributes.height * attributes.blendframes * attributes.xdiv +
zdiv * attributes.width * attributes.height * attributes.blendframes * attributes.xdiv * attributes.ydiv +
anim * attributes.width * attributes.height * attributes.blendframes * attributes.xdiv * attributes.ydiv * attributes.zdiv;
int spriteId = attributes.sprites[sprIndex];
if(!spriteId)
continue;
TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId);
if(spriteTex->isEmpty())
continue;
TexturePtr data = g_tibiaSpr.getSprite(itemId);
int offsetX = 0, offsetY = 0;
if(thingAttributes->hasHeight) {
offsetX = thingAttributes->xOffset;
offsetY = thingAttributes->xOffset; // << look to xoffset
if(attributes.hasHeight) {
offsetX = attributes.xOffset;
offsetY = attributes.xOffset; // << look to xoffset
}
g_graphics.drawTexturedRect(Rect((x - xi*32) - offsetX, (y - yi*32) - offsetY, 32, 32), data, Rect(0, 0, 32, 32));
g_graphics.drawTexturedRect(Rect((x - xi*32) - offsetX, (y - yi*32) - offsetY, 32, 32), spriteTex, Rect(0, 0, 32, 32));
}
}
}

View File

@ -7,22 +7,15 @@
struct ThingAttributes
{
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 id, speed, subParam07, subParam08, lightLevel, lightColor, miniMapColor;
uint16 *sprites;
uint16 speed, subParam07, subParam08, lightLevel, lightColor, miniMapColor;
std::vector<int> sprites;
ThingAttributesGroup group;
};
class Creature;
class Item;
class Thing;
typedef std::shared_ptr<Thing> ThingPtr;
class Thing
{
public:
@ -46,7 +39,7 @@ public:
Position *getPosition() { return &m_position; }
virtual void draw(int, int) {}
virtual ThingAttributes *getAttributes() { return NULL; }
virtual const ThingAttributes& getAttributes() = 0;
virtual Item* getItem() { return NULL; }
virtual const Item *getItem() const { return NULL; }
@ -62,4 +55,4 @@ protected:
};
#endif // THING_H
#endif

View File

@ -1,205 +0,0 @@
#include "tibiadat.h"
#include "tibiaspr.h"
#include <framework/core/resourcemanager.h>
TibiaDat g_tibiaDat;
bool TibiaDat::load(const std::string& filename)
{
std::stringstream fin;
g_resources.loadFile(filename, fin);
fin.read((char*)&m_signature, 4);
fin.read((char*)&m_groupCount[0], 2);
fin.read((char*)&m_groupCount[1], 2);
fin.read((char*)&m_groupCount[2], 2);
fin.read((char*)&m_groupCount[3], 2);
m_groupCount[0] -= 99;
m_totalCount = m_groupCount[0] + m_groupCount[1] + m_groupCount[2] + m_groupCount[3];
m_thingsAttributes = new ThingAttributes*[m_totalCount+1];
for(uint16 i = 0; i <= m_totalCount; i++)
m_thingsAttributes[i] = NULL;
uint8 read_byte;
uint16 read_short;
//uint32 read_long;
for(uint16 id = 0; (id <= m_totalCount) && !fin.eof(); id++) {
m_thingsAttributes[id] = new ThingAttributes();
m_thingsAttributes[id]->id = id;
uint8 opt;
bool done = false;
while(!done) {
fin.read((char*)&opt, 1);
if(opt == 0x00) { // Ground tile
fin.read((char*)&m_thingsAttributes[id]->speed, 2);
m_thingsAttributes[id]->group = THING_GROUP_GROUND;
}
else if(opt == 0x01) { // All OnTop
m_thingsAttributes[id]->alwaysOnTop = true;
m_thingsAttributes[id]->alwaysOnTopOrder = 1;
}
else if(opt == 0x02) { // Can walk trough (open doors, arces, bug pen fence)
m_thingsAttributes[id]->alwaysOnTop = true;
m_thingsAttributes[id]->alwaysOnTopOrder = 2;
}
else if(opt == 0x03) { // Can walk trough (arces)
m_thingsAttributes[id]->alwaysOnTop = true;
m_thingsAttributes[id]->alwaysOnTopOrder = 3;
}
else if(opt == 0x04) { // Container
m_thingsAttributes[id]->group = THING_GROUP_CONTAINER;
}
else if(opt == 0x05) { // Stackable
m_thingsAttributes[id]->stackable = true;
}
else if(opt == 0x06) { // Unknown
}
else if(opt == 0x07) { // Useable
m_thingsAttributes[id]->useable = true;
}
else if(opt == 0x08) { // Writtable
m_thingsAttributes[id]->group = THING_GROUP_WRITEABLE;
m_thingsAttributes[id]->readable = true;
fin.read((char*)&m_thingsAttributes[id]->subParam07, 2);
}
else if(opt == 0x09) { // Writtable once
// Writtable objects that can't be edited by players
m_thingsAttributes[id]->readable = true;
fin.read((char*)&m_thingsAttributes[id]->subParam08, 2);
}
else if(opt == 0x0A) { // Fluid containers
fin.read((char*)&read_byte, 1);
m_thingsAttributes[id]->group = THING_GROUP_FLUID;
}
else if(opt == 0x0B) { // Splashes
m_thingsAttributes[id]->group = THING_GROUP_SPLASH;
}
else if(opt == 0x0C) { // Blocks solid objects (creatures, walls etc)
m_thingsAttributes[id]->blockSolid = true;
}
else if(opt == 0x0D) { // Not moveable
m_thingsAttributes[id]->moveable = false;
}
else if(opt == 0x0E) { // Blocks missiles (walls, magic wall etc)
m_thingsAttributes[id]->blockProjectile = true;
}
else if(opt == 0x0F) { // Blocks pathfind algorithms (monsters)
m_thingsAttributes[id]->blockPathFind = true;
}
else if(opt == 0x10) { // Blocks monster movement (flowers, parcels etc)
m_thingsAttributes[id]->pickupable = true;
}
else if(opt == 0x11) { // Hangable objects (wallpaper etc)
m_thingsAttributes[id]->isHangable = true;
}
else if(opt == 0x12) { // Horizontal wall
m_thingsAttributes[id]->isHorizontal = true;
}
else if(opt == 0x13) { // Vertical wall
m_thingsAttributes[id]->isVertical = true;
}
else if(opt == 0x14) { // Rotable
m_thingsAttributes[id]->rotable = true;
}
else if(opt == 0x15) { // Light info
fin.read((char*)&m_thingsAttributes[id]->lightLevel, 2);
fin.read((char*)&m_thingsAttributes[id]->lightColor, 2);
}
else if(opt == 0x16) {
}
else if(opt == 0x17) { // Changes floor
}
else if(opt == 0x18) { // Thing must be drawed with offset
m_thingsAttributes[id]->hasHeight = true;
fin.read((char*)&m_thingsAttributes[id]->xOffset, 1);
fin.read((char*)&m_thingsAttributes[id]->yOffset, 1);
fin.read((char*)&read_short, 2);
}
else if(opt == 0x19) { // pixels characters height
fin.read((char*)&m_thingsAttributes[id]->xOffset, 1);
fin.read((char*)&m_thingsAttributes[id]->yOffset, 1);
//logDebug((int)m_thingsAttributes[id]->xOffset, " ", (int)m_thingsAttributes[id]->yOffset);
}
else if(opt == 0x1A) {
//m_thingsAttributes[id]->hasHeight = true;
}
else if(opt == 0x1B) {
}
else if(opt == 0x1C) { // Minimap color
fin.read((char*)&m_thingsAttributes[id]->miniMapColor, 2);
m_thingsAttributes[id]->hasMiniMapColor = true;
}
else if(opt == 0x1D) { // Unknown
fin.read((char*)&read_short, 2);
if(read_short == 1112)
m_thingsAttributes[id]->readable = true;
}
else if(opt == 0x1E) {
}
else if(opt == 0x1F) {
m_thingsAttributes[id]->lookThrough = true;
}
else if(opt == 0x20) {
}
else if(opt == 0xFF) {
done = true;
}
else {
logDebug("Unknown byte code: ", opt);
return false;
}
}
fin.read((char*)&m_thingsAttributes[id]->width, 1);
fin.read((char*)&m_thingsAttributes[id]->height, 1);
if((m_thingsAttributes[id]->width > 1) || (m_thingsAttributes[id]->height > 1))
fin.read((char*)&read_byte, 1);
fin.read((char*)&m_thingsAttributes[id]->blendframes, 1);
fin.read((char*)&m_thingsAttributes[id]->xdiv, 1);
fin.read((char*)&m_thingsAttributes[id]->ydiv, 1);
fin.read((char*)&m_thingsAttributes[id]->zdiv, 1);
fin.read((char*)&m_thingsAttributes[id]->animcount, 1);
// Read sprites id.
uint16 totalSprites = m_thingsAttributes[id]->width * m_thingsAttributes[id]->height * m_thingsAttributes[id]->blendframes * m_thingsAttributes[id]->xdiv * m_thingsAttributes[id]->ydiv * m_thingsAttributes[id]->zdiv * m_thingsAttributes[id]->animcount;
m_thingsAttributes[id]->sprites = new uint16[totalSprites];
for(uint16 i = 0; i < totalSprites; i++) {
fin.read((char*)&read_short, 2);
m_thingsAttributes[id]->sprites[i] = read_short-1;
}
}
return true;
}
ThingAttributes *TibiaDat::getItemAttributes(uint16 id)
{
return m_thingsAttributes[id - 100];
}
ThingAttributes *TibiaDat::getCreatureAttributes(uint16 id)
{
return m_thingsAttributes[id - 1 + m_groupCount[0]];
}
ThingAttributes *TibiaDat::getEffectAttributes(uint16 id)
{
return m_thingsAttributes[id - 1 + m_groupCount[0] + m_groupCount[1]];
}
ThingAttributes *TibiaDat::getShotAttributes(uint16 id)
{
return m_thingsAttributes[id - 100 + m_groupCount[0] + m_groupCount[1] + m_groupCount[2]];
}

View File

@ -1,31 +0,0 @@
#ifndef TIBIADAT_H
#define TIBIADAT_H
#include <framework/global.h>
#include "thing.h"
class TibiaDat
{
public:
bool load(const std::string& filename);
ThingAttributes *getItemAttributes(uint16 id);
ThingAttributes *getCreatureAttributes(uint16 id);
ThingAttributes *getEffectAttributes(uint16 id);
ThingAttributes *getShotAttributes(uint16 id);
uint16 getGroupCount(int i) { return m_groupCount[i]; }
uint32 getSignature() { return m_signature; }
uint16 getTotalCount() { return m_totalCount; }
private:
uint32 m_signature, m_totalCount;
uint16 m_groupCount[4];
ThingAttributes **m_thingsAttributes;
};
extern TibiaDat g_tibiaDat;
#endif // TIBIADAT_H

View File

@ -1,120 +0,0 @@
#include "tibiaspr.h"
#include <framework/core/resourcemanager.h>
TibiaSpr g_tibiaSpr;
TibiaSpr::TibiaSpr()
{
m_sprites = NULL;
m_spritesCount = 0;
}
TibiaSpr::~TibiaSpr()
{
//for(uint16 i = 0; i < m_spritesCount; i++)
//if(m_sprites[i])
//delete m_sprites[i];
if(m_sprites)
delete []m_sprites;
//delete m_transparentSprite;
}
bool TibiaSpr::load(const std::string &filename)
{
g_resources.loadFile(filename, m_fin);
m_fin.read((char*)&m_signature, 4);
m_fin.read((char*)&m_spritesCount, 2);
m_sprites = new TexturePtr[m_spritesCount];
//for(uint16 i = 0; i < m_spritesCount; i++)
//m_sprites[i] = NULL;
uchar pixels[4096];
for(int i = 0; i < 32*32*4; i += 4) {
pixels[i + 0] = 0xFF;
pixels[i + 1] = 0x00;
pixels[i + 2] = 0xFF;
pixels[i + 3] = 0xFF;
}
m_transparentSprite = TexturePtr(new Texture(32, 32, 4, pixels));
return true;
}
TexturePtr TibiaSpr::loadSprite(uint32 id)
{
if(m_fin.eof())
return TexturePtr();
m_fin.seekg((id * 4) + 6, std::ios_base::beg);
uint32 spriteAddress;
m_fin.read((char*)&spriteAddress, 4);
if(spriteAddress == 0) // Some error on tibia.spr, save a blank image.
return TexturePtr();
m_fin.seekg(spriteAddress, std::ios_base::beg);
uint32 colorKey = 0;
m_fin.read((char*)&colorKey, 3);
uint16 spriteSize;
m_fin.read((char*)&spriteSize, 2);
uchar image[4096];
uint16 imgPos = 0, read = 0, transparentPixels, coloredPixels, x;
while(read < spriteSize) {
m_fin.read((char*)&transparentPixels, 2);
m_fin.read((char*)&coloredPixels, 2);
for(x = 0; x < transparentPixels; x++) {
image[imgPos + 0] = 0x00;
image[imgPos + 1] = 0x00;
image[imgPos + 2] = 0x00;
image[imgPos + 3] = 0x00;
imgPos += 4;
}
for(x = 0; x < coloredPixels; x++) {
m_fin.read((char*)&image[imgPos + 0], 1);
m_fin.read((char*)&image[imgPos + 1], 1);
m_fin.read((char*)&image[imgPos + 2], 1);
image[imgPos + 3] = 0xFF;
imgPos += 4;
}
read += 4 + (3 * coloredPixels);
}
// Fill remaining bytes with pink.
if(imgPos < 32 * 32 * 4) {
for(x = imgPos; x < 32 * 32 * 4; x += 4) {
image[x + 0] = 0xFF;
image[x + 1] = 0x00;
image[x + 2] = 0xFF;
image[x + 3] = 0x00;
}
}
return TexturePtr(new Texture(32, 32, 4, image));
}
TexturePtr TibiaSpr::getSprite(uint32 id)
{
if(!m_sprites)
return m_transparentSprite;
if(!m_sprites[id]) {
m_sprites[id] = loadSprite(id);
if(!m_sprites[id])
return m_transparentSprite;
}
return m_sprites[id];
}

View File

@ -1,31 +0,0 @@
#ifndef TIBIASPR_H
#define TIBIASPR_H
#include <framework/global.h>
#include <framework/graphics/texture.h>
class TibiaSpr
{
public:
TibiaSpr();
~TibiaSpr();
bool load(const std::string& filename);
uint32 getSignature() { return m_signature; }
uint16 getSpritesCount() { return m_spritesCount; }
TexturePtr getSprite(uint32 id);
private:
TexturePtr loadSprite(uint32 id);
std::stringstream m_fin;
uint32 m_signature;
uint16 m_spritesCount;
TexturePtr *m_sprites;
TexturePtr m_transparentSprite;
};
extern TibiaSpr g_tibiaSpr;
#endif // TIBIASPR_H

View File

@ -1,10 +1,10 @@
#include "tile.h"
#include "item.h"
#include "tibiadat.h"
#include "datmanager.h"
Tile::Tile()
{
m_ground = NULL;
}
void Tile::addThing(ThingPtr thing, uint8 stackpos)
@ -12,23 +12,19 @@ void Tile::addThing(ThingPtr thing, uint8 stackpos)
if(!thing)
return;
ThingAttributes *thingAttributes = thing->getAttributes();
if(thingAttributes) {
if(thing->getType() == Thing::TYPE_ITEM) {
if(thingAttributes->group == THING_GROUP_GROUND)
m_ground = thing;
else {
if(thingAttributes->alwaysOnTop)
m_itemsTop.push_back(thing);
else
m_itemsBot.push_back(thing);
}
}
else if(thing->getType() == Thing::TYPE_CREATURE) {
m_creatures.push_back(thing);
const ThingAttributes& thingAttributes = thing->getAttributes();
if(thing->getType() == Thing::TYPE_ITEM) {
if(thingAttributes.group == THING_GROUP_GROUND)
m_ground = thing;
else {
if(thingAttributes.alwaysOnTop)
m_itemsTop.push_back(thing);
else
m_itemsBot.push_back(thing);
}
} else if(thing->getType() == Thing::TYPE_CREATURE) {
m_creatures.push_back(thing);
}
}
void Tile::draw(int x, int y)
@ -36,20 +32,14 @@ void Tile::draw(int x, int y)
if(m_ground)
m_ground->draw(x, y);
for(auto it = m_itemsTop.begin(), end = m_itemsTop.end(); it != end; ++it)
(*it)->draw(x, y);
for(const ThingPtr& thing : m_itemsBot)
thing->draw(x, y);
for(auto it = m_creatures.begin(), end = m_creatures.end(); it != end; ++it)
(*it)->draw(x, y);
for(const ThingPtr& thing : m_creatures)
thing->draw(x, y);
for(auto it = m_itemsBot.begin(), end = m_itemsBot.end(); it != end; ++it)
(*it)->draw(x, y);
}
bool Tile::hasGround()
{
return m_ground != 0;
for(const ThingPtr& thing : m_itemsTop)
thing->draw(x, y);
}
int Tile::getStackSize()
@ -57,10 +47,8 @@ int Tile::getStackSize()
int ret = 0;
if(m_ground)
ret++;
ret += m_itemsBot.size();
ret += m_creatures.size();
ret += m_itemsTop.size();
return ret;
}

View File

@ -11,14 +11,16 @@ public:
void addThing(ThingPtr thing, uint8 stackpos);
void draw(int x, int y);
bool hasGround();
bool hasGround() { return (!!m_ground); }
int getStackSize();
private:
ThingPtr m_ground;
std::list<ThingPtr> m_itemsBot;
std::list<ThingPtr> m_creatures;
std::list<ThingPtr> m_itemsTop;
std::deque<ThingPtr> m_itemsBot;
std::deque<ThingPtr> m_creatures;
std::deque<ThingPtr> m_itemsTop;
};
#endif

View File

@ -1,7 +1,7 @@
#include "protocolgame.h"
#include <otclient/core/player.h>
#include <otclient/core/tibiadat.h>
#include <otclient/core/datmanager.h>
#include <otclient/core/game.h>
#include <otclient/core/map.h>
#include <otclient/core/effect.h>
@ -926,9 +926,10 @@ ItemPtr ProtocolGame::internalGetItem(InputMessage& msg, uint16 id)
id = msg.getU16();
item->setId(id);
ThingAttributes *itemAttributes = g_tibiaDat.getItemAttributes(id);
if(itemAttributes->stackable || itemAttributes->group == THING_GROUP_FLUID || itemAttributes->group == THING_GROUP_SPLASH)
const ThingAttributes& itemAttributes = g_dat.getItemAttributes(id);
if(itemAttributes.stackable || itemAttributes.group == THING_GROUP_FLUID || itemAttributes.group == THING_GROUP_SPLASH) {
item->setCount(msg.getU8());
}
return item;
}

View File

@ -199,6 +199,7 @@ void OTClient::poll()
void OTClient::render()
{
//TODO: UIMap for map drawing
if(g_game.getOnline())
g_game.getMap()->draw(0, 0);
@ -258,7 +259,7 @@ void OTClient::onResize(const Size& size)
g_ui.resize(size);
}
void OTClient::onInputEvent(const InputEvent& event)
void OTClient::onPlatformEvent(const PlatformEvent& event)
{
g_ui.inputEvent(event);

View File

@ -25,7 +25,7 @@ public:
/// Fired when user resize the window
void onResize(const Size& size);
/// Fired on an user input event
void onInputEvent(const InputEvent& event);
void onPlatformEvent(const PlatformEvent& event);
bool isRunning() const { return m_running; }

View File

@ -1,8 +1,8 @@
#include "otclient.h"
#include <framework/luascript/luainterface.h>
#include <otclient/core/tibiadat.h>
#include <otclient/core/tibiaspr.h>
#include <otclient/core/datmanager.h>
#include <otclient/core/spritemanager.h>
#include <otclient/net/protocollogin.h>
#include <otclient/net/protocolgame.h>
@ -13,8 +13,8 @@ void OTClient::registerLuaFunctions()
g_lua.bindGlobalFunction("exit", std::bind(&OTClient::exit, &g_client));
g_lua.bindGlobalFunction("setOnClose", std::bind(&OTClient::setOnClose, &g_client, _1));
g_lua.bindGlobalFunction("importDat", std::bind(&TibiaDat::load, &g_tibiaDat, _1));
g_lua.bindGlobalFunction("importSpr", std::bind(&TibiaSpr::load, &g_tibiaSpr, _1));
g_lua.bindGlobalFunction("importDat", std::bind(&DatManager::load, &g_dat, _1));
g_lua.bindGlobalFunction("importSpr", std::bind(&SpriteManager::load, &g_sprites, _1));
g_lua.registerClass<ProtocolLogin, Protocol>();
g_lua.bindClassStaticFunction<ProtocolLogin>("create", &ProtocolLogin::create);