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>
428 lines
14 KiB
C#
428 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Globalization;
|
|
|
|
// ================================================
|
|
// ULTRA SMART COLLISION AVOIDANCE
|
|
// Tracks ALL movement and predicts collisions
|
|
// ================================================
|
|
|
|
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})";
|
|
}
|
|
|
|
public class Tile
|
|
{
|
|
public int X { get; set; }
|
|
public int Y { get; set; }
|
|
public double Z { get; set; }
|
|
public Point XY => new Point(X, Y);
|
|
public Tile(int x, int y, double z = 0.0) { X = x; Y = y; Z = z; }
|
|
}
|
|
|
|
public class MovingThreat
|
|
{
|
|
public long Id { get; set; }
|
|
public Point Position { get; set; }
|
|
public Point PreviousPosition { get; set; }
|
|
public Point Velocity { get; set; }
|
|
public DateTime LastUpdate { get; set; }
|
|
public Queue<Point> Trail { get; set; } = new Queue<Point>(10);
|
|
public double Speed { get; set; }
|
|
}
|
|
|
|
Log("ULTRA SMART AVOIDANCE STARTED");
|
|
|
|
// HARDCODED WALKABLE TILES
|
|
HashSet<Point> walkable = new HashSet<Point> {
|
|
(13,13),(14,13),(15,13),(16,13),(17,13),(18,13),(19,13),(20,13),(21,13),(22,13),(23,13),(24,13),(25,13),
|
|
(13,14),(17,14),(21,14),(25,14),
|
|
(13,15),(14,15),(15,15),(17,15),(18,15),(20,15),(21,15),(23,15),(24,15),(25,15),
|
|
(13,16),(15,16),(18,16),(20,16),(23,16),(25,16),
|
|
(13,17),(15,17),(16,17),(17,17),(18,17),(19,17),(20,17),(21,17),(22,17),(23,17),(25,17),
|
|
(13,18),(15,18),(19,18),(23,18),(25,18),
|
|
(13,19),(14,19),(15,19),(17,19),(18,19),(19,19),(20,19),(21,19),(23,19),(24,19),(25,19),
|
|
(13,20),(15,20),(16,20),(17,20),(21,20),(22,20),(23,20),(25,20),
|
|
(12,21),(13,21),(17,21),(18,21),(19,21),(20,21),(21,21),(25,21),(26,21),
|
|
(13,22),(15,22),(16,22),(17,22),(21,22),(22,22),(23,22),(25,22),
|
|
(13,23),(14,23),(15,23),(17,23),(18,23),(19,23),(20,23),(21,23),(23,23),(24,23),(25,23),
|
|
(13,24),(15,24),(19,24),(23,24),(25,24),
|
|
(13,25),(15,25),(16,25),(17,25),(18,25),(19,25),(20,25),(21,25),(22,25),(23,25),(25,25),
|
|
(13,26),(15,26),(18,26),(20,26),(23,26),(25,26),
|
|
(13,27),(14,27),(15,27),(17,27),(18,27),(20,27),(21,27),(23,27),(24,27),(25,27),
|
|
(13,28),(17,28),(21,28),(25,28),
|
|
(13,29),(14,29),(15,29),(16,29),(17,29),(18,29),(19,29),(20,29),(21,29),(22,29),(23,29),(24,29),(25,29)
|
|
};
|
|
|
|
// Pre-calculate neighbors
|
|
Dictionary<Point, List<Point>> neighbors = new Dictionary<Point, List<Point>>();
|
|
Point[] dirs = { (0,1), (0,-1), (1,0), (-1,0), (1,1), (1,-1), (-1,1), (-1,-1) };
|
|
|
|
foreach(var tile in walkable)
|
|
{
|
|
var n = new List<Point>();
|
|
foreach(var d in dirs)
|
|
{
|
|
Point p = new Point(tile.X + d.X, tile.Y + d.Y);
|
|
if(walkable.Contains(p)) n.Add(p);
|
|
}
|
|
neighbors[tile] = n;
|
|
}
|
|
|
|
// Movement tracking
|
|
Dictionary<long, MovingThreat> threats = new Dictionary<long, MovingThreat>();
|
|
Tile targetTile = null;
|
|
Point lastMoveCommand = default(Point);
|
|
DateTime lastMoveTime = DateTime.MinValue;
|
|
Point myLastPosition = default(Point);
|
|
Point myCurrentPosition = default(Point);
|
|
Queue<Point> myMovementHistory = new Queue<Point>(5);
|
|
int stuckCounter = 0;
|
|
HashSet<Point> dangerZonesNextFrame = new HashSet<Point>();
|
|
|
|
// Get current position
|
|
Point GetMyPosition()
|
|
{
|
|
if (Self == null) return default(Point);
|
|
if (targetTile != null) return targetTile.XY;
|
|
if (!lastMoveCommand.Equals(default(Point)) && (DateTime.UtcNow - lastMoveTime).TotalMilliseconds < 250)
|
|
return lastMoveCommand;
|
|
if (Self.Location != null) return new Point(Self.Location.X, Self.Location.Y);
|
|
return default(Point);
|
|
}
|
|
|
|
// Execute move
|
|
void DoMove(int x, int y)
|
|
{
|
|
Move(x, y);
|
|
lastMoveCommand = new Point(x, y);
|
|
lastMoveTime = DateTime.UtcNow;
|
|
targetTile = null;
|
|
}
|
|
|
|
// Predict where threats will be in N frames
|
|
HashSet<Point> PredictDangerZones(int framesAhead)
|
|
{
|
|
var zones = new HashSet<Point>();
|
|
|
|
foreach(var threat in threats.Values)
|
|
{
|
|
// Current position is dangerous
|
|
zones.Add(threat.Position);
|
|
|
|
// Predict based on velocity
|
|
if(!threat.Velocity.Equals(default(Point)))
|
|
{
|
|
for(int i = 1; i <= framesAhead; i++)
|
|
{
|
|
Point predicted = new Point(
|
|
threat.Position.X + threat.Velocity.X * i,
|
|
threat.Position.Y + threat.Velocity.Y * i
|
|
);
|
|
if(walkable.Contains(predicted))
|
|
zones.Add(predicted);
|
|
}
|
|
}
|
|
|
|
// Add all adjacent tiles for frame 1-2 (they could move there)
|
|
if(framesAhead >= 1 && neighbors.ContainsKey(threat.Position))
|
|
{
|
|
foreach(var n in neighbors[threat.Position])
|
|
zones.Add(n);
|
|
}
|
|
|
|
// For frame 2+, add 2-tile radius
|
|
if(framesAhead >= 2)
|
|
{
|
|
foreach(var d1 in dirs)
|
|
{
|
|
Point p1 = new Point(threat.Position.X + d1.X, threat.Position.Y + d1.Y);
|
|
if(walkable.Contains(p1))
|
|
{
|
|
zones.Add(p1);
|
|
foreach(var d2 in dirs)
|
|
{
|
|
Point p2 = new Point(p1.X + d2.X, p1.Y + d2.Y);
|
|
if(walkable.Contains(p2))
|
|
zones.Add(p2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return zones;
|
|
}
|
|
|
|
// Find safest position
|
|
Point FindSafestTile(Point current, HashSet<Point> danger)
|
|
{
|
|
if(!danger.Any()) return walkable.First();
|
|
|
|
double bestScore = double.MinValue;
|
|
Point bestTile = current;
|
|
|
|
foreach(var tile in walkable)
|
|
{
|
|
if(danger.Contains(tile)) continue;
|
|
|
|
double score = 0;
|
|
|
|
// Distance from all danger zones
|
|
double minDist = double.MaxValue;
|
|
foreach(var d in danger)
|
|
{
|
|
double dist = Math.Abs(tile.X - d.X) + Math.Abs(tile.Y - d.Y);
|
|
minDist = Math.Min(minDist, dist);
|
|
score += dist;
|
|
}
|
|
|
|
// Heavily weight minimum distance
|
|
score += minDist * 100;
|
|
|
|
// Prefer tiles with more escape routes
|
|
if(neighbors.ContainsKey(tile))
|
|
{
|
|
int escapes = neighbors[tile].Count(n => !danger.Contains(n));
|
|
score += escapes * 10;
|
|
}
|
|
|
|
// Small penalty for distance from current (prefer closer safe spots)
|
|
double currentDist = Math.Abs(tile.X - current.X) + Math.Abs(tile.Y - current.Y);
|
|
score -= currentDist * 0.5;
|
|
|
|
if(score > bestScore)
|
|
{
|
|
bestScore = score;
|
|
bestTile = tile;
|
|
}
|
|
}
|
|
|
|
return bestTile;
|
|
}
|
|
|
|
// Get best immediate move
|
|
Point GetBestMove(Point current, Point goal, HashSet<Point> danger1, HashSet<Point> danger2, HashSet<Point> danger3)
|
|
{
|
|
if(!neighbors.ContainsKey(current)) return current;
|
|
|
|
// Check if stuck
|
|
if(myMovementHistory.Count >= 3)
|
|
{
|
|
var last3 = myMovementHistory.TakeLast(3).ToArray();
|
|
if(last3[0] == last3[2] && last3[0] != last3[1])
|
|
{
|
|
stuckCounter++;
|
|
if(stuckCounter > 1)
|
|
{
|
|
// Force escape in any safe direction
|
|
var anyMove = neighbors[current]
|
|
.Where(n => !danger1.Contains(n))
|
|
.OrderBy(n => danger2.Contains(n) ? 1 : 0)
|
|
.FirstOrDefault();
|
|
if(!anyMove.Equals(default(Point)))
|
|
{
|
|
stuckCounter = 0;
|
|
return anyMove;
|
|
}
|
|
}
|
|
}
|
|
else stuckCounter = 0;
|
|
}
|
|
|
|
double bestScore = double.MinValue;
|
|
Point bestMove = current;
|
|
|
|
foreach(var next in neighbors[current])
|
|
{
|
|
// NEVER go to immediate danger
|
|
if(danger1.Contains(next)) continue;
|
|
|
|
// NEVER backtrack to previous position
|
|
if(!myLastPosition.Equals(default(Point)) && next.Equals(myLastPosition))
|
|
continue;
|
|
|
|
double score = 0;
|
|
|
|
// Heavy penalty for predicted danger
|
|
if(danger2.Contains(next)) score -= 1000;
|
|
if(danger3.Contains(next)) score -= 500;
|
|
|
|
// Distance to goal
|
|
double goalDist = Math.Abs(next.X - goal.X) + Math.Abs(next.Y - goal.Y);
|
|
score -= goalDist * 10;
|
|
|
|
// Distance from all current threats
|
|
foreach(var threat in threats.Values)
|
|
{
|
|
double dist = Math.Abs(next.X - threat.Position.X) + Math.Abs(next.Y - threat.Position.Y);
|
|
score += dist * 20;
|
|
}
|
|
|
|
// Bonus for tiles with escape routes
|
|
if(neighbors.ContainsKey(next))
|
|
{
|
|
int escapes = neighbors[next].Count(n => !danger1.Contains(n) && !danger2.Contains(n));
|
|
score += escapes * 50;
|
|
}
|
|
|
|
if(score > bestScore)
|
|
{
|
|
bestScore = score;
|
|
bestMove = next;
|
|
}
|
|
}
|
|
|
|
return bestMove;
|
|
}
|
|
|
|
// Room entry
|
|
OnEnteredRoom(e => {
|
|
Log($"Entered room {RoomId}");
|
|
threats.Clear();
|
|
myMovementHistory.Clear();
|
|
myLastPosition = default(Point);
|
|
stuckCounter = 0;
|
|
});
|
|
|
|
// Track ALL wired movements
|
|
OnIntercept(In["WiredMovements"], e => {
|
|
var packet = e.Packet;
|
|
int count = packet.ReadInt();
|
|
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
packet.ReadInt();
|
|
int fromX = packet.ReadInt();
|
|
int fromY = packet.ReadInt();
|
|
int toX = packet.ReadInt();
|
|
int toY = packet.ReadInt();
|
|
packet.ReadString(); // fromHeight
|
|
packet.ReadString(); // toHeight
|
|
int id = packet.ReadInt();
|
|
packet.ReadInt();
|
|
packet.ReadInt();
|
|
|
|
long furniId = id;
|
|
Point newPos = new Point(toX, toY);
|
|
Point oldPos = new Point(fromX, fromY);
|
|
|
|
// Track this threat
|
|
if(!threats.ContainsKey(furniId))
|
|
{
|
|
threats[furniId] = new MovingThreat { Id = furniId };
|
|
}
|
|
|
|
var threat = threats[furniId];
|
|
threat.PreviousPosition = threat.Position;
|
|
threat.Position = newPos;
|
|
threat.Velocity = new Point(toX - fromX, toY - fromY);
|
|
threat.LastUpdate = DateTime.UtcNow;
|
|
|
|
threat.Trail.Enqueue(newPos);
|
|
if(threat.Trail.Count > 10) threat.Trail.Dequeue();
|
|
|
|
// Calculate speed
|
|
if((threat.LastUpdate - DateTime.UtcNow).TotalSeconds < 1)
|
|
{
|
|
threat.Speed = Math.Sqrt(Math.Pow(threat.Velocity.X, 2) + Math.Pow(threat.Velocity.Y, 2));
|
|
}
|
|
}
|
|
});
|
|
|
|
// Track bot position
|
|
OnIntercept(In["UserUpdate"], 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 x = packet.ReadInt();
|
|
int y = packet.ReadInt();
|
|
string zStr = packet.ReadString();
|
|
packet.ReadInt(); // headRot
|
|
packet.ReadInt(); // bodyRot
|
|
string action = packet.ReadString();
|
|
|
|
if(entityIndex == Self.Index)
|
|
{
|
|
myLastPosition = myCurrentPosition;
|
|
myCurrentPosition = new Point(x, y);
|
|
|
|
myMovementHistory.Enqueue(myCurrentPosition);
|
|
if(myMovementHistory.Count > 5) myMovementHistory.Dequeue();
|
|
|
|
// Parse target
|
|
if(action.Contains("/mv"))
|
|
{
|
|
var parts = action.Split(new[] {' ', '/', ','}, StringSplitOptions.RemoveEmptyEntries);
|
|
if(parts.Length >= 4 && parts[0] == "mv")
|
|
{
|
|
if(int.TryParse(parts[1], out int mvX) &&
|
|
int.TryParse(parts[2], out int mvY) &&
|
|
double.TryParse(parts[3], NumberStyles.Any, CultureInfo.InvariantCulture, out double mvZ))
|
|
{
|
|
targetTile = new Tile(mvX, mvY, mvZ);
|
|
lastMoveCommand = default(Point);
|
|
}
|
|
}
|
|
}
|
|
else if(action.EndsWith("//") && !action.Contains("/mv"))
|
|
{
|
|
targetTile = null;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Main loop
|
|
while(Run)
|
|
{
|
|
try
|
|
{
|
|
Point myPos = GetMyPosition();
|
|
if(myPos.Equals(default(Point))) { Delay(20); continue; }
|
|
|
|
if(threats.Any())
|
|
{
|
|
// Predict danger zones
|
|
var danger1Frame = PredictDangerZones(1);
|
|
var danger2Frame = PredictDangerZones(2);
|
|
var danger3Frame = PredictDangerZones(3);
|
|
|
|
// Find safest destination
|
|
Point safeGoal = FindSafestTile(myPos, danger1Frame);
|
|
|
|
// Get best immediate move
|
|
Point nextMove = GetBestMove(myPos, safeGoal, danger1Frame, danger2Frame, danger3Frame);
|
|
|
|
// Execute if different from current
|
|
if(!nextMove.Equals(myPos))
|
|
{
|
|
DoMove(nextMove.X, nextMove.Y);
|
|
}
|
|
}
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
Log($"Error: {ex.Message}");
|
|
}
|
|
|
|
Delay(20); // 50Hz update rate
|
|
}
|
|
|
|
Log("Bot stopped"); |