MonsterAIRule.xml
Defines conditional rules that temporarily override a monster class's active AI Unit based on calendar date and time. While a rule is active, every live monster of the target class switches from its BasicAI to the rule's Unit until the rule expires.
File Location#
Data/Monster/MonsterAIRule.xml
Dependencies#
| Depends On | Purpose |
|---|---|
| MonsterAIUnit.xml | Supplies the replacement AI personality |
| MonsterAIGroup.xml | Assigns each monster's BasicAI (the rule's fallback) |
| Monster.xml | Defines the monster classes referenced by Class |
| Used By | Purpose |
|---|---|
| Monster AI dispatcher | Evaluates every rule on each AI tick and applies overrides |
How It Works#
- The AI dispatcher walks the rule list on every AI tick.
- Each rule is tested against the current server clock (and, when relevant, server events).
- If a rule is valid and past its
WaitTimebut still insideWaitTime + ContinuanceTime, the target class is tagged with the rule'sUnit. - On the next AI update, every live monster of that class has its
CurrentAIswitched to thatUnit; itsBasicAIis preserved untouched. - When no rule is active for the class, monsters fall back to
BasicAIfrom MonsterAIGroup.xml.
Current Status#
<?xml version="1.0" ?>
<MonsterAIRule/>
Configuration Structure#
Rule Attributes#
| Attribute | Type | Required | Description |
|---|---|---|---|
Number | int | Yes | Rule identifier (informational) |
Class | int | Yes | Target monster class (from Monster.xml). All live monsters of this class are affected |
Description | string | No | Human-readable label, up to 99 characters |
Unit | int | Yes | AI Unit that replaces BasicAI while the rule is active. Must exist in MonsterAIUnit.xml |
Condition | int | Yes | Condition type. See below. Only 1 is functional |
WaitTime | int | Yes | Seconds to wait after the condition first becomes true before the override starts |
ContinuanceTime | int | Yes | Seconds the override remains active after WaitTime elapses |
Month | int/string | Conditional | Month 1-12, or * for any |
Day | int/string | Conditional | Day of month 1-31, or * for any |
WeekDay | int/string | Conditional | Day of week 1-7 where 1 = Sunday and 7 = Saturday, or * for any |
Hour | int/string | Conditional | Hour 0-23, or * for any |
Minute | int/string | Conditional | Minute 0-59, or * for any |
Condition Types#
| Condition | Description | Date/Time Fields Used |
|---|---|---|
1 | Specific calendar date/time | Month, Day, WeekDay, Hour, Minute |
71 | Crywolf event start | Hard-coded to always return false |
72 | Crywolf event end | Hard-coded to always return false |
Important Behavior#
Timing Logic#
condition first TRUE -> wait [WaitTime]s -> override ACTIVE for [ContinuanceTime]s -> override EXPIRES
Example with WaitTime="10" and ContinuanceTime="3600":
- 00:00:00 - condition becomes true
- 00:00:10 - override activates (10 s wait elapsed)
- 01:00:10 - override expires (3600 s duration elapsed)
Both WaitTime and ContinuanceTime are in seconds. ContinuanceTime="60" means one minute, not one hour.
Date/Time Matching#
- All non-wildcard fields must match simultaneously for the condition to be true.
WeekDayis tested first. A mismatch short-circuits the rule as invalid for the current tick.Month,Day,Hour,Minuteeach build a "valid from" timestamp when their field differs from the current clock. The rule stays valid from that timestamp throughWaitTime + ContinuanceTimepast it.- Matching is minute-precision. Firing resolution is the AI dispatcher tick (sub-second).
Multiple Rules Per Class#
Rules are evaluated in file order and all write to the same per-class override slot:
- The last rule in the file that touches a given
Classdetermines the outcome for that class. - If the last-listed rule for a class is valid, its
Unitis applied. - If the last-listed rule for a class is invalid (its condition is false or outside the timing window), the override slot is cleared even if an earlier rule for the same class was valid.
Order rules for the same class so the one you actually want to win is listed last, or keep one rule per class to avoid the overwrite.
Fallback to BasicAI#
When no active rule targets a monster's class, that monster uses its BasicAI assigned by MonsterAIGroup.xml. The override never modifies BasicAI itself; it only swaps the runtime CurrentAI pointer.
Performance#
Every rule is checked against the clock on every AI tick, and every live monster of an overridden class has its CurrentAI pointer rewritten on every AI tick. Keep the rule list small. The loader caps it at 200 entries.
Examples#
Golden Goblins (class 8) switch to an aggressive Unit for all of October 31:
<MonsterAIRule>
<Rule
Number="1"
Class="8"
Description="Halloween aggressive Golden Goblin"
Unit="101"
Condition="1"
WaitTime="0"
ContinuanceTime="86400"
Month="10"
Day="31"
WeekDay="*"
Hour="*"
Minute="*"
/>
</MonsterAIRule>
- Activates at October 31 00:00 server time.
- Runs for 86400 s (24 h).
- Every Golden Goblin on the server swaps to Unit 101.
White Wizards (class 20) use an event Unit every Saturday from 20:00 for four hours:
<MonsterAIRule>
<Rule
Number="2"
Class="20"
Description="Saturday night White Wizard event"
Unit="205"
Condition="1"
WaitTime="0"
ContinuanceTime="14400"
Month="*"
Day="*"
WeekDay="7"
Hour="20"
Minute="0"
/>
</MonsterAIRule>
WeekDay="7"= Saturday (1 = Sunday, 7 = Saturday).- Runs Saturdays 20:00 to 24:00.
Budge Dragons (class 3) become more aggressive every evening:
<MonsterAIRule>
<Rule
Number="3"
Class="3"
Description="Evening peak aggression"
Unit="150"
Condition="1"
WaitTime="0"
ContinuanceTime="14400"
Month="*"
Day="*"
WeekDay="*"
Hour="18"
Minute="0"
/>
</MonsterAIRule>
- Fires every day at 18:00 and runs four hours.
Christmas event with a one-hour warmup after midnight:
<MonsterAIRule>
<Rule
Number="4"
Class="50"
Description="Christmas Elf event (delayed start)"
Unit="300"
Condition="1"
WaitTime="3600"
ContinuanceTime="82800"
Month="12"
Day="25"
WeekDay="*"
Hour="0"
Minute="0"
/>
</MonsterAIRule>
- Condition first true at Dec 25 00:00.
- Override starts at 01:00 (after 3600 s wait) and expires at 24:00.
Common Issues#
Use Cases#
Time-Based Events#
- Night aggression: lower
DelayTimeUnit during dark hours - Weekend bosses: swap to boss-behaviour Units on Saturday/Sunday
- Hourly rotations: multiple classes each with their own schedule
Seasonal Events#
- Halloween behaviour on October 31
- December festive patterns
- Anniversary overrides
Dynamic Difficulty#
- Peak-hour challenge: harder Units during prime-time
- Off-peak: easier Units overnight
When NOT to Use MonsterAIRule#
| Need | Better Solution |
|---|---|
| Permanent behaviour change | Edit MonsterAIGroup.xml StartAI directly |
| HP-based skill triggers | Use MonsterSkill.xml |
| Timed spawn/despawn | Use event spawn types in MonsterSetBase/ per-map XML |
| Event-only monsters | Add dedicated monster classes |
| Stat tweaks | Edit Monster.xml |
Related Systems#
- MonsterAIUnit.xml - AI Unit definitions that rules override to
- MonsterAIAutomata.xml - state machine rules used by each Unit
- MonsterAIElement.xml - per-state actions used by each Unit
- MonsterAIGroup.xml - default AI Unit assignments (BasicAI)
- Monster.xml - stats, aggression (
ViewRange), movement patterns - MonsterSkill.xml - HP-gated skill triggers
- MonsterSetBase - spawn timing and locations