Repository navigation
EN UO Topic world geometry
Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
Home · C# · IDE · UO API · A–Z · Examples · Languages
Coordinates, distances, line of sight, cross-country ability and map data. Getting a route is described separately in Movement.
| Topic | Commands and explanations |
|---|---|
| X / Y / Z | UO.GetX · UO.GetY · UO.GetZ |
| Distance | UO.GetDistance · UO.Dist |
| LOS | UO.CheckLOS · UO.LOSOptions |
| World Number | UO.WorldNum |
| World Cells | UO.GetWorldCell · UO.GetWorldTilesArray |
| Passability | UO.IsWorldCellPassable · UO.GetNextStepZ |
| Surface Z | UO.GetSurfaceZ |
| Map Cells | UO.GetMapCell |
| Land Tiles | UO.GetLandTileAt · UO.GetLandTileData · UO.GetLandTilesArray · UO.GetLandTilesArrayEx |
| Static Tiles | UO.GetStaticTileAt · UO.GetStaticTileData · UO.GetStaticTiles · UO.GetStaticTilesArray · UO.GetStaticTilesArrayEx |
| Tile Flags | UO.GetTileFlags · UO.ConvertIntegerToFlags |
| Tile Height | UO.GetTileHeight |
| Tile Layer | UO.GetTileLayer |
| Tile Name | UO.GetTileName |
| Water Tiles | UO.IsWaterTile |
| Tree Tiles | UO.IsTreeTile |
| Mine Tiles | UO.IsMineTile |
UO.X · UO.Y · UO.Z · UO.GetX · UO.GetY · UO.GetZ
UO.GetWorldCell · UO.GetMapCell · UO.IsWorldCellPassable · UO.GetSurfaceZ · UO.GetNextStepZ · UO.GetWorldTilesArray
UO.GetLandscapeTile · UO.GetLandTileAt · UO.GetLandTileData · UO.GetLandTilesArray · UO.GetLandTilesArrayEx
UO.GetStaticArt · UO.GetStaticTileAt · UO.GetStaticTileData · UO.GetStaticTiles · UO.GetStaticTilesArray · UO.GetStaticTilesArrayEx · UO.ReadStaticsXY · UO.PrivateGetTile · UO.GetTileXYM · UO.GetLayerCount
UO.GetTileFlags · UO.GetTileHeight · UO.GetTileLayer · UO.GetTileName · UO.IsWaterTile · UO.IsTreeTile · UO.IsMineTile · UO.ConvertIntegerToFlags
UO.AddUserStatic · UO.ClearUserStatics · UO.GetUserStatic · UO.GetUserStatics · UO.RemoveUserStatic · UO.UserStaticExists
Each command card has several independent scenarios: direct code, functions and classes. Below are selected short scenarios; restrictions and full analysis are in the cards.
Parameters, result and all scenarios
var target = UO.GetSerial("lasttarget");
if (Truth(UO.Exists(target)))
{
var distance = UO.GetDistance(target);
if (Truth(distance <= 2))
{
UO.Print("Target is within two tiles");
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters, result and all scenarios
var x = UO.GetX();
var y = UO.GetY();
var z = UO.GetZ();
var result = UO.IsWorldCellPassable(x,y,z,x+1,y,z,UO.WorldNum());
if (Truth(Truth(result[0]) == true))
{
UO.Print("Passable, Z=" + Convert.ToString(result[1]));
}
else
{
UO.Print("Blocked");
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.AddUserStatic(object? staticItem, object? worldNum);
int UO.AddUserStatic(object? graphic, object? x, object? y, object? z, object? hue, object? map);Adds a custom static entry to the local script state. Numeric graphic is used for local obstacle checking by pathfinder; the object is not created on the server. A two-argument call with unnumbered text preserves legacy values and does not add static to the pathfinder.
-
staticItem— numeric graphic or legacy text value. -
worldNum- index of the card for recording or local static. -
graphic- ID statics from0to65535. -
z— height. When added to pathfinder, the value is limited to the signed byte range. -
hue- hue; when added, limited to the range from0to65535. -
map— map index; for manager processing, the range is limited to0–255. -
x— World X custom statics; int. The manager accepts coordinates within the currently loaded map. -
y— World Y custom statics; int. The manager accepts coordinates within the currently loaded map.
Positive ID of the created entry. For the six-parameter form, negative graphic, x, y or map, as well as graphic above 65535 result in -1. ID can be passed to UO.UserStaticExists, UO.RemoveUserStatic or used to check/delete a legacy record. The returned ID by itself does not confirm that the static will be visible or applied on the server.
-
-
UO.AddUserStatic('tree', 0)- sincetreeis not a number, saves a pair of original values as a legacy record in the runtime state; pathfinder doesn't use it.
-
- A two-parameter call with a numeric graphic adds that graphic's static to the character's current coordinates, with the character's
zand hue0. - The six-parameter call adds a static with the given graphic, coordinates, height, hue and map. Pathfinding only takes it into account on the active map and according to the graphic flags in the client tiledata.
These entries are local to the script client: they do not create a game object, make a network request, or modify shard data.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.AddUserStatic(0x0CCA, UO.GetWorldNum());
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));1. Save the pair as legacy data; text StaticItem does not create an obstacle to the pathfinder. - direct script
Parameters and execution flow:
- Save the pair as legacy data; text StaticItem does not create an obstacle to the pathfinder.
var legacyId = UO.AddUserStatic("tree", 0);
UO.Print(Convert.ToString(legacyId));Parameters and execution flow:
- A numeric graphic is added to the character's position on the current map.
return RunScenario();
object? RunScenario()
{
var staticId = UO.AddUserStatic(0x0CCA, UO.GetWorldNum());
UO.Print(Convert.ToString(staticId));
return null;
}3. Explicitly add a local static graphic at the specified position and to the specified map. - script class
Parameters and execution flow:
- Explicitly add a local static graphic at the specified position and to the specified map.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var staticId = UO.AddUserStatic(0x0CCA, UO.GetX(), UO.GetY(), UO.GetZ(), 0, UO.GetWorldNum());
UO.Print(Convert.ToString(staticId));
return null;
}
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: staticItem (Any), worldNum (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(1, bridge.WorldNumber). -
InjectionScript.Runtime.NumberConversions.TryStr2Int:NumberConversions.TryStr2Int(arguments[0].String, out graphic). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Text:Text(0). -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(arguments[0]). -
InjectionScript.Runtime.InjectionApiUO.AddUserStatic:AddUserStatic(graphic, bridge.GetX(bridge.Self), bridge.GetY(bridge.Self), bridge.GetZ(bridge.Self), 0, map). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetX:bridge.GetX(bridge.Self). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetY:bridge.GetY(bridge.Self). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetZ:bridge.GetZ(bridge.Self). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.WorldNumber:bridge.WorldNumber. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.Self:bridge.Self.
Internal implementation code; this is not a standalone script.
case "adduserstatic":
{
int map = Arg(1, bridge.WorldNumber);
if (arguments[0].Kind != InjectionValueKind.Array)
{
int graphic = 0;
if (arguments[0].Kind == InjectionValueKind.String &&
!NumberConversions.TryStr2Int(arguments[0].String, out graphic))
{
int legacyId = state.NextUserStaticId++;
state.UserStatics[legacyId] = Text(0) + "|" + Text(1);
return new InjectionValue(legacyId);
}
graphic = arguments[0].Kind == InjectionValueKind.String
? graphic
: NumberConversions.ToInt(arguments[0]);
return new InjectionValue(AddUserStatic(graphic, bridge.GetX(bridge.Self), bridge.GetY(bridge.Self),
bridge.GetZ(bridge.Self), 0, map));
}
if (arguments[0].Array.Length < 4)
throw new NativeSubrutineException("AddUserStatic expects [graphic,x,y,z,color] and world number, or graphic,x,y,z,color,world.");
InjectionValue[] item = arguments[0].Array;
return new InjectionValue(AddUserStatic(
NumberConversions.ToInt(item[0]), NumberConversions.ToInt(item[1]), NumberConversions.ToInt(item[2]),
NumberConversions.ToInt(item[3]), item.Length > 4 ? NumberConversions.ToInt(item[4]) : 0, map));
}Parameters: graphic (Any), x (Any), y (Any), z (Any), hue (Any), map (Any)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.Register [AddUserStatic]. -
InjectionScript.Runtime.InjectionApiUO.AddUserStatic:AddUserStatic( NumberConversions.ToInt(values[0]), NumberConversions.ToInt(values[1]), NumberConversions.ToInt(values[2]), NumberConversions.ToInt(values[3]), NumberConversions.ToInt(values[4]), NumberConversions.ToInt(values[5])). -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(values[0]).
The call executes the stored handler delegate. The registration method creates this delegate while building the API.
Internal implementation code; this is not a standalone script.
values => new InjectionValue(AddUserStatic(
NumberConversions.ToInt(values[0]), NumberConversions.ToInt(values[1]), NumberConversions.ToInt(values[2]),
NumberConversions.ToInt(values[3]), NumberConversions.ToInt(values[4]), NumberConversions.ToInt(values[5])))Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.CheckLOS(object? xfrom, object? yfrom, object? zfrom, object? xto, object? yto, object? zto, object? worldNum);Checks the local passability of a line between two map points via CheckPortableLineOfSight.
-
xfrom— Source X: 0..65535. -
yfrom— Source Y: 0..65535. -
zfrom— Initial Z, int. -
xto- End X: 0..65535. -
yto- End Y: 0..65535. -
zto— Final Z, int. -
worldNum- 0..255. A beam of non-zero length reads only the currently loaded _world.Map/World.Map: via CheckWorldStep you need WorldNum == _world.MapIndex and a live Player.Pathfinder. Another facet is not loaded or requested; there is no map/character/pathfinder or the step is not available - 0. Excluding identical X/Y skips the entire cycle of cells: with X/Y in 0..65535, WorldNum in 0..255 and abs(Zfrom-Zto)<=20 returns 1 even without a loaded card or with a different card number. This is not a proof of geometry or reachability. The result is local, not a LOS server solution.
int 1 — the local ray has reached X/Y and the final height differs from Zto by no more than 20; 0—invalid coordinates, obstacle, or check limit.
- The beam travels using the Bresenham algorithm, with a maximum of 4096 steps. On each cell, BadLocations, CheckWorldStep and the returned height are taken into account.
- When LosOptions != 0 additionally CheckLosCell is used; bit 0x100 checks both side squares of the diagonal. Local geometry checking does not validate server-specific LOS rules and does not move anything.
- Low byte (value & 0xFF) selects algorithm 1..4; other low byte values in CheckLosCell use the 3 algorithm. Algorithms 1/2 block Wall and Impassable, 3 additionally NoShoot, and 4 enables NoShoot only with 0x200 and allows Window obstacles only with 0x400. Bit 0x100 additionally checks both side cells of each diagonal beam step for any selected algorithm. value=0 disables the additional CheckLosCell/diagonal checks, but BadLocations and CheckWorldStep remain. For example 4+0x100+0x200+0x400 selects custom with three flags; setter stores the original int, not the normalized algorithm.
- A beam of non-zero length reads only the currently loaded _world.Map/World.Map: via CheckWorldStep you need WorldNum == _world.MapIndex and a live Player.Pathfinder. Another facet is not loaded or requested; there is no map/character/pathfinder or the step is unavailable - 0. Excluding identical X/Y skips the entire cycle of cells: with X/Y in 0..65535, WorldNum in 0..255 and abs(Zfrom-Zto)<=20 returns 1 even without a loaded card or with a different card number. This is not a proof of geometry or reachability. The result is local, not a LOS server solution.
- CheckLosCell bypasses the loaded Land/Static/Multi/Item of one cell. Impassable Land blocks with abs(rayZ-land.Z)<=20. The Static/Multi/Item flags are only valid in the range tile.Z-2 .. tile.Z+max(1,Height)+2; allowed custom Window is skipped until Wall/Impassable/NoShoot is checked. X/Y beam uses Bresenham, maximum 4096 steps; Z is taken from surfaces CheckWorldStep, not interpolated to Zto, final height tolerance is 20.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.CheckLOS(UO.X(), UO.Y(), UO.Z(), UO.X() + 1, UO.Y(), UO.Z(), UO.WorldNum());
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- Identical points pass within acceptable X/Y/map.
var x = UO.GetX();
var y = UO.GetY();
var z = UO.GetZ();
var visible = UO.CheckLOS(x,y,z,x,y,z,UO.WorldNum());
UO.Print(Convert.ToString(visible));Parameters and execution flow:
- The height and permeability of the neighboring cell are read from the local map.
return RunScenario();
object? RunScenario()
{
var x = UO.GetX();
var y = UO.GetY();
var z = UO.GetZ();
var clear = UO.CheckLOS(x, y, z, x + 1, y, z, UO.WorldNum());
UO.Print(Convert.ToString(clear));
return null;
}Parameters and execution flow:
- A negative X is rejected with a result of 0 without passing through the map.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var clear = UO.CheckLOS(-1, 0, 0, 0, 0, 0, 0);
UO.Print(Convert.ToString(clear));
return null;
}
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
UO.CheckLOS(xfrom, yfrom, zfrom, xto, yto, zto, worldNum) — UO.CheckLOS(Any,Any,Any,Any,Any,Any,Any)
Parameters: xfrom (Any), yfrom (Any), zfrom (Any), xto (Any), yto (Any), zto (Any), worldNum (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.CheckPortableLineOfSight:CheckPortableLineOfSight(Arg(0), Arg(1), Arg(2), Arg(3), Arg(4), Arg(5), Arg(6)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Internal implementation code; this is not a standalone script.
case "checklos": return new InjectionValue(CheckPortableLineOfSight(Arg(0), Arg(1), Arg(2), Arg(3), Arg(4), Arg(5), Arg(6)) ? 1 : 0);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.ClearUserStatics();Removes all user static runtime entries and local static manager objects.
There are no parameters.
void - no return value.
- State.UserStatics and manager objects are cleared. Uploaded map files and real server items are not deleted.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The command is a separate statement. The message before it marks the start of the call; it does not confirm a server action.
UO.Print("Calling UO.ClearUserStatics");
UO.ClearUserStatics();Parameters and execution flow:
- Removes all user static runtime entries and local static manager objects.
UO.ClearUserStatics();Parameters and execution flow:
- Add a local static on the current cell, then remove all custom statics.
return RunScenario();
object? RunScenario()
{
var localStatic = UO.AddUserStatic(0x0CCA, UO.GetX(), UO.GetY(), UO.GetZ(), 0, UO.WorldNum());
UO.ClearUserStatics();
return null;
}Parameters and execution flow:
- Clearing an empty set is acceptable and does not create a new setting.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
UO.ClearUserStatics();
UO.ClearUserStatics();
return null;
}
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: No parameters.
Result: void / Unit.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.ClearUserStatics:bridge.ClearUserStatics().
Internal implementation code; this is not a standalone script.
case "clearuserstatics": state.UserStatics.Clear(); bridge.ClearUserStatics(); return InjectionValue.Unit;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.ConvertIntegerToFlags(object? group, object? value);Parses a numeric mask of tile flags into an array of enumeration names TileFlag.
-
group- int: only 1 or 2 enable conversion; any other value results in an empty array. -
value— A mask that Arg converts to a signed 32-bit int, then bridge leads to ulong. For high 64-bit flags, this form does not preserve the full mask.
Array of strings named non-zero TileFlag whose bits are fully present in the mask. The mask 0 produces an empty array.
- Group 1 and 2 use the same Enum.GetValues rather than different directories. This is a local mask transformation; tiledata is not requested.
- API-registration uses object?, but Arg(1) dispatcher passes int. Negative int sign-extends when casting to ulong. GetTileFlags also returns only the low 32 bits as a signed int: this compatible pair does not provide the full 64-bit tiledata contract.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.ConvertIntegerToFlags(1, 0);
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- No non-zero flag is present in the mask 0.
var flags = UO.ConvertIntegerToFlags(1,0);
UO.Print(Convert.ToString(ArrayLength(flags)));
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;Parameters and execution flow:
- The array contains the real names TileFlag of the selected mask.
return RunScenario();
object? RunScenario()
{
var flags = UO.ConvertIntegerToFlags(2, 1);
for (int i = (int)(0); i <= ArrayLength(flags) - 1; i += (int)(1))
{
UO.Print(flags[i]);
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;Parameters and execution flow:
- Group 0 is not accepted by this command and returns an empty array.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var flags = UO.ConvertIntegerToFlags(0, 1);
UO.Print(Convert.ToString(ArrayLength(flags)));
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: group (Any), value (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.ConvertTileFlags:bridge.ConvertTileFlags(Arg(0), Arg(1)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Internal implementation code; this is not a standalone script.
case "convertintegertoflags":
return new InjectionValue(bridge.ConvertTileFlags(Arg(0), Arg(1))
.Select(flag => new InjectionValue(flag)).ToArray());Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.Dist(object? xfrom, object? yfrom, object? xto, object? yto);Calculates the distance in cells between two world points: the greatest of the absolute differences between X and Y.
-
xfrom— X coordinate of the starting point. -
yfrom— Y coordinate of the starting point. -
xto— X coordinate of destination. -
yto— Y coordinate of destination.
int — distance in cells, non-negative for valid coordinates. 0 means the same XY, 1 - one cell. This is a quantity, not a sign of success. A separate comparison distance <= 2 returns bool true or false; the distance itself remains int.
- Calculate coordinates only: no batches, no waiting, no map loading, no obstacle checking, no Z, no world map. The team does not search for a passable route and does not guarantee the achievement of the goal. The points must belong to the same coordinate system; avoiding obstacles can lengthen the path.
- All four parameters are needed. Send world coordinates int in the documented range 0..65535. object? in the signature indicates a universal adapter, not the item's ID. These commands do not have default values, coordinates inside the chest, fifth Z and overload with one object.
- Formula: Max(Abs(Xto-Xfrom), Abs(Yto-Yfrom)). When you rearrange the points, the result is the same. This is not the Euclidean distance, not the sum of the differences, and not the number of steps when going around an obstacle.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
var result = UO.Dist(100, 100, 103, 104);
UO.Print("Dist: " + Convert.ToString(result));Parameters and execution flow:
- From (100,100) to (103,104): the absolute differences are 3 and 4, with a maximum of 4. Main returns int 4.
- int — distance in cells, non-negative for valid coordinates. 0 means the same XY, 1 - one cell. This is a quantity, not a sign of success. A separate comparison distance <= 2 returns bool true or false; the distance itself remains int.
- Formula: Max(Abs(Xto-Xfrom), Abs(Yto-Yfrom)). When you rearrange the points, the result is the same. This is not the Euclidean distance, not the sum of the differences, and not the number of steps when going around an obstacle.
return UO.Dist(100,100,103,104);Parameters and execution flow:
- From (100,100) to (101,99) the distance is 1. A separate comparison of distance<=2 gives true=1. Main returns "1:1": the first unit is the distance, the second is the logical result of the comparison.
- int — distance in cells, non-negative for valid coordinates. 0 means the same XY, 1 - one cell. This is a quantity, not a sign of success. A separate comparison distance <= 2 returns bool true or false; the distance itself remains int.
- Formula: Max(Abs(Xto-Xfrom), Abs(Yto-Yfrom)). When you rearrange the points, the result is the same. This is not the Euclidean distance, not the sum of the differences, and not the number of steps when going around an obstacle.
return RunScenario();
object? RunScenario()
{
var distance = UO.Dist(100, 100, 101, 99);
var close = distance <= 2;
return Convert.ToString(distance) + ":" + Convert.ToString(close);
return null;
}Parameters and execution flow:
- UO.Dist returns 4. RebuildTileDistance calculates the differences via Abs, compares them and returns the larger one, so does 4. Main returns "4:4". The assistant is fully shown in the example and is not another engine command.
- int — distance in cells, non-negative for valid coordinates. 0 means the same XY, 1 - one cell. This is a quantity, not a sign of success. A separate comparison distance <= 2 returns bool true or false; the distance itself remains int.
- Formula: Max(Abs(Xto-Xfrom), Abs(Yto-Yfrom)). When you rearrange the points, the result is the same. This is not the Euclidean distance, not the sum of the differences, and not the number of steps when going around an obstacle.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var actual = UO.Dist(100, 100, 103, 104);
var rebuilt = RebuildTileDistance(100, 100, 103, 104);
return Convert.ToString(actual) + ":" + Convert.ToString(rebuilt);
return null;
}
dynamic RebuildTileDistance(dynamic Xfrom, dynamic Yfrom, dynamic Xto, dynamic Yto)
{
var dx = Math.Abs(Xto - Xfrom);
var dy = Math.Abs(Yto - Yfrom);
if (Truth(dx > dy))
{
return dx;
}
return dy;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: xfrom (Any), yfrom (Any), xto (Any), yto (Any)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.GetDistance:GetDistance(Arg(0), Arg(1), Arg(2), Arg(3)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetDistance:bridge.GetDistance(Arg(0)).
Internal implementation code; this is not a standalone script.
case "dist": return new InjectionValue(arguments.Length >= 4
? GetDistance(Arg(0), Arg(1), Arg(2), Arg(3))
: bridge.GetDistance(Arg(0)));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.GetDistance(object? id);
int UO.GetDistance(object? x, object? y);
int UO.GetDistance(object? id1, object? x2, object? y2);
int UO.GetDistance(object? x1, object? y1, object? x2, object? y2);Measures the distance in cells based on the maximum X/Y differences. This is geometric estimation without pathfinding.
-
id— One argument: serial or alias of the loaded object, the distance to which you want to get. -
x— Two arguments: world destination. The beginning is GetX(self), GetY(self). -
y— Two arguments: world destination. The beginning is GetX(self), GetY(self). -
id1— In three-argument form, the serial/alias of the object whose coordinates serve as the origin. -
x1— In four-argument form, the coordinates of the origin. No object is needed for this form. -
y1— In four-argument form, the coordinates of the origin. No object is needed for this form. -
x2— In forms with three/four arguments, the end coordinates. Don't confuse them with serial of the second object. -
y2— In forms with three/four arguments, the end coordinates. Don't confuse them with serial of the second object.
int - max(abs(x2-x1), abs(y2-y1)): horizontal, vertical and diagonal to an adjacent cell have a distance 1. Z height and obstacles are not taken into account. For unknown serial, the one-argument form returns 0; for an existing object in the absence of a character - 65535. For unknown id1, the three-argument form uses (0,0), so check Exists(id1) first.
- The single-object form uses the current World.RangeSize range center and the last position in the moving mob's step queue. During movement, the result may differ from the calculation via GetX/GetY.
- Coordinate forms work with passed numbers. For game coordinates, use the range 0..65535; extreme int values and difference overflow are not supported coordinates.
- The team does not promise that the goal will be achievable. To move, you need MoveXY/NewMoveXY and checking its result; walls can make the actual path longer.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
var result = UO.GetDistance("lasttarget");
UO.Print("GetDistance: " + Convert.ToString(result));Parameters and execution flow:
- target is serial, not type. The Exists check prevents an unknown object zero from being mistaken for a nearby target.
- distance<=2 checks the X/Y distance. Visibility and passability are checked separately.
var target = UO.GetSerial("lasttarget");
if (Truth(UO.Exists(target)))
{
var distance = UO.GetDistance(target);
if (Truth(distance <= 2))
{
UO.Print("Target is within two tiles");
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- x1=100, y1=200, x2=103, y2=204. The differences are 3 and 4.
- The result is 4, not 7 and not the Euclidean 5.
return RunScenario();
object? RunScenario()
{
var distance = UO.GetDistance(100, 200, 103, 204);
UO.Print(Convert.ToString(distance));
return null;
}Parameters and execution flow:
- The two x/y arguments use the current position of self. The three arguments id1/x2/y2 allow you to explicitly specify the start object.
- At a constant position, both quantities are equal to 3. The coordinates must remain within the boundaries of the map.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var x = UO.GetX() + 3;
var y = UO.GetY() + 1;
var fromSelf = UO.GetDistance(x, y);
var fromObject = UO.GetDistance("self", x, y);
UO.Print(Convert.ToString(fromSelf) + " / " + Convert.ToString(fromObject));
return null;
}
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: id (Any/Integer/String)
Result: int / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetDistance:bridge.GetDistance(Arg(0)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Internal implementation code; this is not a standalone script.
case "getdistance": return new InjectionValue(bridge.GetDistance(Arg(0)));Parameters: id (Any/Integer/String)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetDistance. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetDistance:bridge.GetDistance(id).
Internal implementation code; this is not a standalone script.
public int GetDistance(int id) => bridge.GetDistance(id);Parameters: id (Any/Integer/String)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetDistance. -
InjectionScript.Runtime.InjectionApiUO.GetDistance:GetDistance(GetObject(id)). -
InjectionScript.Runtime.InjectionApiUO.GetObject:GetObject(id).
Internal implementation code; this is not a standalone script.
public int GetDistance(string id) => GetDistance(GetObject(id));Parameters: x (Integer), y (Integer)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetDistance. -
InjectionScript.Runtime.InjectionApiUO.GetDistance:GetDistance(bridge.GetX(bridge.Self), bridge.GetY(bridge.Self), x, y). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetX:bridge.GetX(bridge.Self). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetY:bridge.GetY(bridge.Self). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.Self:bridge.Self.
Internal implementation code; this is not a standalone script.
public int GetDistance(int x, int y) => GetDistance(bridge.GetX(bridge.Self), bridge.GetY(bridge.Self), x, y);Parameters: id1 (Any), x2 (Any), y2 (Any)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetDistance. -
InjectionScript.Runtime.InjectionApiUO.GetObject:GetObject(id1). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetX:bridge.GetX(obj1). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetY:bridge.GetY(obj1). -
InjectionScript.Runtime.InjectionApiUO.GetDistance:GetDistance(x1, y1, NumberConversions.ToInt(x2), NumberConversions.ToInt(y2)). -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(x2).
Internal implementation code; this is not a standalone script.
public int GetDistance(InjectionValue id1, InjectionValue x2, InjectionValue y2)
{
var obj1 = GetObject(id1);
int x1 = bridge.GetX(obj1);
int y1 = bridge.GetY(obj1);
return GetDistance(x1, y1, NumberConversions.ToInt(x2), NumberConversions.ToInt(y2));
}Parameters: x1 (Integer), y1 (Integer), x2 (Integer), y2 (Integer)
Result: int / Integer.
During a call:
Internal implementation code; this is not a standalone script.
public int GetDistance(int x1, int y1, int x2, int y2)
{
int dx = Math.Abs(x1 - x2);
int dy = Math.Abs(y1 - y2);
return Math.Max(dx, dy);
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetLandTileAt(object? x, object? y);
dynamic UO.GetLandTileAt(object? x, object? y, object? map);Returns the extended land record of the selected cell.
-
x— X cell of the currently loaded map; world coordinate, not position inside the gump. -
y— Y cell of the currently loaded map; world coordinate, not position inside the gump. -
map— Card number. If this argument is not present in the selected form, the current map is used. The real client only reads tiles from the currently loaded map.
Array of 11 fields of one record; indices start with 0:
-
[0] kind— string: "land", "static", or "object". -
[1] serial— int: serial of a dynamic item; for land/static is 0. -
[2] graphic— int: graphics type. -
[3] x,[4] y- int: world coordinates of the cell. -
[5] z- int: the height of the base in the world. -
[6] hue- int: color, near the ground 0. -
[7] flags- int: low 32 bits of tiledata flags. -
[8] name— string: name from tiledata. -
[9] layer- int: layer of equipment from tiledata, near the ground 0; not a static index. -
[10] height- int: graphic height from tiledata, near the ground 0; not the Z coordinate.
An empty array [] means no entry or an inaccessible card/cell. For GetStaticTileAt, a negative/too large index also produces []; index overflow does not select someone else's entry.
- The data refers to the currently loaded map. Another card or unreachable cell results in an empty array. Direct tile queries may additionally report map mismatches; GetWorldCell and GetWorldTilesArray immediately return an empty array without such a message.
- Array indices start with 0. Check ArrayLength before reading the field. Z stands for world altitude; layer is the equipment property from tiledata, and index is the serial number of the cell entry.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetLandTileAt(UO.GetX(), UO.GetY());
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- x/y — character position; the card is lowered and selected automatically. For GetStaticTileAt index=0 means the first entry.
- The fields [2], [5], [9] have different meanings; all are read only after checking the length of 11.
var tile = UO.GetLandTileAt(UO.GetX(), UO.GetY());
if (Truth(ArrayLength(tile) == 11))
{
UO.Print("Type: " + Convert.ToString(tile[2]));
UO.Print("World Z: " + Convert.ToString(tile[5]));
UO.Print("Equipment layer: " + Convert.ToString(tile[9]));
}
else
{
UO.Print("Tile is unavailable");
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The same coordinates are used; GetStaticTileAt reads index=0.
- tile[8] is the title string, tile[10] is the height dimension from tiledata, not the Z base.
return RunScenario();
object? RunScenario()
{
var tile = UO.GetLandTileAt(UO.GetX(), UO.GetY());
if (Truth(ArrayLength(tile) == 11))
{
UO.Print(tile[8]);
UO.Print("Graphic height: " + Convert.ToString(tile[10]));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- WaitTargetTile gets graphic, x, y, z from fields 2…5.
- This is just preparation for the next target. The example does not trigger a tool or spell. serial=0 for statics should not be passed as ID of the item.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var tile = UO.GetLandTileAt(UO.GetX(), UO.GetY());
if (Truth(ArrayLength(tile) == 11))
{
UO.WaitTargetTile(tile[2], tile[3], tile[4], tile[5]);
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: x (Any), y (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetLandTileAt. -
InjectionScript.Runtime.InjectionApiUO.GetLandTileAt:GetLandTileAt(x, y, new InjectionValue(bridge.WorldNumber)). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.WorldNumber:bridge.WorldNumber.
Internal implementation code; this is not a standalone script.
public InjectionValue GetLandTileAt(InjectionValue x, InjectionValue y)
=> GetLandTileAt(x, y, new InjectionValue(bridge.WorldNumber));Parameters: x (Any), y (Any), map (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetLandTileAt. -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(x). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetLandscapeTile:bridge.GetLandscapeTile(cellX, cellY, world). -
InjectionScript.Runtime.InjectionApiUO.BuildWorldTileRecord:BuildWorldTileRecord("land", 0, land[0], cellX, cellY, land[1], 0, 0).
Internal implementation code; this is not a standalone script.
public InjectionValue GetLandTileAt(InjectionValue x, InjectionValue y, InjectionValue map)
{
int cellX = NumberConversions.ToInt(x);
int cellY = NumberConversions.ToInt(y);
int world = NumberConversions.ToInt(map);
int[] land = bridge.GetLandscapeTile(cellX, cellY, world) ?? Array.Empty<int>();
return land.Length >= 2
? BuildWorldTileRecord("land", 0, land[0], cellX, cellY, land[1], 0, 0)
: new InjectionValue(Array.Empty<InjectionValue>());
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetLandTileData(object? tile);Reads the extended land reference record from tiledata.
-
tile— Graphic/type of record, not serial and not an index inside the cell. The land table is chosen by the team name itself.
Array of 7 fields for a valid graphic. All fields are int except name (string):
-
[0] graphic— graphic/type of entry. -
[1] flags— low-order 32 flag bits. -
[2] name— name from tiledata (string). -
[3] texId- ID ground textures. -
[4] wet— 1 if wet is installed, otherwise 0. -
[5] impassable— 1 if impassable, otherwise 0. -
[6] noDiagonal— 1 if noDiagonal, otherwise 0.
For an invalid graphic, there are no reference properties: the short array [переданный graphic, 0, ""] is returned. Check the full length before reading the properties. This is not a Pascal record or a list of objects.
- The command reads tiledata and does not require an item with this graphic in the world. Flags describe the resource; the result does not replace a full route check.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetLandTileData(0x0003);
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- Tile — numeric graphic of the selected table.
- data[2] contains the name. Length check separates a full entry from a short entry of invalid graphic.
var data = UO.GetLandTileData(0x0003);
if (Truth(ArrayLength(data) == 7))
{
UO.Print(data[2]);
}
else
{
UO.Print("Tiledata entry is unavailable");
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- data[5] is a separate impassable field: 1 (condition met), 0 (condition not met).
- This check does not take into account other objects in the cell or the character's abilities.
return RunScenario();
object? RunScenario()
{
var data = UO.GetLandTileData(0x0003);
if (Truth(ArrayLength(data) == 7))
{
if (Truth(data[5]))
{
UO.Print("Impassable flag is set");
}
else
{
UO.Print("Impassable flag is not set");
}
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- data[0] repeats the transmitted graphic, data[1] is a general flag mask.
- The mask can contain several bits at the same time; its numeric value is not serial.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var data = UO.GetLandTileData(0x0003);
if (Truth(ArrayLength(data) == 7))
{
UO.Print("Graphic: " + Convert.ToString(data[0]));
UO.Print("Flags: " + Convert.ToString(data[1]));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: tile (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.BuildTileData:BuildTileData(0, Arg(0)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Internal implementation code; this is not a standalone script.
case "getlandtiledata":
return BuildTileData(0, Arg(0));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetLandTilesArray(object? xmin, object? ymin, object? xmax, object? ymax, object? worldNum, object? tileType);Searches for land tiles by graphic/type in a rectangle.
-
xmin— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
ymin— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
xmax— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
ymax— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
worldNum— Map/facet 0..255; use UO.WorldNum(). Another map gives an empty Array. If the map changes between chunks, the partial result is discarded. -
tileType— One graphic/type of tile, usually 0..65535; this is not serial. 0 is the exact graphic 0, -1 does not mean any type. A mismatched type gives an empty result.
Array of entries [graphic, X, Y, Z]; all fields are int. graphic — type of earth, Z — its base. No matches: empty Array. The quantity is ArrayLength(result), not the result itself. The indices start with 0. This is not a bool, serial or Pascal record; there is no seventh output parameter.
- Local data is read. Search does not change FindItem/FindCount and does not perform a move, target, or network command.
- Order: X ascending, within X - Y ascending. Records of one cell preserve the order of bridge; it is not sorted by distance or height.
- The search is processed in chunks of up to 32 cells with a soft budget of about 1 ms. Cancellation is checked between servings. A complex cell or cold read may go over budget. It is better to divide a large area; the world can change while reading.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetLandTilesArray(UO.GetX(), UO.GetY(), UO.GetX() + 2, UO.GetY() + 2, UO.WorldNum(), 0x0003);
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- x/y — position self, map — current map. The region 3×3 includes the boundaries. In Ex two type are transmitted, in normal form one. Change the samples to suit your resources; this is a graphic, not a ID object.
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var rows = UO.GetLandTilesArray(x, y, x + 2, y + 2, map, 0x0003);
UO.Print("Records: " + Convert.ToString(ArrayLength(rows)));
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;Parameters and execution flow:
- The region 2×2 is transferred from the larger angle to the smaller one. The algorithm itself normalizes the boundaries. row - one record; PrintTile is declared in its entirety and only formats numbers, without moving anything. graphic - type, x/y - coordinates, z - height, hue - color. For land, a conditional hue=0 is passed: there is no color field in the land record.
return RunScenario();
object? RunScenario()
{
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var rows = UO.GetLandTilesArray(x + 1, y + 1, x, y, map, 0x0003);
var i = 0;
while (Truth(i < ArrayLength(rows)))
{
var row = rows[i];
PrintTile(row[0], row[1], row[2], row[3], 0);
i = i + 1;
}
return null;
}
void PrintTile(dynamic graphic, dynamic x, dynamic y, dynamic z, dynamic hue)
{
UO.Print("Type=" + Convert.ToString(graphic) + " X=" + Convert.ToString(x) + " Y=" + Convert.ToString(y));
UO.Print("Z=" + Convert.ToString(z) + " hue=" + Convert.ToString(hue));
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- No more than three searches for one cell; between attempts WaitAsync(250). Each call creates a new result. Zero length means there are no matches now, rather than the object being permanently missing from the server.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var attempt = 0;
while (Truth(attempt < 3))
{
var rows = UO.GetLandTilesArray(x, y, x, y, map, 0x0003);
UO.Print("Records: " + Convert.ToString(ArrayLength(rows)));
attempt = attempt + 1;
await Delay(250);
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
UO.GetLandTilesArray(xmin, ymin, xmax, ymax, worldNum, tileType) — UO.GetLandTilesArray(Any,Any,Any,Any,Any,Any)
Parameters: xmin (Any), ymin (Any), xmax (Any), ymax (Any), worldNum (Any), tileType (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.FindPortableTiles:FindPortableTiles(Arg(0), Arg(1), Arg(2), Arg(3), Arg(4), new[] { Arg(5) }, false). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Internal implementation code; this is not a standalone script.
case "getlandtilesarray":
return FindPortableTiles(Arg(0), Arg(1), Arg(2), Arg(3), Arg(4), new[] { Arg(5) }, false);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetLandTilesArrayEx(object? xmin, object? ymin, object? xmax, object? ymax, object? worldNum, object? tileTypes);Searches for land tiles by graphic/type in a rectangle.
-
xmin— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
ymin— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
xmax— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
ymax— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
worldNum— Map/facet 0..255; use UO.WorldNum(). Another map gives an empty Array. If the map changes between chunks, the partial result is discarded. -
tileTypes— Array of numeric graphic/type; every matching type is included. Repeating type does not duplicate entries. A scalar is also accepted as one type. An empty Array means all type; an array of one 0 searches only 0.
Array of entries [graphic, X, Y, Z]; all fields are int. graphic — type of earth, Z — its base. No matches: empty Array. The quantity is ArrayLength(result), not the result itself. The indices start with 0. This is not a bool, serial or Pascal record; there is no seventh output parameter.
- Local data is read. Search does not change FindItem/FindCount and does not perform a move, target, or network command.
- Order: X ascending, within X - Y ascending. Records of one cell preserve the order of bridge; it is not sorted by distance or height.
- The search is processed in chunks of up to 32 cells with a soft budget of about 1 ms. Cancellation is checked between servings. A complex cell or cold read may go over budget. It is better to divide a large area; the world can change while reading.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetLandTilesArrayEx(UO.X(), UO.Y(), UO.X() + 1, UO.Y() + 1, UO.WorldNum(), new[] { 0x0003 });
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- x/y — position self, map — current map. The region 3×3 includes the boundaries. In Ex two type are transmitted, in normal form one. Change the samples to suit your resources; this is a graphic, not a ID object.
dynamic[] types = new dynamic[checked((int)(1) + 1)];
types[0] = 0x0003;
types[1] = 0x0004;
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var rows = UO.GetLandTilesArrayEx(x, y, x + 2, y + 2, map, types);
UO.Print("Records: " + Convert.ToString(ArrayLength(rows)));
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;Parameters and execution flow:
- The region 2×2 is transferred from the larger angle to the smaller one. The algorithm itself normalizes the boundaries. row - one record; PrintTile is declared in its entirety and only formats numbers, without moving anything. graphic - type, x/y - coordinates, z - height, hue - color. For land, a conditional hue=0 is passed: there is no color field in the land record.
return RunScenario();
object? RunScenario()
{
dynamic[] types = new dynamic[checked((int)(1) + 1)];
types[0] = 0x0003;
types[1] = 0x0004;
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var rows = UO.GetLandTilesArrayEx(x + 1, y + 1, x, y, map, types);
var i = 0;
while (Truth(i < ArrayLength(rows)))
{
var row = rows[i];
PrintTile(row[0], row[1], row[2], row[3], 0);
i = i + 1;
}
return null;
}
void PrintTile(dynamic graphic, dynamic x, dynamic y, dynamic z, dynamic hue)
{
UO.Print("Type=" + Convert.ToString(graphic) + " X=" + Convert.ToString(x) + " Y=" + Convert.ToString(y));
UO.Print("Z=" + Convert.ToString(z) + " hue=" + Convert.ToString(hue));
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- No more than three searches for one cell; between attempts WaitAsync(250). Each call creates a new result. Zero length means there are no matches now, rather than the object being permanently missing from the server.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
dynamic[] types = new dynamic[checked((int)(1) + 1)];
types[0] = 0x0003;
types[1] = 0x0004;
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var attempt = 0;
while (Truth(attempt < 3))
{
var rows = UO.GetLandTilesArrayEx(x, y, x, y, map, types);
UO.Print("Records: " + Convert.ToString(ArrayLength(rows)));
attempt = attempt + 1;
await Delay(250);
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
UO.GetLandTilesArrayEx(xmin, ymin, xmax, ymax, worldNum, tileTypes) — UO.GetLandTilesArrayEx(Any,Any,Any,Any,Any,Any)
Parameters: xmin (Any), ymin (Any), xmax (Any), ymax (Any), worldNum (Any), tileTypes (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.FindPortableTiles:FindPortableTiles(Arg(0), Arg(1), Arg(2), Arg(3), Arg(4), ArrayArg(5), false). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::ArrayArg:ArrayArg(5).
Internal implementation code; this is not a standalone script.
case "getlandtilesarrayex":
return FindPortableTiles(Arg(0), Arg(1), Arg(2), Arg(3), Arg(4), ArrayArg(5), false);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetLandscapeTile(object? x, object? y, object? map);Reads the land of one cell of the current card.
-
x— X cell of the currently loaded map; world coordinate, not position inside the gump. -
y— Y cell of the currently loaded map; world coordinate, not position inside the gump. -
map— Card number. If this argument is not present in the selected form, the current map is used. The real client only reads tiles from the currently loaded map.
Array of three int: [0] graphic - type lands; [1] z — world altitude of the earth; [2] flags — low 32 bits of tiledata flags. If the card/tile is not available or there is no land, an empty array [] is returned. This is a flat record, not a list of three tiles.
- The data refers to the currently loaded map. Another card or unreachable cell results in an empty array. Direct tile queries may additionally report map mismatches; GetWorldCell and GetWorldTilesArray immediately return an empty array without such a message.
- Array indices start with 0. Check ArrayLength before reading the field. Z stands for world altitude; layer is the equipment property from tiledata, and index is the serial number of the cell entry.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetLandscapeTile(UO.GetX(), UO.GetY(), UO.WorldNum());
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- x/y are taken from the character's position; map=WorldNum() selects the current map.
- The presence of three fields is checked before indexing; land[0] - graphic, land[1] - Z.
var land = UO.GetLandscapeTile(UO.GetX(), UO.GetY(), UO.WorldNum());
if (Truth(ArrayLength(land) >= 3))
{
UO.Print("Graphic: " + Convert.ToString(land[0]));
UO.Print("Ground Z: " + Convert.ToString(land[1]));
}
else
{
UO.Print("Land is unavailable");
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- x+1 is a neighboring cell, y and map are preserved.
- deltaZ compares land and character. This is not a passability test: bridges and statics are counted separately.
return RunScenario();
object? RunScenario()
{
var land = UO.GetLandscapeTile(UO.GetX() + 1, UO.GetY(), UO.WorldNum());
if (Truth(ArrayLength(land) >= 3))
{
var deltaZ = land[1] - UO.GetZ();
UO.Print("Ground height difference: " + Convert.ToString(deltaZ));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- group=0 selects land; land[0] - graphic.
- GetTileName returns text, whereas GetLandscapeTile returns an array.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var land = UO.GetLandscapeTile(UO.GetX(), UO.GetY(), UO.WorldNum());
if (Truth(ArrayLength(land) >= 3))
{
var name = UO.GetTileName(0, land[0]);
UO.Print(name);
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: x (Any), y (Any), map (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetLandscapeTile. -
InjectionScript.Runtime.InjectionApiUO.ToArray:ToArray(bridge.GetLandscapeTile(NumberConversions.ToInt(x), NumberConversions.ToInt(y), NumberConversions.ToInt(map))). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetLandscapeTile:bridge.GetLandscapeTile(NumberConversions.ToInt(x), NumberConversions.ToInt(y), NumberConversions.ToInt(map)). -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(x).
Internal implementation code; this is not a standalone script.
public InjectionValue GetLandscapeTile(InjectionValue x, InjectionValue y, InjectionValue map)
=> ToArray(bridge.GetLandscapeTile(NumberConversions.ToInt(x), NumberConversions.ToInt(y), NumberConversions.ToInt(map)));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetLayerCount(object? x, object? y, object? worldNum);Counts non-earth geometry records in one cell.
-
x— World coordinate X of the cell of the current map, not the position in the gump. -
y— World Y coordinate of the current map cell. -
worldNum— Card/facet number; use UO.WorldNum(). Only the currently loaded card is read.
int — the number of graphic/Z/hue triples received by GetStaticTiles. In the current client, Static, Multi and Item are taken into account: multiple records of the same height are counted separately. An empty square/another card gives 0. This is not the number of the equipment layer, not the number of floors, not the number of unique heights, or bool.
- The command reads the local map and does not trigger movement or target. A cell outside the size of the map is not replaced by a cell in an adjacent column.
- Z height, graphic/type, hue color, flags and equipment layer have different meanings. Null graphic or Z=0 may be valid data; check the result form.
- The composition corresponds to ReadStaticsXY, not GetLayer or ObjAtLayer. This client includes dynamic items and Multi parts.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetLayerCount(UO.GetX(), UO.GetY(), UO.WorldNum());
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- count — number of cell records; 1 means one entry, not a logical success.
var count = UO.GetLayerCount(UO.GetX(), UO.GetY(), UO.WorldNum());
UO.Print("Tile records: " + Convert.ToString(count));Parameters and execution flow:
- The absence of records does not prove the passage of land. The presence of a recording also does not prove that it is a wall.
return RunScenario();
object? RunScenario()
{
var x = UO.GetX() + 1;
var y = UO.GetY();
var count = UO.GetLayerCount(x, y, UO.WorldNum());
if (Truth(count > 0))
{
UO.Print("Non-land geometry exists: " + Convert.ToString(count));
}
else
{
UO.Print("No loaded non-land records");
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The current and neighboring cells in the same world are checked. The number of layers is not their height or graphic.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
int x = UO.GetX();
int y = UO.GetY();
int world = UO.WorldNum();
int land = UO.GetLayerCount(x, y, world);
int nearby = UO.GetLayerCount(x + 1, y, world);
UO.Print($"Layers here: {land}; adjacent tile: {nearby}");
return null;
}
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: x (Any), y (Any), worldNum (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetStaticTiles:bridge.GetStaticTiles(Arg(0), Arg(1), Arg(2)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Internal implementation code; this is not a standalone script.
case "getlayercount":
// Stealth's deprecated GetLayerCount(X,Y,WorldNum) is the
// number of static records at a map cell. The portable
// bridge returns each record as Graphic/Z/Hue triples.
return new InjectionValue(bridge.GetStaticTiles(Arg(0), Arg(1), Arg(2)).Length / 3);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetMapCell(object? x, object? y, object? worldNum);Reads graphic, height and land flags in one map cell.
-
x— World coordinate X of the cell of the current map, not the position in the gump. -
y— World Y coordinate of the current map cell. -
worldNum— Card/facet number; use UO.WorldNum(). Only the currently loaded card is read.
Array of three int: [0] graphic/type lands, [1] world Z bases land, [2] minor 32 bits of tiledata flags. An inaccessible cell or other card results in an empty Array. This is not a serial, bool or Pascal record; do not use .Tile/.Z fields. For the number of fields, call ArrayLength(cell).
- The command reads the local map and does not trigger movement or target. A cell outside the size of the map is not replaced by a cell in an adjacent column.
- Z height, graphic/type, hue color, flags and equipment layer have different meanings. Null graphic or Z=0 may be valid data; check the result form.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetMapCell(UO.GetX(), UO.GetY(), UO.WorldNum());
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- X/Y is taken from self, WorldNum is the current card. cell stores all fields of one call.
- The indices start with 0. cell[1] is the height, not a sign of a successful search; an empty array is checked before indexing.
var cell = UO.GetMapCell(UO.GetX(), UO.GetY(), UO.WorldNum());
if (Truth(ArrayLength(cell) == 3))
{
UO.Print("Type: " + Convert.ToString(cell[0]));
UO.Print("Land Z: " + Convert.ToString(cell[1]));
UO.Print("Flags: " + Convert.ToString(cell[2]));
}
else
{
UO.Print("Map cell unavailable");
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The second call reads the square to the east, both using the same card.
- The difference in ground heights does not prove passability: walls, statics and other objects are checked separately.
return RunScenario();
object? RunScenario()
{
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var here = UO.GetMapCell(x, y, map);
var east = UO.GetMapCell(x + 1, y, map);
if (Truth(ArrayLength(here) == 3) && Truth(ArrayLength(east) == 3))
{
UO.Print("Land difference: " + Convert.ToString(east[1] - here[1]));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- GetMapCell reads Land.Z; GetSurfaceZ reads Land.AverageZ.
- Both values are height. On sloping ground they may vary; This is not the height of the floor of the house.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var cell = UO.GetMapCell(x, y, map);
if (Truth(ArrayLength(cell) == 3))
{
var average = UO.GetSurfaceZ(x, y, map);
UO.Print("Base: " + Convert.ToString(cell[1]) + ", average: " + Convert.ToString(average));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: x (Any), y (Any), worldNum (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetLandscapeTile:bridge.GetLandscapeTile(Arg(0), Arg(1), Arg(2)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Internal implementation code; this is not a standalone script.
case "getmapcell":
return new InjectionValue(bridge.GetLandscapeTile(Arg(0), Arg(1), Arg(2))
.Select(value => new InjectionValue(value)).ToArray());Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.GetNextStepZ(object? currX, object? currY, object? destX, object? destY, object? worldNum, object? currZ);Calculates the estimated height of the next step in the specified direction.
-
currX— Initial world X, usually UO.GetX(). -
currY— Initial world Y, usually UO.GetY(). -
destX— X destination. To check one specific step, pass an adjacent cell. -
destY— Y destination; together with DestX, it sets the direction of one step, rather than the full route. -
worldNum— Card/facet number; use UO.WorldNum(). Only the currently loaded card is read. -
currZ— Initial height Z, usually UO.GetZ(); geometric calculation uses the range -128..127.
int — calculated Z of the next step; 0 and negative numbers are valid heights. When a character or other card 0 is disabled. The method returns the Z component of the check even if it fails; the number itself is not confirmation of passage. For flag and height together, use IsWorldCellPassable and read [0]/[1].
- The command reads the local map and does not trigger movement or target. A cell outside the size of the map is not replaced by a cell in an adjacent column.
- Z height, graphic/type, hue color, flags and equipment layer have different meanings. Null graphic or Z=0 may be valid data; check the result form.
- The calculation does not take a step and does not open the door. It checks the local geometry; the server may reject the actual movement. If bridge does not return Z, CurrZ is used.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
var result = UO.GetNextStepZ(UO.GetX(), UO.GetY(), UO.GetX() + 1, UO.GetY(), UO.WorldNum(), UO.GetZ());
UO.Print("GetNextStepZ: " + Convert.ToString(result));Parameters and execution flow:
- Six parameters: original X/Y, neighboring X/Y, map and original Z. nextZ - height, not true/false.
var x = UO.GetX();
var y = UO.GetY();
var z = UO.GetZ();
var nextZ = UO.GetNextStepZ(x, y, x + 1, y, UO.WorldNum(), z);
UO.Print("Candidate Z: " + Convert.ToString(nextZ));Parameters and execution flow:
- The call is made only when there is a known connection. Between checking and reading, the connection may be lost; Z=0 is still not a success code.
return RunScenario();
object? RunScenario()
{
if (Truth(Truth(UO.Connected()) == true))
{
var x = UO.GetX();
var y = UO.GetY();
var z = UO.GetNextStepZ(x, y, x, y + 1, UO.WorldNum(), UO.GetZ());
UO.Print("South candidate Z: " + Convert.ToString(z));
}
else
{
UO.Print("Character disconnected");
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The coordinates of the source and target cells are transmitted separately. The result is the expected height, even with obstruction; the pass flag separately gives IsWorldCellPassable.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
int x = UO.GetX();
int y = UO.GetY();
int z = UO.GetZ();
int nextZ = UO.GetNextStepZ(x, y, x + 1, y, UO.WorldNum(), z);
UO.Print($"Current height: {z}; next-step result: {nextZ}");
return null;
}
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
UO.GetNextStepZ(currX, currY, destX, destY, worldNum, currZ) — UO.GetNextStepZ(Any,Any,Any,Any,Any,Any)
Parameters: currX (Any), currY (Any), destX (Any), destY (Any), worldNum (Any), currZ (Any)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.IsOnline:bridge.IsOnline(). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(4). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.CheckWorldStep:bridge.CheckWorldStep(Arg(0), Arg(1), Arg(5), Arg(2), Arg(3), Arg(4)). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.WorldNumber:bridge.WorldNumber.
Internal implementation code; this is not a standalone script.
case "getnextstepz":
{
if (bridge.IsOnline() == 0 || Arg(4) != bridge.WorldNumber)
return new InjectionValue(0);
int[] step = bridge.CheckWorldStep(Arg(0), Arg(1), Arg(5), Arg(2), Arg(3), Arg(4));
return new InjectionValue(step.Length > 1 ? step[1] : Arg(5));
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetStaticArt(object? objType, object? hue);Gets a single Graphic image from the installed Ultima Online graphics files and returns it in memory in BMP format. Useful for checking your game resources, icon sizes, reading pixel color and comparing colored versions of an item. The command itself does not open a window, save a file, or search for items in the world.
-
objType— Mandatory Graphic/type from the static art section: integer 0..65535, string with the same number, or saved name AddType. For example, 0x0EED is an art for a stack of gold. This is not the serial of the item, not the map/tile coordinate, and not the animation number of the body. To get the art of a loaded item, pass UO.GetType(item), where item is its serial. If the numeric type is out of range, the result is an empty array; an unknown string name causes a conversion error. -
hue— Mandatory integer color value: 0 — original colors of the art; a positive value is hue from the client files. Numeric strings are acceptable, including the result UO.GetColor(item). The value is limited to the range 0..65535: negative becomes 0, too large becomes 65535. Here -1 does NOT mean any color. The PartialHue flag art uses partial coloring; for others - complete. The result of a particular hue depends on the loaded color table.
Array is a one-dimensional int array, each element 0..255 represents one byte of the complete BMP file, starting with the header. Indexing with 0. It is not a bool, not ID, not a path, not a Bitmap object, and not a color array RGB. An empty array means the numeric type is not valid, the art is missing, or the required game files are not loaded. Before reading the title, check ArrayLength; the empty array is not equal to the number 0.
- Exactly two arguments are required. Reading is performed from the client's local resources, without a request to the server. The existence of an object in the world is not required. For mobile, the number from GetType means body; here the same number addresses a different resource section and does not provide an image of the character animation.
- Result format: uncompressed 24-bit BMP. Bytes [0]=66 and [1]=77 - BM; [2..5] - size of the entire file; [10..13] - the beginning of the pixels, now 54; [14..17] - size of DIB-header, now 40; [18..21] - width; [22..25] - positive height; [26..27] - 1 plane; [28..29] - 24 bit. Multibyte numbers are written little-endian.
- Each pixel occupies three bytes in the order B, G, R. The lines go from bottom to top and are padded with zero bytes up to a multiple of 4. String length = Int((width * 3 + 3) / 4) * 4. For x,y coordinates from the top left corner, offset = 54 + (height - 1 - y) * stride + x * 3. Check the bounds and size of the array before accessing.
- The transparency of the original art is not preserved: BMP does not contain alpha here. The transparent background becomes black, and it is impossible to distinguish it from the original black pixel by the result. Screenshot, game window scaling, light, visibility range and object coordinates are not involved.
- For each call, an image array is generated. If you need art many times, save the result to a variable and process it again. Don't call loading/coloring for every pixel inside the loop. The same parameters and unchanged files give the same result; different hue are not required to change every pixel, especially with PartialHue.
- A real .bmp needs binary output of the exact bytes without text encoding. A regular File.WriteLine or JsonSave does not create BMP. The examples below process the array in memory and do not promise the presence of a non-existent File.WriteBytes.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetStaticArt(0x0EED, 0);
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- ObjType=0x0EED selects the resource, Hue=0 leaves the original colors. The array is checked before reading offsets 18 and 22. 64 is the example's own limit, not a command limit.
- ArtSizeField is a user-defined function C#, not a UO command. Adds four bytes with weights 1, 256, 65536, 16777216. The script helps you choose the size of your cell; Doesn't create a gump automatically.
var bmp = UO.GetStaticArt(0x0EED, 0);
if (Truth(ArrayLength(bmp) < 54))
{
UO.Print("Gold art is unavailable");
return null;
}
var width = ArtSizeField(bmp, 18);
var height = ArtSizeField(bmp, 22);
if (Truth(width > 64) || Truth(height > 64))
{
UO.Print("Use a larger cell for this icon");
return null;
}
UO.Print("Icon fits: " + Convert.ToString(width) + " x " + Convert.ToString(height));
dynamic ArtSizeField(dynamic bytes, dynamic offset)
{
return bytes[offset] + bytes[offset+1]*256 + bytes[offset+2]*65536 + bytes[offset+3]*16777216;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- GetStaticArt returns BMP; ArtPixelRGB is a separate example function for this format. x=0,y=0 means the top left pixel of the image, not the world coordinates. The replacement height-1-y is required due to the order of the lines from bottom to top.
- The function returns RGB int 0..16777215, and uses -1 only as its indicator of the absence of a pixel. Black 0 is a valid color, not false and not an error. Therefore, the test for if rgb < 0 is separate from if rgb = 0.
return RunScenario();
object? RunScenario()
{
var bmp = UO.GetStaticArt(0x0EED, 0);
var rgb = ArtPixelRGB(bmp, 0, 0);
if (Truth(rgb < 0))
{
UO.Print("No pixel at this position");
return null;
}
if (Truth(rgb == 0))
{
UO.Print("Black pixel: may also be the original transparent background");
}
return null;
}
dynamic ArtPixelRGB(dynamic bmp, dynamic x, dynamic y)
{
if (Truth(ArrayLength(bmp) < 54))
{
return -1;
}
var width = bmp[18] + bmp[19] * 256 + bmp[20] * 65536 + bmp[21] * 16777216;
var height = bmp[22] + bmp[23] * 256 + bmp[24] * 65536 + bmp[25] * 16777216;
if (Truth(x < 0) || Truth(y < 0) || Truth(x >= width) || Truth(y >= height))
{
return -1;
}
var stride = Math.Floor((width * 3 + 3) / 4) * 4;
var offset = 54 + (height - 1 - y) * stride + x * 3;
if (Truth(offset + 2 >= ArrayLength(bmp)))
{
return -1;
}
return bmp[offset + 2] * 65536 + bmp[offset + 1] * 256 + bmp[offset];
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- 0x1F03 — Graphic robes; 0 and 0x0044 are the original and selected hue. The same Graphic gives the same dimensions. If the result is empty, the comparison does not begin.
- changed counts different bytes of color channels, not objects or number of pixels. One pixel can change up to three bytes. PartialHue, color table and original colors may leave part or all of the image the same; this is not evidence of a team error.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var original = UO.GetStaticArt(0x1F03, 0);
var colored = UO.GetStaticArt(0x1F03, 0x0044);
var size = ArrayLength(original);
if (Truth(size < 54) || Truth(size != ArrayLength(colored)))
{
UO.Print("Cannot compare these art resources");
return null;
}
var changed = 0;
for (int offset = (int)(54); offset <= size - 1; offset += (int)(1))
{
if (Truth(original[offset] != colored[offset]))
{
changed = changed + 1;
}
}
if (Truth(changed == 0))
{
UO.Print("This hue did not change the exported bytes");
}
else
{
UO.Print("Changed color bytes: " + Convert.ToString(changed));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: objType (Any), hue (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetStaticArt:bridge.GetStaticArt(ResolveType(arguments[0]), Arg(1)). -
InjectionScript.Runtime.InjectionApiUO.ResolveType:ResolveType(arguments[0]). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(1).
Internal implementation code; this is not a standalone script.
case "getstaticart":
return new InjectionValue(bridge.GetStaticArt(ResolveType(arguments[0]), Arg(1)).Select(value => new InjectionValue(value)).ToArray());Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetStaticTileAt(object? x, object? y, object? index);
dynamic UO.GetStaticTileAt(object? x, object? y, object? map, object? index);Returns an extended record of one record above the ground of the selected cell.
-
x— X cell of the currently loaded map; world coordinate, not position inside the gump. -
y— Y cell of the currently loaded map; world coordinate, not position inside the gump. -
map— Card number. If this argument is not present in the selected form, the current map is used. The real client only reads tiles from the currently loaded map. -
index— The sequence number of the record in the results GetStaticTiles, starting with 0. This is not a graphic, not a Z, and not an equipment layer. In the form of 3 arguments, index comes third; in the form of 4 arguments map third, index fourth.
Array of 11 fields of one record; indices start with 0:
-
[0] kind— string: "land", "static", or "object". -
[1] serial— int: serial of a dynamic item; for land/static is 0. -
[2] graphic— int: graphics type. -
[3] x,[4] y- int: world coordinates of the cell. -
[5] z- int: the height of the base in the world. -
[6] hue- int: color, near the ground 0. -
[7] flags- int: low 32 bits of tiledata flags. -
[8] name— string: name from tiledata. -
[9] layer- int: layer of equipment from tiledata, near the ground 0; not a static index. -
[10] height- int: graphic height from tiledata, near the ground 0; not the Z coordinate.
An empty array [] means no entry or an inaccessible card/cell. For GetStaticTileAt, a negative/too large index also produces []; index overflow does not select someone else's entry.
- The data refers to the currently loaded map. Another card or unreachable cell results in an empty array. Direct tile queries may additionally report map mismatches; GetWorldCell and GetWorldTilesArray immediately return an empty array without such a message.
- Array indices start with 0. Check ArrayLength before reading the field. Z stands for world altitude; layer is the equipment property from tiledata, and index is the serial number of the cell entry.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetStaticTileAt(UO.GetX(), UO.GetY(), 0);
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- x/y — character position; the card is lowered and selected automatically. For GetStaticTileAt index=0 means the first entry.
- The fields [2], [5], [9] have different meanings; all are read only after checking the length of 11.
var tile = UO.GetStaticTileAt(UO.GetX(), UO.GetY(), 0);
if (Truth(ArrayLength(tile) == 11))
{
UO.Print("Type: " + Convert.ToString(tile[2]));
UO.Print("World Z: " + Convert.ToString(tile[5]));
UO.Print("Equipment layer: " + Convert.ToString(tile[9]));
}
else
{
UO.Print("Tile is unavailable");
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The same coordinates are used; GetStaticTileAt reads index=0.
- tile[8] is the title string, tile[10] is the height dimension from tiledata, not the Z base.
return RunScenario();
object? RunScenario()
{
var tile = UO.GetStaticTileAt(UO.GetX(), UO.GetY(), 0);
if (Truth(ArrayLength(tile) == 11))
{
UO.Print(tile[8]);
UO.Print("Graphic height: " + Convert.ToString(tile[10]));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- WaitTargetTile gets graphic, x, y, z from fields 2…5.
- This is just preparation for the next target. The example does not trigger a tool or spell. serial=0 for statics should not be passed as ID of the item.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var tile = UO.GetStaticTileAt(UO.GetX(), UO.GetY(), 0);
if (Truth(ArrayLength(tile) == 11))
{
UO.WaitTargetTile(tile[2], tile[3], tile[4], tile[5]);
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: x (Any), y (Any), index (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetStaticTileAt. -
InjectionScript.Runtime.InjectionApiUO.GetStaticTileAt:GetStaticTileAt(x, y, new InjectionValue(bridge.WorldNumber), index). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.WorldNumber:bridge.WorldNumber.
Internal implementation code; this is not a standalone script.
public InjectionValue GetStaticTileAt(InjectionValue x, InjectionValue y, InjectionValue index)
=> GetStaticTileAt(x, y, new InjectionValue(bridge.WorldNumber), index);Parameters: x (Any), y (Any), map (Any), index (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetStaticTileAt. -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(x). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetStaticTiles:bridge.GetStaticTiles(cellX, cellY, NumberConversions.ToInt(map)). -
InjectionScript.Runtime.InjectionApiUO.BuildWorldTileRecord:BuildWorldTileRecord("static", 0, statics[offset], cellX, cellY, statics[offset + 1], statics[offset + 2], 1).
Internal implementation code; this is not a standalone script.
public InjectionValue GetStaticTileAt(InjectionValue x, InjectionValue y, InjectionValue map, InjectionValue index)
{
int cellX = NumberConversions.ToInt(x);
int cellY = NumberConversions.ToInt(y);
int[] statics = bridge.GetStaticTiles(cellX, cellY, NumberConversions.ToInt(map)) ?? Array.Empty<int>();
int tileIndex = NumberConversions.ToInt(index);
if (tileIndex < 0 || tileIndex >= statics.Length / 3)
return new InjectionValue(Array.Empty<InjectionValue>());
int offset = tileIndex * 3;
return offset + 2 < statics.Length
? BuildWorldTileRecord("static", 0, statics[offset], cellX, cellY, statics[offset + 1], statics[offset + 2], 1)
: new InjectionValue(Array.Empty<InjectionValue>());
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetStaticTileData(object? tile);Reads the static graphic extended help entry from tiledata.
-
tile— Graphic/type of record, not serial and not an index inside the cell. The static table is selected by the command name itself.
Array of 17 fields for a valid graphic. All fields are int except name (string):
-
[0] graphic— graphic/type of entry. -
[1] flags— low-order 32 flag bits. -
[2] name— name from tiledata (string). -
[3] weight— weight from tiledata. -
[4] layer— equipment layer number. -
[5] countis the Count field from tiledata, not the number of items in the world. -
[6] animId- ID animations. -
[7] hue- hue from tiledata. -
[8] lightIndex— index of the light source. -
[9] height— graphic height, not world Z. -
[10] wet— 1 if wet is installed, otherwise 0. -
[11] impassable— 1 if impassable, otherwise 0. -
[12] surface— 1 if surface, otherwise 0. -
[13] foliage— 1 if foliage, otherwise 0. -
[14] door— 1 if door, otherwise 0. -
[15] wall— 1 if wall, otherwise 0. -
[16] container— 1 if container, otherwise 0.
For an invalid graphic, there are no reference properties: the short array [переданный graphic, 0, ""] is returned. Check the full length before reading the properties. This is not a Pascal record or a list of objects.
- The command reads tiledata and does not require an item with this graphic in the world. Flags describe the resource; the result does not replace a full route check.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetStaticTileData(0x0CCA);
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- Tile — numeric graphic of the selected table.
- data[2] contains the name. Length check separates a full entry from a short entry of invalid graphic.
var data = UO.GetStaticTileData(0x0CCA);
if (Truth(ArrayLength(data) == 17))
{
UO.Print(data[2]);
}
else
{
UO.Print("Tiledata entry is unavailable");
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- data[11] is a separate impassable field: 1 (condition met), 0 (condition not met).
- This check does not take into account other objects in the cell or the character's abilities.
return RunScenario();
object? RunScenario()
{
var data = UO.GetStaticTileData(0x0CCA);
if (Truth(ArrayLength(data) == 17))
{
if (Truth(data[11]))
{
UO.Print("Impassable flag is set");
}
else
{
UO.Print("Impassable flag is not set");
}
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- data[0] repeats the transmitted graphic, data[1] is a general flag mask.
- The mask can contain several bits at the same time; its numeric value is not serial.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var data = UO.GetStaticTileData(0x0CCA);
if (Truth(ArrayLength(data) == 17))
{
UO.Print("Graphic: " + Convert.ToString(data[0]));
UO.Print("Flags: " + Convert.ToString(data[1]));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: tile (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.BuildTileData:BuildTileData(1, Arg(0)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Internal implementation code; this is not a standalone script.
case "getstatictiledata":
return BuildTileData(1, Arg(0));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetStaticTiles(object? x, object? y, object? map);Reads entries above the ground in one cell of the current map.
-
x— X cell of the currently loaded map; world coordinate, not position inside the gump. -
y— Y cell of the currently loaded map; world coordinate, not position inside the gump. -
map— Card number. If this argument is not present in the selected form, the current map is used. The real client only reads tiles from the currently loaded map.
Array is a flat sequence of int-triples [graphic0, z0, hue0, graphic1, z1, hue1, …]. The number of entries is equal to the length of the array / 3. For writing, i graphic is in [i*3], Z is in [i*3+1], hue is in [i*3+2]. An empty array means no entries or an inaccessible card/cell. Serial and layer number are not returned here.
- The data refers to the currently loaded map. Another card or unreachable cell results in an empty array. Direct tile queries may additionally report map mismatches; GetWorldCell and GetWorldTilesArray immediately return an empty array without such a message.
- Array indices start with 0. Check ArrayLength before reading the field. Z stands for world altitude; layer is the equipment property from tiledata, and index is the serial number of the cell entry.
- The current bridge lists Static, Multi and world Items in the cell chain. The name of the command does not limit the result solely to statics.mul entries. The chain order does not guarantee Z sort.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetStaticTiles(UO.GetX(), UO.GetY(), UO.WorldNum());
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- x/y/map selects the current cell.
- The length of the array is the number of fields. Dividing by 3 gives the number of entries.
var tiles = UO.GetStaticTiles(UO.GetX(), UO.GetY(), UO.WorldNum());
var count = ArrayLength(tiles) / 3;
UO.Print("Tile records: " + Convert.ToString(count));
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;Parameters and execution flow:
- offset is the index of the first field of the next triple, increased by 3.
- The offset+2 check protects the entire record from being read.
return RunScenario();
object? RunScenario()
{
var tiles = UO.GetStaticTiles(UO.GetX(), UO.GetY(), UO.WorldNum());
var offset = 0;
while (Truth(offset + 2 < ArrayLength(tiles)))
{
UO.Print("Type: " + Convert.ToString(tiles[offset]) + ", Z: " + Convert.ToString(tiles[offset + 1]));
offset = offset + 3;
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- x+1 selects an adjacent cell.
- tiles[2] — color of the first entry; This is not the third tile.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var tiles = UO.GetStaticTiles(UO.GetX() + 1, UO.GetY(), UO.WorldNum());
if (Truth(ArrayLength(tiles) >= 3))
{
var hue = tiles[2];
UO.Print("First tile hue: " + Convert.ToString(hue));
}
else
{
UO.Print("No tile records");
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: x (Any), y (Any), map (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetStaticTiles. -
InjectionScript.Runtime.InjectionApiUO.ToArray:ToArray(bridge.GetStaticTiles(NumberConversions.ToInt(x), NumberConversions.ToInt(y), NumberConversions.ToInt(map))). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetStaticTiles:bridge.GetStaticTiles(NumberConversions.ToInt(x), NumberConversions.ToInt(y), NumberConversions.ToInt(map)). -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(x).
Internal implementation code; this is not a standalone script.
public InjectionValue GetStaticTiles(InjectionValue x, InjectionValue y, InjectionValue map)
=> ToArray(bridge.GetStaticTiles(NumberConversions.ToInt(x), NumberConversions.ToInt(y), NumberConversions.ToInt(map)));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetStaticTilesArray(object? xmin, object? ymin, object? xmax, object? ymax, object? worldNum, object? tileType);Searches for Static/Multi/Item entries by graphic/type in a rectangle.
-
xmin— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
ymin— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
xmax— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
ymax— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
worldNum— Map/facet 0..255; use UO.WorldNum(). Another map gives an empty Array. If the map changes between chunks, the partial result is discarded. -
tileType— One graphic/type of tile, usually 0..65535; this is not serial. 0 is the exact graphic 0, -1 does not mean any type. A mismatched type gives an empty result.
Array of entries [graphic, X, Y, Z, hue]; all fields are int. graphic - type, Z - base, hue - color. Multiple cell entries remain separate. No matches: empty Array. The quantity is ArrayLength(result), not the result itself. The indices start with 0. This is not a bool, serial or Pascal record; there is no seventh output parameter.
- Local data is read. Search does not change FindItem/FindCount and does not perform a move, target, or network command.
- Order: X ascending, within X - Y ascending. Records of one cell preserve the order of bridge; it is not sorted by distance or height.
- The search is processed in chunks of up to 32 cells with a soft budget of about 1 ms. Cancellation is checked between servings. A complex cell or cold read may go over budget. It is better to divide a large area; the world can change while reading.
- The current client's Static branch includes Static, Multi and Item from the cell, including loaded items on the ground; Land and Mobile are not included. It is wider than the classic selection of only static files.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetStaticTilesArray(UO.GetX(), UO.GetY(), UO.GetX() + 2, UO.GetY() + 2, UO.WorldNum(), 0x0CCA);
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- x/y — position self, map — current map. The region 3×3 includes the boundaries. In Ex two type are transmitted, in normal form one. Change the samples to suit your resources; this is a graphic, not a ID object.
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var rows = UO.GetStaticTilesArray(x, y, x + 2, y + 2, map, 0x0CCA);
UO.Print("Records: " + Convert.ToString(ArrayLength(rows)));
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;Parameters and execution flow:
- The region 2×2 is transferred from the larger angle to the smaller one. The algorithm itself normalizes the boundaries. row - one record; PrintTile is declared in its entirety and only formats numbers, without moving anything. graphic - type, x/y - coordinates, z - height, hue - color. For land, a conditional hue=0 is passed: there is no color field in the land record.
return RunScenario();
object? RunScenario()
{
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var rows = UO.GetStaticTilesArray(x + 1, y + 1, x, y, map, 0x0CCA);
var i = 0;
while (Truth(i < ArrayLength(rows)))
{
var row = rows[i];
PrintTile(row[0], row[1], row[2], row[3], row[4]);
i = i + 1;
}
return null;
}
void PrintTile(dynamic graphic, dynamic x, dynamic y, dynamic z, dynamic hue)
{
UO.Print("Type=" + Convert.ToString(graphic) + " X=" + Convert.ToString(x) + " Y=" + Convert.ToString(y));
UO.Print("Z=" + Convert.ToString(z) + " hue=" + Convert.ToString(hue));
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- No more than three searches for one cell; between attempts WaitAsync(250). Each call creates a new result. Zero length means there are no matches now, rather than the object being permanently missing from the server.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var attempt = 0;
while (Truth(attempt < 3))
{
var rows = UO.GetStaticTilesArray(x, y, x, y, map, 0x0CCA);
UO.Print("Records: " + Convert.ToString(ArrayLength(rows)));
attempt = attempt + 1;
await Delay(250);
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
UO.GetStaticTilesArray(xmin, ymin, xmax, ymax, worldNum, tileType) — UO.GetStaticTilesArray(Any,Any,Any,Any,Any,Any)
Parameters: xmin (Any), ymin (Any), xmax (Any), ymax (Any), worldNum (Any), tileType (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.FindPortableTiles:FindPortableTiles(Arg(0), Arg(1), Arg(2), Arg(3), Arg(4), new[] { Arg(5) }, true). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Internal implementation code; this is not a standalone script.
case "getstatictilesarray":
return FindPortableTiles(Arg(0), Arg(1), Arg(2), Arg(3), Arg(4), new[] { Arg(5) }, true);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetStaticTilesArrayEx(object? xmin, object? ymin, object? xmax, object? ymax, object? worldNum, object? tileTypes);Searches for Static/Multi/Item entries by graphic/type in a rectangle.
-
xmin— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
ymin— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
xmax— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
ymax— World coordinates of two angles, inclusive; 0..65535. The rearranged angles are normalized. Area no more than 1 000 000 cells; invalid boundaries cause a script error before the map is read. -
worldNum— Map/facet 0..255; use UO.WorldNum(). Another map gives an empty Array. If the map changes between chunks, the partial result is discarded. -
tileTypes— Array of numeric graphic/type; every matching type is included. Repeating type does not duplicate entries. A scalar is also accepted as one type. An empty Array means all type; an array of one 0 searches only 0.
Array of entries [graphic, X, Y, Z, hue]; all fields are int. graphic - type, Z - base, hue - color. Multiple cell entries remain separate. No matches: empty Array. The quantity is ArrayLength(result), not the result itself. The indices start with 0. This is not a bool, serial or Pascal record; there is no seventh output parameter.
- Local data is read. Search does not change FindItem/FindCount and does not perform a move, target, or network command.
- Order: X ascending, within X - Y ascending. Records of one cell preserve the order of bridge; it is not sorted by distance or height.
- The search is processed in chunks of up to 32 cells with a soft budget of about 1 ms. Cancellation is checked between servings. A complex cell or cold read may go over budget. It is better to divide a large area; the world can change while reading.
- The current client's Static branch includes Static, Multi and Item from the cell, including loaded items on the ground; Land and Mobile are not included. It is wider than the classic selection of only static files.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetStaticTilesArrayEx(UO.X(), UO.Y(), UO.X() + 1, UO.Y() + 1, UO.WorldNum(), new[] { 0x0CCA });
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- x/y — position self, map — current map. The region 3×3 includes the boundaries. In Ex two type are transmitted, in normal form one. Change the samples to suit your resources; this is a graphic, not a ID object.
dynamic[] types = new dynamic[checked((int)(1) + 1)];
types[0] = 0x0CCA;
types[1] = 0x0CCB;
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var rows = UO.GetStaticTilesArrayEx(x, y, x + 2, y + 2, map, types);
UO.Print("Records: " + Convert.ToString(ArrayLength(rows)));
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;Parameters and execution flow:
- The region 2×2 is transferred from the larger angle to the smaller one. The algorithm itself normalizes the boundaries. row - one record; PrintTile is declared in its entirety and only formats numbers, without moving anything. graphic - type, x/y - coordinates, z - height, hue - color. For land, a conditional hue=0 is passed: there is no color field in the land record.
return RunScenario();
object? RunScenario()
{
dynamic[] types = new dynamic[checked((int)(1) + 1)];
types[0] = 0x0CCA;
types[1] = 0x0CCB;
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var rows = UO.GetStaticTilesArrayEx(x + 1, y + 1, x, y, map, types);
var i = 0;
while (Truth(i < ArrayLength(rows)))
{
var row = rows[i];
PrintTile(row[0], row[1], row[2], row[3], row[4]);
i = i + 1;
}
return null;
}
void PrintTile(dynamic graphic, dynamic x, dynamic y, dynamic z, dynamic hue)
{
UO.Print("Type=" + Convert.ToString(graphic) + " X=" + Convert.ToString(x) + " Y=" + Convert.ToString(y));
UO.Print("Z=" + Convert.ToString(z) + " hue=" + Convert.ToString(hue));
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- No more than three searches for one cell; between attempts WaitAsync(250). Each call creates a new result. Zero length means there are no matches now, rather than the object being permanently missing from the server.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
dynamic[] types = new dynamic[checked((int)(1) + 1)];
types[0] = 0x0CCA;
types[1] = 0x0CCB;
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var attempt = 0;
while (Truth(attempt < 3))
{
var rows = UO.GetStaticTilesArrayEx(x, y, x, y, map, types);
UO.Print("Records: " + Convert.ToString(ArrayLength(rows)));
attempt = attempt + 1;
await Delay(250);
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
UO.GetStaticTilesArrayEx(xmin, ymin, xmax, ymax, worldNum, tileTypes) — UO.GetStaticTilesArrayEx(Any,Any,Any,Any,Any,Any)
Parameters: xmin (Any), ymin (Any), xmax (Any), ymax (Any), worldNum (Any), tileTypes (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.FindPortableTiles:FindPortableTiles(Arg(0), Arg(1), Arg(2), Arg(3), Arg(4), ArrayArg(5), true). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::ArrayArg:ArrayArg(5).
Internal implementation code; this is not a standalone script.
case "getstatictilesarrayex":
return FindPortableTiles(Arg(0), Arg(1), Arg(2), Arg(3), Arg(4), ArrayArg(5), true);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetSurfaceZ(object? x, object? y, object? worldNum);Reads the average height of the ground surface in a cell.
-
x— World coordinate X of the cell of the current map, not the position in the gump. -
y— World Y coordinate of the current map cell. -
worldNum— Card/facet number; use UO.WorldNum(). Only the currently loaded card is read.
int — Land.AverageZ, including negative height and 0. If there is no map/ground or a map mismatch, 0 is returned, so this value does not distinguish missing data from the true height 0. This is not bool, the floor or the height of the nearest static.
- The command reads the local map and does not trigger movement or target. A cell outside the size of the map is not replaced by a cell in an adjacent column.
- Z height, graphic/type, hue color, flags and equipment layer have different meanings. Null graphic or Z=0 may be valid data; check the result form.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetSurfaceZ(UO.GetX(), UO.GetY(), UO.WorldNum());
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- All three parameters relate to the current cell of the map. z is a numerical height, not the result of movement.
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var z = UO.GetSurfaceZ(x, y, map);
UO.Print("Average land Z: " + Convert.ToString(z));Parameters and execution flow:
- GetMapCell is needed to distinguish missing data from height 0. The map may still change between two calls.
return RunScenario();
object? RunScenario()
{
var x = UO.GetX() + 1;
var y = UO.GetY();
var map = UO.WorldNum();
var cell = UO.GetMapCell(x, y, map);
if (Truth(ArrayLength(cell) == 3))
{
UO.Print("Average: " + Convert.ToString(UO.GetSurfaceZ(x, y, map)));
}
else
{
UO.Print("No land data");
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The difference shows the slope of the earth. This example does not move anything and does not calculate the route.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var x = UO.GetX();
var y = UO.GetY();
var map = UO.WorldNum();
var a = UO.GetMapCell(x, y, map);
var b = UO.GetMapCell(x + 1, y, map);
if (Truth(ArrayLength(a) == 3) && Truth(ArrayLength(b) == 3))
{
var difference = UO.GetSurfaceZ(x + 1, y, map) - UO.GetSurfaceZ(x, y, map);
UO.Print("Average difference: " + Convert.ToString(difference));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: x (Any), y (Any), worldNum (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetSurfaceZ:bridge.GetSurfaceZ(Arg(0), Arg(1), Arg(2)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Internal implementation code; this is not a standalone script.
case "getsurfacez":
return new InjectionValue(bridge.GetSurfaceZ(Arg(0), Arg(1), Arg(2)));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetTileFlags(object? group, object? tileId);Reads the bitmask of the graphic properties from the tiledata entry.
-
group- 0 - land table; 1 - table of static graphic. The implementation considers any non-null group to be a second table; use 0 or 1. -
tileId— Graphic/type of entry in tiledata, usually an integer 0…65535. This is not a serial of an object and not an index of statics inside a cell.
int — low 32 bits of tiledata flags. The most significant bit set results in a negative sign number. 0 means the absence of these flags or invalid tileId; This is not an independent sign of an error and is not a bool. Multiple properties can be set at the same time.
- This command reads the graphic help entry; world coordinates are not needed. group=0 and group=1 select different tables even if tileId is the same.
- The property is read from the graphic data, not from the current state of a particular item.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetTileFlags(1, 0x0CCA);
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- group=1 selects static tiledata; tileId=0x0CCA - graphic tree.
- value contains the result described in the Returns section; its meaning does not coincide with serial.
var value = UO.GetTileFlags(1, 0x0CCA);
if (Truth((Convert.ToUInt64(value) & 0x40UL) != 0))
{
UO.Print("Impassable flag is set");
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- FindType returns serial. GetType turns it into a numeric graphic.
- group=1 is used for items; in tileId graphic is transmitted, not item.
return RunScenario();
object? RunScenario()
{
var item = UO.FindType(0x0EED, -1, "backpack");
if (Truth(item != ""))
{
var graphic = UO.GetType(item);
var value = UO.GetTileFlags(1, graphic);
UO.Print(Convert.ToString(value));
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The first two arguments GetLandscapeTile are the current world X/Y; the third is the current map.
- land[0] contains a graphic of land. group=0 selects land tiledata. For GetTileLayer/GetTileHeight the ground gives 0.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var land = UO.GetLandscapeTile(UO.GetX(), UO.GetY(), UO.WorldNum());
if (Truth(ArrayLength(land) >= 3))
{
var graphic = land[0];
var value = UO.GetTileFlags(0, graphic);
UO.Print(Convert.ToString(value));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: group (Any), tileId (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetTileFlags. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetTileFlags:bridge.GetTileFlags(NumberConversions.ToInt(group), NumberConversions.ToInt(tileId)). -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(group).
Internal implementation code; this is not a standalone script.
public InjectionValue GetTileFlags(InjectionValue group, InjectionValue tileId)
=> new InjectionValue(unchecked((int)bridge.GetTileFlags(NumberConversions.ToInt(group), NumberConversions.ToInt(tileId))));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.GetTileHeight(object? group, object? tileId);Reads the height of graphic from the tiledata entry.
-
group- 0 - land table; 1 - table of static graphic. The implementation considers any non-null group to be a second table; use 0 or 1. -
tileId— Graphic/type of entry in tiledata, usually an integer 0…65535. This is not a serial of an object and not an index of statics inside a cell.
int is the height of the graphic in Z units from tiledata. This is the height size of the graphic, not the world coordinate of its base Z. For ground, missing entry, or zero height, 0 is returned. Height in itself does not prove cross-country ability.
- This command reads the graphic help entry; world coordinates are not needed. group=0 and group=1 select different tables even if tileId is the same.
- The property is read from the graphic data, not from the current state of a particular item.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
var result = UO.GetTileHeight(1, 0x0CCA);
UO.Print("GetTileHeight: " + Convert.ToString(result));Parameters and execution flow:
- group=1 selects static tiledata; tileId=0x0CCA - graphic tree.
- value contains the result described in the Returns section; its meaning does not coincide with serial.
var value = UO.GetTileHeight(1, 0x0CCA);
UO.Print("Tiledata height: " + Convert.ToString(value));Parameters and execution flow:
- FindType returns serial. GetType turns it into a numeric graphic.
- group=1 is used for items; in tileId graphic is transmitted, not item.
return RunScenario();
object? RunScenario()
{
var item = UO.FindType(0x0EED, -1, "backpack");
if (Truth(item != ""))
{
var graphic = UO.GetType(item);
var value = UO.GetTileHeight(1, graphic);
UO.Print(Convert.ToString(value));
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The first two arguments GetLandscapeTile are the current world X/Y; the third is the current map.
- land[0] contains a graphic of land. group=0 selects land tiledata. For GetTileLayer/GetTileHeight the ground gives 0.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var land = UO.GetLandscapeTile(UO.GetX(), UO.GetY(), UO.WorldNum());
if (Truth(ArrayLength(land) >= 3))
{
var graphic = land[0];
var value = UO.GetTileHeight(0, graphic);
UO.Print(Convert.ToString(value));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: group (Any), tileId (Any)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetTileHeight. -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(group). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetTileDataProperties:bridge.GetTileDataProperties(tileGroup, NumberConversions.ToInt(tileId)).
Internal implementation code; this is not a standalone script.
public int GetTileHeight(InjectionValue group, InjectionValue tileId)
{
int tileGroup = NumberConversions.ToInt(group);
int[] properties = bridge.GetTileDataProperties(tileGroup, NumberConversions.ToInt(tileId)) ?? Array.Empty<int>();
return tileGroup == 0 || properties.Length < 7 ? 0 : properties[6];
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.GetTileLayer(object? group, object? tileId);Reads the equipment layer number from the tiledata entry.
-
group- 0 - land table; 1 - table of static graphic. The implementation considers any non-null group to be a second table; use 0 or 1. -
tileId— Graphic/type of entry in tiledata, usually an integer 0…65535. This is not a serial of an object and not an index of statics inside a cell.
int — graphic equipment layer number: for example 1=Rhand, 2=Lhand, 21=Backpack. For a ground, missing entry, or null layer, 0 is returned. This is not the order of statics in a cell, not a floor, and not Z.
- This command reads the graphic help entry; world coordinates are not needed. group=0 and group=1 select different tables even if tileId is the same.
- The property is read from the graphic data, not from the current state of a particular item.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
var result = UO.GetTileLayer(1, 0x0CCA);
UO.Print("GetTileLayer: " + Convert.ToString(result));Parameters and execution flow:
- group=1 selects static tiledata; tileId=0x0CCA - graphic tree.
- value contains the result described in the Returns section; its meaning does not coincide with serial.
var value = UO.GetTileLayer(1, 0x0CCA);
if (Truth(value == 1))
{
UO.Print("Right-hand graphic");
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- FindType returns serial. GetType turns it into a numeric graphic.
- group=1 is used for items; in tileId graphic is transmitted, not item.
return RunScenario();
object? RunScenario()
{
var item = UO.FindType(0x0EED, -1, "backpack");
if (Truth(item != ""))
{
var graphic = UO.GetType(item);
var value = UO.GetTileLayer(1, graphic);
UO.Print(Convert.ToString(value));
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The first two arguments GetLandscapeTile are the current world X/Y; the third is the current map.
- land[0] contains a graphic of land. group=0 selects land tiledata. For GetTileLayer/GetTileHeight the ground gives 0.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var land = UO.GetLandscapeTile(UO.GetX(), UO.GetY(), UO.WorldNum());
if (Truth(ArrayLength(land) >= 3))
{
var graphic = land[0];
var value = UO.GetTileLayer(0, graphic);
UO.Print(Convert.ToString(value));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: group (Any), tileId (Any)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetTileLayer. -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(group). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetTileDataProperties:bridge.GetTileDataProperties(tileGroup, NumberConversions.ToInt(tileId)).
Internal implementation code; this is not a standalone script.
public int GetTileLayer(InjectionValue group, InjectionValue tileId)
{
int tileGroup = NumberConversions.ToInt(group);
int[] properties = bridge.GetTileDataProperties(tileGroup, NumberConversions.ToInt(tileId)) ?? Array.Empty<int>();
return tileGroup == 0 || properties.Length < 2 ? 0 : properties[1];
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
string UO.GetTileName(object? group, object? tileId);Reads the title graphic from the tiledata entry.
-
group- 0 - land table; 1 - table of static graphic. The implementation considers any non-null group to be a second table; use 0 or 1. -
tileId— Graphic/type of entry in tiledata, usually an integer 0…65535. This is not a serial of an object and not an index of statics inside a cell.
string - name from game tiledata files. An empty string means an empty name or an invalid tileId. The name is taken from the game resources and is not automatically translated into the interface language IDE. This is not the name of a specific item from the server.
- This command reads the graphic help entry; world coordinates are not needed. group=0 and group=1 select different tables even if tileId is the same.
- The property is read from the graphic data, not from the current state of a particular item.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
var result = UO.GetTileName(1, 0x0CCA);
UO.Print("GetTileName: " + Convert.ToString(result));Parameters and execution flow:
- group=1 selects static tiledata; tileId=0x0CCA - graphic tree.
- value contains the result described in the Returns section; its meaning does not coincide with serial.
var value = UO.GetTileName(1, 0x0CCA);
if (Truth(value != ""))
{
UO.Print(value);
}
else
{
UO.Print("No tiledata name");
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- FindType returns serial. GetType turns it into a numeric graphic.
- group=1 is used for items; in tileId graphic is transmitted, not item.
return RunScenario();
object? RunScenario()
{
var item = UO.FindType(0x0EED, -1, "backpack");
if (Truth(item != ""))
{
var graphic = UO.GetType(item);
var value = UO.GetTileName(1, graphic);
UO.Print(Convert.ToString(value));
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The first two arguments GetLandscapeTile are the current world X/Y; the third is the current map.
- land[0] contains a graphic of land. group=0 selects land tiledata. For GetTileLayer/GetTileHeight the ground gives 0.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var land = UO.GetLandscapeTile(UO.GetX(), UO.GetY(), UO.WorldNum());
if (Truth(ArrayLength(land) >= 3))
{
var graphic = land[0];
var value = UO.GetTileName(0, graphic);
UO.Print(Convert.ToString(value));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: group (Any), tileId (Any)
Result: string / String.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetTileName. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetTileDataName:bridge.GetTileDataName(NumberConversions.ToInt(group), NumberConversions.ToInt(tileId)). -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(group).
Internal implementation code; this is not a standalone script.
public string GetTileName(InjectionValue group, InjectionValue tileId)
=> bridge.GetTileDataName(NumberConversions.ToInt(group), NumberConversions.ToInt(tileId));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetTileXYM(object? x, object? y, object? map, object? tileStart, object? tileEnd, object? uoPath);Reads the matching graphic ID from the object chain of the cell of the currently loaded game card.
-
x— X cell coordinate, int. -
y— Y cell coordinate, int. -
map— Card number; must match World.MapIndex, and World.Map must exist. -
tileStart— Lower enabled Graphic border. -
tileEnd— The upper included border of the Graphic. The reverse range is not rearranged and does not produce matches. -
uoPath- The compatibility parameter is converted to string, but the current bridge does not use it and does not load the other file folder UO.
Array int with flat quads [graphic,x,y,z,graphic,x,y,z,...]. The map error gives an empty array and a message; no matches also results in an empty array.
- Follows World.Map.GetTile(x,y).TNext and checks tileStart<=Graphic<=tileEnd. Object types are not filtered separately: it's a chain of cells, not just statics.
- The command reads the client's loaded geometry. Data from another map/facet is not loaded. The uoPath parameter is not used to download files; the number of entries is equal to the length of the array/4.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetTileXYM(UO.GetX(), UO.GetY(), UO.WorldNum(), 0, 65535, "");
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- Each entry takes up four int.
var tiles = UO.GetTileXYM(UO.GetX(),UO.GetY(),UO.WorldNum(),0,65535,"");
UO.Print(Convert.ToString(ArrayLength(tiles)/4));
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;Parameters and execution flow:
- The indices i and i+3 correspond to graphic and z of the same record.
return RunScenario();
object? RunScenario()
{
var tiles = UO.GetTileXYM(UO.GetX(), UO.GetY(), UO.WorldNum(), 0, 65535, "");
for (int i = (int)(0); i <= ArrayLength(tiles) - 1; i += (int)(4))
{
UO.Print(Convert.ToString(tiles[i]) + " " + Convert.ToString(tiles[i + 3]));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;Parameters and execution flow:
- The range 100..99 does not contain any graphic and gives an empty array.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var tiles = UO.GetTileXYM(UO.GetX(), UO.GetY(), UO.WorldNum(), 100, 99, "");
UO.Print(Convert.ToString(ArrayLength(tiles)));
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: x (Any), y (Any), map (Any), tileStart (Any), tileEnd (Any), uoPath (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetTileXYM. -
InjectionScript.Runtime.InjectionApiUO.ToArray:ToArray(bridge.GetTileXYM(NumberConversions.ToInt(x), NumberConversions.ToInt(y), NumberConversions.ToInt(map), NumberConversions.ToInt(tileStart), NumberConversions.ToInt(tileEnd), uoPath.ToString())). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetTileXYM:bridge.GetTileXYM(NumberConversions.ToInt(x), NumberConversions.ToInt(y), NumberConversions.ToInt(map), NumberConversions.ToInt(tileStart), NumberConversions.ToInt(tileEnd), uoPath.ToString()). -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(x). -
InjectionScript.Runtime.InjectionValue.ToString:uoPath.ToString().
Internal implementation code; this is not a standalone script.
public InjectionValue GetTileXYM(InjectionValue x, InjectionValue y, InjectionValue map, InjectionValue tileStart, InjectionValue tileEnd, InjectionValue uoPath)
=> ToArray(bridge.GetTileXYM(NumberConversions.ToInt(x), NumberConversions.ToInt(y), NumberConversions.ToInt(map), NumberConversions.ToInt(tileStart), NumberConversions.ToInt(tileEnd), uoPath.ToString()));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
string UO.GetUserStatic(object? id);Reads a saved user static record.
-
id- int ID received by AddUserStatic; not graphic/type and not serial of the world.
string — saved serialized record; unknown ID gives an empty string.
- state.UserStatics.TryGetValue returns the string without parsing it. Geometric notation - "graphic|x|y|z|hue|map"; old text entries may be different text.
- Reads the current local state. There is no package, target or automatic update; individual reads may see different states.
- In a regular client host, this state data is taken from the GetPersistentState manager and is common to scripts/chat/macros of the same world/profile, and does not belong to one script. Another process or an apparently separate InjectionRuntimeState has a different state. Loading/clearing a profile can replace it; saved serial are still checked against the loaded world.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
var result = UO.GetUserStatic(1);
UO.Print("GetUserStatic: " + Convert.ToString(result));Parameters and execution flow:
- Reads a saved user static record.
UO.Print(UO.GetUserStatic(1));Parameters and execution flow:
- state.UserStatics.TryGetValue returns the string without parsing it. Geometric notation - "graphic|x|y|z|hue|map"; old text entries may be different text.
return RunScenario();
object? RunScenario()
{
if (Truth(UO.UserStaticExists(1)))
{
UO.Print(UO.GetUserStatic(1));
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- Reads the current local state. There is no package, target or automatic update; individual reads may see different states.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var records = UO.GetUserStatics();
if (Truth(UO.GetArrayLength(records) > 0))
{
UO.Print(UO.GetUserStatic(records[0][0]));
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: id (Any)
Result: string / String.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetUserStatic. -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(id).
Internal implementation code; this is not a standalone script.
public string GetUserStatic(InjectionValue id)
=> state.UserStatics.TryGetValue(NumberConversions.ToInt(id), out string value) ? value : string.Empty;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetUserStatics();Reads state.UserStatics.
There are no parameters.
Array of strings [id, serializedText], sorted by id. Each id is int, serializedText is string; an empty dictionary gives an empty array.
- Reads state.UserStatics. The geometric notation is stored as "graphic|x|y|z|hue|map"; older text entries AddUserStatic may have a different format. These are local user entries, not all static maps.
- Reads the current local state. There is no package, target or automatic update; individual reads may see different states.
- In a regular client host, this state data is taken from the GetPersistentState manager and is common to scripts/chat/macros of the same world/profile, and does not belong to one script. Another process or an apparently separate InjectionRuntimeState has a different state. Loading/clearing a profile can replace it; saved serial are still checked against the loaded world.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetUserStatics();
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- Reads state.UserStatics.
var records = UO.GetUserStatics();
UO.Print(UO.GetArrayLength(records));Parameters and execution flow:
- Reads state.UserStatics. The geometric notation is stored as "graphic|x|y|z|hue|map"; older text entries AddUserStatic may have a different format. These are local user entries, not all static maps.
return RunScenario();
object? RunScenario()
{
var records = UO.GetUserStatics();
if (Truth(UO.GetArrayLength(records) > 0))
{
UO.Print(records[0][0]);
UO.Print(records[0][1]);
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- Reads the current local state. There is no package, target or automatic update; individual reads may see different states.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var before = UO.GetUserStatics();
UO.Wait(500);
var after = UO.GetUserStatics();
UO.Print(before);
UO.Print(after);
return null;
}
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: No parameters.
Result: dynamic / Any.
During a call:
Internal implementation code; this is not a standalone script.
public InjectionValue GetUserStatics()
=> new InjectionValue(state.UserStatics.OrderBy(pair => pair.Key)
.Select(pair => new InjectionValue(new[] { new InjectionValue(pair.Key), new InjectionValue(pair.Value) }))
.ToArray());Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetWorldCell(object? x, object? y);
dynamic UO.GetWorldCell(object? x, object? y, object? map);Reads extended ground records, above ground records, and loaded world items in the selected area.
-
x— X cell of the currently loaded map; world coordinate, not position inside the gump. -
y— Y cell of the currently loaded map; world coordinate, not position inside the gump. -
map— Card number. If this argument is not present in the selected form, the current map is used. The real client only reads tiles from the currently loaded map.
Array of records. Each result[i] element has the following format:
Array of 11 fields of one record; indices start with 0:
-
[0] kind— string: "land", "static", or "object". -
[1] serial— int: serial of a dynamic item; for land/static is 0. -
[2] graphic— int: graphics type. -
[3] x,[4] y- int: world coordinates of the cell. -
[5] z- int: the height of the base in the world. -
[6] hue- int: color, near the ground 0. -
[7] flags- int: low 32 bits of tiledata flags. -
[8] name— string: name from tiledata. -
[9] layer- int: layer of equipment from tiledata, near the ground 0; not a static index. -
[10] height- int: graphic height from tiledata, near the ground 0; not the Z coordinate.
ArrayLength(result) - the number of records, not the number of cells and not the number of route steps. The result may be empty. One x/y can have several entries with different Z. The entry "object" has serial; the entry "static" does not have a usable serial.
- The data refers to the currently loaded map. Another card or unreachable cell results in an empty array. Direct tile queries may additionally report map mismatches; GetWorldCell and GetWorldTilesArray immediately return an empty array without such a message.
- Array indices start with 0. Check ArrayLength before reading the field. Z stands for world altitude; layer is the equipment property from tiledata, and index is the serial number of the cell entry.
- The static part uses GetStaticTiles: its current selection also includes Multi/Item. A World Item may additionally be present as an "object" with serial; Don't treat each entry as a unique item.
- GetWorldTilesArray limits the region of 1 000 000 cells. Exceeding or coordinates outside 0…65535/map outside 0…255 causes a command error rather than a partial array. For frequent polling, choose a small area.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetWorldCell(UO.GetX(), UO.GetY());
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- GetWorldCell reads one cell; GetWorldTilesArray in this example reads the square 3×3 with borders enabled.
- cells[i] is a nested array. tile[0] - category, [2] - graphic, [5] - Z.
var cells = UO.GetWorldCell(UO.GetX(), UO.GetY());
var i = 0;
while (Truth(i < ArrayLength(cells)))
{
var tile = cells[i];
UO.Print(tile[0] + ": " + Convert.ToString(tile[2]) + ", Z=" + Convert.ToString(tile[5]));
i = i + 1;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The area is selected by coordinates, not by container.
- The kind="object" check separates serial items from ground/static; [1] contains serial.
return RunScenario();
object? RunScenario()
{
var cells = UO.GetWorldCell(UO.GetX(), UO.GetY());
var i = 0;
while (Truth(i < ArrayLength(cells)))
{
var tile = cells[i];
if (Truth(tile[0] == "object"))
{
UO.Print("Object serial: " + Convert.ToString(tile[1]));
}
i = i + 1;
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- tile[5] and GetZ() are compared in the same world height units.
- Equality Z filters the base, but does not mean passability or matching of the entire floor.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var cells = UO.GetWorldCell(UO.GetX(), UO.GetY());
var i = 0;
while (Truth(i < ArrayLength(cells)))
{
var tile = cells[i];
if (Truth(tile[5] == UO.GetZ()))
{
UO.Print(tile[8]);
}
i = i + 1;
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: x (Any), y (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetWorldCell. -
InjectionScript.Runtime.InjectionApiUO.GetWorldCell:GetWorldCell(x, y, new InjectionValue(bridge.WorldNumber)). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.WorldNumber:bridge.WorldNumber.
Internal implementation code; this is not a standalone script.
public InjectionValue GetWorldCell(InjectionValue x, InjectionValue y)
=> GetWorldCell(x, y, new InjectionValue(bridge.WorldNumber));Parameters: x (Any), y (Any), map (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetWorldCell. -
InjectionScript.Runtime.InjectionApiUO.BuildWorldCell:BuildWorldCell(NumberConversions.ToInt(x), NumberConversions.ToInt(y), NumberConversions.ToInt(map), true). -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(x).
Internal implementation code; this is not a standalone script.
public InjectionValue GetWorldCell(InjectionValue x, InjectionValue y, InjectionValue map)
=> BuildWorldCell(NumberConversions.ToInt(x), NumberConversions.ToInt(y), NumberConversions.ToInt(map), true);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.GetWorldNum();Reads the current card number from the client model.
There are no parameters.
int — index of the client's current card, usually 0=Felucca, 1=Trammel, 2=Ilshenar, 3=Malas, 4=Tokuno, 5=Ter Mur. The user server may use a different set of cards. 0 is a full-fledged map, not a sign of an error.
- Already received local data is read. The request does not open status and does not force the server to send an update. After death, map transition, or object deletion, the values may change between two calls.
- C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
var result = UO.GetWorldNum();
UO.Print("GetWorldNum: " + Convert.ToString(result));Parameters and execution flow:
- A call without arguments refers to self. The current card number is stored in value.
- Convert.ToString converts the number to be output and does not change the meaning of the result.
var value = UO.GetWorldNum();
UO.Print("GetWorldNum: " + Convert.ToString(value));Parameters and execution flow:
- The value is read once without any arguments. The current card number is used in the calculation or condition shown.
- Numerical thresholds are examples of script conditions and not new client limits. The field stores the server units and restrictions described above.
return RunScenario();
object? RunScenario()
{
var value = UO.GetWorldNum();
var land = UO.GetLandscapeTile(UO.GetX(), UO.GetY(), value);
UO.Print("Land record length: " + Convert.ToString(ArrayLength(land)));
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;Parameters and execution flow:
- Both calls without an argument read their current value. UO.Wait(1000) gives a pause in milliseconds between shots.
- The change compared is the number of the current card. An example does not change anything in the world and does not wait endlessly. Events within this second may be missed.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
var before = UO.GetWorldNum();
await Delay(1000);
var after = UO.GetWorldNum();
if (Truth(before != after))
{
UO.Print("Before: " + Convert.ToString(before) + "; after: " + Convert.ToString(after));
}
return null;
}
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: No parameters.
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.RegisterCharacterGetterAliases [GetWorldNum]. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.WorldNumber:bridge.WorldNumber.
The call executes the stored handler delegate. The registration method creates this delegate while building the API.
Internal implementation code; this is not a standalone script.
() => bridge.WorldNumberAPI creation: These functions register the API. They do not run again for every command call.
Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetWorldTilesArray(object? minX, object? minY, object? maxX, object? maxY, object? map);Reads extended ground records, above ground records, and loaded world items in the selected area.
-
minX— The first X border of the rectangle, included; 0…65535. -
minY— The first Y border of the rectangle, included; 0…65535. -
maxX— Second included boundary X; the smaller/larger of the two X's is selected automatically. -
maxY— Second included boundary Y; the smaller/larger of the two Y's is selected automatically. -
map— Card number. If this argument is not present in the selected form, the current map is used. The real client only reads tiles from the currently loaded map.
Array of records. Each result[i] element has the following format:
Array of 11 fields of one record; indices start with 0:
-
[0] kind— string: "land", "static", or "object". -
[1] serial— int: serial of a dynamic item; for land/static is 0. -
[2] graphic— int: graphics type. -
[3] x,[4] y- int: world coordinates of the cell. -
[5] z- int: the height of the base in the world. -
[6] hue- int: color, near the ground 0. -
[7] flags- int: low 32 bits of tiledata flags. -
[8] name— string: name from tiledata. -
[9] layer- int: layer of equipment from tiledata, near the ground 0; not a static index. -
[10] height- int: graphic height from tiledata, near the ground 0; not the Z coordinate.
ArrayLength(result) - the number of records, not the number of cells and not the number of route steps. The result may be empty. One x/y can have several entries with different Z. The entry "object" has serial; the entry "static" does not have a usable serial.
- The data refers to the currently loaded map. Another card or unreachable cell results in an empty array. Direct tile queries may additionally report map mismatches; GetWorldCell and GetWorldTilesArray immediately return an empty array without such a message.
- Array indices start with 0. Check ArrayLength before reading the field. Z stands for world altitude; layer is the equipment property from tiledata, and index is the serial number of the cell entry.
- The static part uses GetStaticTiles: its current selection also includes Multi/Item. A World Item may additionally be present as an "object" with serial; Don't treat each entry as a unique item.
- GetWorldTilesArray limits the region of 1 000 000 cells. Exceeding or coordinates outside 0…65535/map outside 0…255 causes a command error rather than a partial array. For frequent polling, choose a small area.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.GetWorldTilesArray(UO.GetX() - 1, UO.GetY() - 1, UO.GetX() + 1, UO.GetY() + 1, UO.WorldNum());
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- GetWorldCell reads one cell; GetWorldTilesArray in this example reads the square 3×3 with borders enabled.
- cells[i] is a nested array. tile[0] - category, [2] - graphic, [5] - Z.
var cells = UO.GetWorldTilesArray(UO.GetX() - 1, UO.GetY() - 1, UO.GetX() + 1, UO.GetY() + 1, UO.WorldNum());
var i = 0;
while (Truth(i < ArrayLength(cells)))
{
var tile = cells[i];
UO.Print(tile[0] + ": " + Convert.ToString(tile[2]) + ", Z=" + Convert.ToString(tile[5]));
i = i + 1;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- The area is selected by coordinates, not by container.
- The kind="object" check separates serial items from ground/static; [1] contains serial.
return RunScenario();
object? RunScenario()
{
var cells = UO.GetWorldTilesArray(UO.GetX() - 1, UO.GetY() - 1, UO.GetX() + 1, UO.GetY() + 1, UO.WorldNum());
var i = 0;
while (Truth(i < ArrayLength(cells)))
{
var tile = cells[i];
if (Truth(tile[0] == "object"))
{
UO.Print("Object serial: " + Convert.ToString(tile[1]));
}
i = i + 1;
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- tile[5] and GetZ() are compared in the same world height units.
- Equality Z filters the base, but does not mean passability or matching of the entire floor.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var cells = UO.GetWorldTilesArray(UO.GetX() - 1, UO.GetY() - 1, UO.GetX() + 1, UO.GetY() + 1, UO.WorldNum());
var i = 0;
while (Truth(i < ArrayLength(cells)))
{
var tile = cells[i];
if (Truth(tile[5] == UO.GetZ()))
{
UO.Print(tile[8]);
}
i = i + 1;
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: minX (Any), minY (Any), maxX (Any), maxY (Any), map (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetWorldTilesArray. -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(minX). -
InjectionScript.Runtime.InjectionApiUO.BuildWorldCell:BuildWorldCell(cellX, cellY, world, false). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetWorldItems:bridge.GetWorldItems(). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetX:bridge.GetX(serial). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetY:bridge.GetY(serial). -
InjectionScript.Runtime.InjectionApiUO.BuildWorldTileRecord:BuildWorldTileRecord("object", serial, bridge.GetGraphics(serial), objectX, objectY, bridge.GetZ(serial), bridge.GetColor(serial), 1). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetGraphics:bridge.GetGraphics(serial). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetZ:bridge.GetZ(serial). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetColor:bridge.GetColor(serial). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.WorldNumber:bridge.WorldNumber.
Internal implementation code; this is not a standalone script.
public InjectionValue GetWorldTilesArray(InjectionValue minX, InjectionValue minY, InjectionValue maxX, InjectionValue maxY, InjectionValue map)
{
int firstX = Math.Min(NumberConversions.ToInt(minX), NumberConversions.ToInt(maxX));
int lastX = Math.Max(NumberConversions.ToInt(minX), NumberConversions.ToInt(maxX));
int firstY = Math.Min(NumberConversions.ToInt(minY), NumberConversions.ToInt(maxY));
int lastY = Math.Max(NumberConversions.ToInt(minY), NumberConversions.ToInt(maxY));
int world = NumberConversions.ToInt(map);
if (firstX < 0 || firstY < 0 || lastX > ushort.MaxValue || lastY > ushort.MaxValue
|| world < 0 || world > byte.MaxValue)
throw new NativeSubrutineException("World tile coordinates must be 0..65535 and the map must be 0..255.");
if (((long)lastX - firstX + 1) * ((long)lastY - firstY + 1) > 1_000_000L)
throw new NativeSubrutineException("World tile array is limited to 1,000,000 cells per call.");
// Live world items have no per-result map field. Never combine the
// current world's items with a request for a different map, or scan
// every cell only to report the same unloaded-map failure repeatedly.
if (world != bridge.WorldNumber)
return new InjectionValue(Array.Empty<InjectionValue>());
var result = new List<InjectionValue>();
for (int cellX = firstX; cellX <= lastX; cellX++)
for (int cellY = firstY; cellY <= lastY; cellY++)
{
InjectionValue cell = BuildWorldCell(cellX, cellY, world, false);
if (cell.Kind == InjectionValueKind.Array)
result.AddRange(cell.Array);
}
foreach (int serial in bridge.GetWorldItems() ?? Array.Empty<int>())
{
int objectX = bridge.GetX(serial);
int objectY = bridge.GetY(serial);
if (objectX >= firstX && objectX <= lastX && objectY >= firstY && objectY <= lastY)
result.Add(BuildWorldTileRecord("object", serial, bridge.GetGraphics(serial), objectX, objectY,
bridge.GetZ(serial), bridge.GetColor(serial), 1));
}
return new InjectionValue(result.ToArray());
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.GetX();
int UO.GetX(object? id);Reads the X field of the loaded object or current character.
-
id— Serial/ID of the object, not the graphic/type. A number, a hex string, the standard name self/backpack/lasttarget/lastobject/lastcontainer/laststatus/finditem/lastcorpse, or the name AddObject. The alias must be set; existence is checked by Exists. The registered form without arguments uses self.
int is the X coordinate. For an unknown object, 0 is returned. Zero is also a valid coordinate. Measured in cells for world objects; These are not screen pixels.
- The latest data already known to the client is read; the update request is not sent to the server.
- An unknown object and a property that has not yet been retrieved can have a null/empty value. Check Exists and conditions for a specific action.
- For a character or object on the ground, this is the world coordinate. The item inside the container has an X/Y position inside the gump; the command does not translate them into the owner's world coordinates.
- The current coordinate of the object is read. Pending steps are not converted into route calculations by this command.
int x = UO.GetX();
UO.Print($"X = {x}");Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
var result = UO.GetX();
UO.Print("GetX: " + Convert.ToString(result));Parameters and execution flow:
- The form without an argument selects self, the current character.
- position contains the X coordinate, not serial.
var position = UO.GetX();
UO.Print("X: " + Convert.ToString(position));Parameters and execution flow:
- lasttarget should point to the loaded character or item on the ground.
- delta — difference along one axis. It is not the length of the route; the value may be negative.
return RunScenario();
object? RunScenario()
{
var other = UO.GetSerial("lasttarget");
if (Truth(UO.Exists(other)))
{
var delta = UO.GetX(other) - UO.GetX();
UO.Print("Difference: " + Convert.ToString(delta));
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- id="self" is an explicit form of character selection. UO.Wait=500 milliseconds.
- The comparison shows the change in the X axis only. Changes in the other axis or rotation are not taken into account here.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
var before = UO.GetX("self");
await Delay(500);
var after = UO.GetX("self");
if (Truth(before != after))
{
UO.Print("Coordinate changed");
}
return null;
}
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: No parameters.
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetX. -
InjectionScript.Runtime.InjectionApiUO.GetX:GetX("self").
Internal implementation code; this is not a standalone script.
public int GetX() => GetX("self");Parameters: id (Any/Integer/String)
Result: int / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetX:bridge.GetX(Arg(0, bridge.Self)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0, bridge.Self). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.Self:bridge.Self.
Internal implementation code; this is not a standalone script.
case "getx": return new InjectionValue(bridge.GetX(Arg(0, bridge.Self)));Parameters: id (Any/Integer/String)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetX. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetX:bridge.GetX(id).
Internal implementation code; this is not a standalone script.
public int GetX(int id) => bridge.GetX(id);Parameters: id (Any/Integer/String)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetX. -
InjectionScript.Runtime.InjectionApiUO.GetX:GetX(GetObject(id)). -
InjectionScript.Runtime.InjectionApiUO.GetObject:GetObject(id).
Internal implementation code; this is not a standalone script.
public int GetX(string id) => GetX(GetObject(id));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.GetY();
int UO.GetY(object? id);Reads the Y field of the loaded object or current character.
-
id— Serial/ID of the object, not the graphic/type. A number, a hex string, the standard name self/backpack/lasttarget/lastobject/lastcontainer/laststatus/finditem/lastcorpse, or the name AddObject. The alias must be set; existence is checked by Exists. The registered form without arguments uses self.
int is the Y coordinate. For an unknown object, 0 is returned. Zero is also a valid coordinate. Measured in cells for world objects; These are not screen pixels.
- The latest data already known to the client is read; the update request is not sent to the server.
- An unknown object and a property that has not yet been retrieved can have a null/empty value. Check Exists and conditions for a specific action.
- For a character or object on the ground, this is the world coordinate. The item inside the container has an X/Y position inside the gump; the command does not translate them into the owner's world coordinates.
- The current coordinate of the object is read. Pending steps are not converted into route calculations by this command.
int y = UO.GetY();
UO.Print($"Y = {y}");Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
var result = UO.GetY();
UO.Print("GetY: " + Convert.ToString(result));Parameters and execution flow:
- The form without an argument selects self, the current character.
- position contains the Y coordinate, not serial.
var position = UO.GetY();
UO.Print("Y: " + Convert.ToString(position));Parameters and execution flow:
- lasttarget should point to the loaded character or item on the ground.
- delta — difference along one axis. It is not the length of the route; the value may be negative.
return RunScenario();
object? RunScenario()
{
var other = UO.GetSerial("lasttarget");
if (Truth(UO.Exists(other)))
{
var delta = UO.GetY(other) - UO.GetY();
UO.Print("Difference: " + Convert.ToString(delta));
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- id="self" is an explicit form of character selection. UO.Wait=500 milliseconds.
- The comparison shows the change in the Y axis only. Changes in the other axis or rotation are not taken into account here.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
var before = UO.GetY("self");
await Delay(500);
var after = UO.GetY("self");
if (Truth(before != after))
{
UO.Print("Coordinate changed");
}
return null;
}
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: No parameters.
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetY. -
InjectionScript.Runtime.InjectionApiUO.GetY:GetY("self").
Internal implementation code; this is not a standalone script.
public int GetY() => GetY("self");Parameters: id (Any/Integer/String)
Result: int / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetY:bridge.GetY(Arg(0, bridge.Self)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0, bridge.Self). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.Self:bridge.Self.
Internal implementation code; this is not a standalone script.
case "gety": return new InjectionValue(bridge.GetY(Arg(0, bridge.Self)));Parameters: id (Any/Integer/String)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetY. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetY:bridge.GetY(id).
Internal implementation code; this is not a standalone script.
public int GetY(int id) => bridge.GetY(id);Parameters: id (Any/Integer/String)
Result: int / Integer.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.GetY. -
InjectionScript.Runtime.InjectionApiUO.GetY:GetY(GetObject(id)). -
InjectionScript.Runtime.InjectionApiUO.GetObject:GetObject(id).
Internal implementation code; this is not a standalone script.
public int GetY(string id) => GetY(GetObject(id));ClassicUO — Bad Newbie & C# Scripts IDE