Author Topic: [OXCE+] Lua Integration  (Read 25949 times)

Offline Whispers

  • Sergeant
  • **
  • Posts: 44
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #30 on: September 18, 2018, 08:43:29 pm »
So far all events I have planned are global events. I can see circumstances where you want to "only run this function on this particular instance of an object" , but that would be too intrusive for a first pass API. I'd have to go in and modify every spot where an instance of an object is created and either do multi-inheritance to a common base class which holds the necessary functions to allow binding functions to that instance, or I'd have to do some other method of allowing local instance callbacks which would touch more files than I would like to at the moment.

I think for the first version I will only have global events. Things like xcom.geoscape.register5SecCallback, xcom.battlescape.registerTurnBegin and even xcom.geoscape.registerUpdateCallback for those needing frame to frame updates. For other things, like xcom.soldier.get(soldier).registerDamageCallback(), I don't think the initial API will handle it like that. Instead, you could have something like xcom.soldier.registerDamageCallback() which takes a function that has a parameter for which soldier was damaged. It covers the same use case, but perhaps not as cleanly because you'd get that callback for EVERY soldier that receives damage instead of one specific soldier.

has<x>Callback and clear<x>Callback appear to be okay, so I'll move forward with that idea for now.

I'm still toying with ideas on how to architect the API that is less intrusive on the engine, yet allows controlling as much of the underlying data as possible.

Offline Yankes

  • Global Moderator
  • Commander
  • ***
  • Posts: 3350
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #31 on: September 18, 2018, 08:50:32 pm »
One detail, in my version scripts are per armor not per battle unit/solder. Overall I think mods should live in "Mod" folder and modify things from "SaveGame" folder.
« Last Edit: September 19, 2018, 08:23:13 pm by Solarius Scorch »

Offline Whispers

  • Sergeant
  • **
  • Posts: 44
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #32 on: September 18, 2018, 10:23:20 pm »
I'm loosely shaping the API by the save game structure, so the xcom.soldiers api is a bad example(cause soldiers could be in a craft, in a base items list, in transfer, or on the battlescape somewhere.)

But yeah, I see your point

--- posts merged, please don't double-post ---

Updated OP with more details on progress
« Last Edit: September 19, 2018, 08:23:34 pm by Solarius Scorch »

Offline Yankes

  • Global Moderator
  • Commander
  • ***
  • Posts: 3350
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #33 on: September 19, 2018, 08:55:37 pm »
Would be possible to get ride of `getGameFromLuaState` and use some kind of `this` pointer?

Code: [Select]
    if(lua_isuserdata(luaState, -1))
    {
        game = *static_cast<Game**>(lua_touserdata(luaState, -1));
    }
What if someone replace `Game` in that global variable? I think only way it could work properly is have only one type available in user data.
Some thing like this:
Code: [Select]
class DataPtr
{
    int _tag;
    void* _ptr;
public:
    template<typename T>
    T* Get()
    {
        return isType<T>(_tag) ? static_cast<T*>(_ptr) : nullptr;
    }
    template<typename T>
    const T* Get<const T>()
    {
        return isType<T>(_tag) ||  isType<const T>(_tag) ? static_cast<const T*>(_ptr) : nullptr;
    }

    static DataPtr GetPointer(lua_State* luaState)
    {
        if(lua_isuserdata(luaState, -1))
        {
            return *static_cast<DataPtr*>(lua_touserdata(luaState, -1));
        }
        else
        {
            return DataPtr{};
        }
    }
}
And `GetPointer` will be only way to get OXCE data from lua. This will allow checking for correct type and even allow encoding const in typeless language.
I used similar trick in my script engine.

Another thing is existing of `lua_gameGetFunds` and `execute1HourCallbacks`, in both cases it should be generic function that is responsible for boilerplate.
You can compare it to `ScriptBind.h` that I used for this. In best case I could add `so.add<&getRankScript>("getRank");` that convert normal C++ member function to special function that obey my "calling convention".
With this and `Get<T>` you can build one generic function that will convert and check prams before there are send to original C++ function.
Similar case when you call Lua scripts.

[ps]
one picnicking: OXC use tab for indents and it would be good to stick to it.
« Last Edit: September 19, 2018, 08:59:59 pm by Yankes »

Offline Whispers

  • Sergeant
  • **
  • Posts: 44
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #34 on: September 19, 2018, 10:06:00 pm »
Would be possible to get ride of `getGameFromLuaState` and use some kind of `this` pointer?

What if someone replace `Game` in that global variable? I think only way it could work properly is have only one type available in user data.
Some thing like this:

And `GetPointer` will be only way to get OXCE data from lua. This will allow checking for correct type and even allow encoding const in typeless language.
I used similar trick in my script engine.

Well, firstly, I'll be moving "xcom.__self"(the game pointer) to private metadata ASAP(or stick it directly in the registry, a hidden area accessible only to C/C++). Once I do that, I can set the access patterns(making it protected, hidden, and read only - http://lua-users.org/wiki/MetatableEvents), but I just wanted to play around with it and make sure I set it up correctly, so leaving it public for now just allows me to see it. At this moment, it's the only user object I plan on implementing, but once I get to the point where we are implementing local callbacks for objects, then yeah, I'll need to be more careful.   

There is no concept of "this" in Lua. Everything is done on a stack, so while it would be possible to create userdata objects in every metatable for use as an object pointer in C/C++, that is a lot of objects I don't think are necessary at the moment.

Also, the type is stored in the metatable(referenced as "Game") so there is type checking already available by using luaL_checkudata, but for brevity sake, just getting things in and testable is my first goal. Using a wrapper class is a bit extreme for now, but I will likely move to that eventually. Using luaL_checkudata is much better since it is already built in to Lua, just didn't spend the 2 secs to put that in. I'll do that now.

Another thing is existing of `lua_gameGetFunds` and `execute1HourCallbacks`, in both cases it should be generic function that is responsible for boilerplate.
You can compare it to `ScriptBind.h` that I used for this. In best case I could add `so.add<&getRankScript>("getRank");` that convert normal C++ member function to special function that obey my "calling convention".
With this and `Get<T>` you can build one generic function that will convert and check prams before there are send to original C++ function.
Similar case when you call Lua scripts.

Oh, that's exactly where I am going with this, but one thing I know about playing with templates is you ALWAYS want to have a working non-template version before you start wrapping things in nested template classes to make debugging and diagnosing issues easier. Today was hectic at work so I didn't get the chance to start the work on moving over to making it more generic and adding in the required templates. I do plan on showing off a little and using the variadic templates to allow for multiple parameter passing to script execute functions :P

[ps]
one picnicking: OXC use tab for indents and it would be good to stick to it.

Yeah, problem is when I switch from my laptop to desktop they both have different settings which aren't synced at the moment. I'll switch it to tabs for the next checkin :D

--- posts merged, please don't double-post ---

Sorry about that. I'll edit existing posts in cases where I was the last post :D

Yankes, I just saw the github comments. Just FYI that all github emails go to my spam folder.

To answer your question on github, yes, scripts are only ever loaded and executed once during game load. Their context is persisted though, which means that they have to register callbacks or else no part of the script will be run again, as such, yes, they are loaded from disk every time they are run, but they are only ever run once as a normal script. That was/is intentional.
« Last Edit: September 19, 2018, 10:51:19 pm by Whispers »

Offline Yankes

  • Global Moderator
  • Commander
  • ***
  • Posts: 3350
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #35 on: September 19, 2018, 11:03:23 pm »
Ok, I thought that event binding will be in yaml/c++,

And for "this", I recall (from some minor WoW Lua tweaks) that you call call some function that will pass object as one of arguments, syntax was probably `a:func()` or something. This call effective `func(a)`aka "this" pointer. Idea was that getting `game` through arguments will be faster than grabbing it from global context.
Of corse this whole could be wrong because I misremember some import details.

Offline Whispers

  • Sergeant
  • **
  • Posts: 44
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #36 on: September 19, 2018, 11:26:42 pm »
Yeah, event binding needs to be done in Lua to get the pre-indexed function ref. Also allows you to reference nested functions inside tables without the need for writing a function string to lua function ref, err, function.

Basically, if you did the function binding in rules, then I would have to parse out the function name. If the function name was global, like "on1Hour" was in the example, then it's easy, but if the function sits withing an object, then it would need to know what was on the stack prior, so something like "MyTable.on1Hour" would be possible, and "MyTable:on1Hour" would need to be handled as a special case. I'm lazy, so I didn't want to do that :D

On that topic, the call to get the game pointer as it is is slightly more expensive than using a function metamethod table. I might move that direction in a future revision, but having one, and only one userdata object in the xcom table made sense when I first started this. In fact, now that I think about it a little more, with the recent change where I split out the LuaGeoscapeBinding class, I might as well create a LuaGeoscapeApi class and use that for the metamethod table and store the game object there.

Edit: but it's not an optimisation, so much as it is cleaner for the API user
« Last Edit: September 20, 2018, 10:28:42 am by Whispers »

Offline Valmont

  • Sergeant
  • **
  • Posts: 16
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #37 on: September 22, 2018, 06:02:07 pm »
I hope that one day this Lua Integration could be used by modders to add multiplayer to OPEN X-COM in a similar way that Multi Theft Auto adds multiplayer to GTA San Andreas. That would make my life finally complete and I will be able to die in peace =)

Offline Meridian

  • Global Moderator
  • Commander
  • ***
  • Posts: 9094
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #38 on: September 22, 2018, 06:07:56 pm »
I hope that one day this Lua Integration could be used by modders to add multiplayer to OPEN X-COM in a similar way that Multi Theft Auto adds multiplayer to GTA San Andreas. That would make my life finally complete and I will be able to die in peace =)

@Whispers: called it

Also, please be careful with such words... our modders are not developers (with a few exceptions)... and they will believe you when you say they will be able to do "anything they want"... which is just unfair to them. E.g. I'm pretty sure Hobbes will not be able to "script" an online multi-player support, which he wants so much.
« Last Edit: September 22, 2018, 06:09:28 pm by Meridian »

Offline Hobbes

  • Commander
  • *****
  • Posts: 2102
  • Infiltration subroutine in progress
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #39 on: September 24, 2018, 10:39:48 pm »
E.g. I'm pretty sure Hobbes will not be able to "script" an online multi-player support, which he wants so much.

I better start by clarifying this: it's not in my plans to have online multi-player added to OXC

I love talking about UFO2000 because it was the xcom community where I really started modding terrains, and it was very fun to play against human opponents, but I also remember the endless synchronization bugs between players and how limited it was to only being able to mod the tactical part.

Offline Whispers

  • Sergeant
  • **
  • Posts: 44
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #40 on: September 25, 2018, 11:59:07 pm »
Well, I would love to continue the neural network discussion, but today I'm back at my normal keyboard and so I've begun the process of making the interfaces generic and adding in a TON of hooks.

As for the next steps, I want to see if I can get some basic geoscape coverage of events. This includes the usual, onUpdate, on1Hour, on1Day, etc, but also events when the aliens decide to do things(onAlienBaseCreated, onSubMissionStarted, etc) and basic detection (onCraftDetected, onActivityDetected, onTerrorDetected, etc). I'm trying to find ways to make it so that it's possible to override default behaviour so you can skip the popups that come up in a mod.

For instance, I made a quick script today that automatically finds the nearest base for when an alien craft is detected, and if the sub has weapons, has fuel, and isn't damaged, it sorts all subs matching the criteria and selects the one with the highest damage per second. It then allows me to add a button to the detection screen to auto-deploy the craft. That last part I'm still working on.

Offline Hobbes

  • Commander
  • *****
  • Posts: 2102
  • Infiltration subroutine in progress
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #41 on: September 26, 2018, 03:52:28 am »
As for the next steps, I want to see if I can get some basic geoscape coverage of events. This includes the usual, onUpdate, on1Hour, on1Day, etc, but also events when the aliens decide to do things(onAlienBaseCreated, onSubMissionStarted, etc) and basic detection (onCraftDetected, onActivityDetected, onTerrorDetected, etc). I'm trying to find ways to make it so that it's possible to override default behaviour so you can skip the popups that come up in a mod.

I've been thinking since we last discussed somewhere possibilities for the Geoscape and one simple graphical addition I've remembered would be to display infiltrated countries with a different color outline. Or when those countries see UFO activity on their borders, which would make it easier to for the player to spot them than having to constantly check the Graphs. And, from there add a 'contested' outline, for when a country sees both alien and XCom activities on their borders.

Offline Whispers

  • Sergeant
  • **
  • Posts: 44
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #42 on: September 26, 2018, 10:25:18 pm »
That is definitely within the scope of the Lua work. You will be able to read and write the region data, so it's simply a matter of setting the colour of a region and then capturing when a craft is launched and changing the behaviour via overrides.

Offline Whispers

  • Sergeant
  • **
  • Posts: 44
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #43 on: October 05, 2018, 10:56:38 pm »
Just figured I would give an update since I've been silent for the last week. My day job has been rather demanding recently, but I haven't given up on the Lua integration. I will keep you posted once the new version is up on GitHub.

Offline Whispers

  • Sergeant
  • **
  • Posts: 44
    • View Profile
Re: [OXCE+] Lua Integration
« Reply #44 on: November 06, 2018, 11:03:42 pm »
Another update - I'm back!!! Okay, so my real job significantly took up more time than I had planned for, but that is the nature of game development. no, for the record, I had nothing to do with Red Dead Redemption so don't ask :P

New geoscape bindings are pushed up to github. I'm still playing with the API a bit more, so the usual preamble of future changes may break compatibility applies :)