Not quite. Dehardcoding means supplying means to override default behaviors. This does not necessarily mean "reimplementing game mechanics ... as built-in Lua mods" that user mods can then replace. Game mechanics can be implemented as Lua or C++ or whatever is best, but to have the code look and go "if there's a mod hooking into this functionality, call that along side this bit of built-in code". It's a subtle but important difference. A "built-in Lua mod" could be completely overwritten by a user mod, causing any future changes or additions to the built-in code to be lost until and unless the mod incorporates the changes and additions itself. Whereas by providing hooks from an internal subsystem, we can still alter or add to built-in functionality to work with those existing hooks (so the hooks remain available and working, even as the subsystem changes and gets new features).
This way also means better compatibility, since future changes just need to ensure the hooks can do the work they're expected to, rather than interface redesigns causing previous "built-in Lua mod" replacers to no longer function. I can't imagine anything more aggravating than for a modding-focused engine to continually break mods because of internal changes, and require those mods to be updated before they can work on updated versions of the engine. This may mean starting small, since you'll only want to expose things that we can know will be supported forever, but it can grow with time in a way that both ensures continued improvements to the engine and better fitting with what modders need to get the results they want.
The problem here is that dehardcoding and exposing functionality that is currently hardcoded is going to depend heavily on the functionality in question. These two points, for instance:ptmikheev wrote: ↑02 Aug 2021, 18:15 Public API and temporary internal API
Suppose that there is an important C++ function actorDoSomething(ptr) and we want this functionality to be available from Lua as soon as possible. But in future we plan to dehardcode this function and need a way to do it without breaking mods.
Then the steps are:
- Design an interface that will still be relevant after dehardcoding.
In our example we may decide that after dehardcoding "actorDoSomething" will be implemented in a builtin script 'basic_ai.lua' and will be available in local scripts via a script interface as interfaces.BasicAI.doSomething().- Add an internal function self:_doSomething() to the Lua package "openmw.self". This function doesn't need documentation and shouldn't be used by modders.
- Create 'basic_ai.lua' and implement interfaces.BasicAI.doSomething() as a simple wrapper around self:_doSomething(). It is public interface that can be used in mods.
- Later during dehardcoding we can remove self:_doSomething() and replace the wrapper with a real implementation without changing the public interface.
- Add an internal function self:_doSomething() to the Lua package "openmw.self". This function doesn't need documentation and shouldn't be used by modders.
- Create 'basic_ai.lua' and implement interfaces.BasicAI.doSomething() as a simple wrapper around self:_doSomething(). It is public interface that can be used in mods.
There isn't going to be a one-size-fits-all path to dehardcoding internal functionality. How some functionality gets exposed to mods is going to depend heavily on the functionality in question.
This is very much debatable. The engine isn't going to be a collection of Lua scripts that mods can replace as they want, and leave the engine as a glorified Lua script manager. The engine is going to be focused on playing a certain type of game, and the way it interfaces with subsystems and built-in scripts will necessarily change as it improves to get new features, but it's imperative that modded content continues to work regardless of what may be changed internally. As such, there must be internal APIs and built-in scripts that can access them, but which mods cannot. We need to be able to ensure new features can be added and work along side existing content, minimizing the amount of "gotchas", or "sorry, that new engine feature can't work with that mod", and doing everything reasonable to avoid "sorry, that mod doesn't work with newer versions of the engine. stay on the older version to use it".ptmikheev wrote: ↑02 Aug 2021, 18:15 All functions and engine handlers with prefix "_" are internal API that shouldn't be used outside of built-in scripts. But note that it is a temporary thing. At the end there will be no internal API at all and built-in scripts will not have any "special powers" comparing to normal mods.