Keeps the repo root clean - only README.md visible on landing page. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
167 lines
5.9 KiB
C#
167 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Xabbo.Core;
|
|
|
|
public struct Point : IEquatable<Point>
|
|
{
|
|
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<Point, List<IFloorItem>>();
|
|
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<IFloorItem>();
|
|
floorMap[p].Add(item);
|
|
}
|
|
}
|
|
catch (Exception ex) { Log($"AN ERROR OCCURRED during map creation: {ex.Message}"); return; }
|
|
|
|
var numberTileLocations = new HashSet<Point>();
|
|
var numberTileObjects = new List<IFloorItem>();
|
|
var analysisData = new Dictionary<Point, SurroundingAnalysis>();
|
|
|
|
// --- 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<Point>();
|
|
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<Point>();
|
|
Func<Point, bool> 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."); |