diff --git a/GUI.cpp b/GUI.cpp index bfde84ec..ea087f9d 100644 --- a/GUI.cpp +++ b/GUI.cpp @@ -484,50 +484,49 @@ void DrawCurrentLevelOutline(bool backPart) namespace { - void drawSelectionCursor(WorldSegment* segment) + void drawCursorAt(WorldSegment* segment, Crd3D& cursor, const ALLEGRO_COLOR& color) { - auto& ssConfig = stonesenseState.ssConfig; + std::array directions = { eUpLeft, eUp, eUpRight, eRight, eDownRight, eDown, eDownLeft, eLeft }; + std::array dirs = {}; - Crd3D selection = segment->segState.dfSelection; - if ((selection.x != -30000 && ssConfig.config.follow_DFcursor) - || (ssConfig.config.track_mode == Config::TRACKING_FOCUS)) { - segment->CorrectTileForSegmentOffset(selection.x, selection.y, selection.z); - segment->CorrectTileForSegmentRotation(selection.x, selection.y, selection.z); + for (unsigned int i = 0; i < directions.size(); i++) { + dirs[i] = segment->getTileRelativeTo(cursor.x, cursor.y, cursor.z, directions[i]); } - else { - return; + + auto isObscuring = [&](Tile* tile) { + auto& buildType = tile->building.type; + return tile && + buildType != BUILDINGTYPE_NA && + buildType != df::enums::building_type::Civzone && + buildType != df::enums::building_type::Stockpile; + }; + + // Check the tiles in front of the cursor + bool occludeCursor = false; + for (int i : {3, 4, 5}) { + if (occludeCursor) break; + if (!dirs[i]) { + continue; + } + int shape = dirs[i]->tileShapeBasic(); + if (isObscuring(dirs[i]) || + shape == df::tiletype_shape_basic::Ramp || + shape == df::tiletype_shape_basic::Wall) { + occludeCursor = true; + } } - Crd2D point = LocalTileToScreen(selection.x, selection.y, selection.z); - int sheetx = SPRITEOBJECT_CURSOR % SHEET_OBJECTSWIDE; - int sheety = SPRITEOBJECT_CURSOR / SHEET_OBJECTSWIDE; - al_draw_tinted_scaled_bitmap( - stonesenseState.IMGObjectSheet, - uiColor(3), - sheetx * SPRITEWIDTH, - sheety * SPRITEHEIGHT, - SPRITEWIDTH, - SPRITEHEIGHT, - point.x - ((SPRITEWIDTH / 2) * ssConfig.scale), - point.y - (WALLHEIGHT)*ssConfig.scale, - SPRITEWIDTH * ssConfig.scale, - SPRITEHEIGHT * ssConfig.scale, - 0); - } - void drawDebugCursor(WorldSegment* segment) - { auto& ssConfig = stonesenseState.ssConfig; - - Crd3D cursor = segment->segState.dfCursor; segment->CorrectTileForSegmentOffset(cursor.x, cursor.y, cursor.z); segment->CorrectTileForSegmentRotation(cursor.x, cursor.y, cursor.z); Crd2D point = LocalTileToScreen(cursor.x, cursor.y, cursor.z); - int sheetx = SPRITEOBJECT_CURSOR % SHEET_OBJECTSWIDE; - int sheety = SPRITEOBJECT_CURSOR / SHEET_OBJECTSWIDE; + int spriteIDX = (occludeCursor ? SPRITEOBJECT_CURSOROCCLUDE : SPRITEOBJECT_CURSOR); + int sheetx = spriteIDX % SHEET_OBJECTSWIDE; + int sheety = spriteIDX / SHEET_OBJECTSWIDE; al_draw_tinted_scaled_bitmap( stonesenseState.IMGObjectSheet, - uiColor(2), + color, sheetx * SPRITEWIDTH, sheety * SPRITEHEIGHT, SPRITEWIDTH, @@ -539,6 +538,25 @@ namespace 0); } + void drawSelectionCursor(WorldSegment* segment) + { + auto& ssConfig = stonesenseState.ssConfig; + Crd3D& selection = segment->segState.dfSelection; + if ((selection.x != -30000 && ssConfig.config.follow_DFcursor) + || (ssConfig.config.track_mode == Config::TRACKING_FOCUS)) { + drawCursorAt(segment, selection, uiColor(3)); + } + else { + return; + } + } + + void drawDebugCursor(WorldSegment* segment) + { + Crd3D& cursor = segment->segState.dfCursor; + drawCursorAt(segment, cursor, uiColor(2)); + } + void drawAdvmodeMenuTalk(const ALLEGRO_FONT* font, int x, int y) { //df::adventure * menu = df::global::adventure; diff --git a/SpriteMaps.h b/SpriteMaps.h index 5c960c0e..c813f6c9 100644 --- a/SpriteMaps.h +++ b/SpriteMaps.h @@ -45,6 +45,7 @@ enum enumObjectSprites { SPRITEOBJECT_BLUEPRINT = 321, SPRITEOBJECT_STOCKPILE = 322, SPRITEOBJECT_CURSOR = 323, + SPRITEOBJECT_CURSOROCCLUDE = 304, }; diff --git a/docs/changelog.txt b/docs/changelog.txt index bdc9e52b..b2ded775 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -67,6 +67,7 @@ Template for new versions: - `stonesense`: improved the way altars look - `stonesense`: fog no longer unnecessarily renders to a separate bitmap - `stonesense`: added new connective tiles for pools of blood and vomit +- `stonesense`: made the cursor change sprites when it is partially covered by tiles relative to the camera view # 51.02-r1