xabbo-scripts/HopeHabubuAvoid.csx
Administrator b6c31a7feb Add 165 scripts from desktop collection + update README
Added scripts from C:\Users\ploet\Desktop\Habbo\Xabbo Scripte:
- 39 KI/Chatbot scripts (ChatGPT, Gemini, Grok, DeepSeek, Ollama)
- Game solvers (Domino, Dodgeball, Obsidian Maze, IceBall)
- Collision avoidance bots (5 versions)
- Plant/breeding automation (12 scripts)
- Trading tools, packet debuggers, room utilities
- Navigation & teleport helpers

Removed: 9 files (3 empty, 2 trivial, 4 cross-duplicates)
Updated README with full categorized index of all 230+ scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 09:47:56 +01:00

416 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
public struct Point : IEquatable<Point>
{
public int X { get; }
public int Y { get; }
public Point(int x, int y) { X = x; Y = y; }
public static implicit operator Point((int x, int y) tuple) => new Point(tuple.x, tuple.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 static bool operator ==(Point left, Point right) => left.Equals(right);
public static bool operator !=(Point left, Point right) => !(left == right);
public override string ToString() => $"({X},{Y})";
}
Log("=== Hope Habubu Avoider + Auto Gate ===");
// ==================== KONFIGURATION ====================
const string DANGER_FURNI_NAME = "Hope Habubu";
const string GATE_FURNI_NAME = "One Way Gate";
const int DANGER_RADIUS = 2;
const int REACTION_DISTANCE = 4;
const int LOOP_DELAY_MS = 25;
// =======================================================
Regex mvRegex = new Regex(@"/mv (\d+),(\d+),([\d\.]+)/");
HashSet<Point> walkableTiles = new HashSet<Point>();
bool floorPlanReady = false;
DateTime lastFloorPlanParse = DateTime.MinValue;
Dictionary<long, Point> trackedThreats = new Dictionary<long, Point>();
Point myTargetTile = (-1, -1);
DateTime lastMoveTime = DateTime.MinValue;
bool IsInvalidPoint(Point p)
{
return p.X == -1 && p.Y == -1;
}
Point GetMyPosition()
{
if (Self == null || Self.Location == null) return (-1, -1);
if (!IsInvalidPoint(myTargetTile) && (DateTime.UtcNow - lastMoveTime).TotalMilliseconds < 300)
return myTargetTile;
return (Self.Location.X, Self.Location.Y);
}
void DoMove(int x, int y)
{
Move(x, y);
myTargetTile = (x, y);
lastMoveTime = DateTime.UtcNow;
}
double GetDistance(Point a, Point b)
{
return Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2));
}
void ParseFloorPlan()
{
if ((DateTime.UtcNow - lastFloorPlanParse).TotalSeconds < 5 && floorPlanReady) return;
lastFloorPlanParse = DateTime.UtcNow;
try
{
dynamic fp = FloorPlan;
if (fp == null) { floorPlanReady = false; return; }
int width = fp.Width;
int length = fp.Length;
if (width <= 0 || length <= 0) { floorPlanReady = false; return; }
var tiles = new HashSet<Point>();
IReadOnlyList<int> tilesData = null;
string heightmap = null;
try { tilesData = fp.Tiles; } catch { }
try { heightmap = fp.Heightmap?.Replace("\r", "").Replace("\n", ""); } catch { }
if (tilesData != null)
{
for (int y = 0; y < length; y++)
{
for (int x = 0; x < width; x++)
{
int idx = y * width + x;
if (idx < tilesData.Count && tilesData[idx] >= 0 && tilesData[idx] < 250)
tiles.Add((x, y));
}
}
}
else if (heightmap != null && heightmap.Length == width * length)
{
for (int y = 0; y < length; y++)
{
for (int x = 0; x < width; x++)
{
if (heightmap[y * width + x] != 'x')
tiles.Add((x, y));
}
}
}
if (tiles.Count > 0)
{
walkableTiles = tiles;
floorPlanReady = true;
Log($"FloorPlan: {tiles.Count} tiles");
}
}
catch (Exception ex)
{
Log($"FloorPlan error: {ex.Message}");
floorPlanReady = false;
}
}
bool IsWalkable(int x, int y)
{
if (!floorPlanReady || walkableTiles == null) return true;
return walkableTiles.Contains((x, y));
}
// ==================== GATE LOGIC ====================
void CheckAndEnterGate(int userX, int userY)
{
if (FloorItems == null) return;
foreach (var item in FloorItems)
{
if (item == null || item.Location == null) continue;
string itemName = null;
try { itemName = item.GetName(); } catch { continue; }
if (itemName != null && itemName.Contains(GATE_FURNI_NAME))
{
int gateX = item.Location.X;
int gateY = item.Location.Y;
int gateDir = item.Direction;
long gateId = item.Id;
bool shouldEnter = false;
if (gateDir == 0) { if (userX == gateX && userY == gateY - 1) shouldEnter = true; }
else if (gateDir == 2) { if (userX == gateX + 1 && userY == gateY) shouldEnter = true; }
else if (gateDir == 4) { if (userX == gateX && userY == gateY + 1) shouldEnter = true; }
else if (gateDir == 6) { if (userX == gateX - 1 && userY == gateY) shouldEnter = true; }
if (shouldEnter)
{
Log($"Gate! ID:{gateId} at ({gateX},{gateY}) Dir:{gateDir}");
Send(Out.EnterOneWayDoor, gateId);
return;
}
}
}
}
void CheckGateOnObjectUpdate(int furniId, int itemX, int itemY, int newDir)
{
if (Self == null || Self.Location == null) return;
var item = FloorItems?.FirstOrDefault(f => f != null && f.Id == furniId);
if (item == null) return;
string itemName = null;
try { itemName = item.GetName(); } catch { return; }
if (itemName != null && itemName.Contains(GATE_FURNI_NAME))
{
int userX = Self.Location.X;
int userY = Self.Location.Y;
bool shouldEnter = false;
if (newDir == 0) { if (userX == itemX && userY == itemY - 1) shouldEnter = true; }
else if (newDir == 2) { if (userX == itemX + 1 && userY == itemY) shouldEnter = true; }
else if (newDir == 4) { if (userX == itemX && userY == itemY + 1) shouldEnter = true; }
else if (newDir == 6) { if (userX == itemX - 1 && userY == itemY) shouldEnter = true; }
if (shouldEnter)
{
Log($"Gate rotated! ID:{furniId}");
Send(Out.EnterOneWayDoor, furniId);
}
}
}
// ==================== THREAT LOGIC ====================
void ScanThreats()
{
if (FloorItems == null) return;
trackedThreats.Clear();
foreach (var item in FloorItems)
{
if (item == null || item.Location == null) continue;
string name = null;
try { name = item.GetName(); } catch { continue; }
if (name != null && name.Contains(DANGER_FURNI_NAME))
{
trackedThreats[item.Id] = (item.Location.X, item.Location.Y);
}
}
}
Point FindBestEscapeStep(Point myPos)
{
Point bestStep = myPos;
double bestScore = double.MinValue;
for (int dx = -1; dx <= 1; dx++)
{
for (int dy = -1; dy <= 1; dy++)
{
Point candidate = (myPos.X + dx, myPos.Y + dy);
if (!IsWalkable(candidate.X, candidate.Y)) continue;
double minDangerDist = double.MaxValue;
foreach (var threat in trackedThreats.Values)
{
double d = GetDistance(candidate, threat);
if (d < minDangerDist) minDangerDist = d;
}
double score = minDangerDist * 10;
if (dx != 0 || dy != 0) score += 1;
if (score > bestScore)
{
bestScore = score;
bestStep = candidate;
}
}
}
return bestStep;
}
// ==================== EVENT HANDLERS ====================
void HandleUserUpdate(dynamic e)
{
if (Self == null) return;
var packet = e.Packet;
int numUpdates = packet.ReadInt();
for (int i = 0; i < numUpdates; i++)
{
int entityIndex = packet.ReadInt();
int currentX = packet.ReadInt();
int currentY = packet.ReadInt();
packet.ReadString();
packet.ReadInt();
packet.ReadInt();
string action = packet.ReadString();
if (entityIndex == Self.Index)
{
Point tileForGateCheck;
Match match = mvRegex.Match(action);
if (match.Success)
{
try
{
int targetX = int.Parse(match.Groups[1].Value);
int targetY = int.Parse(match.Groups[2].Value);
myTargetTile = (targetX, targetY);
lastMoveTime = DateTime.UtcNow;
tileForGateCheck = myTargetTile;
}
catch { tileForGateCheck = (currentX, currentY); }
}
else
{
if (action.EndsWith("//") && !action.Contains("/mv"))
myTargetTile = (-1, -1);
tileForGateCheck = (currentX, currentY);
}
CheckAndEnterGate(tileForGateCheck.X, tileForGateCheck.Y);
}
}
}
void HandleObjectUpdate(dynamic e)
{
if (Self == null || Self.Location == null) return;
var packet = e.Packet;
int furniId = packet.ReadInt();
packet.ReadInt();
int itemX = packet.ReadInt();
int itemY = packet.ReadInt();
int newDir = packet.ReadInt();
// Update threat position
if (trackedThreats.ContainsKey(furniId))
{
trackedThreats[furniId] = (itemX, itemY);
}
// Check gate
CheckGateOnObjectUpdate(furniId, itemX, itemY, newDir);
}
void HandleWiredMovements(dynamic e)
{
var packet = e.Packet;
int count = packet.ReadInt();
for (int i = 0; i < count; i++)
{
packet.ReadInt();
packet.ReadInt();
packet.ReadInt();
int toX = packet.ReadInt();
int toY = packet.ReadInt();
packet.ReadString();
packet.ReadString();
int id = packet.ReadInt();
packet.ReadInt();
packet.ReadInt();
if (trackedThreats.ContainsKey(id))
{
trackedThreats[id] = (toX, toY);
}
}
}
void HandleRoomEnter(dynamic e)
{
Log("Room entered - scanning...");
trackedThreats.Clear();
myTargetTile = (-1, -1);
ParseFloorPlan();
ScanThreats();
Log($"Found: {trackedThreats.Count} '{DANGER_FURNI_NAME}' objects");
if (Self != null && Self.Location != null)
CheckAndEnterGate(Self.Location.X, Self.Location.Y);
}
// ==================== REGISTER EVENTS ====================
OnIntercept(In["UserUpdate"], e => HandleUserUpdate(e));
OnIntercept(In["ObjectUpdate"], e => HandleObjectUpdate(e));
OnIntercept(In["WiredMovements"], e => HandleWiredMovements(e));
OnEnteredRoom(e => HandleRoomEnter(e));
// Initial setup
if (Self != null && Self.Location != null)
{
ParseFloorPlan();
ScanThreats();
Log($"Initial: {trackedThreats.Count} threats found");
CheckAndEnterGate(Self.Location.X, Self.Location.Y);
}
// ==================== MAIN LOOP ====================
int tick = 0;
while (Run)
{
try
{
tick++;
if (!floorPlanReady) ParseFloorPlan();
if (tick % 50 == 0) ScanThreats();
Point myPos = GetMyPosition();
if (IsInvalidPoint(myPos)) { Delay(LOOP_DELAY_MS); continue; }
if (trackedThreats.Count == 0) { Delay(LOOP_DELAY_MS); continue; }
double closestDanger = double.MaxValue;
Point closestThreat = (-1, -1);
foreach (var threat in trackedThreats.Values)
{
double d = GetDistance(myPos, threat);
if (d < closestDanger)
{
closestDanger = d;
closestThreat = threat;
}
}
if (closestDanger <= REACTION_DISTANCE)
{
Point nextStep = FindBestEscapeStep(myPos);
if (!nextStep.Equals(myPos))
{
if (tick % 10 == 0)
Log($"DODGE! Threat at {closestThreat} dist:{closestDanger:F1} -> {nextStep}");
DoMove(nextStep.X, nextStep.Y);
}
}
else if (tick % 100 == 0 && trackedThreats.Count > 0)
{
Log($"Monitoring {trackedThreats.Count} threats... nearest: {closestDanger:F1}");
}
}
catch (Exception ex)
{
Log($"Error: {ex.Message}");
}
if (!Run) break;
Delay(LOOP_DELAY_MS);
}
Log("=== Stopped ===");