fix gitignore and add missing sources
This commit is contained in:
parent
d8cc37afdb
commit
b21ccd16f9
|
@ -4,7 +4,7 @@ CMakeFiles
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
Makefile
|
Makefile
|
||||||
otclient
|
./otclient
|
||||||
otclient.exe
|
otclient.exe
|
||||||
*.dll
|
*.dll
|
||||||
.kdev*
|
.kdev*
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef OTCLIENT_CORE_CONST_H
|
||||||
|
#define OTCLIENT_CORE_CONST_H
|
||||||
|
|
||||||
|
enum ThingAttributesGroup {
|
||||||
|
THING_GROUP_NONE = 0,
|
||||||
|
THING_GROUP_GROUND,
|
||||||
|
THING_GROUP_CONTAINER,
|
||||||
|
THING_GROUP_WEAPON,
|
||||||
|
THING_GROUP_AMMUNITION,
|
||||||
|
THING_GROUP_ARMOR,
|
||||||
|
THING_GROUP_RUNE,
|
||||||
|
THING_GROUP_TELEPORT,
|
||||||
|
THING_GROUP_MAGICFIELD,
|
||||||
|
THING_GROUP_WRITEABLE,
|
||||||
|
THING_GROUP_KEY,
|
||||||
|
THING_GROUP_SPLASH,
|
||||||
|
THING_GROUP_FLUID,
|
||||||
|
THING_GROUP_DOOR,
|
||||||
|
THING_GROUP_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,64 @@
|
||||||
|
#include "creature.h"
|
||||||
|
#include "tibiadat.h"
|
||||||
|
#include <framework/graphics/graphics.h>
|
||||||
|
#include <framework/graphics/framebuffer.h>
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <GL/glu.h>
|
||||||
|
#include <GL/glext.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// OW BART TEM COMO USAR 2 FRAMEBUFFER?
|
||||||
|
// SERIA O IDEAL PARA DESENHAR A COR DOS BONEQUIN.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Creature::Creature()
|
||||||
|
{
|
||||||
|
m_type = Thing::TYPE_CREATURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThingAttributes *Creature::getAttributes()
|
||||||
|
{
|
||||||
|
return g_tibiaDat.getCreatureAttributes(m_outfit.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Creature::draw(int x, int y)
|
||||||
|
{
|
||||||
|
//ThingAttributes *creatureAttributes = getAttributes();
|
||||||
|
int anim = 0;
|
||||||
|
|
||||||
|
// draw outfit
|
||||||
|
internalDraw(x, y, 0, m_direction, 0, 0, anim);
|
||||||
|
|
||||||
|
// draw addons
|
||||||
|
//for(int a = 0; a < m_outfit.addons; ++a) {
|
||||||
|
//internalDraw(x, y, 0, m_direction, m_outfit.addons & (1 << a), 0, anim);
|
||||||
|
//}
|
||||||
|
//glPushAttrib(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
//glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
//Color colors[4] = {Color::yellow, Color::red, Color::green, Color::blue};
|
||||||
|
|
||||||
|
//for(int i = 0; i < 4; ++i) {
|
||||||
|
|
||||||
|
|
||||||
|
/*g_graphics.bindColor(colors[i]);
|
||||||
|
internalDraw(creatureAttributes->width*32 - 32, creatureAttributes->height*32 - 32, 1, m_direction, 0, 0, 0);
|
||||||
|
framebuffer.unbind();
|
||||||
|
|
||||||
|
|
||||||
|
g_graphics.bindColor(Color::green);*/
|
||||||
|
//framebuffer.draw(x, y, creatureAttributes->width*32, creatureAttributes->height*32);
|
||||||
|
//}
|
||||||
|
//glPopAttrib();
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef CREATURE_H
|
||||||
|
#define CREATURE_H
|
||||||
|
|
||||||
|
#include "thing.h"
|
||||||
|
|
||||||
|
struct Outfit
|
||||||
|
{
|
||||||
|
uint16 type;
|
||||||
|
uint8 head;
|
||||||
|
uint8 body;
|
||||||
|
uint8 legs;
|
||||||
|
uint8 feet;
|
||||||
|
uint8 addons;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Creature : public Thing
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Creature();
|
||||||
|
|
||||||
|
virtual ThingAttributes *getAttributes();
|
||||||
|
void draw(int x, int y);
|
||||||
|
|
||||||
|
void setName(const std::string& name) { m_name = name; }
|
||||||
|
std::string getName() { return m_name; }
|
||||||
|
|
||||||
|
void setHealthPercent(uint8 healthPercent) { m_healthPercent = healthPercent; }
|
||||||
|
uint8 getHealthPercent() { return m_healthPercent; }
|
||||||
|
|
||||||
|
void setDirection(Direction direction) { m_direction = direction; }
|
||||||
|
Direction getDirection() { return m_direction; }
|
||||||
|
|
||||||
|
void setOutfit(const Outfit& outfit) { m_outfit = outfit; }
|
||||||
|
Outfit getOutfit() { return m_outfit; }
|
||||||
|
|
||||||
|
virtual Creature *getCreature() { return this; }
|
||||||
|
virtual const Creature *getCreature() const { return this; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_name;
|
||||||
|
uint8 m_healthPercent;
|
||||||
|
Direction m_direction;
|
||||||
|
Outfit m_outfit;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CREATURE_H
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef OTCLIENT_CORE_DECLARATIONS_H
|
||||||
|
#define OTCLIENT_CORE_DECLARATIONS_H
|
||||||
|
|
||||||
|
#include <otclient/global.h>
|
||||||
|
#include "const.h"
|
||||||
|
|
||||||
|
class Thing;
|
||||||
|
class Item;
|
||||||
|
class Tile;
|
||||||
|
class Creature;
|
||||||
|
class Player;
|
||||||
|
class Effect;
|
||||||
|
|
||||||
|
typedef std::shared_ptr<Thing> ThingPtr;
|
||||||
|
typedef std::shared_ptr<Item> ItemPtr;
|
||||||
|
typedef std::shared_ptr<Tile> TilePtr;
|
||||||
|
typedef std::shared_ptr<Creature> CreaturePtr;
|
||||||
|
typedef std::shared_ptr<Player> PlayerPtr;
|
||||||
|
typedef std::shared_ptr<Effect> EffectPtr;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "effect.h"
|
||||||
|
#include "tibiadat.h"
|
||||||
|
|
||||||
|
Effect::Effect()
|
||||||
|
{
|
||||||
|
m_type = Thing::TYPE_EFFECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThingAttributes *Effect::getAttributes()
|
||||||
|
{
|
||||||
|
return g_tibiaDat.getEffectAttributes(m_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Effect::draw(int x, int y)
|
||||||
|
{
|
||||||
|
int anim = 0;
|
||||||
|
internalDraw(x, y, 0, 0, 0, 0, anim);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef EFFECT_H
|
||||||
|
#define EFFECT_H
|
||||||
|
|
||||||
|
#include <framework/global.h>
|
||||||
|
#include "thing.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Effect : public Thing
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Effect();
|
||||||
|
|
||||||
|
virtual ThingAttributes *getAttributes();
|
||||||
|
void draw(int x, int y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EFFECT_H
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
Game g_game;
|
||||||
|
|
||||||
|
Game::Game()
|
||||||
|
{
|
||||||
|
m_online = false;
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef GAME_H
|
||||||
|
#define GAME_H
|
||||||
|
|
||||||
|
#include <framework/global.h>
|
||||||
|
#include "map.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include <otclient/net/protocolgame.h>
|
||||||
|
|
||||||
|
class Game
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Game();
|
||||||
|
|
||||||
|
void setProtocol(ProtocolGamePtr protocolGame) { m_protocolGame = protocolGame; }
|
||||||
|
ProtocolGamePtr getProtocol() { return m_protocolGame; }
|
||||||
|
|
||||||
|
Map *getMap() { return &m_map; }
|
||||||
|
Player *getPlayer() { return &m_player; }
|
||||||
|
|
||||||
|
void setOnline(bool online) { m_online = online; }
|
||||||
|
bool getOnline() { return m_online; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Map m_map;
|
||||||
|
Player m_player;
|
||||||
|
ProtocolGamePtr m_protocolGame;
|
||||||
|
bool m_online;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Game g_game;
|
||||||
|
|
||||||
|
#endif // GAME_H
|
|
@ -0,0 +1,35 @@
|
||||||
|
#include "item.h"
|
||||||
|
#include "tibiadat.h"
|
||||||
|
#include "tibiaspr.h"
|
||||||
|
#include <framework/graphics/graphics.h>
|
||||||
|
#include "thing.h"
|
||||||
|
|
||||||
|
Item::Item()
|
||||||
|
{
|
||||||
|
m_type = Thing::TYPE_ITEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThingAttributes *Item::getAttributes()
|
||||||
|
{
|
||||||
|
return g_tibiaDat.getItemAttributes(m_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Item::draw(int x, int y)
|
||||||
|
{
|
||||||
|
ThingAttributes *itemAttributes = getAttributes();
|
||||||
|
|
||||||
|
int xdiv = 0, ydiv = 0, zdiv = 0, anim = 0;
|
||||||
|
|
||||||
|
if(itemAttributes->group == THING_GROUP_SPLASH || itemAttributes->group == THING_GROUP_FLUID || itemAttributes->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int b = 0; b < itemAttributes->blendframes; b++)
|
||||||
|
internalDraw(x, y, b, xdiv, ydiv, zdiv, anim);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef ITEM_H
|
||||||
|
#define ITEM_H
|
||||||
|
|
||||||
|
#include <framework/global.h>
|
||||||
|
#include "thing.h"
|
||||||
|
|
||||||
|
class Item : public Thing
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Item();
|
||||||
|
|
||||||
|
virtual ThingAttributes *getAttributes();
|
||||||
|
void draw(int x, int y);
|
||||||
|
|
||||||
|
void setCount(uint8 count) { m_count = count; }
|
||||||
|
|
||||||
|
virtual Item* getItem() { return this; }
|
||||||
|
virtual const Item* getItem() const { return this; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 m_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ITEM_H
|
|
@ -0,0 +1,74 @@
|
||||||
|
#include "map.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include <framework/graphics/graphics.h>
|
||||||
|
#include <framework/graphics/framebuffer.h>
|
||||||
|
|
||||||
|
void Map::draw(int x, int y)
|
||||||
|
{
|
||||||
|
if(!m_framebuffer)
|
||||||
|
m_framebuffer = FrameBufferPtr(new FrameBuffer(15*32, 11*32));
|
||||||
|
|
||||||
|
g_graphics.bindColor(Color::white);
|
||||||
|
m_framebuffer->bind();
|
||||||
|
|
||||||
|
Position *playerPos = g_game.getPlayer()->getPosition();
|
||||||
|
|
||||||
|
// player is above 7
|
||||||
|
if(playerPos->z <= 7) {
|
||||||
|
|
||||||
|
// player pos it 8-6. check if we can draw upper floors.
|
||||||
|
bool draw = true;
|
||||||
|
for(int jz = 6; jz >= 0; --jz) {
|
||||||
|
Position coverPos = Position(playerPos->x-(6-jz), playerPos->y-(6-jz), jz);
|
||||||
|
if(m_tiles[coverPos]) {
|
||||||
|
if(m_tiles[coverPos]->getStackSize() > 0 && jz < playerPos->z) {
|
||||||
|
draw = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int iz = 7; iz > 0; --iz) {
|
||||||
|
|
||||||
|
// +1 in draws cause 64x64 items may affect view.
|
||||||
|
for(int ix = -7; ix < + 8+7; ++ix) {
|
||||||
|
for(int iy = -5; iy < + 6+7; ++iy) {
|
||||||
|
Position itemPos = Position(playerPos->x + ix, playerPos->y + iy, iz);
|
||||||
|
//Position drawPos = Position(ix + 8, iy - playerPos->y + 6, iz);
|
||||||
|
//logDebug("x: ", relativePos.x, " y: ", relativePos.y, " z: ", (int)relativePos.z);
|
||||||
|
if(m_tiles[itemPos])
|
||||||
|
m_tiles[itemPos]->draw((ix + 7 - (7-iz))*32, (iy + 5 - (7-iz))*32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!draw)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw effects
|
||||||
|
for(auto it = m_effects.begin(), end = m_effects.end(); it != end; ++it) {
|
||||||
|
Position *effectPos = (*it)->getPosition();
|
||||||
|
(*it)->draw((effectPos->x - playerPos->x + 7) * 32, (effectPos->y - playerPos->y + 5) * 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug draws
|
||||||
|
g_graphics.drawBoundingRect(Rect(7*32, 5*32, 32, 32), Color::red);
|
||||||
|
|
||||||
|
m_framebuffer->unbind();
|
||||||
|
m_framebuffer->draw(Rect(x, y, g_graphics.getScreenSize()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::addThing(ThingPtr thing, uint8 stackpos)
|
||||||
|
{
|
||||||
|
if(thing->getType() == Thing::TYPE_ITEM || thing->getType() == Thing::TYPE_CREATURE) {
|
||||||
|
if(!m_tiles[*thing->getPosition()]) {
|
||||||
|
m_tiles[*thing->getPosition()] = TilePtr(new Tile());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_tiles[*thing->getPosition()]->addThing(thing, stackpos);
|
||||||
|
}
|
||||||
|
else if(thing->getType() == Thing::TYPE_EFFECT) {
|
||||||
|
m_effects.push_back(thing);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef MAP_H
|
||||||
|
#define MAP_H
|
||||||
|
|
||||||
|
#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 {
|
||||||
|
return ((((pos.x * 65536) + pos.y) * 15) + pos.z) % 1000000;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Map
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void addThing(ThingPtr thing, uint8 stackpos = 0);
|
||||||
|
|
||||||
|
void draw(int x, int y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<Position, TilePtr, MapPositionHasher> m_tiles;
|
||||||
|
std::list<ThingPtr> m_effects;
|
||||||
|
|
||||||
|
FrameBufferPtr m_framebuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef PLAYER_H
|
||||||
|
#define PLAYER_H
|
||||||
|
|
||||||
|
#include "creature.h"
|
||||||
|
|
||||||
|
class Player : public Creature
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void setDrawSpeed(uint16 drawSpeed) { m_drawSpeed = drawSpeed; }
|
||||||
|
uint16 getDrawSpeed() { return m_drawSpeed; }
|
||||||
|
|
||||||
|
void setCanReportBugs(uint8 canReportBugs) { m_canReportBugs = (canReportBugs != 0); }
|
||||||
|
bool getCanReportBugs() { return m_canReportBugs; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint16 m_drawSpeed;
|
||||||
|
bool m_canReportBugs;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,83 @@
|
||||||
|
#include "thing.h"
|
||||||
|
#include "tibiaspr.h"
|
||||||
|
#include <framework/graphics/graphics.h>
|
||||||
|
|
||||||
|
ThingAttributes::ThingAttributes()
|
||||||
|
{
|
||||||
|
group = THING_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;
|
||||||
|
xOffset = 0;
|
||||||
|
yOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThingAttributes::~ThingAttributes()
|
||||||
|
{
|
||||||
|
if(sprites)
|
||||||
|
delete []sprites;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thing::Thing()
|
||||||
|
{
|
||||||
|
m_type = TYPE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thing::internalDraw(int x, int y, int blendframes, int xdiv, int ydiv, int zdiv, int anim)
|
||||||
|
{
|
||||||
|
ThingAttributes *thingAttributes = getAttributes();
|
||||||
|
if(!thingAttributes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
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)
|
||||||
|
continue;
|
||||||
|
TexturePtr data = g_tibiaSpr.getSprite(itemId);
|
||||||
|
|
||||||
|
int offsetX = 0, offsetY = 0;
|
||||||
|
if(thingAttributes->hasHeight) {
|
||||||
|
offsetX = thingAttributes->xOffset;
|
||||||
|
offsetY = thingAttributes->xOffset; // << look to xoffset
|
||||||
|
}
|
||||||
|
|
||||||
|
g_graphics.drawTexturedRect(Rect((x - xi*32) - offsetX, (y - yi*32) - offsetY, 32, 32), data, Rect(0, 0, 32, 32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
#ifndef THING_H
|
||||||
|
#define THING_H
|
||||||
|
|
||||||
|
#include <otclient/global.h>
|
||||||
|
#include "declarations.h"
|
||||||
|
|
||||||
|
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;
|
||||||
|
ThingAttributesGroup group;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Creature;
|
||||||
|
class Item;
|
||||||
|
|
||||||
|
class Thing;
|
||||||
|
typedef std::shared_ptr<Thing> ThingPtr;
|
||||||
|
|
||||||
|
class Thing
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Thing();
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
TYPE_NONE,
|
||||||
|
TYPE_ITEM,
|
||||||
|
TYPE_CREATURE,
|
||||||
|
TYPE_EFFECT,
|
||||||
|
TYPE_SHOT
|
||||||
|
};
|
||||||
|
|
||||||
|
void setId(uint32 id) { m_id = id; }
|
||||||
|
uint32 getId() { return m_id; }
|
||||||
|
|
||||||
|
void setType(Type type) { m_type = type; }
|
||||||
|
Type getType() const { return m_type; }
|
||||||
|
|
||||||
|
void setPosition(const Position& position) { m_position = position; }
|
||||||
|
Position *getPosition() { return &m_position; }
|
||||||
|
|
||||||
|
virtual void draw(int, int) {}
|
||||||
|
virtual ThingAttributes *getAttributes() { return NULL; }
|
||||||
|
|
||||||
|
virtual Item* getItem() { return NULL; }
|
||||||
|
virtual const Item *getItem() const { return NULL; }
|
||||||
|
virtual Creature *getCreature() { return NULL; }
|
||||||
|
virtual const Creature *getCreature() const { return NULL; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void internalDraw(int x, int y, int blendframes, int xdiv, int ydiv, int zdiv, int anim);
|
||||||
|
|
||||||
|
uint32 m_id;
|
||||||
|
Type m_type;
|
||||||
|
Position m_position;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // THING_H
|
|
@ -0,0 +1,205 @@
|
||||||
|
#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]];
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#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
|
|
@ -0,0 +1,120 @@
|
||||||
|
#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];
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#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
|
|
@ -0,0 +1,66 @@
|
||||||
|
#include "tile.h"
|
||||||
|
#include "item.h"
|
||||||
|
#include "tibiadat.h"
|
||||||
|
|
||||||
|
Tile::Tile()
|
||||||
|
{
|
||||||
|
m_ground = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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(auto it = m_creatures.begin(), end = m_creatures.end(); it != end; ++it)
|
||||||
|
(*it)->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Tile::getStackSize()
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
if(m_ground)
|
||||||
|
ret++;
|
||||||
|
|
||||||
|
ret += m_itemsBot.size();
|
||||||
|
ret += m_creatures.size();
|
||||||
|
ret += m_itemsTop.size();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef TILE_H
|
||||||
|
#define TILE_H
|
||||||
|
|
||||||
|
#include "thing.h"
|
||||||
|
|
||||||
|
class Tile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Tile();
|
||||||
|
|
||||||
|
void addThing(ThingPtr thing, uint8 stackpos);
|
||||||
|
|
||||||
|
void draw(int x, int y);
|
||||||
|
bool hasGround();
|
||||||
|
int getStackSize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ThingPtr m_ground;
|
||||||
|
std::list<ThingPtr> m_itemsBot;
|
||||||
|
std::list<ThingPtr> m_creatures;
|
||||||
|
std::list<ThingPtr> m_itemsTop;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef OTCLIENT_GLOBAL_H
|
||||||
|
#define OTCLIENT_GLOBAL_H
|
||||||
|
|
||||||
|
#include <framework/global.h>
|
||||||
|
|
||||||
|
// widely used headers
|
||||||
|
#include <otclient/util/position.h>
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef OTCLIENT_NET_DECLARATIONS_H
|
||||||
|
#define OTCLIENT_NET_DECLARATIONS_H
|
||||||
|
|
||||||
|
#include <otclient/global.h>
|
||||||
|
#include <framework/net/declarations.h>
|
||||||
|
|
||||||
|
class ProtocolLogin;
|
||||||
|
class ProtocolGame;
|
||||||
|
|
||||||
|
typedef std::shared_ptr<ProtocolGame> ProtocolGamePtr;
|
||||||
|
typedef std::shared_ptr<ProtocolLogin> ProtocolLoginPtr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define CIPSOFT_PUBLIC_RSA "1321277432058722840622950990822933849527763264961655079678763618" \
|
||||||
|
"4334395343554449668205332383339435179772895415509701210392836078" \
|
||||||
|
"6959821132214473291575712138800495033169914814069637740318278150" \
|
||||||
|
"2907336840325241747827401343576296990629870233111328210165697754" \
|
||||||
|
"88792221429527047321331896351555606801473202394175817"
|
||||||
|
|
||||||
|
|
||||||
|
#define OTSERV_PUBLIC_RSA "1091201329673994292788609605089955415282375029027981291234687579" \
|
||||||
|
"3726629149257644633073969600111060390723088861007265581882535850" \
|
||||||
|
"3429057592827629436413108566029093628212635953836686562675849720" \
|
||||||
|
"6207862794310902180176810615217550567108238764764442605581471797" \
|
||||||
|
"07119674283982419152118103759076030616683978566631413"
|
||||||
|
|
||||||
|
// TODO: place it somewhere else
|
||||||
|
enum SpeakClasses {
|
||||||
|
SPEAK_SAY = 0x01, //normal talk
|
||||||
|
SPEAK_WHISPER = 0x02, //whispering - #w text
|
||||||
|
SPEAK_YELL = 0x03, //yelling - #y text
|
||||||
|
SPEAK_PRIVATE_PN = 0x04, //Player-to-NPC speaking(NPCs channel)
|
||||||
|
SPEAK_PRIVATE_NP = 0x05, //NPC-to-Player speaking
|
||||||
|
SPEAK_PRIVATE = 0x06, //Players speaking privately to players
|
||||||
|
SPEAK_CHANNEL_Y = 0x07, //Yellow message in chat
|
||||||
|
SPEAK_CHANNEL_W = 0x08, //White message in chat
|
||||||
|
SPEAK_RVR_CHANNEL = 0x09, //Reporting rule violation - Ctrl+R
|
||||||
|
SPEAK_RVR_ANSWER = 0x0A, //Answering report
|
||||||
|
SPEAK_RVR_CONTINUE = 0x0B, //Answering the answer of the report
|
||||||
|
SPEAK_BROADCAST = 0x0C, //Broadcast a message - #b
|
||||||
|
SPEAK_CHANNEL_R1 = 0x0D, //Talk red on chat - #c
|
||||||
|
SPEAK_PRIVATE_RED = 0x0E, //Red private - @name@ text
|
||||||
|
SPEAK_CHANNEL_O = 0x0F, //Talk orange on text
|
||||||
|
//SPEAK_ = 0x10, //?
|
||||||
|
SPEAK_CHANNEL_R2 = 0x11, //Talk red anonymously on chat - #d
|
||||||
|
//SPEAK_ = 0x12, //?
|
||||||
|
SPEAK_MONSTER_SAY = 0x13, //Talk orange
|
||||||
|
SPEAK_MONSTER_YELL = 0x14 //Yell orange
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,99 @@
|
||||||
|
#include <otclient/net/protocolgame.h>
|
||||||
|
#include <otclient/core/game.h>
|
||||||
|
#include <framework/net/rsa.h>
|
||||||
|
|
||||||
|
ProtocolGame::ProtocolGame()
|
||||||
|
{
|
||||||
|
m_checksumEnabled = false;
|
||||||
|
g_game.setProtocol(ProtocolGamePtr(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtocolGame::~ProtocolGame()
|
||||||
|
{
|
||||||
|
sendLogout();
|
||||||
|
g_game.setProtocol(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::login(const std::string& accountName, const std::string& accountPassword, uint32 ip, uint16 port, const std::string& characterName)
|
||||||
|
{
|
||||||
|
if(accountName.empty() || accountPassword.empty()) {
|
||||||
|
callLuaField("onError", "You must enter an account name and password.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_accountName = accountName;
|
||||||
|
m_accountPassword = accountPassword;
|
||||||
|
m_characterName = characterName;
|
||||||
|
|
||||||
|
char host[16];
|
||||||
|
sprintf(host, "%d.%d.%d.%d", (uint8)ip, (uint8)(ip >> 8), (uint8)(ip >> 16), (uint8)(ip >> 24));
|
||||||
|
|
||||||
|
connect(host, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::onConnect()
|
||||||
|
{
|
||||||
|
recv();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::sendLoginPacket(uint32 timestamp, uint8 unknown)
|
||||||
|
{
|
||||||
|
OutputMessage oMsg;
|
||||||
|
|
||||||
|
oMsg.addU8(0x0A); // Protocol id
|
||||||
|
oMsg.addU16(0x02); // OS
|
||||||
|
oMsg.addU16(862); // Client version
|
||||||
|
|
||||||
|
oMsg.addU8(0); // First RSA byte must be 0x00 // 1
|
||||||
|
|
||||||
|
// Generete xtea key.
|
||||||
|
m_xteaKey[0] = 432324;
|
||||||
|
m_xteaKey[1] = 24324;
|
||||||
|
m_xteaKey[2] = 423432;
|
||||||
|
m_xteaKey[3] = 234324;
|
||||||
|
|
||||||
|
// Add xtea key
|
||||||
|
oMsg.addU32(m_xteaKey[0]); // 5
|
||||||
|
oMsg.addU32(m_xteaKey[1]); // 9
|
||||||
|
oMsg.addU32(m_xteaKey[2]); // 13
|
||||||
|
oMsg.addU32(m_xteaKey[3]); // 17
|
||||||
|
|
||||||
|
oMsg.addU8(0); // is gm set?
|
||||||
|
oMsg.addString(m_accountName); // Account Name // 20
|
||||||
|
oMsg.addString(m_characterName); // Character Name // 22
|
||||||
|
oMsg.addString(m_accountPassword); // Password // 24
|
||||||
|
|
||||||
|
oMsg.addU32(timestamp); // 28
|
||||||
|
oMsg.addU8(unknown); // 29
|
||||||
|
|
||||||
|
// Packet data must have since byte 0, start, 128 bytes
|
||||||
|
oMsg.addPaddingBytes(128 - (29 + m_accountName.length() + m_characterName.length() + m_accountPassword.length()));
|
||||||
|
|
||||||
|
// Encrypt msg with RSA
|
||||||
|
if(!Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, OTSERV_PUBLIC_RSA))
|
||||||
|
return;
|
||||||
|
|
||||||
|
send(oMsg);
|
||||||
|
|
||||||
|
m_xteaEncryptionEnabled = true;
|
||||||
|
|
||||||
|
recv();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::onRecv(InputMessage& inputMessage)
|
||||||
|
{
|
||||||
|
static bool firstRecv = true;
|
||||||
|
if(firstRecv) {
|
||||||
|
inputMessage.skipBytes(3);
|
||||||
|
uint32 timestamp = inputMessage.getU32();
|
||||||
|
uint8 unknown = inputMessage.getU8();
|
||||||
|
|
||||||
|
m_checksumEnabled = true;
|
||||||
|
sendLoginPacket(timestamp, unknown);
|
||||||
|
|
||||||
|
firstRecv = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parseMessage(inputMessage);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
#ifndef PROTOCOLGAME_H
|
||||||
|
#define PROTOCOLGAME_H
|
||||||
|
|
||||||
|
#include "declarations.h"
|
||||||
|
#include <framework/net/protocol.h>
|
||||||
|
|
||||||
|
#include <otclient/core/player.h>
|
||||||
|
#include <otclient/core/item.h>
|
||||||
|
|
||||||
|
class ProtocolGame : public Protocol
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProtocolGame();
|
||||||
|
~ProtocolGame();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void login(const std::string& accountName, const std::string& accountPassword, uint32 ip, uint16 port, const std::string& characterName);
|
||||||
|
|
||||||
|
void onConnect();
|
||||||
|
void onRecv(InputMessage& inputMessage);
|
||||||
|
|
||||||
|
// Send Messages
|
||||||
|
void sendLogout();
|
||||||
|
void sendPing();
|
||||||
|
void sendWalkNorth();
|
||||||
|
void sendWalkEast();
|
||||||
|
void sendWalkSouth();
|
||||||
|
void sendWalkWest();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void sendLoginPacket(uint32 timestamp, uint8 unknown);
|
||||||
|
|
||||||
|
// Parse Messages
|
||||||
|
void parseMessage(InputMessage& msg);
|
||||||
|
|
||||||
|
void parsePlayerLogin(InputMessage& msg);
|
||||||
|
void parseGMActions(InputMessage& msg);
|
||||||
|
void parseErrorMessage(InputMessage& msg);
|
||||||
|
void parseFYIMessage(InputMessage& msg);
|
||||||
|
void parseWaitList(InputMessage& msg);
|
||||||
|
void parsePing(InputMessage&);
|
||||||
|
void parseDeath(InputMessage&);
|
||||||
|
void parseCanReportBugs(InputMessage& msg);
|
||||||
|
void parseMapDescription(InputMessage& msg);
|
||||||
|
void parseMoveNorth(InputMessage& msg);
|
||||||
|
void parseMoveEast(InputMessage& msg);
|
||||||
|
void parseMoveSouth(InputMessage& msg);
|
||||||
|
void parseMoveWest(InputMessage& msg);
|
||||||
|
void parseUpdateTile(InputMessage& msg);
|
||||||
|
void parseTileAddThing(InputMessage& msg);
|
||||||
|
void parseTileTransformThing(InputMessage& msg);
|
||||||
|
void parseTileRemoveThing(InputMessage& msg);
|
||||||
|
void parseCreatureMove(InputMessage& msg);
|
||||||
|
void parseOpenContainer(InputMessage& msg);
|
||||||
|
void parseCloseContainer(InputMessage& msg);
|
||||||
|
void parseContainerAddItem(InputMessage& msg);
|
||||||
|
void parseContainerUpdateItem(InputMessage& msg);
|
||||||
|
void parseContainerRemoveItem(InputMessage& msg);
|
||||||
|
void parseAddInventoryItem(InputMessage& msg);
|
||||||
|
void parseRemoveInventoryItem(InputMessage& msg);
|
||||||
|
void parseOpenShopWindow(InputMessage& msg);
|
||||||
|
void parsePlayerCash(InputMessage& msg);
|
||||||
|
void parseCloseShopWindow(InputMessage&);
|
||||||
|
void parseWorldLight(InputMessage& msg);
|
||||||
|
void parseMagicEffect(InputMessage& msg);
|
||||||
|
void parseAnimatedText(InputMessage& msg);
|
||||||
|
void parseDistanceShot(InputMessage& msg);
|
||||||
|
void parseCreatureSquare(InputMessage& msg);
|
||||||
|
void parseCreatureHealth(InputMessage& msg);
|
||||||
|
void parseCreatureLight(InputMessage& msg);
|
||||||
|
void parseCreatureOutfit(InputMessage& msg);
|
||||||
|
void parseCreatureSpeed(InputMessage& msg);
|
||||||
|
void parseCreatureSkulls(InputMessage& msg);
|
||||||
|
void parseCreatureShields(InputMessage& msg);
|
||||||
|
void parseCreatureTurn(InputMessage& msg);
|
||||||
|
void parseItemTextWindow(InputMessage& msg);
|
||||||
|
void parseHouseTextWindow(InputMessage& msg);
|
||||||
|
void parsePlayerStats(InputMessage& msg);
|
||||||
|
void parsePlayerSkills(InputMessage& msg);
|
||||||
|
void parsePlayerIcons(InputMessage& msg);
|
||||||
|
void parsePlayerCancelAttack(InputMessage& msg);
|
||||||
|
void parseCreatureSpeak(InputMessage& msg);
|
||||||
|
void parseChannelList(InputMessage& msg);
|
||||||
|
void parseOpenChannel(InputMessage& msg);
|
||||||
|
void parseOpenPrivatePlayerChat(InputMessage& msg);
|
||||||
|
void parseOpenRuleViolation(InputMessage& msg);
|
||||||
|
void parseRuleViolationAF(InputMessage& msg);
|
||||||
|
void parseRuleViolationB0(InputMessage& msg);
|
||||||
|
void parseRuleViolationB1(InputMessage& msg);
|
||||||
|
void parseCreatePrivateChannel(InputMessage& msg);
|
||||||
|
void parseClosePrivateChannel(InputMessage& msg);
|
||||||
|
void parseSafeTradeRequest(InputMessage& msg);
|
||||||
|
void parseSafeTradeClose(InputMessage&);
|
||||||
|
void parseTextMessage(InputMessage& msg);
|
||||||
|
void parseCancelWalk(InputMessage& msg);
|
||||||
|
void parseFloorChangeUp(InputMessage& msg);
|
||||||
|
void parseFloorChangeDown(InputMessage& msg);
|
||||||
|
void parseOutfitWindow(InputMessage& msg);
|
||||||
|
void parseVipState(InputMessage& msg);
|
||||||
|
void parseVipLogin(InputMessage& msg);
|
||||||
|
void parseVipLogout(InputMessage& msg);
|
||||||
|
void parseShowTutorial(InputMessage& msg);
|
||||||
|
void parseAddMarker(InputMessage& msg);
|
||||||
|
void parseQuestList(InputMessage& msg);
|
||||||
|
void parseQuestPartList(InputMessage& msg);
|
||||||
|
|
||||||
|
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);
|
||||||
|
ThingPtr internalGetThing(InputMessage& msg);
|
||||||
|
Outfit internalCreatureOutfit(InputMessage& msg);
|
||||||
|
ItemPtr internalGetItem(InputMessage& msg, uint16 id);
|
||||||
|
|
||||||
|
Position parsePosition(InputMessage& msg);
|
||||||
|
|
||||||
|
std::string m_accountName, m_accountPassword, m_characterName;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PROTOCOLGAME_H
|
|
@ -0,0 +1,943 @@
|
||||||
|
#include "protocolgame.h"
|
||||||
|
|
||||||
|
#include <otclient/core/player.h>
|
||||||
|
#include <otclient/core/tibiadat.h>
|
||||||
|
#include <otclient/core/game.h>
|
||||||
|
#include <otclient/core/map.h>
|
||||||
|
#include <otclient/core/effect.h>
|
||||||
|
|
||||||
|
void ProtocolGame::parseMessage(InputMessage& msg)
|
||||||
|
{
|
||||||
|
while(!msg.end()) {
|
||||||
|
uint8 opt = msg.getU8();
|
||||||
|
|
||||||
|
dump << "Protocol opt: " << std::hex << (int)opt << std::dec;
|
||||||
|
|
||||||
|
switch(opt) {
|
||||||
|
case 0x0A:
|
||||||
|
parsePlayerLogin(msg);
|
||||||
|
break;
|
||||||
|
case 0x0B:
|
||||||
|
parseGMActions(msg);
|
||||||
|
break;
|
||||||
|
case 0x14:
|
||||||
|
parseErrorMessage(msg);
|
||||||
|
break;
|
||||||
|
case 0x15:
|
||||||
|
parseFYIMessage(msg);
|
||||||
|
break;
|
||||||
|
case 0x16:
|
||||||
|
parseWaitList(msg);
|
||||||
|
break;
|
||||||
|
case 0x1E:
|
||||||
|
parsePing(msg);
|
||||||
|
break;
|
||||||
|
case 0x28:
|
||||||
|
parseDeath(msg);
|
||||||
|
break;
|
||||||
|
case 0x32:
|
||||||
|
parseCanReportBugs(msg);
|
||||||
|
break;
|
||||||
|
case 0x64:
|
||||||
|
parseMapDescription(msg);
|
||||||
|
break;
|
||||||
|
case 0x65:
|
||||||
|
parseMoveNorth(msg);
|
||||||
|
break;
|
||||||
|
case 0x66:
|
||||||
|
parseMoveEast(msg);
|
||||||
|
break;
|
||||||
|
case 0x67:
|
||||||
|
parseMoveSouth(msg);
|
||||||
|
break;
|
||||||
|
case 0x68:
|
||||||
|
parseMoveWest(msg);
|
||||||
|
break;
|
||||||
|
case 0x69:
|
||||||
|
parseUpdateTile(msg);
|
||||||
|
break;
|
||||||
|
case 0x6A:
|
||||||
|
parseTileAddThing(msg);
|
||||||
|
break;
|
||||||
|
case 0x6B:
|
||||||
|
parseTileTransformThing(msg);
|
||||||
|
break;
|
||||||
|
case 0x6C:
|
||||||
|
parseTileRemoveThing(msg);
|
||||||
|
break;
|
||||||
|
case 0x6D:
|
||||||
|
parseCreatureMove(msg);
|
||||||
|
break;
|
||||||
|
case 0x6E:
|
||||||
|
parseOpenContainer(msg);
|
||||||
|
break;
|
||||||
|
case 0x6F:
|
||||||
|
parseCloseContainer(msg);
|
||||||
|
break;
|
||||||
|
case 0x70:
|
||||||
|
parseContainerAddItem(msg);
|
||||||
|
break;
|
||||||
|
case 0x71:
|
||||||
|
parseContainerUpdateItem(msg);
|
||||||
|
break;
|
||||||
|
case 0x72:
|
||||||
|
parseContainerRemoveItem(msg);
|
||||||
|
break;
|
||||||
|
case 0x78:
|
||||||
|
parseAddInventoryItem(msg);
|
||||||
|
break;
|
||||||
|
case 0x79:
|
||||||
|
parseRemoveInventoryItem(msg);
|
||||||
|
break;
|
||||||
|
case 0x7A:
|
||||||
|
parseOpenShopWindow(msg);
|
||||||
|
break;
|
||||||
|
case 0x7B:
|
||||||
|
parsePlayerCash(msg);
|
||||||
|
break;
|
||||||
|
case 0x7C:
|
||||||
|
parseCloseShopWindow(msg);
|
||||||
|
break;
|
||||||
|
case 0x7D:
|
||||||
|
parseSafeTradeRequest(msg);
|
||||||
|
break;
|
||||||
|
case 0x7E:
|
||||||
|
parseSafeTradeRequest(msg);
|
||||||
|
break;
|
||||||
|
case 0x7F:
|
||||||
|
parseSafeTradeClose(msg);
|
||||||
|
break;
|
||||||
|
case 0x82:
|
||||||
|
parseWorldLight(msg);
|
||||||
|
break;
|
||||||
|
case 0x83:
|
||||||
|
parseMagicEffect(msg);
|
||||||
|
break;
|
||||||
|
case 0x84:
|
||||||
|
parseAnimatedText(msg);
|
||||||
|
break;
|
||||||
|
case 0x85:
|
||||||
|
parseDistanceShot(msg);
|
||||||
|
break;
|
||||||
|
case 0x86:
|
||||||
|
parseCreatureSquare(msg);
|
||||||
|
break;
|
||||||
|
case 0x8C:
|
||||||
|
parseCreatureHealth(msg);
|
||||||
|
break;
|
||||||
|
case 0x8D:
|
||||||
|
parseCreatureLight(msg);
|
||||||
|
break;
|
||||||
|
case 0x8E:
|
||||||
|
parseCreatureOutfit(msg);
|
||||||
|
break;
|
||||||
|
case 0x8F:
|
||||||
|
parseCreatureSpeed(msg);
|
||||||
|
break;
|
||||||
|
case 0x90:
|
||||||
|
parseCreatureSkulls(msg);
|
||||||
|
break;
|
||||||
|
case 0x91:
|
||||||
|
parseCreatureShields(msg);
|
||||||
|
break;
|
||||||
|
case 0x96:
|
||||||
|
parseItemTextWindow(msg);
|
||||||
|
break;
|
||||||
|
case 0x97:
|
||||||
|
parseHouseTextWindow(msg);
|
||||||
|
break;
|
||||||
|
case 0xA0:
|
||||||
|
parsePlayerStats(msg);
|
||||||
|
break;
|
||||||
|
case 0xA1:
|
||||||
|
parsePlayerSkills(msg);
|
||||||
|
break;
|
||||||
|
case 0xA2:
|
||||||
|
parsePlayerIcons(msg);
|
||||||
|
break;
|
||||||
|
case 0xA3:
|
||||||
|
parsePlayerCancelAttack(msg);
|
||||||
|
break;
|
||||||
|
case 0xAA:
|
||||||
|
parseCreatureSpeak(msg);
|
||||||
|
break;
|
||||||
|
case 0xAB:
|
||||||
|
parseChannelList(msg);
|
||||||
|
break;
|
||||||
|
case 0xAC:
|
||||||
|
parseOpenChannel(msg);
|
||||||
|
break;
|
||||||
|
case 0xAD:
|
||||||
|
parseOpenPrivatePlayerChat(msg);
|
||||||
|
break;
|
||||||
|
case 0xAE:
|
||||||
|
parseOpenRuleViolation(msg);
|
||||||
|
break;
|
||||||
|
case 0xAF:
|
||||||
|
parseRuleViolationAF(msg);
|
||||||
|
break;
|
||||||
|
case 0xB0:
|
||||||
|
parseRuleViolationB0(msg);
|
||||||
|
break;
|
||||||
|
case 0xB1:
|
||||||
|
parseRuleViolationB1(msg);
|
||||||
|
break;
|
||||||
|
case 0xB2:
|
||||||
|
parseCreatePrivateChannel(msg);
|
||||||
|
break;
|
||||||
|
case 0xB3:
|
||||||
|
parseClosePrivateChannel(msg);
|
||||||
|
break;
|
||||||
|
case 0xB4:
|
||||||
|
parseTextMessage(msg);
|
||||||
|
break;
|
||||||
|
case 0xB5:
|
||||||
|
parseCancelWalk(msg);
|
||||||
|
break;
|
||||||
|
case 0xBE:
|
||||||
|
parseFloorChangeUp(msg);
|
||||||
|
break;
|
||||||
|
case 0xBF:
|
||||||
|
parseFloorChangeDown(msg);
|
||||||
|
break;
|
||||||
|
case 0xC8:
|
||||||
|
parseOutfitWindow(msg);
|
||||||
|
break;
|
||||||
|
case 0xD2:
|
||||||
|
parseVipState(msg);
|
||||||
|
break;
|
||||||
|
case 0xD3:
|
||||||
|
parseVipLogin(msg);
|
||||||
|
break;
|
||||||
|
case 0xD4:
|
||||||
|
parseVipLogout(msg);
|
||||||
|
break;
|
||||||
|
case 0xDC:
|
||||||
|
parseShowTutorial(msg);
|
||||||
|
break;
|
||||||
|
case 0xDD:
|
||||||
|
parseAddMarker(msg);
|
||||||
|
break;
|
||||||
|
case 0xF0:
|
||||||
|
parseQuestList(msg);
|
||||||
|
break;
|
||||||
|
case 0xF1:
|
||||||
|
parseQuestPartList(msg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logDebug("UNKNOWN PACKET BYTE.", opt);
|
||||||
|
//skipPacket = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
recv();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parsePlayerLogin(InputMessage& msg)
|
||||||
|
{
|
||||||
|
Player *player = g_game.getPlayer();
|
||||||
|
player->setId(msg.getU32());
|
||||||
|
player->setDrawSpeed(msg.getU16());
|
||||||
|
player->setCanReportBugs(msg.getU8());
|
||||||
|
|
||||||
|
g_game.setOnline(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseGMActions(InputMessage& msg)
|
||||||
|
{
|
||||||
|
for(uint8 i = 0; i < 28; ++i)
|
||||||
|
msg.getU8();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseErrorMessage(InputMessage& msg)
|
||||||
|
{
|
||||||
|
std::string error = msg.getString();
|
||||||
|
callLuaField("onError", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseFYIMessage(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getString(); // message
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseWaitList(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getString(); // message
|
||||||
|
msg.getU8();// + 1 // time
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parsePing(InputMessage&)
|
||||||
|
{
|
||||||
|
sendPing();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseDeath(InputMessage&)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCanReportBugs(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // report bugs
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseMapDescription(InputMessage& msg)
|
||||||
|
{
|
||||||
|
Player *player = g_game.getPlayer();
|
||||||
|
player->setPosition(parsePosition(msg));
|
||||||
|
setMapDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, player->getPosition()->z, 18, 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseMoveNorth(InputMessage& msg)
|
||||||
|
{
|
||||||
|
Player *player = g_game.getPlayer();
|
||||||
|
player->getPosition()->y--;
|
||||||
|
setMapDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, player->getPosition()->z, 18, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseMoveEast(InputMessage& msg)
|
||||||
|
{
|
||||||
|
Player *player = g_game.getPlayer();
|
||||||
|
player->getPosition()->x++;
|
||||||
|
setMapDescription(msg, player->getPosition()->x + 9, player->getPosition()->y - 6, player->getPosition()->z, 1, 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseMoveSouth(InputMessage& msg)
|
||||||
|
{
|
||||||
|
Player *player = g_game.getPlayer();
|
||||||
|
player->getPosition()->y++;
|
||||||
|
setMapDescription(msg, player->getPosition()->x - 8, player->getPosition()->y + 7, player->getPosition()->z, 18, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseMoveWest(InputMessage& msg)
|
||||||
|
{
|
||||||
|
Player *player = g_game.getPlayer();
|
||||||
|
player->getPosition()->x--;
|
||||||
|
setMapDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, player->getPosition()->z, 1, 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseUpdateTile(InputMessage& msg)
|
||||||
|
{
|
||||||
|
Position tilePos = parsePosition(msg);
|
||||||
|
uint16 thingId = msg.getU16(true);
|
||||||
|
if(thingId == 0xFF01) {
|
||||||
|
msg.getU16();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setTileDescription(msg, tilePos);
|
||||||
|
msg.getU16();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseTileAddThing(InputMessage& msg)
|
||||||
|
{
|
||||||
|
parsePosition(msg); // tilePos
|
||||||
|
msg.getU8(); // stackPos
|
||||||
|
internalGetThing(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseTileTransformThing(InputMessage& msg)
|
||||||
|
{
|
||||||
|
parsePosition(msg); // tilePos
|
||||||
|
msg.getU8(); // stackPos
|
||||||
|
|
||||||
|
uint16 thingId = msg.getU16();
|
||||||
|
if(thingId == 0x0061 || thingId == 0x0062 || thingId == 0x0063) {
|
||||||
|
msg.getU32(); // creatureId
|
||||||
|
msg.getU8(); // direction
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
internalGetItem(msg, thingId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseTileRemoveThing(InputMessage& msg)
|
||||||
|
{
|
||||||
|
parsePosition(msg); // tilePos
|
||||||
|
msg.getU8(); // stackPos
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCreatureMove(InputMessage& msg)
|
||||||
|
{
|
||||||
|
parsePosition(msg); // oldPos
|
||||||
|
msg.getU8(); // oldStackPos
|
||||||
|
parsePosition(msg); // newPos
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseOpenContainer(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // cid
|
||||||
|
msg.getU16(); // itemid
|
||||||
|
msg.getString(); // name
|
||||||
|
msg.getU8(); // capacity
|
||||||
|
msg.getU8(); // hasParent
|
||||||
|
uint8 size = msg.getU8(); // size
|
||||||
|
|
||||||
|
for(uint32 i = 0; i < size; i++)
|
||||||
|
internalGetItem(msg, 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCloseContainer(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // cid
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseContainerAddItem(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // cid
|
||||||
|
internalGetItem(msg, 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseContainerUpdateItem(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // cid
|
||||||
|
msg.getU8(); // slot
|
||||||
|
internalGetItem(msg, 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseContainerRemoveItem(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // cid
|
||||||
|
msg.getU8(); // slot
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseAddInventoryItem(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // slot
|
||||||
|
internalGetItem(msg, 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseRemoveInventoryItem(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // slot
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseOpenShopWindow(InputMessage& msg)
|
||||||
|
{
|
||||||
|
uint8 listCount = msg.getU8();
|
||||||
|
for(uint8 i = 0; i < listCount; ++i) {
|
||||||
|
msg.getU16(); // item id
|
||||||
|
msg.getU8(); // runecharges
|
||||||
|
msg.getString(); // item name
|
||||||
|
msg.getU32(); // weight
|
||||||
|
msg.getU32(); // buy price
|
||||||
|
msg.getU32(); // sell price
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parsePlayerCash(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32();
|
||||||
|
uint8 size = msg.getU8();
|
||||||
|
|
||||||
|
for(int i = 0; i < size; i++) {
|
||||||
|
msg.getU16(); // itemid
|
||||||
|
msg.getU8(); // runecharges
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCloseShopWindow(InputMessage&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseSafeTradeRequest(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getString(); // name
|
||||||
|
uint8 count = msg.getU8();
|
||||||
|
|
||||||
|
for(uint8 i = 0; i < count; i++)
|
||||||
|
internalGetItem(msg, 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseSafeTradeClose(InputMessage&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseWorldLight(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // level
|
||||||
|
msg.getU8(); // color
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseMagicEffect(InputMessage& msg)
|
||||||
|
{
|
||||||
|
EffectPtr effect = EffectPtr(new Effect());
|
||||||
|
effect->setPosition(parsePosition(msg));
|
||||||
|
effect->setId(msg.getU8());
|
||||||
|
|
||||||
|
g_game.getMap()->addThing(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseAnimatedText(InputMessage& msg)
|
||||||
|
{
|
||||||
|
parsePosition(msg); // textPos
|
||||||
|
msg.getU8(); // color
|
||||||
|
msg.getString(); // text
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseDistanceShot(InputMessage& msg)
|
||||||
|
{
|
||||||
|
parsePosition(msg); // fromPos
|
||||||
|
parsePosition(msg); // toPos
|
||||||
|
msg.getU8(); // effect
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCreatureSquare(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // creatureId
|
||||||
|
msg.getU8(); // color
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCreatureHealth(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // creatureId
|
||||||
|
msg.getU8(); // percent
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCreatureLight(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // creature id
|
||||||
|
msg.getU8(); // level
|
||||||
|
msg.getU8(); // color
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCreatureOutfit(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // creature id
|
||||||
|
internalCreatureOutfit(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCreatureSpeed(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // creature id
|
||||||
|
msg.getU16(); // speed
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCreatureSkulls(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // creature id
|
||||||
|
msg.getU8(); // skull
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCreatureShields(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // creature id
|
||||||
|
msg.getU8(); // shield
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCreatureTurn(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // creature id
|
||||||
|
msg.getU8(); // direction
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseItemTextWindow(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // windowId
|
||||||
|
msg.getU16(); // itemid
|
||||||
|
msg.getU16(); // max length
|
||||||
|
msg.getString(); // text
|
||||||
|
msg.getString(); // writter
|
||||||
|
msg.getString(); // date
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseHouseTextWindow(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // unknown
|
||||||
|
msg.getU32(); // windowId
|
||||||
|
msg.getString(); // text
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parsePlayerStats(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU16(); // health
|
||||||
|
msg.getU16(); // max health
|
||||||
|
msg.getU32(); // free capacity
|
||||||
|
msg.getU32(); // experience
|
||||||
|
msg.getU16(); // level
|
||||||
|
msg.getU8(); // level percent
|
||||||
|
msg.getU16(); // mana
|
||||||
|
msg.getU16(); // max mana
|
||||||
|
msg.getU8(); // magic level
|
||||||
|
msg.getU8(); // magic level percent
|
||||||
|
msg.getU8(); // soul
|
||||||
|
msg.getU16(); // stamina
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parsePlayerSkills(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // fist skill
|
||||||
|
msg.getU8(); // fist percent
|
||||||
|
|
||||||
|
msg.getU8(); // club skill
|
||||||
|
msg.getU8(); // club percent
|
||||||
|
|
||||||
|
msg.getU8(); // sword skill
|
||||||
|
msg.getU8(); // sword percent
|
||||||
|
|
||||||
|
msg.getU8(); // axe skill
|
||||||
|
msg.getU8(); // axe percent
|
||||||
|
|
||||||
|
msg.getU8(); // distance skill
|
||||||
|
msg.getU8(); // distance percent
|
||||||
|
|
||||||
|
msg.getU8(); // shielding skill
|
||||||
|
msg.getU8(); // shielding percent
|
||||||
|
|
||||||
|
msg.getU8(); // fishing skill
|
||||||
|
msg.getU8(); // fishing percent
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parsePlayerIcons(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU16(); // icons
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parsePlayerCancelAttack(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCreatureSpeak(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // unkSpeak
|
||||||
|
msg.getString(); // name
|
||||||
|
msg.getU16(); // level
|
||||||
|
uint8 type = msg.getU8();
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case SPEAK_SAY:
|
||||||
|
case SPEAK_WHISPER:
|
||||||
|
case SPEAK_YELL:
|
||||||
|
case SPEAK_MONSTER_SAY:
|
||||||
|
case SPEAK_MONSTER_YELL:
|
||||||
|
case SPEAK_PRIVATE_NP:
|
||||||
|
parsePosition(msg); // creaturePos
|
||||||
|
break;
|
||||||
|
case SPEAK_CHANNEL_R1:
|
||||||
|
case SPEAK_CHANNEL_R2:
|
||||||
|
case SPEAK_CHANNEL_O:
|
||||||
|
case SPEAK_CHANNEL_Y:
|
||||||
|
case SPEAK_CHANNEL_W:
|
||||||
|
msg.getU16(); // channelId
|
||||||
|
break;
|
||||||
|
case SPEAK_RVR_CHANNEL:
|
||||||
|
msg.getU32(); // time
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//qDebug() << "Unknown speak type. opt: 0xAA, type: " << type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.getString(); // message
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseChannelList(InputMessage& msg)
|
||||||
|
{
|
||||||
|
uint8 count = msg.getU8();
|
||||||
|
for(uint8 i = 0; i < count; i++) {
|
||||||
|
msg.getU16();
|
||||||
|
msg.getString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseOpenChannel(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU16(); // channelId
|
||||||
|
msg.getString(); // name
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseOpenPrivatePlayerChat(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getString(); // name
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseOpenRuleViolation(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU16(); // a
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseRuleViolationAF(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU16(); // a
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseRuleViolationB0(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU16(); // a
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseRuleViolationB1(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU16(); // a
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCreatePrivateChannel(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU16(); // channel id
|
||||||
|
msg.getString(); // channel name
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseClosePrivateChannel(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU16(); // channel id
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseTextMessage(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // messageType
|
||||||
|
std::string message = msg.getString();
|
||||||
|
logDebug(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseCancelWalk(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // direction
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseFloorChangeUp(InputMessage& msg)
|
||||||
|
{
|
||||||
|
Player *player = g_game.getPlayer();
|
||||||
|
player->getPosition()->z--;
|
||||||
|
|
||||||
|
int32 skip = 0;
|
||||||
|
if(player->getPosition()->z == 7)
|
||||||
|
for(int32 i = 5; i >= 0; i--)
|
||||||
|
setFloorDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, i, 18, 14, 8 - i, &skip);
|
||||||
|
else if(player->getPosition()->z > 7)
|
||||||
|
setFloorDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, player->getPosition()->z - 2, 18, 14, 3, &skip);
|
||||||
|
|
||||||
|
player->getPosition()->x++;
|
||||||
|
player->getPosition()->y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseFloorChangeDown(InputMessage& msg)
|
||||||
|
{
|
||||||
|
Player *player = g_game.getPlayer();
|
||||||
|
player->getPosition()->z++;
|
||||||
|
|
||||||
|
int32 skip = 0;
|
||||||
|
if(player->getPosition()->z == 8) {
|
||||||
|
int32 j, i;
|
||||||
|
for(i = player->getPosition()->z, j = -1; i < (int32)player->getPosition()->z + 3; ++i, --j)
|
||||||
|
setFloorDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, i, 18, 14, j, &skip);
|
||||||
|
}
|
||||||
|
else if(player->getPosition()->z > 8 && player->getPosition()->z < 14)
|
||||||
|
setFloorDescription(msg, player->getPosition()->x - 8, player->getPosition()->y - 6, player->getPosition()->z + 2, 18, 14, -3, &skip);
|
||||||
|
|
||||||
|
player->getPosition()->x--;
|
||||||
|
player->getPosition()->y--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseOutfitWindow(InputMessage& msg)
|
||||||
|
{
|
||||||
|
internalCreatureOutfit(msg);
|
||||||
|
uint8 outfitCount = msg.getU8();
|
||||||
|
|
||||||
|
for(int i = 0; i < outfitCount; i++) {
|
||||||
|
msg.getU16(); // outfit id
|
||||||
|
msg.getString(); // outfit name
|
||||||
|
msg.getU8(); // addons
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseVipState(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // player id
|
||||||
|
msg.getString(); // player name
|
||||||
|
msg.getU8(); // online
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseVipLogin(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // player id
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseVipLogout(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU32(); // player id
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseShowTutorial(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU8(); // tutorial id
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseAddMarker(InputMessage& msg)
|
||||||
|
{
|
||||||
|
parsePosition(msg); // position
|
||||||
|
msg.getU8(); // icon
|
||||||
|
msg.getString(); // message
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseQuestList(InputMessage& msg)
|
||||||
|
{
|
||||||
|
uint16 questsCount = msg.getU16();
|
||||||
|
for(uint16 i = 0; i < questsCount; i++) {
|
||||||
|
msg.getU16(); // quest id
|
||||||
|
msg.getString(); // quest name
|
||||||
|
msg.getU8(); // quest state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::parseQuestPartList(InputMessage& msg)
|
||||||
|
{
|
||||||
|
msg.getU16(); // quest id
|
||||||
|
uint8 missionCount = msg.getU8();
|
||||||
|
for(uint8 i = 0; i < missionCount; i++) {
|
||||||
|
msg.getString(); // quest name
|
||||||
|
msg.getString(); // quest description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::setMapDescription(InputMessage& msg, int32 x, int32 y, int32 z, int32 width, int32 height)
|
||||||
|
{
|
||||||
|
int startz, endz, zstep, skip = 0;
|
||||||
|
|
||||||
|
if(z > 7) {
|
||||||
|
startz = z - 2;
|
||||||
|
endz = (15 < z+2) ? 15 : z+2;
|
||||||
|
zstep = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
startz = 7;
|
||||||
|
endz = 0;
|
||||||
|
zstep = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
logDebug((int)startz);
|
||||||
|
|
||||||
|
for(int nz = startz; nz != endz + zstep; nz += zstep)
|
||||||
|
setFloorDescription(msg, x, y, nz, width, height, z - nz, &skip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::setFloorDescription(InputMessage& msg, int32 x, int32 y, int32 z, int32 width, int32 height, int32 offset, int32* skipTiles)
|
||||||
|
{
|
||||||
|
int32 skip = *skipTiles;
|
||||||
|
|
||||||
|
for(int32 nx = 0; nx < width; nx++) {
|
||||||
|
for(int32 ny = 0; ny < height; ny++) {
|
||||||
|
if(skip == 0) {
|
||||||
|
uint16 tileOpt = msg.getU16(true);
|
||||||
|
if(tileOpt >= 0xFF00)
|
||||||
|
skip = (msg.getU16() & 0xFF);
|
||||||
|
else {
|
||||||
|
Position pos(x + nx + offset, y + ny + offset, z);
|
||||||
|
setTileDescription(msg, pos);
|
||||||
|
skip = (msg.getU16() & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
skip--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*skipTiles = skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::setTileDescription(InputMessage& msg, Position position)
|
||||||
|
{
|
||||||
|
int stackpos = 0;
|
||||||
|
while(1){
|
||||||
|
stackpos++;
|
||||||
|
uint16 inspectTileId = msg.getU16(true);
|
||||||
|
if(inspectTileId >= 0xFF00)
|
||||||
|
return;
|
||||||
|
else {
|
||||||
|
if(stackpos > 10) {
|
||||||
|
logDebug("[ProtocolGame::setTileDescription] Too many things!.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThingPtr thing = internalGetThing(msg);
|
||||||
|
if(thing)
|
||||||
|
thing->setPosition(position);
|
||||||
|
g_game.getMap()->addThing(thing, stackpos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThingPtr ProtocolGame::internalGetThing(InputMessage& msg)
|
||||||
|
{
|
||||||
|
ThingPtr thing;
|
||||||
|
|
||||||
|
uint16 thingId = msg.getU16();
|
||||||
|
if(thingId == 0x0061 || thingId == 0x0062) { // add new creature
|
||||||
|
CreaturePtr creature = CreaturePtr(new Creature);
|
||||||
|
|
||||||
|
if(thingId == 0x0062) { //creature is known
|
||||||
|
creature->setId(msg.getU32());
|
||||||
|
}
|
||||||
|
else if(thingId == 0x0061) { //creature is not known
|
||||||
|
msg.getU32(); // remove id
|
||||||
|
creature->setId(msg.getU32());
|
||||||
|
creature->setName(msg.getString());
|
||||||
|
}
|
||||||
|
|
||||||
|
creature->setHealthPercent(msg.getU8());
|
||||||
|
creature->setDirection((Direction)msg.getU8());
|
||||||
|
creature->setOutfit(internalCreatureOutfit(msg));
|
||||||
|
msg.getU8(); // light level
|
||||||
|
msg.getU8(); // light color
|
||||||
|
msg.getU16(); // speed
|
||||||
|
msg.getU8(); // skull
|
||||||
|
msg.getU8(); // shield
|
||||||
|
|
||||||
|
if(thingId == 0x0061) // emblem is sent only in packet type 0x61
|
||||||
|
msg.getU8();
|
||||||
|
msg.getU8(); // impassable
|
||||||
|
|
||||||
|
thing = creature;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(thingId == 0x0063) { // creature turn
|
||||||
|
parseCreatureTurn(msg);
|
||||||
|
}
|
||||||
|
else // item
|
||||||
|
thing = internalGetItem(msg, thingId);
|
||||||
|
|
||||||
|
return thing;
|
||||||
|
}
|
||||||
|
|
||||||
|
Outfit ProtocolGame::internalCreatureOutfit(InputMessage& msg)
|
||||||
|
{
|
||||||
|
Outfit outfit;
|
||||||
|
|
||||||
|
outfit.type = msg.getU16(); // looktype
|
||||||
|
if(outfit.type != 0) {
|
||||||
|
outfit.head = msg.getU8();
|
||||||
|
outfit.body = msg.getU8();
|
||||||
|
outfit.legs = msg.getU8();
|
||||||
|
outfit.feet = msg.getU8();
|
||||||
|
outfit.addons = msg.getU8();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
outfit.type = msg.getU16();
|
||||||
|
}
|
||||||
|
|
||||||
|
return outfit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemPtr ProtocolGame::internalGetItem(InputMessage& msg, uint16 id)
|
||||||
|
{
|
||||||
|
ItemPtr item = ItemPtr(new Item());
|
||||||
|
|
||||||
|
if(id == 0xFFFF)
|
||||||
|
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)
|
||||||
|
item->setCount(msg.getU8());
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
Position ProtocolGame::parsePosition(InputMessage& msg)
|
||||||
|
{
|
||||||
|
uint16 x = msg.getU16();
|
||||||
|
uint16 y = msg.getU16();
|
||||||
|
uint8 z = msg.getU8();
|
||||||
|
|
||||||
|
return Position(x, y, z);
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "protocolgame.h"
|
||||||
|
|
||||||
|
void ProtocolGame::sendLogout()
|
||||||
|
{
|
||||||
|
OutputMessage oMsg;
|
||||||
|
oMsg.addU8(0x14);
|
||||||
|
send(oMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::sendPing()
|
||||||
|
{
|
||||||
|
OutputMessage oMsg;
|
||||||
|
oMsg.addU8(0x1E);
|
||||||
|
send(oMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::sendWalkNorth()
|
||||||
|
{
|
||||||
|
OutputMessage oMsg;
|
||||||
|
oMsg.addU8(0x65);
|
||||||
|
send(oMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::sendWalkEast()
|
||||||
|
{
|
||||||
|
OutputMessage oMsg;
|
||||||
|
oMsg.addU8(0x66);
|
||||||
|
send(oMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::sendWalkSouth()
|
||||||
|
{
|
||||||
|
OutputMessage oMsg;
|
||||||
|
oMsg.addU8(0x67);
|
||||||
|
send(oMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolGame::sendWalkWest()
|
||||||
|
{
|
||||||
|
OutputMessage oMsg;
|
||||||
|
oMsg.addU8(0x68);
|
||||||
|
send(oMsg);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
#include "protocollogin.h"
|
||||||
|
#include <framework/net/outputmessage.h>
|
||||||
|
#include <framework/net/rsa.h>
|
||||||
|
#include <framework/luascript/luainterface.h>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
// TODO just testing
|
||||||
|
#include "protocolgame.h"
|
||||||
|
|
||||||
|
ProtocolLogin::ProtocolLogin()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtocolLogin::~ProtocolLogin()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolLogin::login(const std::string& accountName, const std::string& accountPassword)
|
||||||
|
{
|
||||||
|
if(accountName.empty() || accountPassword.empty()) {
|
||||||
|
callLuaField("onError", "You must enter an account name and password.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_accountName = accountName;
|
||||||
|
m_accountPassword = accountPassword;
|
||||||
|
|
||||||
|
/*static const char hosts[][32] = {
|
||||||
|
"login01.tibia.com",
|
||||||
|
"login02.tibia.com",
|
||||||
|
"login03.tibia.com",
|
||||||
|
"login04.tibia.com",
|
||||||
|
"login05.tibia.com",
|
||||||
|
"tibia01.cipsoft.com",
|
||||||
|
"tibia02.cipsoft.com",
|
||||||
|
"tibia03.cipsoft.com",
|
||||||
|
"tibia04.cipsoft.com",
|
||||||
|
"tibia05.cipsoft.com"
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string host = hosts[rand() % 10];*/
|
||||||
|
std::string host = "sv3.radbr.com";
|
||||||
|
uint16 port = 7171;
|
||||||
|
|
||||||
|
connect(host, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolLogin::onConnect()
|
||||||
|
{
|
||||||
|
sendLoginPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolLogin::sendLoginPacket()
|
||||||
|
{
|
||||||
|
OutputMessage oMsg;
|
||||||
|
|
||||||
|
oMsg.addU8(0x01); // Protocol id
|
||||||
|
oMsg.addU16(0x02); // OS
|
||||||
|
oMsg.addU16(862); // Client version
|
||||||
|
|
||||||
|
oMsg.addU32(0x4E12DAFF); // Data Signature
|
||||||
|
oMsg.addU32(0x4E12DB27); // Sprite Signature
|
||||||
|
oMsg.addU32(0x4E119CBF); // Picture Signature
|
||||||
|
|
||||||
|
oMsg.addU8(0); // First RSA byte must be 0x00 // 1
|
||||||
|
|
||||||
|
// Generete xtea key.
|
||||||
|
m_xteaKey[0] = 432324;
|
||||||
|
m_xteaKey[1] = 24324;
|
||||||
|
m_xteaKey[2] = 423432;
|
||||||
|
m_xteaKey[3] = 234324;
|
||||||
|
|
||||||
|
// Add xtea key
|
||||||
|
oMsg.addU32(m_xteaKey[0]); // 5
|
||||||
|
oMsg.addU32(m_xteaKey[1]); // 9
|
||||||
|
oMsg.addU32(m_xteaKey[2]); // 13
|
||||||
|
oMsg.addU32(m_xteaKey[3]); // 17
|
||||||
|
|
||||||
|
oMsg.addString(m_accountName); // Account Name // 19
|
||||||
|
oMsg.addString(m_accountPassword); // Password // 21
|
||||||
|
|
||||||
|
// Packet data must have since byte 0, start, 128 bytes
|
||||||
|
oMsg.addPaddingBytes(128 - (21 + m_accountName.length() + m_accountPassword.length()));
|
||||||
|
|
||||||
|
// Encrypt msg with RSA
|
||||||
|
if(!Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, OTSERV_PUBLIC_RSA))
|
||||||
|
return;
|
||||||
|
|
||||||
|
send(oMsg);
|
||||||
|
|
||||||
|
m_xteaEncryptionEnabled = true;
|
||||||
|
|
||||||
|
recv();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolLogin::onRecv(InputMessage& inputMessage)
|
||||||
|
{
|
||||||
|
while(!inputMessage.end()) {
|
||||||
|
uint8 opt = inputMessage.getU8();
|
||||||
|
logDebug("opt:",(uint)opt);
|
||||||
|
switch(opt) {
|
||||||
|
case 0x0A:
|
||||||
|
parseError(inputMessage);
|
||||||
|
break;
|
||||||
|
case 0x14:
|
||||||
|
parseMOTD(inputMessage);
|
||||||
|
break;
|
||||||
|
case 0x1e:
|
||||||
|
callLuaField("onError", "Client needs update.");
|
||||||
|
break;
|
||||||
|
case 0x64:
|
||||||
|
parseCharacterList(inputMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolLogin::parseError(InputMessage& inputMessage)
|
||||||
|
{
|
||||||
|
std::string error = inputMessage.getString();
|
||||||
|
logDebug(error);
|
||||||
|
callLuaField("onError", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolLogin::parseMOTD(InputMessage& inputMessage)
|
||||||
|
{
|
||||||
|
std::string motd = inputMessage.getString();
|
||||||
|
logDebug(motd);
|
||||||
|
callLuaField("onMotd", motd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolLogin::parseCharacterList(InputMessage& inputMessage)
|
||||||
|
{
|
||||||
|
uint8 characters = inputMessage.getU8();
|
||||||
|
for(int i = 0; i < characters; ++i) {
|
||||||
|
std::string name = inputMessage.getString();
|
||||||
|
std::string world = inputMessage.getString();
|
||||||
|
uint32 ip = inputMessage.getU32();
|
||||||
|
uint16 port = inputMessage.getU16();
|
||||||
|
|
||||||
|
logDebug("character: ", name.c_str(), world.c_str(), ip, " ", port);
|
||||||
|
|
||||||
|
// TODO just test
|
||||||
|
if(i == 0) {
|
||||||
|
ProtocolGamePtr protocolGame = ProtocolGamePtr(new ProtocolGame);
|
||||||
|
protocolGame->login(m_accountName, m_accountPassword, ip, port, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint16 premiumDays = inputMessage.getU16();
|
||||||
|
logDebug("prem days: ", premiumDays);
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef PROTOCOLLOGIN_H
|
||||||
|
#define PROTOCOLLOGIN_H
|
||||||
|
|
||||||
|
#include "declarations.h"
|
||||||
|
#include <framework/net/protocol.h>
|
||||||
|
|
||||||
|
class ProtocolLogin;
|
||||||
|
typedef std::shared_ptr<ProtocolLogin> ProtocolLoginPtr;
|
||||||
|
|
||||||
|
class ProtocolLogin : public Protocol
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProtocolLogin();
|
||||||
|
~ProtocolLogin();
|
||||||
|
|
||||||
|
static ProtocolLoginPtr create() { return ProtocolLoginPtr(new ProtocolLogin); }
|
||||||
|
|
||||||
|
void login(const std::string& accountName, const std::string& accountPassword);
|
||||||
|
|
||||||
|
void onConnect();
|
||||||
|
void onRecv(InputMessage& inputMessage);
|
||||||
|
|
||||||
|
void cancel() { /* TODO: this func */ }
|
||||||
|
|
||||||
|
ProtocolLoginPtr asProtocolLogin() { return std::static_pointer_cast<ProtocolLogin>(shared_from_this()); }
|
||||||
|
virtual const char* getLuaTypeName() const { return "ProtocolLogin"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void sendLoginPacket();
|
||||||
|
|
||||||
|
void parseError(InputMessage& inputMessage);
|
||||||
|
void parseMOTD(InputMessage& inputMessage);
|
||||||
|
void parseCharacterList(InputMessage& inputMessage);
|
||||||
|
|
||||||
|
std::string m_accountName, m_accountPassword;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,278 @@
|
||||||
|
#include "otclient.h"
|
||||||
|
|
||||||
|
#include <framework/core/modulemanager.h>
|
||||||
|
#include <framework/core/configmanager.h>
|
||||||
|
#include <framework/core/resourcemanager.h>
|
||||||
|
#include <framework/core/eventdispatcher.h>
|
||||||
|
#include <framework/luascript/luainterface.h>
|
||||||
|
#include <framework/platform/platform.h>
|
||||||
|
#include <framework/graphics/graphics.h>
|
||||||
|
#include <framework/graphics/fontmanager.h>
|
||||||
|
#include <framework/ui/uimanager.h>
|
||||||
|
#include <framework/ui/uiwidget.h>
|
||||||
|
#include <framework/net/connection.h>
|
||||||
|
|
||||||
|
#include <otclient/net/protocolgame.h>
|
||||||
|
#include <otclient/core/game.h>
|
||||||
|
#include <otclient/core/map.h>
|
||||||
|
|
||||||
|
#define POLL_CYCLE_DELAY 10
|
||||||
|
|
||||||
|
OTClient g_client;
|
||||||
|
|
||||||
|
void OTClient::init(std::vector<std::string> args)
|
||||||
|
{
|
||||||
|
m_running = false;
|
||||||
|
m_stopping = false;
|
||||||
|
|
||||||
|
// print client information
|
||||||
|
logInfo("OTClient 0.2.0");
|
||||||
|
|
||||||
|
// initialize platform related stuff
|
||||||
|
g_platform.init(this, "OTClient");
|
||||||
|
|
||||||
|
// initialize script environment
|
||||||
|
g_lua.init();
|
||||||
|
|
||||||
|
// register otclient lua functions
|
||||||
|
registerLuaFunctions();
|
||||||
|
|
||||||
|
// initialize resources
|
||||||
|
g_resources.init(args[0].c_str());
|
||||||
|
|
||||||
|
// load configurations
|
||||||
|
loadConfigurations();
|
||||||
|
|
||||||
|
// create the client window
|
||||||
|
g_platform.createWindow(g_configs.get("window x"), g_configs.get("window y"),
|
||||||
|
g_configs.get("window width"), g_configs.get("window height"),
|
||||||
|
550, 450,
|
||||||
|
g_configs.get("window maximized"));
|
||||||
|
g_platform.setWindowTitle("OTClient");
|
||||||
|
|
||||||
|
// initialize graphics
|
||||||
|
g_graphics.init();
|
||||||
|
|
||||||
|
// initialize event dispatcher
|
||||||
|
g_dispatcher.init();
|
||||||
|
|
||||||
|
// initialize network
|
||||||
|
//g_network.init();
|
||||||
|
|
||||||
|
// initialize the ui
|
||||||
|
g_ui.init();
|
||||||
|
|
||||||
|
// discover and load modules
|
||||||
|
g_modules.discoverAndLoadModules();
|
||||||
|
|
||||||
|
// now that everything is initialized, setup configurations
|
||||||
|
setupConfigurations();
|
||||||
|
|
||||||
|
// now that everything is loaded, show the window
|
||||||
|
g_platform.showWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTClient::run()
|
||||||
|
{
|
||||||
|
std::string fpsText;
|
||||||
|
Size fpsTextSize;
|
||||||
|
FontPtr defaultFont = g_fonts.getDefaultFont();
|
||||||
|
int frameTicks = g_platform.getTicks();
|
||||||
|
int lastFpsTicks = frameTicks;
|
||||||
|
int lastPollTicks = frameTicks;
|
||||||
|
int frameCount = 0;
|
||||||
|
|
||||||
|
m_stopping = false;
|
||||||
|
m_running = true;
|
||||||
|
|
||||||
|
if(g_ui.getRootWidget()->getChildCount() == 0) {
|
||||||
|
logError("ERROR: there is no root widgets to display, the app will close");
|
||||||
|
m_stopping = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// run the first poll
|
||||||
|
poll();
|
||||||
|
|
||||||
|
while(!m_stopping) {
|
||||||
|
frameTicks = g_platform.getTicks();
|
||||||
|
|
||||||
|
// calculate fps
|
||||||
|
frameCount++;
|
||||||
|
if(frameTicks - lastFpsTicks >= 1000) {
|
||||||
|
fpsText = fw::mkstr("FPS: ", frameCount);
|
||||||
|
fpsTextSize = defaultFont->calculateTextRectSize(fpsText);
|
||||||
|
frameCount = 0;
|
||||||
|
lastFpsTicks = frameTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
// poll events every POLL_CYCLE_DELAY
|
||||||
|
// this delay exists to avoid massive polling thus increasing framerate
|
||||||
|
if(frameTicks - lastPollTicks >= POLL_CYCLE_DELAY) {
|
||||||
|
poll();
|
||||||
|
lastPollTicks = frameTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only render when the windows is visible
|
||||||
|
if(g_platform.isWindowVisible()) {
|
||||||
|
// render begin
|
||||||
|
g_graphics.beginRender();
|
||||||
|
|
||||||
|
// render everything
|
||||||
|
render();
|
||||||
|
|
||||||
|
// render fps
|
||||||
|
defaultFont->renderText(fpsText, Point(g_graphics.getScreenSize().width() - fpsTextSize.width() - 10, 10));
|
||||||
|
|
||||||
|
// render end
|
||||||
|
g_graphics.endRender();
|
||||||
|
|
||||||
|
// swap the old buffer with the new rendered
|
||||||
|
g_platform.swapBuffers();
|
||||||
|
} else {
|
||||||
|
// sleeps until next poll to avoid massive cpu usage
|
||||||
|
g_platform.sleep(POLL_CYCLE_DELAY+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_stopping = false;
|
||||||
|
m_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTClient::terminate()
|
||||||
|
{
|
||||||
|
// hide the window because there is no render anymore
|
||||||
|
g_platform.hideWindow();
|
||||||
|
|
||||||
|
// run modules unload event
|
||||||
|
g_modules.unloadModules();
|
||||||
|
|
||||||
|
// terminate ui
|
||||||
|
g_ui.terminate();
|
||||||
|
|
||||||
|
// release remaining lua object references
|
||||||
|
g_lua.collectGarbage();
|
||||||
|
|
||||||
|
// poll remaining events
|
||||||
|
poll();
|
||||||
|
|
||||||
|
// terminate network
|
||||||
|
//g_network.terminate();
|
||||||
|
|
||||||
|
// terminate dispatcher
|
||||||
|
g_dispatcher.terminate();
|
||||||
|
|
||||||
|
// terminate graphics
|
||||||
|
g_graphics.terminate();
|
||||||
|
|
||||||
|
// save configurations
|
||||||
|
saveConfigurations();
|
||||||
|
|
||||||
|
// release resources
|
||||||
|
g_resources.terminate();
|
||||||
|
|
||||||
|
// terminate script environment
|
||||||
|
g_lua.terminate();
|
||||||
|
|
||||||
|
// end platform related stuff
|
||||||
|
g_platform.terminate();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTClient::exit()
|
||||||
|
{
|
||||||
|
// stops the main loop
|
||||||
|
m_stopping = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTClient::poll()
|
||||||
|
{
|
||||||
|
// poll platform events
|
||||||
|
g_platform.poll();
|
||||||
|
|
||||||
|
// poll network events
|
||||||
|
//g_network.poll();
|
||||||
|
Connection::poll();
|
||||||
|
|
||||||
|
// poll dispatcher events
|
||||||
|
g_dispatcher.poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTClient::render()
|
||||||
|
{
|
||||||
|
if(g_game.getOnline())
|
||||||
|
g_game.getMap()->draw(0, 0);
|
||||||
|
|
||||||
|
// everything is rendered by UI components
|
||||||
|
g_ui.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTClient::loadConfigurations()
|
||||||
|
{
|
||||||
|
// default window size
|
||||||
|
int defWidth = 550;
|
||||||
|
int defHeight = 450;
|
||||||
|
|
||||||
|
// sets default window configuration
|
||||||
|
g_configs.set("window x", (g_platform.getDisplayWidth() - defWidth)/2);
|
||||||
|
g_configs.set("window y", (g_platform.getDisplayHeight() - defHeight)/2);
|
||||||
|
g_configs.set("window width", defWidth);
|
||||||
|
g_configs.set("window height", defHeight);
|
||||||
|
g_configs.set("window maximized", false);
|
||||||
|
g_configs.set("vsync", true);
|
||||||
|
|
||||||
|
// loads user configuration
|
||||||
|
if(!g_configs.load("config.otml"))
|
||||||
|
logInfo("Using default configurations.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTClient::setupConfigurations()
|
||||||
|
{
|
||||||
|
// activate vertical synchronization?
|
||||||
|
g_platform.setVerticalSync(g_configs.get("vsync"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTClient::saveConfigurations()
|
||||||
|
{
|
||||||
|
g_configs.set("window x", g_platform.getWindowX());
|
||||||
|
g_configs.set("window y", g_platform.getWindowY());
|
||||||
|
g_configs.set("window width", g_platform.getWindowWidth());
|
||||||
|
g_configs.set("window height", g_platform.getWindowHeight());
|
||||||
|
g_configs.set("window maximized", g_platform.isWindowMaximized());
|
||||||
|
|
||||||
|
// saves user configuration
|
||||||
|
if(!g_configs.save())
|
||||||
|
logError("ERROR: configurations are lost because it couldn't be saved");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTClient::onClose()
|
||||||
|
{
|
||||||
|
if(m_onCloseCallback)
|
||||||
|
m_onCloseCallback();
|
||||||
|
else
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTClient::onResize(const Size& size)
|
||||||
|
{
|
||||||
|
g_graphics.resize(size);
|
||||||
|
g_ui.resize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTClient::onInputEvent(const InputEvent& event)
|
||||||
|
{
|
||||||
|
g_ui.inputEvent(event);
|
||||||
|
|
||||||
|
ProtocolGamePtr protocol = g_game.getProtocol();
|
||||||
|
if(protocol) {
|
||||||
|
if(event.type == EventKeyDown) {
|
||||||
|
if(event.keycode == KC_UP)
|
||||||
|
protocol->sendWalkNorth();
|
||||||
|
if(event.keycode == KC_RIGHT)
|
||||||
|
protocol->sendWalkEast();
|
||||||
|
if(event.keycode == KC_DOWN)
|
||||||
|
protocol->sendWalkSouth();
|
||||||
|
if(event.keycode == KC_LEFT)
|
||||||
|
protocol->sendWalkWest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef OTCLIENT_H
|
||||||
|
#define OTCLIENT_H
|
||||||
|
|
||||||
|
#include <framework/platform/platformlistener.h>
|
||||||
|
|
||||||
|
class OTClient : public PlatformListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Where everything begins...
|
||||||
|
void init(std::vector<std::string> args);
|
||||||
|
/// Main loop
|
||||||
|
void run();
|
||||||
|
/// Called when the client is terminating
|
||||||
|
void terminate();
|
||||||
|
|
||||||
|
/// Stop running
|
||||||
|
void exit();
|
||||||
|
/// Poll platform, dispatcher and network events
|
||||||
|
void poll();
|
||||||
|
/// Render each frame
|
||||||
|
void render();
|
||||||
|
|
||||||
|
/// Fired when user tryes to close the window
|
||||||
|
void onClose();
|
||||||
|
/// Fired when user resize the window
|
||||||
|
void onResize(const Size& size);
|
||||||
|
/// Fired on an user input event
|
||||||
|
void onInputEvent(const InputEvent& event);
|
||||||
|
|
||||||
|
bool isRunning() const { return m_running; }
|
||||||
|
|
||||||
|
void setOnClose(const SimpleCallback& onCloseCallback) { m_onCloseCallback = onCloseCallback; }
|
||||||
|
SimpleCallback getOnClose() const { return m_onCloseCallback; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Set default configurations and load the user configurations
|
||||||
|
void loadConfigurations();
|
||||||
|
/// Use the loaded configurations to setup other classes
|
||||||
|
void setupConfigurations();
|
||||||
|
void saveConfigurations();
|
||||||
|
|
||||||
|
void registerLuaFunctions();
|
||||||
|
|
||||||
|
bool m_running;
|
||||||
|
bool m_stopping;
|
||||||
|
|
||||||
|
SimpleCallback m_onCloseCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern OTClient g_client;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include "otclient.h"
|
||||||
|
|
||||||
|
#include <framework/luascript/luainterface.h>
|
||||||
|
#include <otclient/core/tibiadat.h>
|
||||||
|
#include <otclient/core/tibiaspr.h>
|
||||||
|
#include <otclient/net/protocollogin.h>
|
||||||
|
#include <otclient/net/protocolgame.h>
|
||||||
|
|
||||||
|
void OTClient::registerLuaFunctions()
|
||||||
|
{
|
||||||
|
// easy typing _1, _2, ...
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
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.registerClass<ProtocolLogin, Protocol>();
|
||||||
|
g_lua.bindClassStaticFunction<ProtocolLogin>("create", &ProtocolLogin::create);
|
||||||
|
g_lua.bindClassMemberFunction("login", &ProtocolLogin::login);
|
||||||
|
g_lua.bindClassMemberFunction("cancel", &ProtocolLogin::cancel);
|
||||||
|
|
||||||
|
g_lua.registerClass<ProtocolGame, Protocol>();
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef POSITION_H
|
||||||
|
#define POSITION_H
|
||||||
|
|
||||||
|
#include <framework/util/types.h>
|
||||||
|
|
||||||
|
enum Direction
|
||||||
|
{
|
||||||
|
DIRECTION_NORTH,
|
||||||
|
DIRECTION_EAST,
|
||||||
|
DIRECTION_SOUTH,
|
||||||
|
DIRECTION_WEST
|
||||||
|
};
|
||||||
|
|
||||||
|
class Position
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Position() : x(-1), y(-1), z(-1) { }
|
||||||
|
Position(int x, int y, int z) : x(x), y(y), z(z) { }
|
||||||
|
|
||||||
|
bool isValid() const { return x >= 0 && y >= 0 && z >= 0 && x < 65536 && y < 65536 && z < 15; }
|
||||||
|
|
||||||
|
Position operator+(const Position& other) const { return Position(x + other.x, y + other.y, z + other.z); }
|
||||||
|
Position& operator+=(const Position& other) { x+=other.x; y+=other.y; z +=other.z; return *this; }
|
||||||
|
Position operator-(const Position& other) const { return Position(x - other.x, y - other.y, z + other.z); }
|
||||||
|
Position& operator-=(const Position& other) { x-=other.x; y-=other.y; z-=other.z; return *this; }
|
||||||
|
|
||||||
|
Position& operator=(const Position& other) { x = other.x; y = other.y; z = other.z; return *this; }
|
||||||
|
bool operator==(const Position& other) const { return other.x == x && other.y == y && other.z == z; }
|
||||||
|
bool operator!=(const Position& other) const { return other.x!=x || other.y!=y || other.z!=z; }
|
||||||
|
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
std::ostream& operator<<(std::ostream& out, const Position& pos)
|
||||||
|
{
|
||||||
|
out << pos.x << " " << pos.y << " " << pos.z;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
std::istream& operator>>(std::istream& in, Position& pos)
|
||||||
|
{
|
||||||
|
in >> pos.x >> pos.y >> pos.z;
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue