diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index cf9f39cb..31455540 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -66,18 +66,16 @@ int MASK_TEXTURE_UNIFORM = 14; void Creature::draw(const Point& dest, float scaleFactor, bool animate) { - int scaledTileSize = Otc::TILE_PIXELS * scaleFactor; - Point animationOffset = animate ? m_walkOffset : Point(0,0); if(m_showVolatileSquare && animate) { g_painter.setColor(m_volatileSquareColor); - g_painter.drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 3)*scaleFactor, Size(28*scaleFactor, 28*scaleFactor)), std::max((int)(2*scaleFactor), 1)); + g_painter.drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 3)*scaleFactor, Size(28, 28)*scaleFactor), std::max((int)(2*scaleFactor), 1)); } if(m_showStaticSquare && animate) { g_painter.setColor(m_staticSquareColor); - g_painter.drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 1)*scaleFactor, Size(scaledTileSize, scaledTileSize)), std::max((int)(2*scaleFactor), 1)); + g_painter.drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 1)*scaleFactor, Size(Otc::TILE_PIXELS, Otc::TILE_PIXELS)*scaleFactor), std::max((int)(2*scaleFactor), 1)); } g_painter.setColor(Fw::white); @@ -124,13 +122,6 @@ void Creature::draw(const Point& dest, float scaleFactor, bool animate) for(int h = 0; h < getDimensionHeight(); h++) { for(int w = 0; w < getDimensionWidth(); w++) { - int spriteId = getSpriteId(w, h, 0, xPattern, yPattern, zPattern, m_walkAnimationPhase); - if(!spriteId) - continue; - TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); - if(!spriteTex) - continue; - // setup texture outfit mask TexturePtr maskTex; if(getLayers() > 1) { @@ -139,10 +130,8 @@ void Creature::draw(const Point& dest, float scaleFactor, bool animate) } outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); - Rect drawRect(dest.x + (animationOffset.x - w*Otc::TILE_PIXELS - getDisplacementX())*scaleFactor, - dest.y + (animationOffset.y - h*Otc::TILE_PIXELS - getDisplacementY())*scaleFactor, - scaledTileSize, scaledTileSize); - g_painter.drawTexturedRect(drawRect, spriteTex); + internalDraw(dest + (animationOffset - Point(w,h)*Otc::TILE_PIXELS)*scaleFactor, + scaleFactor, w, h, xPattern, yPattern, zPattern, 0, animationPhase); } } @@ -171,8 +160,7 @@ void Creature::draw(const Point& dest, float scaleFactor, bool animate) if(m_outfit.getCategory() == ThingsType::Effect) animationPhase = std::min(animationPhase+1, getAnimationPhases()); - for(int layer = 0; layer < getLayers(); layer++) - internalDraw(dest + animationOffset*scaleFactor, scaleFactor, 0, 0, 0, layer, animationPhase); + internalDraw(dest + animationOffset*scaleFactor, scaleFactor, 0, 0, 0, animationPhase); } } diff --git a/src/otclient/core/effect.cpp b/src/otclient/core/effect.cpp index 1d1661da..54b12596 100644 --- a/src/otclient/core/effect.cpp +++ b/src/otclient/core/effect.cpp @@ -32,9 +32,10 @@ void Effect::draw(const Point& dest, float scaleFactor, bool animate) if(m_id == 0) return; - int animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / Otc::EFFECT_TICKS_PER_FRAME), getAnimationPhases() - 1); - for(int layer = 0; layer < getLayers(); layer++) - internalDraw(dest, scaleFactor, 0, 0, 0, layer, animate ? animationPhase : 0); + int animationPhase = 0; + if(animate) + animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / Otc::EFFECT_TICKS_PER_FRAME), getAnimationPhases() - 1); + internalDraw(dest, scaleFactor, 0, 0, 0, animationPhase); } void Effect::startAnimation() diff --git a/src/otclient/core/item.cpp b/src/otclient/core/item.cpp index 617e22fc..17f26cc8 100644 --- a/src/otclient/core/item.cpp +++ b/src/otclient/core/item.cpp @@ -170,9 +170,8 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate) } g_painter.setCustomProgram(itemProgram); - // draw all item layers - for(int layer = 0; layer < getLayers(); layer++) - internalDraw(dest, scaleFactor, xPattern, yPattern, zPattern, layer, animationPhase); + // now we can draw the item + internalDraw(dest, scaleFactor, xPattern, yPattern, zPattern, animationPhase); // release draw shader g_painter.releaseCustomProgram(); diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 18d670a4..c13ca90f 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -122,9 +122,7 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos) if(!thing) return; - TilePtr tile = getTile(pos); - if(!tile) - tile = createTile(pos); + TilePtr tile = getOrCreateTile(pos); if(CreaturePtr creature = thing->asCreature()) { Position oldPos = thing->getPosition(); @@ -225,11 +223,21 @@ const TilePtr& Map::getTile(const Position& pos) return nulltile; } +TilePtr Map::getOrCreateTile(const Position& pos) +{ + const TilePtr& tile = getTile(pos); + if(tile) + return tile; + else + return createTile(pos); +} + void Map::cleanTile(const Position& pos) { if(TilePtr tile = getTile(pos)) { tile->clean(); - m_tiles.erase(m_tiles.find(pos)); + if(tile->canErase()) + m_tiles.erase(m_tiles.find(pos)); notificateTileUpdateToMapViews(pos); } diff --git a/src/otclient/core/map.h b/src/otclient/core/map.h index 469e6788..6e153c80 100644 --- a/src/otclient/core/map.h +++ b/src/otclient/core/map.h @@ -46,6 +46,7 @@ public: // tile related TilePtr createTile(const Position& pos); const TilePtr& getTile(const Position& pos); + TilePtr getOrCreateTile(const Position& pos); void cleanTile(const Position& pos); bool removeThing(const ThingPtr& thing); diff --git a/src/otclient/core/thing.cpp b/src/otclient/core/thing.cpp index 678780db..c886806d 100644 --- a/src/otclient/core/thing.cpp +++ b/src/otclient/core/thing.cpp @@ -25,6 +25,7 @@ #include "thingstype.h" #include #include "map.h" +#include "tile.h" Thing::Thing() { @@ -52,23 +53,30 @@ const TilePtr& Thing::getTile() return g_map.getTile(m_position); } -void Thing::internalDraw(const Point& dest, float scaleFactor, int xPattern, int yPattern, int zPattern, int layer, int animationPhase) +int Thing::getStackpos() +{ + const TilePtr& tile = getTile(); + if(tile) + return tile->getThingStackpos(asThing()); + return -1; +} + +void Thing::internalDraw(const Point& dest, float scaleFactor, int w, int h, int xPattern, int yPattern, int zPattern, int layer, int animationPhase) { int scaledSize = Otc::TILE_PIXELS * scaleFactor; - for(int h = 0; h < getDimensionHeight(); h++) { - for(int w = 0; w < getDimensionWidth(); w++) { - int spriteId = getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animationPhase); - if(!spriteId) - continue; - - TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); - Rect drawRect(dest.x - (w*Otc::TILE_PIXELS - getDisplacementX())*scaleFactor, - dest.y - (h*Otc::TILE_PIXELS - getDisplacementY())*scaleFactor, - scaledSize, scaledSize); - - g_painter.drawTexturedRect(drawRect, spriteTex); - } + int spriteId = getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animationPhase); + if(spriteId) { + Rect drawRect(dest - getDisplacement()*scaleFactor, Size(scaledSize, scaledSize)); + g_painter.setColor(Fw::white); + g_painter.drawTexturedRect(drawRect, g_sprites.getSpriteTexture(spriteId)); } } +void Thing::internalDraw(const Point& dest, float scaleFactor, int xPattern, int yPattern, int zPattern, int animationPhase) +{ + for(int l = 0; l < getLayers(); ++l) + for(int w = 0; w < getDimensionWidth(); ++w) + for(int h = 0; h < getDimensionHeight(); ++h) + internalDraw(dest - Point(w,h)*Otc::TILE_PIXELS*scaleFactor, scaleFactor, w, h, xPattern, yPattern, zPattern, l, animationPhase); +} diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index fadc10c0..f1176274 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -49,6 +49,7 @@ public: Position getPosition() { return m_position; } int getStackPriority(); const TilePtr& getTile(); + int getStackpos(); ThingPtr asThing() { return std::static_pointer_cast(shared_from_this()); } virtual ItemPtr asItem() { return nullptr; } @@ -82,6 +83,7 @@ public: bool isHookSouth() { return m_type->properties[ThingType::HookSouth]; } bool isHookEast() { return m_type->properties[ThingType::HookEast]; } bool isStackable() { return m_type->properties[ThingType::IsStackable]; } + bool isLyingCorpse() { return m_type->properties[ThingType::IsLyingCorpse]; } bool blocksProjectile() { return m_type->properties[ThingType::BlockProjectile]; } bool isFluid() { return m_type->properties[ThingType::IsFluid]; } bool isFluidContainer() { return m_type->properties[ThingType::IsFluidContainer]; } @@ -98,10 +100,14 @@ public: int getAnimationPhases() { return m_type->dimensions[ThingType::AnimationPhases]; } int getGroundSpeed() { return m_type->parameters[ThingType::GroundSpeed]; } int getElevation() { return m_type->parameters[ThingType::Elevation]; } - int getSpriteId(int w = 0, int h = 0, int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animation = 0) { return m_type->getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animation); } + + int getSpriteId(int w = 0, int h = 0, int layer = 0, + int xPattern = 0, int yPattern = 0, int zPattern = 0, + int animation = 0) { return m_type->getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animation); } protected: - void internalDraw(const Point& dest, float scaleFactor, int xPattern, int yPattern, int zPattern, int layer, int animationPhase); + void internalDraw(const Point& dest, float scaleFactor, int w, int h, int xPattern, int yPattern, int zPattern, int layer, int animationPhase); + void internalDraw(const Point& dest, float scaleFactor, int xPattern, int yPattern, int zPattern, int animationPhase); Position m_position; ThingType *m_type; diff --git a/src/otclient/core/tile.cpp b/src/otclient/core/tile.cpp index 8264b840..63f8d27f 100644 --- a/src/otclient/core/tile.cpp +++ b/src/otclient/core/tile.cpp @@ -42,14 +42,14 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags) bool animate = drawFlags & Otc::DrawAnimations; // first bottom items - if(drawFlags & Otc::DrawGround || drawFlags & Otc::DrawWalls || drawFlags & Otc::DrawGroundBorders) { + if(drawFlags & Otc::DrawGround || drawFlags & Otc::DrawGroundBorders || drawFlags & Otc::DrawCommonItems) { for(const ThingPtr& thing : m_things) { if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom()) break; if((thing->isGround() && drawFlags & Otc::DrawGround) || (thing->isGroundBorder() && drawFlags & Otc::DrawGroundBorders) || - (thing->isOnBottom() && drawFlags & Otc::DrawWalls)) + (thing->isOnBottom() && drawFlags & Otc::DrawCommonItems)) thing->draw(dest - drawElevation*scaleFactor, scaleFactor, animate); drawElevation += thing->getElevation(); @@ -58,20 +58,45 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags) } } - // now common items in reverse order + int redrawPreviousOnTopW = 0; + int redrawPreviousOnTopH = 0; + if(drawFlags & Otc::DrawCommonItems) { + // now common items in reverse order for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) { const ThingPtr& thing = *it; if(thing->isOnTop() || thing->isOnBottom() || thing->isGroundBorder() || thing->isGround() || thing->asCreature()) break; thing->draw(dest - drawElevation*scaleFactor, scaleFactor, animate); + if(thing->isLyingCorpse()) { + redrawPreviousOnTopW = std::max(thing->getDimensionWidth(), redrawPreviousOnTopW); + redrawPreviousOnTopH = std::max(thing->getDimensionHeight(), redrawPreviousOnTopH); + } + drawElevation += thing->getElevation(); if(drawElevation > Otc::MAX_ELEVATION) drawElevation = Otc::MAX_ELEVATION; } } + // must redraw previous creatures/ontop above lying corpses + if(redrawPreviousOnTopH > 0 || redrawPreviousOnTopW > 0) { + int onTopRedrawFlags = drawFlags & (Otc::DrawCreatures | Otc::DrawEffects | Otc::DrawWalls); + if(onTopRedrawFlags) { + for(int y=-redrawPreviousOnTopH;y<=0;++y) { + for(int x=-redrawPreviousOnTopW;x<=0;++x) { + if(x == 0 && y == 0) + continue; + const TilePtr& tile = g_map.getTile(m_position.translated(x,y)); + if(tile) { + tile->draw(dest + Point(x*Otc::TILE_PIXELS, y*Otc::TILE_PIXELS)*scaleFactor, scaleFactor, onTopRedrawFlags); + } + } + } + } + } + // creatures if(drawFlags & Otc::DrawCreatures) { if(animate) { @@ -106,8 +131,8 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags) void Tile::clean() { - m_things.clear(); - m_effects.clear(); + while(!m_things.empty()) + removeThing(m_things.front()); } void Tile::addWalkingCreature(const CreaturePtr& creature) @@ -153,7 +178,7 @@ ThingPtr Tile::addThing(const ThingPtr& thing, int stackPos) return oldObject; } -bool Tile::removeThing(const ThingPtr& thing) +bool Tile::removeThing(ThingPtr thing) { if(!thing) return false; @@ -406,3 +431,9 @@ bool Tile::limitsFloorsView() return true; return false; } + +bool Tile::canErase() +{ + return m_walkingCreatures.empty() && m_effects.empty() && m_things.empty(); +} + diff --git a/src/otclient/core/tile.h b/src/otclient/core/tile.h index 91d28210..cc8dddbb 100644 --- a/src/otclient/core/tile.h +++ b/src/otclient/core/tile.h @@ -40,7 +40,7 @@ public: void removeWalkingCreature(const CreaturePtr& creature); ThingPtr addThing(const ThingPtr& thing, int stackPos = -1); - bool removeThing(const ThingPtr& thing); + bool removeThing(ThingPtr thing); ThingPtr getThing(int stackPos); int getThingStackpos(const ThingPtr& thing); ThingPtr getTopThing(); @@ -57,6 +57,7 @@ public: const std::vector& getThings() { return m_things; } ItemPtr getGround(); int getGroundSpeed(); + int getThingCount() { return m_things.size() + m_effects.size(); } bool isWalkable(); bool isFullGround(); bool isFullyOpaque(); @@ -67,7 +68,7 @@ public: bool mustHookEast(); bool hasCreature(); bool limitsFloorsView(); - int getThingCount() { return m_things.size() + m_effects.size(); } + bool canErase(); TilePtr asTile() { return std::static_pointer_cast(shared_from_this()); } @@ -76,7 +77,7 @@ private: std::vector m_effects; // leave this outside m_things because it has no stackpos. std::vector m_things; Position m_position; - int m_drawElevation; + uint8 m_drawElevation; }; #endif