1. We have added the ability to collapse/expand forum categories and widgets on forum home.
    Dismiss Notice
  2. All Civ avatars are brought back and available for selection in the Avatar Gallery! There are 945 avatars total.
    Dismiss Notice
  3. To make the site more secure, we have installed SSL certificates and enabled HTTPS for both the main site and forums.
    Dismiss Notice
  4. Civ6 is released! Order now! (Amazon US | Amazon UK | Amazon CA | Amazon DE | Amazon FR)
    Dismiss Notice
  5. Dismiss Notice
  6. Forum account upgrades are available for ad-free browsing.
    Dismiss Notice

Lua Objects

Discussion in 'Civ6 - Modding Tutorials & Reference' started by Gedemon, Oct 23, 2016.

  1. Siesta Guru

    Siesta Guru Chieftain

    Joined:
    Dec 2, 2007
    Messages:
    489
    Location:
    The Netherlands
    So I did a bunch of testing on this, because it sounds like it could work, but no luck so far.
    Stopping the AI from doing any thing with the units works, but then I've been unable to find a way to get the RequestOperation to work

    Every turn these four events get processed in this order: PlayerTurnStarted, PlayerTurnStartComplete, PlayerTurnActivated, PlayerTurnDeactivated
    Additionally, the events RemotePlayerTurnBegin and RemotePlayerTurnEnd seem to get called every turn. But their ordering is independent of the order of the other 4

    Move points get restored between PlayerTurnStarted and PlayerTurnStartComplete.
    The AI seems to do its thing between PlayerTurnStartComplete and PlayerTurnActivated.

    The AI could indeed be prevented from acting by setting the unit moves to 0 in PlayerTurnStartComplete
    But then regardless of what other Event I tried to put the move restore and operation request in, I couldn't get anything to work.

    CanStartOperation always returns true in PlayerTurnStarted and PlayerTurnStartComplete and always returns false in PlayerTurnActivated and PlayerTurnDeactivated, regardless of how I placed the restores

    Strangely enough, by immediately checking a units moves after calling the replenish I can confirm the replenish works, however, when back in the UI context method, the amount of moves is back to 0. This happens regardless of whether I check instantly or wait until the next event.

    I'm not sure whether the problem is that it's just fundamentally impossible, or that the events are not timed well enough, or whether the move replenish is not working as intended.
     
  2. Ewok-Bacon-Bits

    Ewok-Bacon-Bits Chieftain

    Joined:
    Oct 23, 2016
    Messages:
    166
    Can we *now* edit/define exposed member values in the UI context and still get those values from the gameplay script? I wasn't able to do that so I was using different methods to pass UI variables to the gameplay script before.
     
  3. Gedemon

    Gedemon Modder Moderator

    Joined:
    Oct 4, 2004
    Messages:
    7,640
    Location:
    France
    Damn, that's frustrating !

    I was going to answer that I was always able to pass them from UI to gameplay, but now that I think of it, that could explain some inconsistencies in my data...
     
  4. Ewok-Bacon-Bits

    Ewok-Bacon-Bits Chieftain

    Joined:
    Oct 23, 2016
    Messages:
    166
    You guys got my hopes up :lol: but maybe it did change I don't know.

    Also this might be a stupid question but since we can use Include("File") could we pass variables/functions through that between script and UI that way?
     
  5. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,559
    Location:
    Illinois, USA
    Code:
    include("File")
    adds the contents of whatever is in the file called "File" into the lua code at the point where the include("File") is positioned. You can therefore use it to add identical functions or variable names/values into multiple files, but it is not in any way dynamic, and does not allow passing of changes in the values assigned to these variables between contexts. So you cannot use it to pass info back and forth. Even if two Gameplay scripts both have the same include statement, changes to the value of a variable that was stated in "Flie" in the first of these Gameplay Scripts will not generally be picked up in the second -- the second will continue to use the original unaltered value that was established for that variable name within "File".

    You need to think of the "include" command as saying
    The problem with including the same file into both a Gameplay Script and a UI Script is that methods that are valid in UI are not always valid in Gameplay and vice versa, and the wrong method in the wrong context (UI or Gameplay) will either lock the game or cause the file to fail loading. So you must ensure that the entire contents of such a file are valid in both UI and Gameplay.
     
    Last edited: Mar 2, 2018
    Ewok-Bacon-Bits likes this.
  6. Infixo

    Infixo Warlord

    Joined:
    Jan 9, 2016
    Messages:
    2,210
    Gender:
    Male
    Location:
    Warsaw
    It’s not clear from your post, but do you run all this ops within AI events or LocalPlayer events?
     
  7. Infixo

    Infixo Warlord

    Joined:
    Jan 9, 2016
    Messages:
    2,210
    Gender:
    Male
    Location:
    Warsaw
  8. Siesta Guru

    Siesta Guru Chieftain

    Joined:
    Dec 2, 2007
    Messages:
    489
    Location:
    The Netherlands
    Not entirely sure what you mean. I've got lua scripts in both the gameplay and ui contexts and am using events (mostly GameEvents.PlayerTurnStartComplete) to execute code

    Yes, I had to split my code to make this possible. I'm hooking up both the UI and Gameplay based code using events. I've both tried to do the ordering of code executions purely through those game events, and also through using ExposedMembers to execute in the other context. I could confirm the latter was in fact capable of executing Gameplay-context inside of code triggered in the UI-context
     
  9. Infixo

    Infixo Warlord

    Joined:
    Jan 9, 2016
    Messages:
    2,210
    Gender:
    Male
    Location:
    Warsaw
    I am refering to this:
    UI might expect that the unit is selected. The game internally moves units in its own "enginy" way, but RequestOperation and RequestCommand are designed to be used within UI context.
     
  10. Siesta Guru

    Siesta Guru Chieftain

    Joined:
    Dec 2, 2007
    Messages:
    489
    Location:
    The Netherlands
    I'm calling these in the UI context. I've also suspected that selection may be important and tried manually calling the SelectUnit function. The result was a lot of noise, and the unit bar popping in and out during AI turns, but with no impact on the ability to use UnitManager.RequestOperation. It's clear RequestOperation was never really intended to be used this way, but sometimes it still ends up being possible.
    Not sure yet whether RequestCommand does work, it's a little harder to test.

    Interestingly, CityManager.RequestOperation does in fact work (at least for some units) and overrides all AI building choices, which is something I'm going to heavily abuse for AI+.
     
  11. MAHRana

    MAHRana Chieftain

    Joined:
    May 22, 2010
    Messages:
    268
    Any chance somebody can update this with Rise and Fall objects?
     
  12. blackbutterfly

    blackbutterfly Chieftain

    Joined:
    May 9, 2016
    Messages:
    712
    Gender:
    Male
    Location:
    Leeds, UK
    Do we know the reason why there are separate contexts for UI and gameplay?

    Does the UI run in a separate thread to gameplay?

    If so (which maybe the case cos Civ VI is noticeably more multi-threaded than Civ V) then is it thread safe to pass parameters?

    AFAIK Lua doesn't appear to have been designed with thread safety in mind (unlike say Scala, a language I'm a lot more experienced with). IDK

    Perhaps passing parameters between contexts might cause hangs or deadlocks.

    Just sayin' :)
     
  13. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,559
    Location:
    Illinois, USA
    It was to speed up the game. And yes, UI and Gameplay run in different threads.

    Firaxis' design intent for Civ6 was to eliminate as much as possible the need for complex "gameplay" scripts by moving the crazy stuff we did in Civ5 with lua into the XML/SQL Dynamic Modifiers system. The game's DLL therefore directly runs the Modifiers code, and is about 100 - 1000 times faster than execution in lua ever can be. Because of this approach to what can be done in mods, they did not implement a lot of things in the Gameplay context because the assumption was this would all be done in the XML and executed by the DLL at "game-engine" level. Plus they also wanted to make complex modding more accessible, which the DynamicModifiers and GameEffects systems do, but at a price that if Firaxis did not think of the need for EFFECT_X or REQUIREMENT_X or COLLECTION_X there is no way to achieve an effect with the DynamicModifiers system -- which a completely-implemented Gameplay lua API would take care of (as it pretty much darn near did in Civ5).
     
    Atlas627, blackbutterfly and FearSunn like this.
  14. Gedemon

    Gedemon Modder Moderator

    Joined:
    Oct 4, 2004
    Messages:
    7,640
    Location:
    France
    I don't think modifiers can replace scripting, it allows nearly infinite variations using the core rules of the game and is fantastic for civilizations/leaders modding, but it's completely useless when you want to change those core rules.
     
  15. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,559
    Location:
    Illinois, USA
    I agree. I was just explaining what it is that we have, and what Firaxis' intent seems to have been. What we actually want or need as mod-makers is another vat of haggus entirely.
     
  16. blackbutterfly

    blackbutterfly Chieftain

    Joined:
    May 9, 2016
    Messages:
    712
    Gender:
    Male
    Location:
    Leeds, UK
    Then modders have to be careful about passing values between the gameplay and UI context. It is inter process communication.

    This is already challenging with open published APIs. Here we know next to nothing about these APIs apart from introspection by the modding community. Civ VI is already pretty flaky, so modders should take care not to add any more contention.

    Anyway, like you, I expect the reason you would want to access the other context is cos of API.

    In particular, for my scenario Colonization of The New World, I try to score VP for artefacts. But the API to help determine the type of a great work is in the UI context. So I was also thinking of trying to access the UI context from gameplay.

    But now on second thought, this may be a very bad idea and avoided if at all possible, cos they run in different threads.

    So any suggestions how to do this? I also looked at the event for when a resource is removed, cos archeology is considered a resource, but it gets called twice. Also it seems a little hacky to me :p
     
    Last edited: May 31, 2018
  17. Gedemon

    Gedemon Modder Moderator

    Joined:
    Oct 4, 2004
    Messages:
    7,640
    Location:
    France
    AFAIK you won't crash the game doing that, you just need to keep in mind that UI is working on cached data, while gameplay use game core data.
     
  18. Tiramisu

    Tiramisu Chieftain

    Joined:
    Aug 16, 2013
    Messages:
    129
    Location:
    Leonberg (BW, Germany)
    So it is possible to send informations from UI context to Gameplay context and vice versa? I am still a Lua beginner. So can someone explain this to me please?

    E.g. I want to to check if a city is an original capital city in gameplay context. The function IsOriginalCapital is only available in UI context, so I need to find a way to pass this information to my gameplay script.
    Another reason why I need to send informations from one context to another is that I want to use the UI-function GameConfiguration.SetValue to save datas from gameplay context (see https://forums.civfanatics.com/threads/saving-loading-simple-tables-with-a-game.609397/)
     
  19. Gedemon

    Gedemon Modder Moderator

    Joined:
    Oct 4, 2004
    Messages:
    7,640
    Location:
    France
    in the page you've linked, see
    Code:
    ExposedMembers.SaveTableToSlot = SaveTableToSlot
    at the end of the first code block (the one in UI context)

    it then allows the use of
    Code:
    ExposedMembers.SaveTableToSlot(t, "myTable")
    in any context, once all files are loaded.

    you can also pass values using LuaEvents as shown here :
    https://forums.civfanatics.com/threads/help-with-changegoldbalance.623730/#post-14900833
     
  20. Chrisy15

    Chrisy15 Limmu

    Joined:
    Jul 9, 2015
    Messages:
    1,935
    Code:
    
    -- UI
    
    function FunctionInUI(args)
        local pCity = -- Get the City
        if pCity:IsOriginalCapital() then
            LuaEvents.Tiramisu_OriginalCity_Event(someOtherArgs)
        end
    end
    
    GameEvents.SomeEvent.Add(FunctionInUI)
    
    -- Gameplay
    
    function FunctionInGameplay(someOtherArgs)
        -- Do stuff
    end
    
    LuaEvents.Tiramisu_OriginalCity_Event.AdD(FunctionInGameplay)
    
    LuaEvents (like all Events) will run functions from both contexts when called.

    Hm ninjaing's really boring now isn't it :(
     

Share This Page

Ebates: Get Paid to Shop