Repository navigation
KenshiLua v0.3.5-alpha
Overview
KenshiLua v0.3.5-alpha expands the Lua scripting API with arithmetic and comparison operator overloading, new engine lifecycle constructor events, MyGUI widget factories, and broader gameplay class method bindings.
This release also introduces a dedicated backward compatibility layer in src/Compatibility/LegacyCompat.cpp. This layer addresses breaking changes introduced in recent updates regarding event names, enum tables, and MyGUI APIs, ensuring existing scripts continue running while providing clear paths for migration.
Backward Compatibility & API Migration (LegacyCompat.cpp)
Recent releases introduced changes to event registration, enum naming conventions, and MyGUI widget access. To prevent breaking existing scripts, src/Compatibility/LegacyCompat.cpp automatically bridges legacy script invocations to their modern equivalents at runtime.
How Existing Scripts Are Affected
- Non-Breaking Execution: Older scripts run without crashing or requiring immediate code edits. Lookups for legacy event names, deprecated enum tables, and older MyGUI convenience helpers are intercepted and resolved transparently.
- Advisory Deprecation Logs: Accessing legacy interfaces emits an advisory warning in
kenshilua.logdetailing the deprecated call and the exact replacement syntax. - Migration Timeline: These backward compatibility shims are temporary. Script authors should update their code to canonical APIs, as legacy shims will be phased out in subsequent releases.
1. Event Subscription Migration (registerHandler to Events.on)
Event handling across engine systems has been unified under the global Events table with standard on and off syntax, replacing global registration functions and redundant aliases.
- Legacy Functions:
registerHandler(eventName, handler)(global function)unregisterHandler(handlerId)(global function)
- Canonical API:
Events.on(eventName, handler): Registers an event listener and returns an integerhandlerId.Events.off(handlerId): Unregisters the listener by its ID.
- Event Naming Migration:
- Legacy shorthand:
"onCharacterDeath","onKeyDown","onPlayerRecruit","onBuildingConstructed". - Canonical scoped symbols:
"Character::declareDead","InputHandler::keyDownEvent","PlayerInterface::recruit","Building::_CONSTRUCTOR".
- Legacy shorthand:
- Backward Compatibility: Global
registerHandlerandunregisterHandlerremain available as compatibility wrappers. Deprecated shorthand strings are intercepted byLegacyCompat::ResolveEventNameas a fallback, translating them to their canonical C++ symbols and logging an advisory warning.
-- ============================================================
-- Engine Events: Before & After
-- ============================================================
-- Legacy Syntax:
local handlerId = registerHandler("onKeyDown", function(inputHandler, keyCode)
print("Key pressed:", keyCode)
end)
unregisterHandler(handlerId)
-- Modern Canonical Syntax:
local handlerId = Events.on("InputHandler::keyDownEvent", function(inputHandler, keyCode)
print("Key pressed:", keyCode)
end)
Events.off(handlerId)2. MyGUI Widget Callback Migration (registerCallback to widget:on)
UI event handling has undergone the exact same standardization: all widget listener management is now unified on widget:on and widget:off.
- Legacy Methods:
widget:registerCallback(eventType, handler)(deprecated)
- Canonical API:
widget:on(eventType, handler): Attaches an event listener to the widget and returns an integercallbackId.widget:off(idOrEvent): Detaches the listener by its integer callback ID, or detaches all listeners for a given event type string (e.g.widget:off("eventMouseButtonClick")).
- Canonical Event Names (1:1 with C++ Delegate Members):
- Widget event names are now strictly 1:1 with MyGUI's C++ delegate member variables (e.g.
"eventMouseButtonClick","eventEditTextChange","eventWindowButtonPressed","eventKeyButtonPressed").
- Widget event names are now strictly 1:1 with MyGUI's C++ delegate member variables (e.g.
- Backward Compatibility:
- All legacy shorthand names and aliases (such as
"OnClick","click","MouseButtonClick","change","OnTextChanged","keyDown") are deprecated and automatically resolved viaLegacyCompat::ResolveWidgetEventName, logging an advisory warning inkenshilua.logthat points to the canonicalevent*name.
- All legacy shorthand names and aliases (such as
-- ============================================================
-- MyGUI Widget Events: Before & After
-- ============================================================
-- Legacy Syntax (deprecated, emits log warning):
local button = window:createWidget("Button", "Button", 10, 10, 100, 30, "Align", "MyButton")
local callbackId = button:registerCallback("OnClick", function(sender)
print("Button clicked!")
end)
-- Modern Canonical Syntax:
local button = window:createWidget("Button", "Button", 10, 10, 100, 30, "Align", "MyButton")
local callbackId = button:on("eventMouseButtonClick", function(sender)
print("Button clicked!")
end)
-- Detach listener when no longer needed:
button:off(callbackId)
-- Or detach all click listeners on that widget:
button:off("eventMouseButtonClick")3. Enum Scoping and Constant Naming
Enums have been aligned 1:1 with literal C++ enum types and scoped constants declared in the KenshiLib SDK.
- Table Names: Scoped under their declaring classes or full C++ enum typenames (e.g.
CrimeEnum,CharacterTypeEnum,Character.CharMessage,BuildingPlacementGroundType.Enum). - Member Constants: Retain original C++ prefixes to prevent collisions (e.g.
CRIME_MURDERinstead ofMURDER,OT_CIVILIANinstead ofCIVILIAN,BF_RESEARCHinstead ofRESEARCH). - Backward Compatibility:
LegacyCompat::InstallEnumCompatibilitygenerates legacy global tables and installs__indexmetatable forwarders on canonical tables. Legacy accesses resolve to canonical values and log a one-time migration warning.
-- ============================================================
-- Enum Scoping: Before & After
-- ============================================================
-- Legacy (deprecated, emits log warning):
local crime = Crime.MURDER
local charType = CharacterType.CIVILIAN
local func = BuildingFunction.RESEARCH
-- Canonical API:
local crime = CrimeEnum.CRIME_MURDER
local charType = CharacterTypeEnum.OT_CIVILIAN
local func = BuildingFunction.BF_RESEARCH4. MyGUI Helpers & Widget Properties
MyGUI bindings have been refactored to align with the underlying MyGUI C++ class structure and ForgottenGUI widget creation systems.
- Global Helpers: Restored legacy global convenience functions on the
MyGUItable (MyGUI.resetKeyFocus(),MyGUI.setPointerVisible(),MyGUI.isResourceExist(),MyGUI.loadResource(), and legacy parameter layouts forMyGUI.createWidget()). - Widget Properties: Metatable bridges restore property accessors (
setFontName,setEditReadOnly,setMinSize,setImageTexture,setPositionReal,setCoordReal,attachToWidget,detachFromWidget) directly across widget instances.
5. Why These Changes Were Made
During the alpha phase, KenshiLua's API has transitioned from experimental, handwritten shorthands to strict 1:1 parity with Kenshi's underlying C++ SDK (KenshiLib) and MyGUI:
- Predictability & 1:1 SDK Parity: Replacing ad-hoc event names (
"onKeyDown") and widget callbacks ("OnClick") with literal C++ symbols ("InputHandler::keyDownEvent","eventMouseButtonClick") eliminates guesswork. Developers can inspect KenshiLib headers and reference docs directly to know the exact event and delegate names. - Collision Prevention & Disambiguation: Scoping enum tables under their true C++ types and retaining SDK prefixes prevents constant collisions and eliminates subtle naming bugs. In legacy tables where prefixes and underscores were stripped, distinct engine values collided into fragile casing differences—such as legacy
Stats.FARMING(STAT_FARMINGskill) versusStats.Farming(_Farmingwork-rate multiplier). Canonical identifiers likeStatsEnumerated.STAT_FARMINGandStatsEnumerated._Farmingguarantee 1:1 clarity with KenshiLib and eliminate global namespace clutter. - Unified Event Lifecycle: Standardizing both engine hooks and widget delegates on symmetrical
onandoffmethods (Events.on/Events.offandwidget:on/widget:off) replaces fragmented registration helpers with a single consistent API pattern. - Clear Terminology (
registervs.on): The previous use of "register" (registerHandler,widget:registerCallback) created confusion. In the Lua C API and throughout KenshiLua's own codebase, "register" exclusively refers to exposing C++ classes, metatables, and functions to the Lua runtime (e.g.luaL_register,registerBinding,registerConstructor). Overloading the word "register" to also mean dynamic event subscription conflated engine setup with runtime script logic. Transitioning toEvents.on/Events.offestablishes a clear distinction between binding infrastructure and event subscription, while adopting the standard.on()/.off()listener pattern widely used across Node.js (EventEmitter), modern Lua event libraries, and event-driven frameworks.
New Features
- Operator Overloads & Math Bindings: Implemented arithmetic (
+,-,*,/, unary-), comparison (<,<=,>,>=), equality (==), and explicitoperator_boolacross 40+ core math and engine classes (includingNxVec3,hkVector4f,TimeOfDay,hand,InstanceID, andCPerfTimer). - Engine Lifecycle Hooks: Added
_CONSTRUCTORevent hooks across major subsystems (GameData,Tasker,GameWorld,FactionManager,ZoneManager,DialogueWindow,InventoryGUI,RootObject, and others insrc/Callbacks.h), plus constructor bindings for value-type objects. - MyGUI Factories & Window Callbacks: Added
ForgottenGUIwidget creation factory methods (createWidget,createWidgetReal) and event callbacks across interface windows (BuildModeWindow,CharacterEditWindow,InventoryGUI,LevelEditor, tooltips, and layout classes). - Extended Gameplay Bindings: Implemented unmapped methods for
Armour,Building,Crossbow,Sword,TagsClass,ZoneManager, and inventory layout classes. - Binary Version Detection: Startup logging in
src/Plugin.cppnow reports whether the running game is the GOG or Steam executable along with the binary version string.
Fixes
- Metatable Inheritance: Corrected class inheritance wiring in
src/Lua/RegisterBindings.cppforResourceLoader -> ThreadClassandhkContainerHeapAllocator::Allocator -> hkMemoryAllocator. - Doc Tooling Path Fix: Resolved script path resolution in
tools/docs/generate_enums_reference.py, restoring missing entries indocs/EnumsReference.md. - Documentation Typo: Corrected documentation filename typo from
UnboundRefrence.mdtodocs/UnboundReference.md.
Refactors & Documentation
- Example Scripts Modernization: Updated all bundled example scripts and example mods to use canonical event subscriptions and modern API calls.
- Directory Cleanup: Renamed
src/Compatabilitytosrc/Compatibilityand relocatedSDKCompat.htosrc/Compatibility/TypeShims.h. - Project Maintenance: Added a Visual Studio
Debug|x64profile, added GitHub issue templates, and regenerateddocs/BindingsReference.mdanddocs/CallbacksReference.md.