How to Create Custom Events on Your MU Online Server
Learn how to design, configure, and schedule fully custom events on your MU Online server to boost player engagement and community activity.
Understanding the MU Online Event Architecture
Before writing a single line of configuration, it is important to understand how the MU Online server engine handles events internally. Most open-source server emulators — including the widely used Season 6 and Season 9 cores — separate event logic into three layers: the scheduler, the event handler, and the reward dispatcher.
The scheduler reads a timetable (usually an XML or INI file) and fires a signal at the configured time. The event handler receives that signal, validates player conditions, transitions the target map into event mode, and manages the game loop for the duration. The reward dispatcher runs when the event ends, iterates over qualifying players, and delivers items or experience to their inventories.
Understanding this separation is critical because configuration errors at each layer produce different symptoms. A scheduler misconfiguration means the event never starts. An event handler misconfiguration means the event starts but behaves incorrectly. A reward dispatcher misconfiguration means the event completes but players receive nothing.
Defining the Event in the Configuration File
Custom events are defined in the EventSchedule.xml (or EventConfig.ini on older cores) file located in the GameServer/Data/ directory. Each event occupies its own block and requires at minimum five parameters: a unique identifier, a map target, a start time, a duration, and a minimum player count.
Below is a fully annotated example of a custom Boss Invasion event:
[CustomEvent]
EventID → 1001
EventName → "Ancient Boss Invasion"
TargetMap → 32 ; Map index for Kanturu Relics
StartTime → 20:00 ; 24-hour server time
Duration → 30 ; Minutes
MinPlayers → 5 ; Event cancels if fewer players enter
MaxPlayers → 50 ; Hard cap enforced at map entry
AllowedClasses → 0,1,2,3,4 ; All standard classes permitted
EntryLevel → 300 ; Minimum character level to enter
EntryFee → 0 ; Zen cost to enter (0 = free)
RecurRule → DAILY ; DAILY | WEEKLY | ONCE | INTERVAL
RecurInterval → 0 ; Used only when RecurRule = INTERVAL (minutes)
[BossSpawn]
BossID → 447 ; Monster ID from MonsterList.xml
SpawnX → 128
SpawnY → 128
SpawnCount → 1
RespawnOnDeath → false
[RewardItem]
WinnerCount → 3 ; Top 3 damage dealers receive reward
ItemID → 13 ; Wings
ItemIndex → 38 ; Specific wing type
ItemLevel → 15
ItemSkill → true
ItemLuck → false
ItemOpt → 7
[Announcement]
PreEventMsg → "Ancient Boss Invasion begins in 5 minutes! Head to Kanturu Relics."
StartMsg → "The Ancient Boss has appeared in Kanturu Relics! Defeat it for legendary rewards."
EndMsg → "The Ancient Boss has been defeated! Rewards have been distributed."
Channel → GLOBAL ; GLOBAL | GUILD | NOTICE
Save the file and do not restart the server yet. You still need to register the event with the scheduler and verify the reward chain.
> [!WARNING] > Never use EventID values below 1000 for custom events. The base game reserves IDs 1 through 999 for built-in events such as Blood Castle, Devil Square, and Chaos Castle. Reusing a reserved ID will cause your custom event to overwrite the original event behavior, which is extremely difficult to debug.
Registering the Event with the Scheduler
The scheduler file (EventScheduler.xml or Schedule.ini) maintains a master list of all events the engine should track. Adding your event here is what causes the server to actually load and execute it. Without this step, the configuration block you wrote in the previous section is parsed but never activated.
Locate the <EventList> section and append your entry:
<EventList>
<!-- Built-in events above this line — do not modify -->
<Event id="1001" enabled="true" priority="normal" log="true" />
</EventList>
The priority parameter accepts low, normal, and high. High-priority events preempt map transitions that would otherwise interrupt them. Use high only for events that should never be canceled by routine server maintenance cycles.
The log="true" flag writes a timestamped entry to Logs/EventLog.txt every time the event starts, ends, or is canceled. Always enable logging during development and testing. You can disable it later once the event has been stable for several weeks.
After saving both files, perform a controlled server restart during a low-population window. Watch the console output during boot for lines beginning with [EventScheduler]. A successful load looks like:
[EventScheduler] Loaded event ID 1001 → "Ancient Boss Invasion" → next run: 20:00
If you see [EventScheduler] WARNING: Event ID 1001 skipped — invalid map index, the TargetMap value does not match any map registered in your MapData.xml. Correct the index and restart again.
Testing and Iterating on Custom Event Logic
Testing a time-based event during development is impractical if you have to wait for the scheduled time. All major server cores expose a GM console command that forces an event to start immediately regardless of the schedule.
Connect with a GM-level account and run:
/eventstart 1001
If the command is not recognized, your core uses a different prefix. Check the GMCommandList.xml or equivalent file. Common alternatives are /eventforce, /startevent, and /gm_event.
Once the event fires, verify these behaviors in sequence:
- The announcement message appears in global chat
- Players at the correct level and map receive the entry portal
- The boss spawns at the configured coordinates
- The event timer counts down correctly in the UI
- When the boss dies (or time expires), the reward dispatcher runs and items are delivered
> [!TIP] > Create a dedicated test character at the minimum allowed level with a second GM account logged in simultaneously. This lets you validate the entry level restriction and the reward delivery in one test session without having to involve real players. Use the /additem command to give your test character placeholder inventory space if needed.
Advanced Customization: Conditional Logic and Chained Events
Once your base event is stable, you can introduce conditional logic to make it more dynamic. The event handler supports a simple scripting layer in most Season 6+ cores, accessed through an inline script block in the configuration.
A common pattern is a chained event, where completing the first event unlocks a second:
[ChainEvent]
TriggerEventID → 1001 ; This event fires when 1001 ends with success
ChainEventID → 1002 ; EventID of the follow-up event
TriggerCondition → BOSS_KILLED ; BOSS_KILLED | TIME_EXPIRED | PLAYER_COUNT
DelayAfterTrigger → 2 ; Minutes to wait before starting the chain event
Chained events are powerful for building multi-stage content — for example, a boss kill that immediately opens a treasure room with a 2-minute loot window. Keep chains to a maximum of three stages. Longer chains introduce session management complexity that can lead to event state corruption if a player disconnects mid-chain.
Always document every custom event in a local administration log, recording the EventID, purpose, date added, and any known issues. This practice becomes invaluable when handing off server administration responsibilities or diagnosing conflicts months after the initial implementation.
Perguntas frequentes
Can I run multiple custom events simultaneously?
Yes, as long as each event uses a distinct EventID and the server has sufficient memory allocated. Overlapping events that share the same maps can cause conflict, so assign unique map instances or stagger start times by at least 5 minutes.
What happens if the server crashes during an event?
Custom events do not auto-resume after a crash unless you implement a recovery script that reads the event log and re-initializes the state. It is strongly recommended to back up event state to a flat file or database table every 60 seconds during active events.
How do I restrict an event to a specific character class?
Use the AllowedClasses parameter in the event block. List class IDs separated by commas, for example AllowedClasses = 0,1,2. Refer to your server source's class enumeration file for the correct numeric values.
Is it possible to award items that are not in the standard drop table?
Yes. Define the reward item using its ItemID and ItemLevel directly in the RewardItem block of the event configuration. The item does not need to appear in any drop table, but it must exist in the ItemManager definition files.