using System; using System.Collections.Generic; using System.Linq; using Xabbo.Core; public struct Point : IEquatable { public int X { get; } public int Y { get; } public Point(int x, int y) { X = x; Y = y; } public bool Equals(Point other) => X == other.X && Y == other.Y; public override bool Equals(object obj) => obj is Point other && Equals(other); public override int GetHashCode() => HashCode.Combine(X, Y); public override string ToString() => $"({X}, {Y})"; } public struct SurroundingAnalysis { public int DarkNeighborCount; public int LightNeighborCount; } string targetFurniName = "Number Tile Dark"; int minX = 16; int minY = 28; int maxX = 54; int maxY = 62; Log("Script started. Identifying Connections and Surroundings..."); var floorMap = new Dictionary>(); try { if (FloorItems == null) { Log("ERROR: Cannot access FloorItems."); return; } foreach (IFloorItem item in FloorItems) { if (item == null || item.Location == null) continue; var p = new Point(item.Location.X, item.Location.Y); if (!floorMap.ContainsKey(p)) floorMap[p] = new List(); floorMap[p].Add(item); } } catch (Exception ex) { Log($"AN ERROR OCCURRED during map creation: {ex.Message}"); return; } var numberTileLocations = new HashSet(); var numberTileObjects = new List(); var analysisData = new Dictionary(); // --- Step 1: Scan all Number Tiles and analyze their immediate surroundings --- foreach (var stack in floorMap.Values) { var numberTile = stack.FirstOrDefault(f => f.GetName() == targetFurniName); if (numberTile == null) continue; int x = numberTile.Location.X; int y = numberTile.Location.Y; if (x >= minX && x <= maxX && y >= minY && y <= maxY) { var p = new Point(x, y); numberTileLocations.Add(p); numberTileObjects.Add(numberTile); int darkNeighbors = 0, lightNeighbors = 0; for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { if (dx == 0 && dy == 0) continue; Point neighborPoint = new Point(x + dx, y + dy); if (floorMap.TryGetValue(neighborPoint, out var neighborStack)) { var relevantNeighbor = neighborStack.FirstOrDefault(f => (f.GetName() == "Dark Tile" || f.GetName() == "Light Tile") && Math.Abs(f.Location.Z - 0.25) < 0.001); if (relevantNeighbor != null) { if (relevantNeighbor.GetName() == "Dark Tile") darkNeighbors++; else if (relevantNeighbor.GetName() == "Light Tile") lightNeighbors++; } } } } analysisData[p] = new SurroundingAnalysis { DarkNeighborCount = darkNeighbors, LightNeighborCount = lightNeighbors }; } } // --- Step 2: Find all potential Connection Tiles --- var connectionPoints = new HashSet(); foreach (Point p1 in numberTileLocations) { if (numberTileLocations.Contains(new Point(p1.X + 4, p1.Y))) connectionPoints.Add(new Point(p1.X + 2, p1.Y)); if (numberTileLocations.Contains(new Point(p1.X, p1.Y + 4))) connectionPoints.Add(new Point(p1.X, p1.Y + 2)); } // --- Step 3: Test each Connection Tile to see if it's a "Connected Piece" --- var connectedPieces = new HashSet(); Func isGapTileConnected = (p) => { if (floorMap.TryGetValue(p, out var stack)) return stack.Any(f => f.GetName() == "Dark Tile" && Math.Abs(f.Location.Z - 0.25) < 0.001); return false; }; foreach (var p in connectionPoints) { bool isHorizontal = numberTileLocations.Contains(new Point(p.X - 2, p.Y)); if (isHorizontal) { if (isGapTileConnected(new Point(p.X - 1, p.Y)) && isGapTileConnected(p) && isGapTileConnected(new Point(p.X + 1, p.Y))) connectedPieces.Add(p); } else // It must be vertical { if (isGapTileConnected(new Point(p.X, p.Y - 1)) && isGapTileConnected(p) && isGapTileConnected(new Point(p.X, p.Y + 1))) connectedPieces.Add(p); } } // --- Step 4: Log all results --- Log("\n--- [CONNECTION ANALYSIS] ---"); if (connectionPoints.Any()) { foreach (var p in connectionPoints.OrderBy(p => p.Y).ThenBy(p => p.X)) { if (connectedPieces.Contains(p)) { Log($" -> ** Connected Piece ** at {p}"); } else { Log($" -> Open Connection at {p}"); } } } else { Log(" -> No connections found."); } Log("---------------------------\n"); foreach (var furni in numberTileObjects.OrderBy(f => f.Location.Y).ThenBy(f => f.Location.X)) { var p = new Point(furni.Location.X, furni.Location.Y); var analysis = analysisData[p]; string furniId = "N/A", furniHeight = "N/A", furniState = "N/A"; try { furniId = furni.Id.ToString(); } catch { } try { furniHeight = furni.Location.Z.ToString("0.0#"); } catch { } try { furniState = furni.State.ToString(); } catch { } Log("--- [FURNI STATE FOUND] ---"); Log($" Name: {furni.GetName()}"); Log($" ID: {furniId}"); Log($" Position (X, Y): {p}"); Log($" Height (Z): {furniHeight}"); Log($" FurniState: {furniState}"); if (analysis.DarkNeighborCount > 0 && analysis.LightNeighborCount > 0) Log($" Surrounding: {analysis.DarkNeighborCount}x 'Dark Tile', {analysis.LightNeighborCount}x 'Light Tile'"); else if (analysis.DarkNeighborCount > 0) Log($" Surrounding: {analysis.DarkNeighborCount}x 'Dark Tile'"); else if (analysis.LightNeighborCount > 0) Log($" Surrounding: {analysis.LightNeighborCount}x 'Light Tile'"); else Log(" Surrounding: None"); Log("---------------------------"); } Log($"\nSearch complete. Found {numberTileObjects.Count} matching furni."); Log("Execution complete.");