Summary
- Adds CLAUDE.md at repo root with 14 terse code audit rules (always loaded, low token cost)
- Adds pointer files for other AI tools: AGENTS.md (Codex), GEMINI.md, .github/COPILOT-INSTRUCTIONS.md (Copilot), .cursorrules (Cursor) — all redirect to CLAUDE.md as single source of truth
- Gitignores /.claude so personal AI config isn't distributed
- Moves Claude skills to dev-docs/claude-skills/ (opt-in, not auto-loaded)
- Adds 14 dev-docs covering codebase conventions
Code Audit Rules (in CLAUDE.md)
1. LINQ tiered rules (Tier 1 free, Tier 2 warm, Tier 3 forbidden)
2. No Console.WriteLine — use LogFactory.GetLogger()
3. No concurrency primitives in game code
4. No World.Mobiles/World.Items iteration
5. Clean up refs in OnDelete()/OnAfterDelete()
6. Cancel timers in OnDelete()/OnAfterDelete()
7. STArrayPool<T>.Shared not ArrayPool<T>.Shared
8. PooledRefList<T> not new List<T>() on hot paths
9. Serialization: partial class, [Constructible], no serialized TimerExecutionToken
10. No Task.Run/new Thread() in game code
11. Never assume era — ask which expansion
12. _camelCase fields, PascalCase properties/methods
13. No empty gumps — use DisplayTo() pattern
14. PropertyList string literals must be {} holes, cliloc-as-argument uses :#
223 lines
6.8 KiB
Markdown
223 lines
6.8 KiB
Markdown
---
|
|
name: modernuo-commands-targeting
|
|
description: >
|
|
Trigger when creating in-game commands, targeting mechanics, or working with CommandSystem/Target. When implementing [commands or player interactions.
|
|
---
|
|
|
|
# ModernUO Commands & Targeting
|
|
|
|
## When This Activates
|
|
- Creating new in-game `[` commands
|
|
- Implementing targeting mechanics
|
|
- Working with `CommandSystem.Register()` or `Target` class
|
|
- Adding GM/admin tools
|
|
|
|
## Key Rules
|
|
|
|
1. **Register commands in `Configure()`** static method (called at startup)
|
|
2. **Use `[Usage]` and `[Description]`** attributes on handler methods
|
|
3. **Prefix is `[`** by default (e.g., `[mycommand`)
|
|
4. **Target inherits from `Target`** class, override `OnTarget()`
|
|
5. **Always validate inputs** in command handlers
|
|
|
|
## Command Registration
|
|
|
|
```csharp
|
|
using Server.Commands;
|
|
|
|
namespace Server.Custom;
|
|
|
|
public static class MyCommands
|
|
{
|
|
public static void Configure()
|
|
{
|
|
CommandSystem.Register("MyCommand", AccessLevel.GameMaster, MyCommand_OnCommand);
|
|
CommandSystem.Register("MyOtherCmd", AccessLevel.Player, MyOtherCmd_OnCommand);
|
|
}
|
|
|
|
[Usage("MyCommand <name> [count]")]
|
|
[Description("Does something with a name and optional count")]
|
|
public static void MyCommand_OnCommand(CommandEventArgs e)
|
|
{
|
|
var from = e.Mobile;
|
|
|
|
if (e.Length < 1)
|
|
{
|
|
from.SendMessage("Usage: [MyCommand <name> [count]");
|
|
return;
|
|
}
|
|
|
|
var name = e.GetString(0);
|
|
var count = e.Length > 1 ? e.GetInt32(1) : 1;
|
|
|
|
from.SendMessage($"Processing {name} x{count}");
|
|
}
|
|
}
|
|
```
|
|
|
|
## CommandEventArgs
|
|
|
|
```csharp
|
|
e.Mobile // Mobile who issued the command
|
|
e.Command // Command name string
|
|
e.ArgString // Raw argument string
|
|
e.Arguments // string[] split arguments
|
|
e.Length // Number of arguments
|
|
|
|
// Typed argument accessors:
|
|
e.GetString(0) // Get string at index (empty string if missing)
|
|
e.GetInt32(1) // Get int at index (0 if missing/invalid)
|
|
e.GetUInt32(0) // Get uint at index
|
|
e.GetBoolean(0) // Get bool at index
|
|
e.GetDouble(0) // Get double at index
|
|
e.GetTimeSpan(0) // Get TimeSpan at index
|
|
```
|
|
|
|
## Access Levels
|
|
|
|
```csharp
|
|
AccessLevel.Player // Regular players
|
|
AccessLevel.Counselor // Support staff
|
|
AccessLevel.GameMaster // GMs
|
|
AccessLevel.Seer // Event coordinators
|
|
AccessLevel.Administrator // Server admins
|
|
AccessLevel.Developer // Developers
|
|
AccessLevel.Owner // Server owner
|
|
```
|
|
|
|
## Target System
|
|
|
|
### Basic Target
|
|
```csharp
|
|
using Server.Targeting;
|
|
|
|
private class MyTarget : Target
|
|
{
|
|
public MyTarget() : base(
|
|
12, // Range (-1 for unlimited)
|
|
false, // AllowGround
|
|
TargetFlags.None // None, Harmful, or Beneficial
|
|
)
|
|
{
|
|
// Optional settings:
|
|
// CheckLOS = false; // Skip line-of-sight check
|
|
// DisallowMultis = true; // Don't allow targeting multi objects
|
|
}
|
|
|
|
protected override void OnTarget(Mobile from, object targeted)
|
|
{
|
|
if (targeted is Mobile m)
|
|
{
|
|
from.SendMessage($"You targeted {m.Name}");
|
|
}
|
|
else if (targeted is Item item)
|
|
{
|
|
from.SendMessage($"You targeted item {item.Name}");
|
|
}
|
|
else if (targeted is LandTarget land)
|
|
{
|
|
from.SendMessage($"You targeted land at {land.Location}");
|
|
}
|
|
else if (targeted is StaticTarget st)
|
|
{
|
|
from.SendMessage($"You targeted static {st.ItemID}");
|
|
}
|
|
}
|
|
|
|
protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType)
|
|
{
|
|
from.SendMessage("Targeting cancelled.");
|
|
}
|
|
|
|
protected override void OnTargetFinish(Mobile from)
|
|
{
|
|
// Always called after targeting completes (success or cancel)
|
|
}
|
|
}
|
|
|
|
// Usage:
|
|
from.Target = new MyTarget();
|
|
```
|
|
|
|
### TargetFlags
|
|
```csharp
|
|
TargetFlags.None // Neutral targeting
|
|
TargetFlags.Harmful // Criminal check, combat targeting
|
|
TargetFlags.Beneficial // Healing, buffing
|
|
```
|
|
|
|
### Target Object Types
|
|
- `Mobile` -- a player or creature
|
|
- `Item` -- an item in the world or container
|
|
- `LandTarget` -- ground tile (`Location`, `TileID`, `Name`)
|
|
- `StaticTarget` -- static map object (`Location`, `ItemID`, `Name`, `Hue`)
|
|
|
|
### Command + Target Pattern
|
|
```csharp
|
|
public static void Configure()
|
|
{
|
|
CommandSystem.Register("Tame", AccessLevel.GameMaster, Tame_OnCommand);
|
|
}
|
|
|
|
[Usage("Tame")]
|
|
[Description("Force-tames a creature")]
|
|
public static void Tame_OnCommand(CommandEventArgs e)
|
|
{
|
|
e.Mobile.SendMessage("Select a creature to tame.");
|
|
e.Mobile.Target = new TameTarget();
|
|
}
|
|
|
|
private class TameTarget : Target
|
|
{
|
|
public TameTarget() : base(-1, false, TargetFlags.None) { }
|
|
|
|
protected override void OnTarget(Mobile from, object targeted)
|
|
{
|
|
if (targeted is BaseCreature { Tamable: true } creature)
|
|
{
|
|
creature.SetControlMaster(from);
|
|
from.SendMessage($"You have tamed {creature.Name}.");
|
|
}
|
|
else
|
|
{
|
|
from.SendMessage("That cannot be tamed.");
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Target Validation Overrides
|
|
```csharp
|
|
// Override these for custom validation:
|
|
protected override bool CanTarget(Mobile from, Mobile mobile, ref Point3D loc, ref Map map)
|
|
protected override bool CanTarget(Mobile from, Item item, ref Point3D loc, ref Map map)
|
|
protected override bool CanTarget(Mobile from, LandTarget land, ref Point3D loc, ref Map map)
|
|
protected override bool CanTarget(Mobile from, StaticTarget st, ref Point3D loc, ref Map map)
|
|
|
|
// Error handlers:
|
|
protected override void OnTargetOutOfRange(Mobile from, object targeted)
|
|
protected override void OnTargetOutOfLOS(Mobile from, object targeted)
|
|
protected override void OnTargetNotAccessible(Mobile from, object targeted)
|
|
protected override void OnTargetDeleted(Mobile from, object targeted)
|
|
protected override void OnTargetUntargetable(Mobile from, object targeted)
|
|
```
|
|
|
|
## Anti-Patterns
|
|
|
|
- **Registering commands outside `Configure()`**: Won't be called during startup
|
|
- **Missing access level validation**: Always set appropriate `AccessLevel`
|
|
- **Not checking `e.Length`**: Accessing missing arguments returns defaults silently
|
|
- **Hardcoded range in targeting**: Use -1 for unlimited, appropriate range for game mechanics
|
|
|
|
## Real Examples
|
|
- Command registration: `Projects/UOContent/Commands/StaffAccess.cs`
|
|
- Target from item: `Projects/UOContent/Items/Misc/InteriorDecorator.cs`
|
|
- Spell targeting: `Projects/UOContent/Spells/First/MagicArrow.cs`
|
|
- Command system: `Projects/Server/Commands.cs`
|
|
- Target base: `Projects/Server/Targeting/Target.cs`
|
|
- Attributes: `Projects/Server/Attributes.cs` (Usage, Description, Aliases)
|
|
|
|
## See Also
|
|
- `dev-docs/commands-targeting.md` - Complete documentation
|
|
- `dev-docs/claude-skills/modernuo-gump-system.md` - Commands that open gumps
|
|
- `dev-docs/claude-skills/modernuo-content-patterns.md` - Content creation
|