change how tile stack works

This commit is contained in:
Eduardo Bart 2011-08-31 17:22:57 -03:00
parent 8e08decd25
commit 0b4d7ace05
13 changed files with 245 additions and 305 deletions

View File

@ -85,7 +85,7 @@ namespace Otc
DatLensHelp = 29, DatLensHelp = 29,
DatFullGround = 30, DatFullGround = 30,
DatIgnoreLook = 31, DatIgnoreLook = 31,
DatClothe = 32, DatCloth = 32,
DatAnimation = 33, DatAnimation = 33,
DatLastOpt = 255 DatLastOpt = 255
}; };
@ -249,13 +249,6 @@ namespace Otc
ClientGetObjectInfo = 243 ClientGetObjectInfo = 243
}; };
enum ThingType {
Item,
Creature,
Effect,
Shot
};
enum SpriteMask { enum SpriteMask {
SpriteRedMask = 0, SpriteRedMask = 0,
SpriteGreenMask, SpriteGreenMask,

View File

@ -24,11 +24,14 @@
#include "thingstype.h" #include "thingstype.h"
#include "localplayer.h" #include "localplayer.h"
#include "map.h" #include "map.h"
#include "tile.h"
#include "item.h"
#include <framework/platform/platform.h> #include <framework/platform/platform.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
Creature::Creature() : Thing(Otc::Creature) Creature::Creature() : Thing()
{ {
m_healthPercent = 0; m_healthPercent = 0;
m_direction = Otc::South; m_direction = Otc::South;
@ -218,9 +221,10 @@ void Creature::walk(const Position& position)
} }
// update map tiles // update map tiles
g_map.removeThingByPtr(asThing()); TilePtr oldTile = g_map.getTile(m_position);
m_position = position; TilePtr newTile = g_map.getTile(position);
g_map.addThing(asThing()); oldTile->removeThing(asThing());
newTile->addThing(asThing(), -1);
if(m_walking) { if(m_walking) {
// Calculate xPattern // Calculate xPattern
@ -237,7 +241,7 @@ void Creature::walk(const Position& position)
// get walk speed // get walk speed
int groundSpeed = 0; int groundSpeed = 0;
ThingPtr ground = g_map.getThing(m_position, 0); ItemPtr ground = newTile->getGround();
if(ground) if(ground)
groundSpeed = ground->getType().groundSpeed; groundSpeed = ground->getType().groundSpeed;

View File

@ -23,10 +23,11 @@
#include "effect.h" #include "effect.h"
#include "thingstype.h" #include "thingstype.h"
#include "map.h" #include "map.h"
#include "tile.h"
#include <framework/platform/platform.h> #include <framework/platform/platform.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
Effect::Effect() : Thing(Otc::Effect) Effect::Effect() : Thing()
{ {
m_lastTicks = g_platform.getTicks(); m_lastTicks = g_platform.getTicks();
m_finished = false; m_finished = false;
@ -38,7 +39,11 @@ void Effect::draw(int x, int y)
if(g_platform.getTicks() - m_lastTicks > 75) { if(g_platform.getTicks() - m_lastTicks > 75) {
const ThingType& type = getType(); const ThingType& type = getType();
if(m_animation+1 == type.animationPhases) { if(m_animation+1 == type.animationPhases) {
g_dispatcher.addEvent(std::bind(&Map::removeThingByPtr, &g_map, asThing())); EffectPtr self = asEffect();
g_dispatcher.addEvent([self] {
TilePtr tile = g_map.getTile(self->getPosition());
tile->removeEffect(self);
});
m_finished = true; m_finished = true;
} }
else else

View File

@ -26,7 +26,7 @@
#include "thing.h" #include "thing.h"
#include <framework/platform/platform.h> #include <framework/platform/platform.h>
Item::Item() : Thing(Otc::Item) Item::Item() : Thing()
{ {
m_count = 0; m_count = 0;
m_lastTicks = g_platform.getTicks(); m_lastTicks = g_platform.getTicks();

View File

@ -76,18 +76,16 @@ void Map::draw(const Rect& rect)
// draw player names and health bars // draw player names and health bars
for(int x = 0; x < MAP_VISIBLE_WIDTH; ++x) { for(int x = 0; x < MAP_VISIBLE_WIDTH; ++x) {
for(int y = 0; y < MAP_VISIBLE_HEIGHT; ++y) { for(int y = 0; y < MAP_VISIBLE_HEIGHT; ++y) {
Position tilePos = Position(m_centralPosition.x + (x - PLAYER_OFFSET_X - 1), m_centralPosition.y + (y - PLAYER_OFFSET_Y - 1), m_centralPosition.z); Position tilePos = Position(m_centralPosition.x + (x - PLAYER_OFFSET_X + 1), m_centralPosition.y + (y - PLAYER_OFFSET_Y + 1), m_centralPosition.z);
if(const TilePtr& tile = m_tiles[tilePos]) { if(const TilePtr& tile = m_tiles[tilePos]) {
auto& creatures = tile->getCreatures(); auto creatures = tile->getCreatures();
if(creatures.size() == 0) if(creatures.size() == 0)
continue; continue;
for(auto it = creatures.rbegin(), end = creatures.rend(); it != end; ++it) { for(const CreaturePtr& creature : creatures) {
CreaturePtr creature = (*it)->asCreature(); int x = (7 + (tilePos.x - m_centralPosition.x))*NUM_TILE_PIXELS + 10 - tile->getDrawElevation();
int y = (5 + (tilePos.y - m_centralPosition.y))*NUM_TILE_PIXELS - 10 - tile->getDrawElevation();
int x = (7 + (tilePos.x - m_centralPosition.x))*NUM_TILE_PIXELS + 10 - tile->getDrawNextOffset();
int y = (5 + (tilePos.y - m_centralPosition.y))*NUM_TILE_PIXELS - 10 - tile->getDrawNextOffset();
if(creature != localPlayer) { if(creature != localPlayer) {
x += creature->getWalkOffsetX() - walkOffsetX; x += creature->getWalkOffsetX() - walkOffsetX;
@ -101,6 +99,11 @@ void Map::draw(const Rect& rect)
} }
} }
void Map::clean()
{
m_tiles.clear();
}
int Map::getMaxVisibleFloor() int Map::getMaxVisibleFloor()
{ {
Position tilePos = m_centralPosition; Position tilePos = m_centralPosition;
@ -159,7 +162,7 @@ bool Map::isCompletlyCovered(const Position& pos, int maxFloor)
for(int x=0;x<2;++x) { for(int x=0;x<2;++x) {
for(int y=0;y<2;++y) { for(int y=0;y<2;++y) {
TilePtr tile = m_tiles[tilePos + Position(-x, -y, 0)]; TilePtr tile = m_tiles[tilePos + Position(-x, -y, 0)];
if(!tile || !tile->isOpaque()) { if(!tile || !tile->isFullyOpaque()) {
covered = false; covered = false;
break; break;
} }
@ -172,50 +175,46 @@ bool Map::isCompletlyCovered(const Position& pos, int maxFloor)
return false; return false;
} }
void Map::addThing(ThingPtr thing, int stackpos) void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos)
{ {
if(!thing) if(!thing)
return; return;
TilePtr& tile = m_tiles[thing->getPosition()]; TilePtr tile = getTile(pos);
if(!tile) { tile->addThing(thing, stackPos);
tile = TilePtr(new Tile(thing->getPosition()));
if(CreaturePtr creature = thing->asCreature())
m_creatures[creature ->getId()] = creature;
} }
tile->addThing(thing, stackpos); ThingPtr Map::getThing(const Position& pos, int stackPos)
if(const CreaturePtr& creature = thing->asCreature())
m_creatures[thing->getId()] = creature;
}
ThingPtr Map::getThing(const Position& pos, int stackpos)
{ {
if(const TilePtr& tile = m_tiles[pos]) { if(const TilePtr& tile = m_tiles[pos])
return tile->getThing(stackpos); return tile->getThing(stackPos);
} return nullptr;
return ThingPtr();
} }
void Map::removeThing(const Position& pos, int stackpos) void Map::removeThing(const Position& pos, int stackPos)
{ {
if(TilePtr& tile = m_tiles[pos]) { if(TilePtr& tile = m_tiles[pos])
tile->removeThing(stackpos); tile->removeThing(stackPos);
}
} }
void Map::removeThingByPtr(ThingPtr thing) void Map::removeThing(const ThingPtr& thing)
{ {
if(!thing) if(!thing)
return; return;
if(TilePtr& tile = m_tiles[thing->getPosition()]) { if(TilePtr& tile = m_tiles[thing->getPosition()])
tile->removeThingByPtr(thing); tile->removeThing(thing);
}
} }
void Map::clean() TilePtr Map::getTile(const Position& pos)
{ {
m_tiles.clear(); TilePtr& tile = m_tiles[pos];
if(!tile)
tile = TilePtr(new Tile(pos));
return tile;
} }
void Map::cleanTile(const Position& pos) void Map::cleanTile(const Position& pos)
@ -224,6 +223,11 @@ void Map::cleanTile(const Position& pos)
tile->clean(); tile->clean();
} }
void Map::addCreature(const CreaturePtr& creature)
{
m_creatures[creature->getId()] = creature;
}
CreaturePtr Map::getCreatureById(uint32 id) CreaturePtr Map::getCreatureById(uint32 id)
{ {
if(g_game.getLocalPlayer() && g_game.getLocalPlayer()->getId() == id) if(g_game.getLocalPlayer() && g_game.getLocalPlayer()->getId() == id)

View File

@ -42,18 +42,18 @@ class Map
public: public:
void draw(const Rect& rect); void draw(const Rect& rect);
void clean();
int getMaxVisibleFloor(); int getMaxVisibleFloor();
bool isCovered(const Position& pos, int maxFloor); bool isCovered(const Position& pos, int maxFloor);
bool isCompletlyCovered(const Position& pos, int maxFloor); bool isCompletlyCovered(const Position& pos, int maxFloor);
void addThing(ThingPtr thing, int stackpos = -1); void addThing(const ThingPtr& thing, const Position& pos, int stackPos = -1);
ThingPtr getThing(const Position& pos, int stackpos); ThingPtr getThing(const Position& pos, int stackPos);
void removeThing(const Position& pos, int stackpos); void removeThing(const Position& pos, int stackPos);
void removeThingByPtr(ThingPtr thing); void removeThing(const ThingPtr& thing);
void clean();
void cleanTile(const Position& pos); void cleanTile(const Position& pos);
TilePtr getTile(const Position& pos);
void setLight(const Light& light) { m_light = light; } void setLight(const Light& light) { m_light = light; }
Light getLight() { return m_light; } Light getLight() { return m_light; }
@ -61,6 +61,7 @@ public:
void setCentralPosition(const Position& centralPosition); void setCentralPosition(const Position& centralPosition);
Position getCentralPosition() { return m_centralPosition; } Position getCentralPosition() { return m_centralPosition; }
void addCreature(const CreaturePtr& creature);
CreaturePtr getCreatureById(uint32 id); CreaturePtr getCreatureById(uint32 id);
void removeCreatureById(uint32 id); void removeCreatureById(uint32 id);

View File

@ -24,7 +24,7 @@
#include "spritemanager.h" #include "spritemanager.h"
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
Thing::Thing(Otc::ThingType type) : m_id(0), m_type(type) Thing::Thing() : m_id(0)
{ {
m_xPattern = 0; m_xPattern = 0;
m_yPattern = 0; m_yPattern = 0;
@ -67,3 +67,20 @@ void Thing::internalDraw(int x, int y, int layers, Otc::SpriteMask mask)
} }
} }
} }
int Thing::getStackPriority()
{
const ThingType& type = getType();
if(type.isGround)
return 0;
else if(type.isGroundClip)
return 1;
else if(type.isOnBottom)
return 2;
else if(type.isOnTop)
return 3;
else if(asCreature())
return 4;
return 5;
}

View File

@ -36,7 +36,7 @@ struct Light
class Thing : public LuaObject class Thing : public LuaObject
{ {
public: public:
Thing(Otc::ThingType type); Thing();
virtual ~Thing() { } virtual ~Thing() { }
virtual void draw(int x, int y) = 0; virtual void draw(int x, int y) = 0;
@ -45,8 +45,8 @@ public:
void setPosition(const Position& position); void setPosition(const Position& position);
uint32 getId() const { return m_id; } uint32 getId() const { return m_id; }
Otc::ThingType getType() const { return m_type; }
Position getPosition() const { return m_position; } Position getPosition() const { return m_position; }
int getStackPriority();
virtual const ThingType& getType() = 0; virtual const ThingType& getType() = 0;
virtual void onPositionChange(const Position&) {} virtual void onPositionChange(const Position&) {}
@ -62,7 +62,6 @@ protected:
void internalDraw(int x, int y, int layers, Otc::SpriteMask mask = Otc::SpriteNoMask); void internalDraw(int x, int y, int layers, Otc::SpriteMask mask = Otc::SpriteNoMask);
uint32 m_id; uint32 m_id;
Otc::ThingType m_type;
Position m_position; Position m_position;
int m_xPattern, m_yPattern, m_zPattern, m_animation; int m_xPattern, m_yPattern, m_zPattern, m_animation;

View File

@ -174,7 +174,7 @@ void ThingsType::parseThingType(std::stringstream& fin, ThingType& thingType)
break; break;
case Otc::DatLensHelp: // Used for giving players tips? case Otc::DatLensHelp: // Used for giving players tips?
thingType.isLensHelp = true; thingType.isLensHelp = true;
thingType.lensHelpParam = Fw::getU16(fin); thingType.lensHelp = Fw::getU16(fin);
break; break;
case Otc::DatFullGround: // Grounds that has no transparent pixels case Otc::DatFullGround: // Grounds that has no transparent pixels
thingType.isFullGround = true; thingType.isFullGround = true;
@ -182,9 +182,9 @@ void ThingsType::parseThingType(std::stringstream& fin, ThingType& thingType)
case Otc::DatIgnoreLook: // Ignore look, then looks at the item on the bottom of it case Otc::DatIgnoreLook: // Ignore look, then looks at the item on the bottom of it
thingType.isIgnoreLook = true; thingType.isIgnoreLook = true;
break; break;
case Otc::DatClothe: // Clothes case Otc::DatCloth: // Clothes
break; thingType.isCloth = true;
case Otc::DatAnimation: // Not used in 8.62 thingType.clothSlot = Fw::getU16(fin);
break; break;
case Otc::DatLastOpt: case Otc::DatLastOpt:
done = true; done = true;
@ -207,6 +207,8 @@ void ThingsType::parseThingType(std::stringstream& fin, ThingType& thingType)
thingType.yPattern = Fw::getU8(fin); thingType.yPattern = Fw::getU8(fin);
thingType.zPattern = Fw::getU8(fin); thingType.zPattern = Fw::getU8(fin);
thingType.animationPhases = Fw::getU8(fin); thingType.animationPhases = Fw::getU8(fin);
if(thingType.animationPhases > 1)
thingType.isAnimation = true;
int totalSprites = thingType.width int totalSprites = thingType.width
* thingType.height * thingType.height

View File

@ -64,7 +64,8 @@ struct ThingType
isLensHelp = false; isLensHelp = false;
isFullGround = false; isFullGround = false;
isIgnoreLook = false; isIgnoreLook = false;
isClothe = false; isCloth = false;
isAnimation = false;
hasLight = false; hasLight = false;
hasMiniMapColor = false; hasMiniMapColor = false;
@ -73,7 +74,8 @@ struct ThingType
maxTextLength = 0; maxTextLength = 0;
lightLevel = lightColor = 0; lightLevel = lightColor = 0;
miniMapColor = 0; miniMapColor = 0;
lensHelpParam = 0; lensHelp = 0;
clothSlot = 0;
} }
uint8 layers; uint8 layers;
@ -113,7 +115,8 @@ struct ThingType
bool isLensHelp; bool isLensHelp;
bool isFullGround; bool isFullGround;
bool isIgnoreLook; bool isIgnoreLook;
bool isClothe; bool isCloth;
bool isAnimation;
bool hasLight; bool hasLight;
bool hasMiniMapColor; bool hasMiniMapColor;
@ -122,7 +125,8 @@ struct ThingType
uint16 maxTextLength; uint16 maxTextLength;
uint16 lightLevel, lightColor; uint16 lightLevel, lightColor;
uint16 miniMapColor; uint16 miniMapColor;
uint16 lensHelpParam; uint16 lensHelp;
uint16 clothSlot;
}; };
typedef std::vector<ThingType> ThingTypeList; typedef std::vector<ThingType> ThingTypeList;

View File

@ -26,221 +26,146 @@
#include "map.h" #include "map.h"
#include "game.h" #include "game.h"
#include "localplayer.h" #include "localplayer.h"
#include "effect.h"
#include <framework/graphics/fontmanager.h> #include <framework/graphics/fontmanager.h>
Tile::Tile(const Position& position) Tile::Tile(const Position& position)
{ {
m_drawNextOffset = 0; m_drawElevation = 0;
m_position = position; m_position = position;
} }
void Tile::draw(int x, int y) void Tile::draw(int x, int y)
{ {
m_drawNextOffset = 0; m_drawElevation = 0;
if(m_ground) // first bottom items
m_ground->draw(x, y); for(const ThingPtr& thing : m_things) {
const ThingType& type = thing->getType();
for(auto it = m_itemsTop.rbegin(), end = m_itemsTop.rend(); it != end; ++it) { if(thing->asCreature() || type.isOnTop)
const ThingPtr& thing = *it; continue;
const ThingType& thingType = thing->getType(); thing->draw(x - m_drawElevation, y - m_drawElevation);
m_drawElevation += type.elevation;
if(thingType.isGroundClip) {
thing->draw(x - m_drawNextOffset, y - m_drawNextOffset);
m_drawNextOffset += thingType.elevation;
}
} }
for(auto it = m_itemsTop.rbegin(), end = m_itemsTop.rend(); it != end; ++it) { // creatures
const ThingPtr& thing = *it; for(const ThingPtr& thing : m_things) {
const ThingType& thingType = thing->getType(); if(thing->asCreature())
thing->draw(x - m_drawElevation, y - m_drawElevation);
if(thingType.isOnBottom) {
thing->draw(x - m_drawNextOffset, y - m_drawNextOffset);
m_drawNextOffset += thingType.elevation;
}
} }
for(auto it = m_itemsBottom.rbegin(), end = m_itemsBottom.rend(); it != end; ++it) { // effects
const ThingPtr& thing = *it; for(const EffectPtr& effect : m_effects)
const ThingType& thingType = thing->getType(); effect->draw(x - m_drawElevation, y - m_drawElevation);
thing->draw(x - m_drawNextOffset, y - m_drawNextOffset);
m_drawNextOffset += thingType.elevation;
}
for(auto it = m_creatures.rbegin(), end = m_creatures.rend(); it != end; ++it) { // top items
const ThingPtr& thing = *it; for(const ThingPtr& thing : m_things) {
thing->draw(x - m_drawNextOffset, y - m_drawNextOffset); const ThingType& type = thing->getType();
} if(type.isOnTop)
thing->draw(x - m_drawElevation, y - m_drawElevation);
for(auto it = m_effects.rbegin(), end = m_effects.rend(); it != end; ++it) {
const ThingPtr& thing = *it;
thing->draw(x - m_drawNextOffset, y - m_drawNextOffset);
}
for(auto it = m_itemsTop.rbegin(), end = m_itemsTop.rend(); it != end; ++it) {
const ThingPtr& thing = *it;
const ThingType& thingType = thing->getType();
if(thingType.isOnTop) {
thing->draw(x, y);
}
}
}
void Tile::addThing(ThingPtr thing, int stackpos)
{
// TODO: rework this. that -1 sucks
if(!thing)
return;
const ThingType& thingType = thing->getType();
if(thing->asItem()) {
if(thingType.isGround)
m_ground = thing;
else {
if(thingType.isGroundClip || thingType.isOnBottom || thingType.isOnTop)
m_itemsTop.push_back(thing);
else {
if(stackpos == -1)
m_itemsBottom.push_back(thing);
else {
m_itemsBottom.insert(m_itemsBottom.begin()+(stackpos-getStackSize(2)), thing);
}
}
}
}
else if(thing->asCreature()) {
m_creatures.push_back(thing);
}
else if(thing->asEffect()) {
m_effects.push_back(thing);
}
}
ThingPtr Tile::getThing(unsigned int stackpos)
{
if(stackpos == 0)
return m_ground;
--stackpos;
if(stackpos < m_itemsTop.size())
return m_itemsTop[stackpos];
stackpos -= m_itemsTop.size();
if(stackpos < m_creatures.size())
return m_creatures[stackpos];
stackpos -= m_creatures.size();
if(stackpos < m_itemsBottom.size())
return m_itemsBottom[stackpos];
return ThingPtr();
}
void Tile::removeThing(unsigned int stackpos)
{
if(stackpos == 0) {
m_ground.reset();
return;
}
--stackpos;
if(stackpos < m_itemsTop.size()) {
m_itemsTop.erase(m_itemsTop.begin() + stackpos);
return;
}
stackpos -= m_itemsTop.size();
if(stackpos < m_creatures.size()) {
m_creatures.erase(m_creatures.begin() + stackpos);
return;
}
stackpos -= m_creatures.size();
if(stackpos < m_itemsBottom.size()) {
m_itemsBottom.erase(m_itemsBottom.begin() + stackpos);
return;
}
logDebug("Invalid stackpos.");
}
void Tile::removeThingByPtr(ThingPtr thing)
{
// Items
if(thing->asItem()) {
const ThingType& thingType = thing->getType();
if(!(thingType.isGroundClip || thingType.isOnBottom || thingType.isOnTop)) {
for(auto it = m_itemsBottom.begin(), end = m_itemsBottom.end(); it != end; ++it) {
if(*it == thing) {
m_itemsBottom.erase(it);
break;
}
}
}
else {
for(auto it = m_itemsTop.begin(), end = m_itemsTop.end(); it != end; ++it) {
if(*it == thing) {
m_itemsTop.erase(it);
break;
}
}
}
}
// Creatures
else if(thing->asCreature()) {
for(auto it = m_creatures.begin(), end = m_creatures.end(); it != end; ++it) {
if(*it == thing) {
m_creatures.erase(it);
break;
}
}
}
// Effects
else if(thing->asEffect()) {
for(auto it = m_effects.begin(), end = m_effects.end(); it != end; ++it) {
if(*it == thing) {
m_effects.erase(it);
break;
}
}
} }
} }
void Tile::clean() void Tile::clean()
{ {
m_itemsTop.clear(); m_things.clear();
m_creatures.clear();
m_itemsBottom.clear();
m_effects.clear(); m_effects.clear();
} }
int Tile::getStackSize(int stop) void Tile::addEffect(const EffectPtr& effect)
{ {
int ret = m_ground ? 1 : 0; m_effects.push_back(effect);
if(stop == 0) effect->setPosition(m_position);
return ret;
ret += m_itemsTop.size();
if(stop == 1)
return ret;
ret += m_creatures.size();
if(stop == 2)
return ret;
ret += m_itemsBottom.size();
return ret;
} }
bool Tile::isOpaque() void Tile::removeEffect(const EffectPtr& effect)
{ {
if(m_ground && !m_ground->getType().isTranslucent) auto it = std::find(m_effects.begin(), m_effects.end(), effect);
if(it != m_effects.end()) {
m_effects.erase(it);
}
}
ThingPtr Tile::addThing(const ThingPtr& thing, int stackPos)
{
if(!thing)
return nullptr;
if(stackPos < 0) {
stackPos = 0;
int priority = thing->getStackPriority();
for(stackPos = 0; stackPos < (int)m_things.size(); ++stackPos) {
int otherPriority = m_things[stackPos]->getStackPriority();
if(otherPriority > priority || (otherPriority == priority && otherPriority == 5))
break;
}
} else if(stackPos > (int)m_things.size())
stackPos = m_things.size();
ThingPtr oldObject;
if(stackPos < (int)m_things.size())
oldObject = m_things[stackPos];
m_things.insert(m_things.begin() + stackPos, thing);
thing->setPosition(m_position);
return oldObject;
}
ThingPtr Tile::getThing(int stackPos)
{
if(stackPos >= 0 && stackPos < (int)m_things.size())
return m_things[stackPos];
return nullptr;
}
ThingPtr Tile::removeThing(int stackPos)
{
ThingPtr oldObject;
if(stackPos >= 0 && stackPos < (int)m_things.size()) {
oldObject = m_things[stackPos];
m_things.erase(m_things.begin() + stackPos);
}
return oldObject;
}
ThingPtr Tile::removeThing(const ThingPtr& thing)
{
ThingPtr oldObject;
auto it = std::find(m_things.begin(), m_things.end(), thing);
if(it != m_things.end()) {
oldObject = *it;
m_things.erase(it);
}
return oldObject;
}
std::vector<CreaturePtr> Tile::getCreatures()
{
std::vector<CreaturePtr> creatures;
for(const ThingPtr& thing : m_things) {
if(CreaturePtr creature = thing->asCreature())
creatures.push_back(creature);
}
return creatures;
}
ItemPtr Tile::getGround()
{
ThingPtr firstObject = getThing(0);
if(!firstObject)
return nullptr;
const ThingType& type = firstObject->getType();
if(type.isGround)
return firstObject->asItem();
return nullptr;
}
bool Tile::isFullyOpaque()
{
ThingPtr firstObject = getThing(0);
if(firstObject) {
const ThingType& type = firstObject->getType();
if(type.isGround && !type.isTranslucent)
return true; return true;
}
return false; return false;
} }

View File

@ -32,34 +32,26 @@ public:
Tile(const Position& position); Tile(const Position& position);
void draw(int x, int y); void draw(int x, int y);
void addThing(ThingPtr thing, int stackpos);
ThingPtr getThing(unsigned int stackpos);
void removeThing(unsigned int stackpos);
void removeThingByPtr(ThingPtr thing);
void clean(); void clean();
bool hasGround() { return (!!m_ground); } void addEffect(const EffectPtr& effect);
void removeEffect(const EffectPtr& effect);
int getStackSize(int stop); ThingPtr addThing(const ThingPtr& thing, int stackPos = -1);
ThingPtr getThing(int stackPos);
const ThingList& getCreatures() { return m_creatures; } ThingPtr removeThing(int stackPos);
int getDrawNextOffset() { return m_drawNextOffset; } ThingPtr removeThing(const ThingPtr& thing);
const Position& getPosition() { return m_position; } const Position& getPosition() { return m_position; }
int getDrawElevation() { return m_drawElevation; }
bool isOpaque(); std::vector<CreaturePtr> getCreatures();
ItemPtr getGround();
bool isFullyOpaque();
private: private:
ThingPtr m_ground; std::vector<EffectPtr> m_effects;
ThingList m_itemsBottom; std::vector<ThingPtr> m_things;
ThingList m_creatures;
ThingList m_itemsTop;
ThingList m_effects;
Position m_position; Position m_position;
int m_drawElevation;
int m_drawNextOffset;
}; };
#endif #endif

View File

@ -28,6 +28,7 @@
#include <otclient/core/map.h> #include <otclient/core/map.h>
#include <otclient/core/item.h> #include <otclient/core/item.h>
#include <otclient/core/effect.h> #include <otclient/core/effect.h>
#include <otclient/core/tile.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
void ProtocolGame::parseMessage(InputMessage& msg) void ProtocolGame::parseMessage(InputMessage& msg)
@ -364,18 +365,16 @@ void ProtocolGame::parseUpdateTile(InputMessage& msg)
void ProtocolGame::parseTileAddThing(InputMessage& msg) void ProtocolGame::parseTileAddThing(InputMessage& msg)
{ {
Position pos = parsePosition(msg); Position pos = parsePosition(msg);
uint8 stackpos = msg.getU8(); uint8 stackPos = msg.getU8();
ThingPtr thing = internalGetThing(msg); ThingPtr thing = internalGetThing(msg);
thing->setPosition(pos); g_map.addThing(thing, pos, stackPos);
g_map.addThing(thing, stackpos);
} }
void ProtocolGame::parseTileTransformThing(InputMessage& msg) void ProtocolGame::parseTileTransformThing(InputMessage& msg)
{ {
Position pos = parsePosition(msg); Position pos = parsePosition(msg);
uint8 stackpos = msg.getU8(); uint8 stackPos = msg.getU8();
uint16 thingId = msg.getU16(); uint16 thingId = msg.getU16();
if(thingId == 0x0061 || thingId == 0x0062 || thingId == 0x0063) { if(thingId == 0x0061 || thingId == 0x0062 || thingId == 0x0063) {
@ -383,19 +382,17 @@ void ProtocolGame::parseTileTransformThing(InputMessage& msg)
} }
else { else {
ThingPtr thing = internalGetItem(msg, thingId); ThingPtr thing = internalGetItem(msg, thingId);
thing->setPosition(pos); g_map.removeThing(pos, stackPos);
g_map.addThing(thing, pos, stackPos);
g_map.removeThing(pos, stackpos);
g_map.addThing(thing, stackpos);
} }
} }
void ProtocolGame::parseTileRemoveThing(InputMessage& msg) void ProtocolGame::parseTileRemoveThing(InputMessage& msg)
{ {
Position pos = parsePosition(msg); Position pos = parsePosition(msg);
uint8 stackpos = msg.getU8(); uint8 stackPos = msg.getU8();
g_map.removeThing(pos, stackpos); g_map.removeThing(pos, stackPos);
} }
void ProtocolGame::parseCreatureMove(InputMessage& msg) void ProtocolGame::parseCreatureMove(InputMessage& msg)
@ -404,13 +401,12 @@ void ProtocolGame::parseCreatureMove(InputMessage& msg)
uint8 oldStackpos = msg.getU8(); uint8 oldStackpos = msg.getU8();
Position newPos = parsePosition(msg); Position newPos = parsePosition(msg);
ThingPtr thing = g_map.getThing(oldPos, oldStackpos); ThingPtr thing = g_map.getTile(oldPos)->getThing(oldStackpos);
if(thing) { assert(thing);
CreaturePtr creature = thing->asCreature(); CreaturePtr creature = thing->asCreature();
if(creature) assert(creature);
creature->walk(newPos); creature->walk(newPos);
} }
}
void ProtocolGame::parseOpenContainer(InputMessage& msg) void ProtocolGame::parseOpenContainer(InputMessage& msg)
{ {
@ -512,11 +508,13 @@ void ProtocolGame::parseWorldLight(InputMessage& msg)
void ProtocolGame::parseMagicEffect(InputMessage& msg) void ProtocolGame::parseMagicEffect(InputMessage& msg)
{ {
Position pos = parsePosition(msg);
int effectId = msg.getU8();
EffectPtr effect = EffectPtr(new Effect()); EffectPtr effect = EffectPtr(new Effect());
effect->setPosition(parsePosition(msg)); effect->setId(effectId);
effect->setId(msg.getU8());
g_map.addThing(effect); TilePtr tile = g_map.getTile(pos);
tile->addEffect(effect);
} }
void ProtocolGame::parseAnimatedText(InputMessage& msg) void ProtocolGame::parseAnimatedText(InputMessage& msg)
@ -895,23 +893,19 @@ void ProtocolGame::setTileDescription(InputMessage& msg, Position position)
{ {
g_map.cleanTile(position); g_map.cleanTile(position);
int stackpos = 0; int stackPos = 0;
while(1){ while(1){
uint16 inspectTileId = msg.getU16(true); uint16 inspectTileId = msg.getU16(true);
if(inspectTileId >= 0xFF00) if(inspectTileId >= 0xFF00)
return; return;
else { else {
if(stackpos >= 10) { if(stackPos >= 10)
logTraceDebug("Too many things!."); logWarning("Too many things!");
return;
}
ThingPtr thing = internalGetThing(msg); ThingPtr thing = internalGetThing(msg);
if(thing) g_map.addThing(thing, position);
thing->setPosition(position);
g_map.addThing(thing);
} }
stackpos++; stackPos++;
} }
} }