[TOTPP] Lua Scenario Template

If I want to "require" another custom Lua file, I know that I can place the command to do so at the top of one of the "on___.lua" files within the EventsFiles folder, and that works fine to make my separate module (consisting of multiple local variables and functions) available in that file. But if I want my code to be available to several such files, and I place a separate "require" statement at the top of each corresponding file, this is basically re-reading my file each time, and -- here's my issue -- creating a separate instance of it in memory. This means the contents of the local variables I'm defining there have limited scope -- they aren't being broadly shared.

That's not how require works. Require only runs the file once, then checks package.loaded[module_name] for the table that is returned after that (or rather, if there is nothing in package.loaded, it runs the file). See here. You can also check this by using a civ.ui.text call in a file that you require by multiple files. That message will only be shown once, since the file is only read once.

The local variables will have adequate scope. For example, in the General Library, I provide a function gen.getState() which provides a way to access the state table (in the template, it actually links to a subtable, I believe), and gen.linkState(stateTable) to store the stateTable in a local variable. gen.linkState is called in the discreteEventsRegistrar.lua file, while gen.getState is called in whatever file is needed, and they work.

I think this means that using require('customModule') at the top of any relevant file actually does what you want.
 
Well, I wasn't getting the behavior I wanted, but perhaps there's another reason for that. I may have attributed it incorrectly to this type of "scope" issue. I'll retest in light of this additional info about "require". Thanks for your response!

EDIT: I did discover and fix a different issue, which was causing the variables that I set to get cleared out before they were checked. After fixing that, now it works as you said: putting require('customModule') at the top of every file where I need to reference either the variables or functions gives me access to the single memory instance. :thumbsup:
 
Last edited:
@Prof. Garfield I have another couple questions, sorry. (Hopefully they're easy ones for you... I could probably start looking through the LST code to try and find the answers myself, but I suspect that would take far longer!)

TOTPP 0.17 added support for firing civ.scen.onActivateUnit after every move by a human-controlled unit. How has this been integrated into the LST? Is it enabled by default in the most recent version? If so and if this behavior was not desirable for some reason, is there a configuration flag that will turn it off and restore the previous behavior?

Secondly: in the latest version of the LST, I see there is a file named onEnterTile.lua file which I think is what you discussed here. It seems to work well in my basic testing, so great job building that as a way to meet a need that TNO hasn't yet addressed. My question is, does that functionality depend upon enabling civ.scen.compatibility.activateUnitEveryMove? If I can disable that new activation behavior, will that break onEnterTile?
 
TOTPP 0.17 added support for firing civ.scen.onActivateUnit after every move by a human-controlled unit. How has this been integrated into the LST? Is it enabled by default in the most recent version? If so and if this behavior was not desirable for some reason, is there a configuration flag that will turn it off and restore the previous behavior?

I activate it in parameters.lua
Code:
function discreteEvents.onScenarioLoaded()
    civ.scen.compatibility.activateUnitEveryMove = true
end

Secondly: in the latest version of the LST, I see there is a file named onEnterTile.lua file which I think is what you discussed here. It seems to work well in my basic testing, so great job building that as a way to meet a need that TNO hasn't yet addressed. My question is, does that functionality depend upon enabling civ.scen.compatibility.activateUnitEveryMove? If I can disable that new activation behavior, will that break onEnterTile?

I expect it to break if you disable activateUnitEveryMove. I also tied it into an unused onDrawTile event, but that is only meant to trigger when there is no "next" active unit.

Use the repeatMove argument in onActivateUnit(unit,source,repeatMove) to determine if the unit is being activated because it just moved:

onActivateUnit
civ.scen.onActivateUnit(function (unit, source, repeatMove [since 0.17]) -> void) -> void

Registers a function to be called every time a unit is activated. The callback takes the unit activated as a parameter, and the source of unit activation. `source` is `true` if activated by keyboard or mouse click, `false` if activated by the game itself. `repeatMove` is `true` if it's a repeat activation caused by moving (see civ.scen.compatibility), `false` otherwise.

The only thing I can think of that this breaks is if you want attack bonuses to remain after a unit leaves a leader's square, which I suppose has been fairly popular. My intention is to reimplement attack bonuses in the combat calculator module, and use the state table to bestow bonuses to units for the remainder of a turn.
 
I activate it in parameters.lua
Thanks. I couldn't find it in simpleSettings.lua, and then decided that I really didn't know my way around the LST structure well enough to narrow down my search (without opening every single file).

I expect it to break if you disable activateUnitEveryMove. I also tied it into an unused onDrawTile event, but that is only meant to trigger when there is no "next" active unit.

Use the repeatMove argument in onActivateUnit(unit,source,repeatMove) to determine if the unit is being activated because it just moved:
Thanks for the reminder about the additional "repeatMove" parameter for onActivateUnit. I think I can leverage that to do what I need without disabling the feature after all.

The only thing I can think of that this breaks is if you want attack bonuses to remain after a unit leaves a leader's square, which I suppose has been fairly popular. My intention is to reimplement attack bonuses in the combat calculator module, and use the state table to bestow bonuses to units for the remainder of a turn.
In this case it was actually custom popup messages that are appearing too often (after every move) instead of only upon the fresh activation of a unit. But I think suppressing them when repeatMove == true should be effective. Thanks again.
 
@Prof. Garfield Me again. Can I propose a change to LuaCore/helpkey.lua?

I'd like to request that line 64 be changed from
helpWindow:addText(func.splitlines("\n^"..unitTextFunction(helpUnit)))
to
text.addMultiLineTextToDialog("\n^"..unitTextFunction(helpUnit),helpWindow)

This necessitates adding local text = require "text" to the top of the file (moving the changed line down to 65).

Rationale: right now, unitTextFunction() in MechanicsFiles/helpkeySettings.lua can only return a single line of text. If I attempt to return multiple lines, only the first is added to the dialog and the remainder are discarded. With this change, multi-line support seems to work well.
 
Hello @Prof. Garfield,
I'm currently using your latest LUA Template and an error message was displayed when one of my units got promoted. I didn't change anything on the promotion module so I would like to ask you what I have to do to solve the error
upload_2022-6-26_17-13-19.png
 
Option 1: Use CTRL+Shift+F4 to create an LST rules file.

Option 2: in MechanicsFiles/promotionSettings.lua comment out line 12
Code:
promotionChanceTable = rules.promotionChanceTable
 
Hello @Prof. Garfield,

another little question:
I'm using the following code which should give a 50% chance that the Ottomans can capture an enemy Galleon.
Code:
if loser.type == object.uGalleon and loser.owner == object.pSpanishHabsburgEmpire and loser.location.terrainType ~= 10  and math.random() < .5 then
    local tribe = object.pOttomanEmpire
    civ.ui.text("Our navy captured a "..tostring(loser.adjective).." Galleon.")
    civlua.createUnit(object.uGalleon, object.pOttomanEmpire {{winner.location.x,winner.location.y,winner.location.z}}, {randomize=false, veteran=false})
    end

Unfortunatelly it doesn't work so I think it's because of the value given at
Code:
loser.location.terrainType ~= 10
. Which value do I have to use so that the code also works on ocean terrains?
 
Which value do I have to use so that the code also works on ocean terrains?

Just remove the check completely. That is,
Code:
if loser.type == object.uGalleon and loser.owner == object.pSpanishHabsburgEmpire and math.random() < .5 then
 
I've now another problem, though I actually don't know if it is caused by the LUA template, ToTPP or a bug from the game itself. I'm currently using the latest versions of ToTPP and LUA template, so I'm afraid it's caused by one of them.
I've an event running which spawns barbarian units who attacks the players cities. Everytime when more units attacking another unit or a city, the game crashes and I get back to the desktop.

I will try to check this with my old files.
 
Hello @Prof. Garfield,
I've tested the event on my old Reformation scenario, where I used a former version of your template. The game didn't crash. I think there could be troubles with your latest template.
I would like to ask you, if you have the version of your template available I used for my scenario? As far as I know it should be from summer last year.

If you wish I can send you my current scenario files including the event, where the game crashes.
 
If you wish I can send you my current scenario files including the event, where the game crashes.

That would be helpful. Git should be able to backtrack to an older version of the template, but I'd rather actually fix the problem if I can re-create it.
 
@civ2units, @tootall_2012

This events.lua file appears to fix the crash described above. Let me know if you still have issues.
 

Attachments

This should work.

The onEnterTile feature normally takes advantage of the onActivateUnit execution point for the next unit to work (and the end of player turn point for the last unit). However, since the human player sometimes has no unit active, I leveraged onDrawTile (an apparently unfinished feature) to occasionally check if there is a unit that needs the onEnterTile code to be run. This appears to be malfunctioning, so I have removed it completely here.

Note: The issue actually appears to have something to do with civ.getCurrentTribe(), based on my earlier tests, and I thought that I had worked around that issue.
 

Attachments

Hello @Prof. Garfield,
I would like to ask you if I have to initialize the flags manually? Until now I only set in object.lua the flags like this example
Code:
flag.define("OttomanDamascusconquered", false)
and changed the value of it in another code (conquering a city for example) which worked fine.

I got this error message and would like to ask if I have to list all flags in consolidated.lua again for initializing?
upload_2022-7-1_18-34-19.png
 
Back
Top Bottom