Skip to main content

Commands & Targeting

Overview

ModernUO uses a command system where all player/staff commands are prefixed with [ by default (this is configurable). Commands are registered in static Configure() methods that the server discovers automatically at startup. Each command is bound to a minimum access level, so only authorized players can execute it.


Registering a Command

Commands are registered by calling CommandSystem.Register inside a static Configure() method. The server calls all Configure() methods during initialization -- no manual wiring is needed.

public static class MyCommands
{
public static void Configure()
{
CommandSystem.Register("MyCommand", AccessLevel.GameMaster, MyCommand_OnCommand);
}

[Usage("MyCommand <name>")]
[Description("Does something with a name")]
public static void MyCommand_OnCommand(CommandEventArgs e)
{
var from = e.Mobile;
if (e.Length < 1)
{
from.SendMessage("Usage: [MyCommand <name>");
return;
}

var name = e.GetString(0);
from.SendMessage($"Processing {name}");
}
}

The [Usage] and [Description] attributes provide help text that appears in the in-game help system.


CommandEventArgs API

When a command handler fires, it receives a CommandEventArgs object with the following members:

MemberTypeDescription
MobileMobileThe mobile that issued the command
CommandstringThe command name that was typed
ArgStringstringThe full argument string after the command name
Argumentsstring[]Arguments split by spaces
LengthintNumber of arguments (Arguments.Length)
GetString(i)stringGet argument at index i as a string
GetInt32(i)intGet argument at index i as an integer
GetBoolean(i)boolGet argument at index i as a boolean
GetDouble(i)doubleGet argument at index i as a double

Access Levels

Each command requires a minimum access level. Players below that level cannot execute the command.

LevelValueDescription
Player0Normal player (default)
Counselor1Support staff with limited powers
GameMaster2GM with full world interaction
Seer3Event coordinator with extra tools
Administrator4Server administrator
Developer5Developer with access to debug commands
Owner6Server owner with unrestricted access

Targeting System

The targeting system lets a command (or any code) ask a player to click on something in the game world. The flow is:

  1. Code sets mobile.Target = new MyTarget().
  2. The client displays a targeting cursor.
  3. The player clicks on a mobile, item, land tile, or static object.
  4. The OnTarget method fires with what was clicked.

Target Implementation

A target class inherits from Target and overrides OnTarget. The targeted parameter can be a Mobile, Item, LandTarget, or StaticTarget -- use a switch to handle each case.

public class IdentifyTarget : Target
{
public IdentifyTarget() : base(12, false, TargetFlags.None)
{
}

protected override void OnTarget(Mobile from, object targeted)
{
switch (targeted)
{
case Mobile m:
{
from.SendMessage($"That is a mobile named {m.Name}.");
break;
}
case Item item:
{
from.SendMessage($"That is an item: {item.GetType().Name} (0x{item.ItemID:X4}).");
break;
}
case LandTarget land:
{
from.SendMessage($"That is land tile at {land.Location}.");
break;
}
case StaticTarget st:
{
from.SendMessage($"That is a static: 0x{st.ItemID:X4}.");
break;
}
}
}
}

The Target constructor takes three parameters:

  • range -- Maximum distance the target can be from the player.
  • allowGround -- Whether clicking the ground is valid.
  • flags -- TargetFlags value controlling criminal/beneficial checks.

Command + Targeting Pattern

A common pattern is for a command to initiate targeting, then the target handler performs the actual work. This cleanly separates input from logic.

public static class HealCommands
{
public static void Configure()
{
CommandSystem.Register("Heal", AccessLevel.GameMaster, Heal_OnCommand);
}

[Usage("Heal")]
[Description("Fully heals the targeted mobile")]
public static void Heal_OnCommand(CommandEventArgs e)
{
e.Mobile.SendMessage("Who do you want to heal?");
e.Mobile.Target = new HealTarget();
}

private class HealTarget : Target
{
public HealTarget() : base(12, false, TargetFlags.Beneficial)
{
}

protected override void OnTarget(Mobile from, object targeted)
{
if (targeted is Mobile m)
{
m.Hits = m.HitsMax;
m.SendMessage("You have been fully healed.");
from.SendMessage($"You healed {m.Name}.");
}
else
{
from.SendMessage("That is not a mobile.");
}
}
}
}

TargetFlags

Target flags tell the server what kind of action the player is performing, which affects criminal checks and other systems.

FlagDescription
NoneNeutral action -- no criminal or beneficial checks
HarmfulHostile action -- triggers criminal flagging if targeting innocents
BeneficialHelpful action -- triggers beneficial checks (healing, buffing)
tip

Always set the correct flag. Using Harmful on a healing target (or None on an attack) bypasses important game mechanics like the criminal system.


Best Practices

  • Register in Configure() -- The server discovers these methods automatically. Do not register commands in constructors or other lifecycle methods.
  • Validate argument count -- Always check e.Length before accessing arguments to avoid index-out-of-range errors.
  • Use appropriate access levels -- Do not default to Owner. Choose the lowest level that makes sense for the command.
  • Use Harmful/Beneficial flags correctly -- This ensures the criminal and notoriety systems work as intended.
  • Keep target handlers focused -- Let the command set up the target, and let the target handler do the work.