Merge branch 'main' into feat/otui-editor

This commit is contained in:
Renan Miyashiro 2026-07-28 11:37:53 -03:00 committed by GitHub
commit f71d252be3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 100 additions and 38 deletions

View file

@ -24,6 +24,7 @@
#include "animator.h"
#include "attachedeffect.h"
#include "client/const.h"
#include "game.h"
#include "gameconfig.h"
#include "lightview.h"
@ -741,12 +742,22 @@ void Creature::updateWalkingTile()
g_gameConfig.getSpriteSize() + (m_walkOffset.y - displacementY),
g_gameConfig.getSpriteSize(), g_gameConfig.getSpriteSize());
if (m_walkedPixels < g_gameConfig.getSpriteSize() / 2) {
if (m_direction == Otc::Direction::NorthWest)
newWalkingTile = m_walkingTile ? m_walkingTile : getTile();
else if (m_direction == Otc::Direction::SouthEast)
newWalkingTile = g_map.getTile(getPosition().translated(-1, -1, 0));
}
for (int xi = -1; xi <= 1 && !newWalkingTile; ++xi) {
for (int yi = -1; yi <= 1 && !newWalkingTile; ++yi) {
Rect virtualTileRect((xi + 1) * g_gameConfig.getSpriteSize(), (yi + 1) * g_gameConfig.getSpriteSize(), g_gameConfig.getSpriteSize(), g_gameConfig.getSpriteSize());
// only render creatures where bottom right is inside tile rect
if (virtualTileRect.contains(virtualCreatureRect.bottomRight())) {
// when creature is moving to the upper left tile, because of drawing order (we want creature to be behind the object to the left if its a tree for example)
if (m_direction == Otc::Direction::NorthWest && virtualTileRect.contains(virtualCreatureRect.topLeft())) {
newWalkingTile = g_map.getOrCreateTile(getPosition().translated(xi, yi, 0));
} else if (virtualTileRect.contains(virtualCreatureRect.bottomRight())) {
// only render creatures where bottom right is inside tile rect
newWalkingTile = g_map.getOrCreateTile(getPosition().translated(xi, yi, 0));
}
}

View file

@ -23,6 +23,7 @@
#include "map.h"
#include "animatedtext.h"
#include "client/const.h"
#include "creatures.h"
#include "game.h"
#include "gameconfig.h"
@ -1249,7 +1250,7 @@ bool Map::removeAttachedWidgetFromObject(const UIWidgetPtr& widget) {
void Map::updateAttachedWidgets(const MapViewPtr& mapView)
{
g_drawPool.select(DrawPoolType::MAP);
bool should_repaint = false;
for (const auto& [widget, object] : m_attachedObjectWidgetMap) {
if (widget->isDestroyed()) {
continue;
@ -1300,9 +1301,16 @@ void Map::updateAttachedWidgets(const MapViewPtr& mapView)
const auto& widgetRect = widget->getRect();
const auto& newWidgetRect = Rect(p, widgetRect.width(), widgetRect.height());
widget->disableUpdateTemporarily();
widget->setRect(newWidgetRect);
if (widgetRect != newWidgetRect) {
widget->disableUpdateTemporarily();
widget->setRect(newWidgetRect);
should_repaint = true;
}
}
// only repaint if some widget changed position on the screen
if (should_repaint)
g_drawPool.repaint(DrawPoolType::FOREGROUND);
}
std::map<std::string, std::tuple<int, int, int, std::string>> Map::findEveryPath(const Position& start, int maxDistance, const std::map<std::string, std::string>& params)
@ -1543,4 +1551,4 @@ const TilePtr& TileBlock::getOrCreate(const Position& pos)
if (!tile)
tile = std::make_shared<Tile>(pos);
return tile;
}
}

View file

@ -141,6 +141,7 @@ void MapView::drawFloor()
const bool alwaysTransparent = m_floorViewMode == Otc::ALWAYS_WITH_TRANSPARENCY && z < m_cachedFirstVisibleFloor && _camera.coveredUp(cameraPosition.z - z);
const auto& map = m_floors[z].cachedVisibleTiles;
std::vector<TilePtr> walking_tiles;
for (const auto& tile : map.tiles) {
uint32_t tileFlags = flags;
@ -148,15 +149,27 @@ void MapView::drawFloor()
if (!m_drawViewportEdge && !tile->canRender(tileFlags, cameraPosition, m_viewport))
continue;
if (alwaysTransparent) {
const bool inRange = tile->getPosition().isInRange(_camera, g_gameConfig.getTileTransparentFloorViewRange(), g_gameConfig.getTileTransparentFloorViewRange(), true);
g_drawPool.setOpacity(inRange ? .16 : .7);
walking_tiles.emplace_back(tile);
// if this tile is the edge or if upper right tile doesn't have walking creatures
// -> draw it and all walking_tiles depending on it (if there are any queued up)
TilePtr upper_right_tile = g_map.getTile(tile->getPosition().translated(1, -1, 0));
if (!upper_right_tile || !upper_right_tile->hasWalkingCreature()) {
for (int i = walking_tiles.size() - 1; i >= 0; i--) {
auto const &tile = walking_tiles[i];
if (alwaysTransparent) {
const bool inRange = tile->getPosition().isInRange(_camera, g_gameConfig.getTileTransparentFloorViewRange(), g_gameConfig.getTileTransparentFloorViewRange(), true);
g_drawPool.setOpacity(inRange ? .16 : .7);
}
tile->draw(m_posInfo, transformPositionTo2D(tile->getPosition()), tileFlags);
if (alwaysTransparent)
g_drawPool.resetOpacity();
}
walking_tiles.clear();
}
tile->draw(m_posInfo, transformPositionTo2D(tile->getPosition()), tileFlags);
if (alwaysTransparent)
g_drawPool.resetOpacity();
}
for (const auto& missile : g_map.getFloorMissiles(z))

View file

@ -78,6 +78,28 @@ void Tile::draw(const MapPosInfo& mapRect, const Point& dest, const int flags, L
return;
}
// when walking diagonally over a tile that has a object on it like a tree the creature should be rendered behind it
// i.e. render creature first then the tree
if (hasWalkingCreature()) {
g_drawPool.setDrawOrder(DrawOrder::THIRD);
for (const auto& creature : m_walkingCreatures) {
if (creature->getDirection() == Otc::Direction::NorthEast || creature->getDirection() == Otc::Direction::SouthWest) {
const auto& cDest = Point(
dest.x + ((creature->getPosition().x - m_position.x) * g_gameConfig.getSpriteSize() - creature->getDrawElevation()) * g_drawPool.getScaleFactor(),
dest.y + ((creature->getPosition().y - m_position.y) * g_gameConfig.getSpriteSize() - creature->getDrawElevation()) * g_drawPool.getScaleFactor()
);
if (flags == Otc::DrawLights)
creature->drawLight(cDest, lightView);
else {
creature->draw(cDest, flags & Otc::DrawThings);
creature->drawInformation(mapRect, cDest, flags);
}
}
}
g_drawPool.resetDrawOrder();
}
for (const auto& thing : m_things) {
if (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom())
break;
@ -133,6 +155,26 @@ void Tile::drawCreature(const MapPosInfo& mapRect, const Point& dest, const int
if (!forceDraw && !m_drawTopAndCreature)
return;
g_drawPool.setDrawOrder(DrawOrder::THIRD);
for (const auto& creature : m_walkingCreatures) {
// already drawn by this point
if (creature->getDirection() == Otc::Direction::NorthEast || creature->getDirection() == Otc::Direction::SouthWest)
continue;
const auto& cDest = Point(
dest.x + ((creature->getPosition().x - m_position.x) * g_gameConfig.getSpriteSize() - creature->getDrawElevation()) * g_drawPool.getScaleFactor(),
dest.y + ((creature->getPosition().y - m_position.y) * g_gameConfig.getSpriteSize() - creature->getDrawElevation()) * g_drawPool.getScaleFactor()
);
if (flags == Otc::DrawLights)
creature->drawLight(cDest, lightView);
else {
creature->draw(cDest, flags & Otc::DrawThings);
creature->drawInformation(mapRect, cDest, flags);
}
}
g_drawPool.resetDrawOrder();
bool localPlayerDrawed = false;
if (hasCreatures()) {
for (const auto& thing : m_things) {
@ -148,22 +190,6 @@ void Tile::drawCreature(const MapPosInfo& mapRect, const Point& dest, const int
}
}
g_drawPool.setDrawOrder(DrawOrder::THIRD);
for (const auto& creature : m_walkingCreatures) {
const auto& cDest = Point(
dest.x + ((creature->getPosition().x - m_position.x) * g_gameConfig.getSpriteSize() - creature->getDrawElevation()) * g_drawPool.getScaleFactor(),
dest.y + ((creature->getPosition().y - m_position.y) * g_gameConfig.getSpriteSize() - creature->getDrawElevation()) * g_drawPool.getScaleFactor()
);
if (flags == Otc::DrawLights)
creature->drawLight(cDest, lightView);
else {
creature->draw(cDest, flags & Otc::DrawThings);
creature->drawInformation(mapRect, cDest, flags);
}
}
g_drawPool.resetDrawOrder();
// draw the local character if he is on a virtual tile, that is, his visual position is not the same as the server.
if (!localPlayerDrawed && g_game.getLocalPlayer() && !g_game.getLocalPlayer()->isWalking() && g_game.getLocalPlayer()->getPosition() == m_position) {
drawThing(g_game.getLocalPlayer(), dest, flags, drawElevation, lightView);

View file

@ -93,6 +93,7 @@ public:
bool hasCreatures() const { return (m_thingTypeFlag & HAS_CREATURE) != 0; }
bool hasCreatures() { return static_cast<const Tile&>(*this).hasCreatures(); }
bool hasWalkingCreature() { return !m_walkingCreatures.empty(); }
void appendSpectators(std::vector<CreaturePtr>& out) const;

View file

@ -169,7 +169,8 @@ bool GraphicalApplication::canDrawMap() const {
if (!m_drawEvents->canDraw(MAP))
return false;
static constexpr std::array<DrawPoolType, 4> types{ MAP, LIGHT, FOREGROUND_MAP, CREATURE_INFORMATION };
// FOREGROUND is here only because of attached widgets on the map (like tile widgets)
static constexpr std::array<DrawPoolType, 5> types{ MAP, LIGHT, FOREGROUND_MAP, CREATURE_INFORMATION, FOREGROUND };
for (DrawPoolType type : types) {
if (g_drawPool.isDrawing(type))
@ -212,7 +213,7 @@ void GraphicalApplication::run()
continue;
}
{
if (g_game.isOnline()) {
AutoStat s(STATS_RENDER, "DrawPreload");
m_drawEvents->preLoad();
}
@ -222,11 +223,13 @@ void GraphicalApplication::run()
if (!g_game.isOnline() && canDrawForeground) {
AutoStat s(STATS_RENDER, "DrawForegroundUI");
g_ui.render(DrawPoolType::FOREGROUND);
} else if (canDrawMap() && canDrawForeground) {
tasks.emplace_back(g_asyncDispatcher->submit_task([] {
AutoStat s(STATS_RENDER, "DrawForegroundUI");
g_ui.render(DrawPoolType::FOREGROUND);
}));
} else if (canDrawMap()) {
if (canDrawForeground) {
tasks.emplace_back(g_asyncDispatcher->submit_task([] {
AutoStat s(STATS_RENDER, "DrawForegroundUI");
g_ui.render(DrawPoolType::FOREGROUND);
}));
}
static constexpr std::array<DrawPoolType, 2> types{ DrawPoolType::LIGHT, DrawPoolType::FOREGROUND_MAP };
for (const auto type : types) {

View file

@ -524,4 +524,4 @@ std::shared_ptr<CoordsBuffer> DrawPool::getCoordsBuffer() {
delete ptr;
}
});
}
}