map draw working with lil bugs

This commit is contained in:
Henrique 2011-08-11 02:52:30 -03:00
parent 3a5683b549
commit 651315d4cd
24 changed files with 616 additions and 163 deletions

View File

@ -50,11 +50,20 @@ SET(SOURCES
# game files
src/tibiadat.cpp
src/tibiaspr.cpp
# game contents
src/game.cpp
src/map.cpp
src/tile.cpp
src/thing.cpp
src/item.cpp
# game net
src/protocollogin.cpp
src/protocolgame.cpp
src/protocolgameparse.cpp
src/protocolgamesend.cpp
# framework core
src/framework/core/dispatcher.cpp

View File

@ -8,6 +8,7 @@
#include <ui/uiskins.h>
#include <script/luainterface.h>
#include <net/connection.h>
#include <../game.h>
Engine g_engine;
@ -95,6 +96,9 @@ void Engine::run()
if(m_calculateFps)
defaultFont->renderText(fpsText, Point(g_graphics.getScreenSize().width() - fpsTextSize.width() - 10, 10));
// todo remove. render map
g_game.getMap()->draw(0, 0, g_graphics.getScreenSize().width(), g_graphics.getScreenSize().height());
g_graphics.endRender();
// swap buffers

View File

@ -34,7 +34,9 @@ Texture::Texture(int width, int height, int channels, uchar *pixels)
uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int height)
{
GLint texSize;
g_graphics.disableDrawing();
GLint texSize = 0;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
if(width > texSize || height > texSize) {
logError("loading texture with size ",width,"x",height," failed, the maximum size is ",texSize,"x",texSize);

3
src/game.cpp Normal file
View File

@ -0,0 +1,3 @@
#include "game.h"
Game g_game;

22
src/game.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef GAME_H
#define GAME_H
#include <global.h>
#include "map.h"
#include "player.h"
class Game
{
public:
Map *getMap() { return &m_map; }
Player *getPlayer() { return &m_player; }
private:
Map m_map;
Player m_player;
};
extern Game g_game;
#endif // GAME_H

79
src/item.cpp Normal file
View File

@ -0,0 +1,79 @@
#include "item.h"
#include "tibiadat.h"
#include "tibiaspr.h"
#include <graphics/graphics.h>
ItemAttributes::ItemAttributes()
{
group = ITEM_GROUP_NONE;
blockSolid = false;
hasHeight = false;
blockPathFind = false;
blockProjectile = false;
alwaysOnTop = false;
alwaysOnTopOrder = 0;
stackable = false;
useable = false;
moveable = true;
pickupable = false;
rotable = false;
readable = false;
lookThrough = false;
speed = 0;
lightLevel = 0;
lightColor = 0;
isVertical = false;
isHorizontal = false;
isHangable = false;
miniMapColor = 0;
hasMiniMapColor = false;
subParam07 = 0;
subParam08 = 0;
sprites = NULL;
width = 0;
height = 0;
blendframes = 0;
xdiv = 0;
ydiv = 0;
zdiv = 0;
animcount = 0;
}
ItemAttributes::~ItemAttributes()
{
if(sprites)
delete []sprites;
}
Item::Item()
{
m_type = Thing::TYPE_ITEM;
}
void Item::draw(int x, int y)
{
ItemAttributes *itemAttributes = g_tibiaDat.getItemAttributes(m_id);
int cDivX = 0, cDivY = 0, cDivZ = 0, cAnim = 0;
for(int b = 0; b < itemAttributes->blendframes; b++) {
for(int yi = 0; yi < itemAttributes->height; yi++) {
for(int xi = 0; xi < itemAttributes->width; xi++) {
uint16 sprIndex = xi +
yi * itemAttributes->width +
b * itemAttributes->width * itemAttributes->height +
cDivX * itemAttributes->width * itemAttributes->height * itemAttributes->blendframes +
cDivY * itemAttributes->width * itemAttributes->height * itemAttributes->blendframes * itemAttributes->xdiv +
cDivZ * itemAttributes->width * itemAttributes->height * itemAttributes->blendframes * itemAttributes->xdiv * itemAttributes->ydiv +
cAnim * itemAttributes->width * itemAttributes->height * itemAttributes->blendframes * itemAttributes->xdiv * itemAttributes->ydiv * itemAttributes->zdiv;
uint16 itemId = itemAttributes->sprites[sprIndex];
if(itemId == 0xFFFF)
continue;
TexturePtr data = g_tibiaSpr.getSprite(itemId);
// todo verify this to draw in correct pos (screenX, screenY)
g_graphics.drawTexturedRect(Rect(x - xi*32 - 32, y - yi*32 - 32, 32, 32), data, Rect(0, 0, 32, 32));
}
}
}
}

59
src/item.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef ITEM_H
#define ITEM_H
#include <global.h>
#include "thing.h"
enum ItemGroup {
ITEM_GROUP_NONE = 0,
ITEM_GROUP_GROUND,
ITEM_GROUP_CONTAINER,
ITEM_GROUP_WEAPON,
ITEM_GROUP_AMMUNITION,
ITEM_GROUP_ARMOR,
ITEM_GROUP_RUNE,
ITEM_GROUP_TELEPORT,
ITEM_GROUP_MAGICFIELD,
ITEM_GROUP_WRITEABLE,
ITEM_GROUP_KEY,
ITEM_GROUP_SPLASH,
ITEM_GROUP_FLUID,
ITEM_GROUP_DOOR,
ITEM_GROUP_LAST
};
class ItemAttributes
{
public:
ItemAttributes();
~ItemAttributes();
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;
uint16 id, speed, subParam07, subParam08, lightLevel, lightColor, uheight, miniMapColor;
uint16 *sprites;
ItemGroup group;
};
class Item : virtual public Thing
{
public:
Item();
void draw(int x, int y);
void setId(uint16 id) { m_id = id; }
uint16 getId() const { return m_id; }
void setCount(uint8 count) { m_count = count; }
virtual Item* getItem() { return this; }
virtual const Item* getItem() const { return this; }
private:
uint16 m_id;
uint8 m_count;
};
#endif

View File

@ -9,6 +9,7 @@
#include <ui/uicontainer.h>
#include <script/luainterface.h>
#include "tibiadat.h"
#include "tibiaspr.h"
#include <csignal>
@ -79,10 +80,6 @@ int main(int argc, const char *argv[])
// load resources paths
g_resources.init(args[0].c_str());
// load Tibia.dat TODO this is temporary
if(!g_tibiaDat.load("Tibia.dat"))
return -1;
// load configurations
loadDefaultConfigs();
if(!g_configs.load("config.otml"))
@ -98,6 +95,15 @@ int main(int argc, const char *argv[])
// init engine
g_engine.init();
// load Tibia.spr TODO this is temporary
if(!g_tibiaSpr.load("tibiafiles/Tibia.spr"))
return -1;
// load Tibia.dat TODO this is temporary
if(!g_tibiaDat.load("tibiafiles/Tibia.dat"))
return -1;
g_engine.enableFpsCounter();
// load ui skins

32
src/map.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "map.h"
#include "game.h"
void Map::draw(int x, int y, int width, int heigth)
{
Position playerPos = g_game.getPlayer()->getPosition();
for(int ix = 0; ix < 19; ++ix) {
for(int iy = 0; iy < 15; ++iy) {
if(playerPos.getZ() >= 7) {
for(int iz = 7; iz > 0; --iz) {
m_map[ix][iy][iz].draw(x+ix*32-(7-iz)*32, y+iy*32-(7-iz)*32);
}
}
}
}
}
void Map::addThing(Thing *thing, const Position& pos)
{
Position playerPos = g_game.getPlayer()->getPosition();
Position relativePos = Position(pos.getX() - playerPos.getX() + 8, pos.getY() - playerPos.getY() + 6, pos.getZ());
if(relativePos.getX() >= 18)
logDebug("relativePos is invalid.");
if(relativePos.getY() >= 14)
logDebug("relativePos is invalid.");
if(relativePos.getZ() >= 15)
logDebug("relativePos is invalid.");
logDebug("x: ", (int)relativePos.getX(), " y: ", (int)relativePos.getY(), " z: ", (int)relativePos.getZ());
m_map[relativePos.getX()][relativePos.getY()][relativePos.getZ()].addThing(thing);
}

19
src/map.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef MAP_H
#define MAP_H
#include "position.h"
#include "tile.h"
class Map
{
public:
void addThing(Thing *thing, const Position& pos);
void draw(int x, int y, int width, int heigth);
private:
// Visible tiles are 15x11, but we have a +3 value. We have 15 floors.
Tile m_map[19][15][15];
};
#endif // MAP_H

View File

@ -7,7 +7,7 @@ class Player
{
public:
void setPosition(Position position) { m_position = position; }
void setPosition(const Position& position) { m_position = position; }
Position getPosition() { return m_position; }
private:

View File

@ -1,6 +1,8 @@
#ifndef POSITION_H
#define POSITION_H
#include <global.h>
class Position
{
public:
@ -14,9 +16,12 @@ public:
void setY(uint16 y) { m_y = y; }
void setZ(uint8 z) { m_z = z; }
uint16 getX() { return m_x; }
uint16 getY() { return m_y; }
uint8 getZ() { return m_z; }
uint16 getX() const { return m_x; }
uint16 getY() const { return m_y; }
uint8 getZ() const { return m_z; }
//const Position operator+(const Position& other) const { return Position(other.m_x + m_x, other.m_y + m_y, other.m_z + m_z); }
//const Position operator-(const Position& other) const { return Position(other.m_x - m_x, other.m_y - m_y, other.m_z - m_z); }
private:
uint16 m_x, m_y;

View File

@ -1,4 +1,5 @@
#include "protocolgame.h"
#include "game.h"
#include <net/rsa.h>
ProtocolGame::ProtocolGame()

View File

@ -3,6 +3,7 @@
#include <net/protocol.h>
#include "player.h"
#include "thing.h"
class ProtocolGame;
typedef std::shared_ptr<ProtocolGame> ProtocolGamePtr;
@ -95,19 +96,18 @@ private:
void parseQuestList(InputMessage& msg);
void parseQuestPartList(InputMessage& msg);
void sendPing();
void setMapDescription(InputMessage& msg, int32 x, int32 y, int32 z, int32 width, int32 height);
void setFloorDescription(InputMessage& msg, int32 x, int32 y, int32 z, int32 width, int32 height, int32 offset, int32* skipTiles);
void setTileDescription(InputMessage& msg, Position position);
void internalGetThing(InputMessage& msg);
Thing *internalGetThing(InputMessage& msg);
void internalCreatureOutfit(InputMessage& msg);
void internalGetItem(InputMessage& msg, uint16 id);
Item *internalGetItem(InputMessage& msg, uint16 id);
Position parsePosition(InputMessage& msg);
std::string m_accountName, m_accountPassword, m_characterName;
// TODO this is unknown
Player m_player;
};
// TODO: place it somewhere else

View File

@ -1,6 +1,8 @@
#include "protocolgame.h"
#include "player.h"
#include "tibiadat.h"
#include "game.h"
#include "map.h"
#include <iomanip>
void ProtocolGame::parseMessage(InputMessage& msg)
@ -260,9 +262,7 @@ void ProtocolGame::parseWaitList(InputMessage& msg)
void ProtocolGame::parsePing(InputMessage&)
{
//mSendmsg.reset();
//mSendmsg.addByte(0x1E);
//sendMessage(mSendMsg);
sendPing();
}
void ProtocolGame::parseDeath(InputMessage&)
@ -277,32 +277,37 @@ void ProtocolGame::parseCanReportBugs(InputMessage& msg)
void ProtocolGame::parseMapDescription(InputMessage& msg)
{
m_player.setPosition(parsePosition(msg));
setMapDescription(msg, m_player.getPosition().getX() - 8, m_player.getPosition().getY() - 6, m_player.getPosition().getZ(), 18, 14);
Player *player = g_game.getPlayer();
player->setPosition(parsePosition(msg));
setMapDescription(msg, player->getPosition().getX() - 8, player->getPosition().getY() - 6, player->getPosition().getZ(), 18, 14);
}
void ProtocolGame::parseMoveNorth(InputMessage& msg)
{
m_player.getPosition().setY(m_player.getPosition().getY() - 1);
setMapDescription(msg, m_player.getPosition().getX() - 8, m_player.getPosition().getY() - 6, m_player.getPosition().getZ(), 18, 1);
Player *player = g_game.getPlayer();
player->getPosition().setY(player->getPosition().getY() - 1);
setMapDescription(msg, player->getPosition().getX() - 8, player->getPosition().getY() - 6, player->getPosition().getZ(), 18, 1);
}
void ProtocolGame::parseMoveEast(InputMessage& msg)
{
m_player.getPosition().setX(m_player.getPosition().getX() + 1);
setMapDescription(msg, m_player.getPosition().getX() + 9, m_player.getPosition().getY() - 6, m_player.getPosition().getZ(), 1, 14);
Player *player = g_game.getPlayer();
player->getPosition().setX(player->getPosition().getX() + 1);
setMapDescription(msg, player->getPosition().getX() + 9, player->getPosition().getY() - 6, player->getPosition().getZ(), 1, 14);
}
void ProtocolGame::parseMoveSouth(InputMessage& msg)
{
m_player.getPosition().setY(m_player.getPosition().getY() + 1);
setMapDescription(msg, m_player.getPosition().getX() - 8, m_player.getPosition().getY() + 7, m_player.getPosition().getZ(), 18, 1);
Player *player = g_game.getPlayer();
player->getPosition().setY(player->getPosition().getY() + 1);
setMapDescription(msg, player->getPosition().getX() - 8, player->getPosition().getY() + 7, player->getPosition().getZ(), 18, 1);
}
void ProtocolGame::parseMoveWest(InputMessage& msg)
{
m_player.getPosition().setX(m_player.getPosition().getX() - 1);
setMapDescription(msg, m_player.getPosition().getX() - 8, m_player.getPosition().getY() - 6, m_player.getPosition().getZ(), 1, 14);
Player *player = g_game.getPlayer();
player->getPosition().setX(player->getPosition().getX() - 1);
setMapDescription(msg, player->getPosition().getX() - 8, player->getPosition().getY() - 6, player->getPosition().getZ(), 1, 14);
}
void ProtocolGame::parseUpdateTile(InputMessage& msg)
@ -677,34 +682,36 @@ void ProtocolGame::parseCancelWalk(InputMessage& msg)
void ProtocolGame::parseFloorChangeUp(InputMessage& msg)
{
m_player.getPosition().setZ(m_player.getPosition().getZ() - 1);
Player *player = g_game.getPlayer();
player->getPosition().setZ(player->getPosition().getZ() - 1);
int32 skip = 0;
if(m_player.getPosition().getZ() == 7)
if(player->getPosition().getZ() == 7)
for(int32 i = 5; i >= 0; i--)
setFloorDescription(msg, m_player.getPosition().getX() - 8, m_player.getPosition().getY() - 6, i, 18, 14, 8 - i, &skip);
else if(m_player.getPosition().getZ() > 7)
setFloorDescription(msg, m_player.getPosition().getX() - 8, m_player.getPosition().getY() - 6, m_player.getPosition().getZ() - 2, 18, 14, 3, &skip);
setFloorDescription(msg, player->getPosition().getX() - 8, player->getPosition().getY() - 6, i, 18, 14, 8 - i, &skip);
else if(player->getPosition().getZ() > 7)
setFloorDescription(msg, player->getPosition().getX() - 8, player->getPosition().getY() - 6, player->getPosition().getZ() - 2, 18, 14, 3, &skip);
m_player.getPosition().setX(m_player.getPosition().getX() + 1);
m_player.getPosition().setY(m_player.getPosition().getY() + 1);
player->getPosition().setX(player->getPosition().getX() + 1);
player->getPosition().setY(player->getPosition().getY() + 1);
}
void ProtocolGame::parseFloorChangeDown(InputMessage& msg)
{
m_player.getPosition().setZ(m_player.getPosition().getZ() + 1);
Player *player = g_game.getPlayer();
player->getPosition().setZ(player->getPosition().getZ() + 1);
int32 skip = 0;
if(m_player.getPosition().getZ() == 8) {
if(player->getPosition().getZ() == 8) {
int32 j, i;
for(i = m_player.getPosition().getZ(), j = -1; i < (int32)m_player.getPosition().getZ() + 3; ++i, --j)
setFloorDescription(msg, m_player.getPosition().getX() - 8, m_player.getPosition().getY() - 6, i, 18, 14, j, &skip);
for(i = player->getPosition().getZ(), j = -1; i < (int32)player->getPosition().getZ() + 3; ++i, --j)
setFloorDescription(msg, player->getPosition().getX() - 8, player->getPosition().getY() - 6, i, 18, 14, j, &skip);
}
else if(m_player.getPosition().getZ() > 8 && m_player.getPosition().getZ() < 14)
setFloorDescription(msg, m_player.getPosition().getX() - 8, m_player.getPosition().getY() - 6, m_player.getPosition().getZ() + 2, 18, 14, -3, &skip);
else if(player->getPosition().getZ() > 8 && player->getPosition().getZ() < 14)
setFloorDescription(msg, player->getPosition().getX() - 8, player->getPosition().getY() - 6, player->getPosition().getZ() + 2, 18, 14, -3, &skip);
m_player.getPosition().setX(m_player.getPosition().getX() - 1);
m_player.getPosition().setY(m_player.getPosition().getY() - 1);
player->getPosition().setX(player->getPosition().getX() - 1);
player->getPosition().setY(player->getPosition().getY() - 1);
}
void ProtocolGame::parseOutfitWindow(InputMessage& msg)
@ -823,13 +830,16 @@ void ProtocolGame::setTileDescription(InputMessage& msg, Position position)
logDebug("[ProtocolGame::setTileDescription] Too many things!.");
return;
}
internalGetThing(msg);
g_game.getMap()->addThing(internalGetThing(msg), position);
}
}
}
void ProtocolGame::internalGetThing(InputMessage& msg)
Thing *ProtocolGame::internalGetThing(InputMessage& msg)
{
Thing *thing = NULL;
uint16 thingId = msg.getU16();
if(thingId == 0x0061 || thingId == 0x0062) { // add new creature
if(thingId == 0x0062) { //creature is known
@ -860,7 +870,9 @@ void ProtocolGame::internalGetThing(InputMessage& msg)
msg.getU8(); // direction
}
else // item
internalGetItem(msg, thingId);
thing = internalGetItem(msg, thingId);
return thing;
}
void ProtocolGame::internalCreatureOutfit(InputMessage& msg)
@ -878,14 +890,19 @@ void ProtocolGame::internalCreatureOutfit(InputMessage& msg)
}
}
void ProtocolGame::internalGetItem(InputMessage& msg, uint16 id)
Item *ProtocolGame::internalGetItem(InputMessage& msg, uint16 id)
{
Item *item = new Item();
if(id == 0xFFFF)
id = msg.getU16();
item->setId(id);
Item *item = g_tibiaDat.getItem(id);
if(item->stackable || item->group == ITEM_GROUP_FLUID || item->group == ITEM_GROUP_SPLASH)
msg.getU8();
ItemAttributes *itemAttributes = g_tibiaDat.getItemAttributes(id);
if(itemAttributes->stackable || itemAttributes->group == ITEM_GROUP_FLUID || itemAttributes->group == ITEM_GROUP_SPLASH)
item->setCount(msg.getU8());
return item;
}
Position ProtocolGame::parsePosition(InputMessage& msg)

9
src/protocolgamesend.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "protocolgame.h"
void ProtocolGame::sendPing()
{
OutputMessage oMsg;
oMsg.reset();
oMsg.addU8(0x1E);
send(oMsg);
}

6
src/thing.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "thing.h"
Thing::Thing()
{
m_type = TYPE_NONE;
}

31
src/thing.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef THING_H
#define THING_H
#include <global.h>
class Item;
class Thing
{
public:
Thing();
enum Type {
TYPE_NONE,
TYPE_ITEM,
TYPE_CREATURE
};
void setType(Type type) { m_type = type; }
Type getType() const { return m_type; }
virtual void draw(int, int) {}
virtual Item* getItem() { return NULL; }
virtual const Item *getItem() const { return NULL; }
protected:
Type m_type;
};
#endif // THING_H

View File

@ -1,4 +1,5 @@
#include "tibiadat.h"
#include "tibiaspr.h"
#include <core/resources.h>
TibiaDat g_tibiaDat;
@ -20,17 +21,17 @@ bool TibiaDat::load(const std::string& filename)
m_totalCount = m_groupCount[0] + m_groupCount[1] + m_groupCount[2] + m_groupCount[3];
m_items = new Item*[m_totalCount+1];
m_itemsAttributes = new ItemAttributes*[m_totalCount+1];
for(uint16 i = 0; i <= m_totalCount; i++)
m_items[i] = NULL;
m_itemsAttributes[i] = NULL;
uint8 read_byte;
uint16 read_short;
uint32 read_long;
for(uint16 id = 0; (id <= m_totalCount) && !fin.eof(); id++) {
m_items[id] = new Item();
m_items[id]->id = id;
m_itemsAttributes[id] = new ItemAttributes();
m_itemsAttributes[id]->id = id;
uint8 opt;
bool done = false;
@ -38,80 +39,80 @@ bool TibiaDat::load(const std::string& filename)
fin.read((char*)&opt, 1);
if(opt == 0x00) { // Ground tile
fin.read((char*)&m_items[id]->speed, 2);
m_items[id]->group = ITEM_GROUP_GROUND;
fin.read((char*)&m_itemsAttributes[id]->speed, 2);
m_itemsAttributes[id]->group = ITEM_GROUP_GROUND;
}
else if(opt == 0x01) { // All OnTop
m_items[id]->alwaysOnTop = true;
m_items[id]->alwaysOnTopOrder = 1;
m_itemsAttributes[id]->alwaysOnTop = true;
m_itemsAttributes[id]->alwaysOnTopOrder = 1;
}
else if(opt == 0x02) { // Can walk trough (open doors, arces, bug pen fence)
m_items[id]->alwaysOnTop = true;
m_items[id]->alwaysOnTopOrder = 2;
m_itemsAttributes[id]->alwaysOnTop = true;
m_itemsAttributes[id]->alwaysOnTopOrder = 2;
}
else if(opt == 0x03) { // Can walk trough (arces)
m_items[id]->alwaysOnTop = true;
m_items[id]->alwaysOnTopOrder = 3;
m_itemsAttributes[id]->alwaysOnTop = true;
m_itemsAttributes[id]->alwaysOnTopOrder = 3;
}
else if(opt == 0x04) { // Container
m_items[id]->group = ITEM_GROUP_CONTAINER;
m_itemsAttributes[id]->group = ITEM_GROUP_CONTAINER;
}
else if(opt == 0x05) { // Stackable
m_items[id]->stackable = true;
m_itemsAttributes[id]->stackable = true;
}
else if(opt == 0x06) { // Unknown
}
else if(opt == 0x07) { // Useable
m_items[id]->useable = true;
m_itemsAttributes[id]->useable = true;
}
else if(opt == 0x08) { // Writtable
m_items[id]->group = ITEM_GROUP_WRITEABLE;
m_items[id]->readable = true;
fin.read((char*)&m_items[id]->subParam07, 2);
m_itemsAttributes[id]->group = ITEM_GROUP_WRITEABLE;
m_itemsAttributes[id]->readable = true;
fin.read((char*)&m_itemsAttributes[id]->subParam07, 2);
}
else if(opt == 0x09) { // Writtable once
// Writtable objects that can't be edited by players
m_items[id]->readable = true;
fin.read((char*)&m_items[id]->subParam08, 2);
m_itemsAttributes[id]->readable = true;
fin.read((char*)&m_itemsAttributes[id]->subParam08, 2);
}
else if(opt == 0x0A) { // Fluid containers
fin.read((char*)&read_byte, 1);
m_items[id]->group = ITEM_GROUP_FLUID;
m_itemsAttributes[id]->group = ITEM_GROUP_FLUID;
}
else if(opt == 0x0B) { // Splashes
m_items[id]->group = ITEM_GROUP_SPLASH;
m_itemsAttributes[id]->group = ITEM_GROUP_SPLASH;
}
else if(opt == 0x0C) { // Blocks solid objects (creatures, walls etc)
m_items[id]->blockSolid = true;
m_itemsAttributes[id]->blockSolid = true;
}
else if(opt == 0x0D) { // Not moveable
m_items[id]->moveable = false;
m_itemsAttributes[id]->moveable = false;
}
else if(opt == 0x0E) { // Blocks missiles (walls, magic wall etc)
m_items[id]->blockProjectile = true;
m_itemsAttributes[id]->blockProjectile = true;
}
else if(opt == 0x0F) { // Blocks pathfind algorithms (monsters)
m_items[id]->blockPathFind = true;
m_itemsAttributes[id]->blockPathFind = true;
}
else if(opt == 0x10) { // Blocks monster movement (flowers, parcels etc)
m_items[id]->pickupable = true;
m_itemsAttributes[id]->pickupable = true;
}
else if(opt == 0x11) { // Hangable objects (wallpaper etc)
m_items[id]->isHangable = true;
m_itemsAttributes[id]->isHangable = true;
}
else if(opt == 0x12) { // Horizontal wall
m_items[id]->isHorizontal = true;
m_itemsAttributes[id]->isHorizontal = true;
}
else if(opt == 0x13) { // Vertical wall
m_items[id]->isVertical = true;
m_itemsAttributes[id]->isVertical = true;
}
else if(opt == 0x14) { // Rotable
m_items[id]->rotable = true;
m_itemsAttributes[id]->rotable = true;
}
else if(opt == 0x15) { // Light info
fin.read((char*)&m_items[id]->lightLevel, 2);
fin.read((char*)&m_items[id]->lightColor, 2);
fin.read((char*)&m_itemsAttributes[id]->lightLevel, 2);
fin.read((char*)&m_itemsAttributes[id]->lightColor, 2);
}
else if(opt == 0x16) {
}
@ -121,26 +122,26 @@ bool TibiaDat::load(const std::string& filename)
fin.read((char*)&read_long, 4);
}
else if(opt == 0x19) { // Has height
m_items[id]->hasHeight = true;
fin.read((char*)&m_items[id]->uheight, 2);
m_itemsAttributes[id]->hasHeight = true;
fin.read((char*)&m_itemsAttributes[id]->uheight, 2);
}
else if(opt == 0x1A) {
}
else if(opt == 0x1B) {
}
else if(opt == 0x1C) { // Minimap color
fin.read((char*)&m_items[id]->miniMapColor, 2);
m_items[id]->hasMiniMapColor = true;
fin.read((char*)&m_itemsAttributes[id]->miniMapColor, 2);
m_itemsAttributes[id]->hasMiniMapColor = true;
}
else if(opt == 0x1D) { // Unknown
fin.read((char*)&read_short, 2);
if(read_short == 1112)
m_items[id]->readable = true;
m_itemsAttributes[id]->readable = true;
}
else if(opt == 0x1E) {
}
else if(opt == 0x1F) {
m_items[id]->lookThrough = true;
m_itemsAttributes[id]->lookThrough = true;
}
else if(opt == 0x20) {
}
@ -153,32 +154,32 @@ bool TibiaDat::load(const std::string& filename)
}
}
fin.read((char*)&m_items[id]->width, 1);
fin.read((char*)&m_items[id]->height, 1);
if((m_items[id]->width > 1) || (m_items[id]->height > 1))
fin.read((char*)&m_itemsAttributes[id]->width, 1);
fin.read((char*)&m_itemsAttributes[id]->height, 1);
if((m_itemsAttributes[id]->width > 1) || (m_itemsAttributes[id]->height > 1))
fin.read((char*)&read_byte, 1);
fin.read((char*)&m_items[id]->blendframes, 1);
fin.read((char*)&m_items[id]->xdiv, 1);
fin.read((char*)&m_items[id]->ydiv, 1);
fin.read((char*)&m_items[id]->zdiv, 1);
fin.read((char*)&m_items[id]->animcount, 1);
fin.read((char*)&m_itemsAttributes[id]->blendframes, 1);
fin.read((char*)&m_itemsAttributes[id]->xdiv, 1);
fin.read((char*)&m_itemsAttributes[id]->ydiv, 1);
fin.read((char*)&m_itemsAttributes[id]->zdiv, 1);
fin.read((char*)&m_itemsAttributes[id]->animcount, 1);
// Read sprites id.
uint16 totalSprites = m_items[id]->width * m_items[id]->height * m_items[id]->blendframes * m_items[id]->xdiv * m_items[id]->ydiv * m_items[id]->zdiv * m_items[id]->animcount;
uint16 totalSprites = m_itemsAttributes[id]->width * m_itemsAttributes[id]->height * m_itemsAttributes[id]->blendframes * m_itemsAttributes[id]->xdiv * m_itemsAttributes[id]->ydiv * m_itemsAttributes[id]->zdiv * m_itemsAttributes[id]->animcount;
m_items[id]->sprites = new uint16[totalSprites];
m_itemsAttributes[id]->sprites = new uint16[totalSprites];
for(uint16 i = 0; i < totalSprites; i++) {
fin.read((char*)&read_short, 2);
m_items[id]->sprites[i] = read_short-1;
m_itemsAttributes[id]->sprites[i] = read_short-1;
}
}
return true;
}
Item *TibiaDat::getItem(uint16 id)
ItemAttributes *TibiaDat::getItemAttributes(uint16 id)
{
// items id start at 100.
return m_items[id - 100];
return m_itemsAttributes[id - 100];
}

View File

@ -2,73 +2,14 @@
#define TIBIADAT_H
#include <global.h>
enum ItemGroup {
ITEM_GROUP_NONE = 0,
ITEM_GROUP_GROUND,
ITEM_GROUP_CONTAINER,
ITEM_GROUP_WEAPON,
ITEM_GROUP_AMMUNITION,
ITEM_GROUP_ARMOR,
ITEM_GROUP_RUNE,
ITEM_GROUP_TELEPORT,
ITEM_GROUP_MAGICFIELD,
ITEM_GROUP_WRITEABLE,
ITEM_GROUP_KEY,
ITEM_GROUP_SPLASH,
ITEM_GROUP_FLUID,
ITEM_GROUP_DOOR,
ITEM_GROUP_LAST
};
struct Item
{
Item() {
group = ITEM_GROUP_NONE;
blockSolid = false;
hasHeight = false;
blockPathFind = false;
blockProjectile = false;
alwaysOnTop = false;
alwaysOnTopOrder = 0;
stackable = false;
useable = false;
moveable = true;
pickupable = false;
rotable = false;
readable = false;
lookThrough = false;
speed = 0;
lightLevel = 0;
lightColor = 0;
isVertical = false;
isHorizontal = false;
isHangable = false;
miniMapColor = 0;
hasMiniMapColor = false;
subParam07 = 0;
subParam08 = 0;
sprites = NULL;
}
~Item() {
if(sprites)
delete []sprites;
}
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;
uint16 id, speed, subParam07, subParam08, lightLevel, lightColor, uheight, miniMapColor;
uint16 *sprites;
ItemGroup group;
};
#include "item.h"
class TibiaDat
{
public:
bool load(const std::string& filename);
Item *getItem(uint16 id);
ItemAttributes *getItemAttributes(uint16 id);
uint16 getGroupCount(int i) { return m_groupCount[i]; }
@ -79,7 +20,7 @@ private:
uint32 m_signature, m_totalCount;
uint16 m_groupCount[4];
Item **m_items;
ItemAttributes **m_itemsAttributes;
};
extern TibiaDat g_tibiaDat;

121
src/tibiaspr.cpp Executable file
View File

@ -0,0 +1,121 @@
#include "tibiaspr.h"
#include <core/resources.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)
{
if(!g_resources.loadFile(filename, m_fin))
return false;
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];
}

31
src/tibiaspr.h Executable file
View File

@ -0,0 +1,31 @@
#ifndef TIBIASPR_H
#define TIBIASPR_H
#include <global.h>
#include <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

34
src/tile.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "tile.h"
#include "item.h"
#include "tibiadat.h"
void Tile::addThing(Thing *thing)
{
if(!thing)
return;
if(thing->getType() == Thing::TYPE_ITEM) {
const Item *item = thing->getItem();
if(item) {
ItemAttributes *itemAttributes = g_tibiaDat.getItemAttributes(item->getId());
if(itemAttributes->alwaysOnTop)
m_itemsTop.push_back(thing);
else
m_itemsBot.push_back(thing);
}
}
else if(thing->getType() == Thing::TYPE_CREATURE) {
}
}
void Tile::draw(int x, int y)
{
for(auto it = m_itemsBot.begin(), end = m_itemsBot.end(); it != end; ++it)
(*it)->draw(x, y);
for(auto it = m_creatures.begin(), end = m_creatures.end(); it != end; ++it)
(*it)->draw(x, y);
for(auto it = m_itemsTop.begin(), end = m_itemsTop.end(); it != end; ++it)
(*it)->draw(x, y);
}

21
src/tile.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef TILE_H
#define TILE_H
#include <global.h>
#include "thing.h"
class Tile
{
public:
void addThing(Thing *thing);
void draw(int x, int y);
private:
// ground
std::list<Thing*> m_itemsBot;
std::list<Thing*> m_creatures;
std::list<Thing*> m_itemsTop;
};
#endif // TILE_H