using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; const int SOURCE_MIN_X = 18; const int SOURCE_MAX_X = 29; const int SOURCE_MIN_Y = 25; const int SOURCE_MAX_Y = 36; const int FIELD_MIN_X = 18; const int FIELD_MAX_X = 29; const int FIELD_MIN_Y = 9; const int FIELD_MAX_Y = 20; int GetColorNumber(string name) { var match = Regex.Match(name, @"\d+$"); return match.Success ? int.Parse(match.Value) : -1; } bool InField(int x, int y) => x >= FIELD_MIN_X && x <= FIELD_MAX_X && y >= FIELD_MIN_Y && y <= FIELD_MAX_Y; Log("=== WAITING FOR FIELD POSITION ==="); while (true) { int selfX = Self.Location.X; int selfY = Self.Location.Y; if (selfX == 14 && selfY >= 16 && selfY <= 35) { Log("Moving to (14, 15)..."); await SendAsync(Out["MoveAvatar"], 14, 15); await Task.Delay(500); continue; } if (InField(selfX, selfY)) { Log($"In field at ({selfX}, {selfY}), starting!"); break; } await Task.Delay(100); } Log("=== AUTO DETECTING COLORS ==="); var selectors = new Dictionary(); foreach (var item in FloorItems) { string name = item.GetName(); if (name.Contains("Cylinder Block") || name.Contains("Hemisphere Block")) { int colorNum = GetColorNumber(name); if (colorNum > 0 && !selectors.ContainsKey(colorNum)) { selectors[colorNum] = (int)item.Id; Log($"Selector: {name} -> Color {colorNum}"); } } } Log($"Total selectors: {selectors.Count}"); var sourcePixels = new Dictionary<(int x, int y), int>(); foreach (var item in FloorItems) { int x = item.Location.X; int y = item.Location.Y; double z = item.Location.Z; if (x < SOURCE_MIN_X || x > SOURCE_MAX_X || y < SOURCE_MIN_Y || y > SOURCE_MAX_Y) continue; if (z < 0.7 || z > 1.0) continue; int colorNum = GetColorNumber(item.GetName()); if (colorNum > 0) sourcePixels[(x, y)] = colorNum; } Log($"Source pixels: {sourcePixels.Count}"); int offsetY = SOURCE_MIN_Y - FIELD_MIN_Y; int changed = 0; for (int attempt = 1; attempt <= 3; attempt++) { var fieldTiles = new Dictionary<(int x, int y), (int id, int colorNum)>(); foreach (var item in FloorItems) { int x = item.Location.X; int y = item.Location.Y; double z = item.Location.Z; if (x < FIELD_MIN_X || x > FIELD_MAX_X || y < FIELD_MIN_Y || y > FIELD_MAX_Y) continue; int colorNum = GetColorNumber(item.GetName()); if (z > 0.5) fieldTiles[(x, y)] = ((int)item.Id, colorNum); else if (!fieldTiles.ContainsKey((x, y))) fieldTiles[(x, y)] = ((int)item.Id, -1); } var toChange = new List<(int fieldId, int srcColor)>(); foreach (var src in sourcePixels) { int fieldX = src.Key.x; int fieldY = src.Key.y - offsetY; int srcColor = src.Value; if (!fieldTiles.TryGetValue((fieldX, fieldY), out var field)) continue; if (field.colorNum == srcColor) continue; if (!selectors.ContainsKey(srcColor)) continue; toChange.Add((field.id, srcColor)); } if (toChange.Count == 0) { Log($"Attempt {attempt}: All correct!"); break; } Log($"Attempt {attempt}: {toChange.Count} to change"); var sorted = toChange.OrderBy(x => x.srcColor).ToList(); int lastColor = -1; foreach (var item in sorted) { if (item.srcColor != lastColor) { await SendAsync(Out["ClickFurni"], selectors[item.srcColor], 0); await Task.Delay(50); lastColor = item.srcColor; } await SendAsync(Out["ClickFurni"], item.fieldId, 0); await Task.Delay(50); changed++; } await Task.Delay(500); } Log("=== SUBMITTING ==="); var badge = FloorItems.FirstOrDefault(f => f.GetName() == "Badge Display Case"); if (badge != null) { await SendAsync(Out["ClickFurni"], (int)badge.Id, 0); Log($"Clicked Badge Display Case (ID: {badge.Id})"); } else { Log("Badge Display Case not found!"); } Log($"Done! Total changed: {changed}");