One Life Event (OLE) slot-blocking hook script for DCS World.
Purpose
Controls which player slots are available based on:
UCID bans — administrators can block / unblock specific players via chat commands.
MW-50 quota — limits how many players can occupy the MW-50 asset depending on the blue-vs-red player ratio.
Instructor bypass — instructor slots (instructor_red_1, instructor_blue_1) are never blocked.
Installation and Deployment
This file is a DCS World GameGUI hook, not a mission script. It must be placed on the DCS dedicated server (or host machine) in the hooks directory.
Server-side placement
Copy WWII_OLE_GameGUI_8.lua into your DCS World hooks folder:
Open Beta:Saved Games\DCS.openbeta\Scripts\Hooks\
Stable / Release:Saved Games\DCS\Scripts\Hooks\
Restart the DCS server process. The script self-registers via DCS.setUserCallbacks(); no mission-level dofile or trigger action is required.
Deployment notes
The .miz missions only need to contain units named MW-50 (or containing that substring) for the quota logic to apply.
Instructor slots must use the exact names listed in CFG.instructor_slots.
Bans are RAM-only and are reset when the server restarts.
If the server is paused (e.g., by a menu or another hook), kick scheduling uses model time, so pauses delay the kick. This is acceptable; the kick fires as soon as model time resumes.
Access control (optional)
By default any player who knows the chat prefix can issue commands. Restrict this to trusted UCIDs by editing the CFG.admin_ucids table near the top of the script:
slot nil or empty?instructor slot?UCID banned?MW-50 unit?under quota?yesnoyesnoyesnonoyesyesno
Admin Chat Command Flow
message starts with ole?sender is admin?ole ban u003cucidu003e?ole unban u003cucidu003e?ole status?ole help?add UCID to blocked setqueue kick if not already queuedremove UCID from blocked setlog blocked UCIDslog command usagenoyesyesnoyesnoyesnoyesnoyesno
Simulation Frame Kick Flow
kick_scheduled set?now >= scheduled time?iterate all playersplayer UCID banned?player has active slot?force_player_slot(0, "")clear kick_schedulednoyesnoyesyesnoyesnodone
Configuration
Variable
Type
Description
mw50_rules
table
Ordered list of {max_ratio, max_mw50} limits. Ratio = blue / red.
chat_prefix
string
Admin command prefix (default "ole").
kick_delay
number
Seconds before a newly banned player is kicked (default 15). If already scheduled, earlier kick wins.
instructor_slots
table
Slot IDs that bypass all checks.
admin_ucids
table
Optional authorised UCID whitelist. Empty = no restriction.
Default MW-50 rules:
Blue / Red ratio
Max MW-50 slots
\u003c= 0.75
6
\u003c= 1.00
8
\u003c= 1.50
10
\u003e 1.50 (or red = 0)
12
Admin Chat Commands
Command
Arguments
Example
Action
ole ban
\u003cucid\u003e
ole ban A1B2C3D4
Blocks a UCID; schedules kick sweep in 15 s.
ole unban
\u003cucid\u003e
ole unban A1B2C3D4
Unblocks a UCID.
ole status
none
ole status
Returns the current blocked list.
ole help
none
ole help
Returns command usage hints.
Security note: Only the first word (ole) is checked. Messages beginning with the prefix are replaced by the response in the chat stream. Only players listed in CFG.admin_ucids can issue commands; when the whitelist is empty, anyone who knows the prefix can ban.
Files
WWII_OLE_GameGUI_8_old.lua — original v8 script (archived)
WWII_OLE_GameGUI_8.lua — refactored v8.2 script
README.md / README.html — documentation
Known Limitations
RAM-only bans: The block list is not persisted to disk. A server restart clears all bans.
No in-game UI: All admin interaction is via chat commands.
Kick on pause: Scheduled kicks use DCS model time, so if the server is paused the kick is delayed until the game resumes.
Changelog
v8.2
Chat suppression fix: Only messages beginning with ole are intercepted. Words containing "ole" (e.g. "mole") are no longer swallowed.
Kick scheduler fix: If a ban is issued while a kick is already pending, the earlier scheduled kick is preserved. Overwriting removed entirely.
Player-count cache removed: Counts are now real-time. Eliminates stale data when the server is paused (model time stops, real time does not).
Red=0 handling: When red team has 0 players, ratio is treated as very high, defaulting to the highest cap (12) instead of the lowest (6).
Iteration safety: Switched ipairs to pairs for net.get_player_list() (handles sparse arrays better).
O(1) block lookup: Replaced array scan with a hash set (blocked_set[ucid] = true).
UCID validation: Ban / unban commands now validate hex-length UCIDs.
Optional admin whitelist: Added CFG.admin_ucids to restrict commands to specific UCIDs. Empty by default for backward compatibility.
In-chat feedback: Commands now echo confirmation or error messages back to the sender instead of only logging to the server console.
Documentation: Added Installation & Deployment section and Known Limitations.
v8.1
Refactored from monolithic to modular structure (config, state, utilities, commands, hooks).
Added ole unban, ole status, and ole help commands.
Replaced cryptic splitStr(message, "=") parsing with clean space-delimited token parsing.
Added 1-second memoisation cache for player counts.
Fixed variable shadowing (ID used for both outer player ID and loop index).
Fixed potential division-by-zero when red team has 0 players.
Fixed OLE.KickTime / OLE.KickTimeNow logic — now uses a single kick_scheduled timestamp.
Fixed instructor slot check to use a lookup table instead of string comparisons.
Added comprehensive inline documentation and D2 flow diagrams.