Lua modules
Moderator: Panzer Corps 2 Moderators
Lua modules
The UE4 plugin for Lua https://github.com/rdeioris/LuaMachine supports Lua 5.3 (https://www.lua.org/manual/5.3/manual.html), which supports modules.
As it turns out, the plugin used in PC2 sets package.path to a value reflecting the location of the campaign directory containing the script.lua file. e.g. ../../../PanzerCorps2/Content/Campaigns/AO0Spain/?.lua
What this means is that the scenario scripts can stop the copy and paste of utility functions like FindItemInTable(), SpawnWave(), &c.
Putting these in a module file in the same directory as the campaign's script.lua file should make it possible for scenario script files to require the file and share/reuse the utility functions.
As it turns out, the plugin used in PC2 sets package.path to a value reflecting the location of the campaign directory containing the script.lua file. e.g. ../../../PanzerCorps2/Content/Campaigns/AO0Spain/?.lua
What this means is that the scenario scripts can stop the copy and paste of utility functions like FindItemInTable(), SpawnWave(), &c.
Putting these in a module file in the same directory as the campaign's script.lua file should make it possible for scenario script files to require the file and share/reuse the utility functions.
Last edited by n0b0dy007 on Sat Apr 10, 2021 7:28 pm, edited 1 time in total.
-
- Administrative Corporal - SdKfz 232 8Rad
- Posts: 173
- Joined: Mon Oct 26, 2015 9:01 pm
Re: Lua modules
Not sure if i understood your post so maybe my answer might be silly ...
.
If you want to implement a LUA script for your scenario scenario it must be named as the current scenario and included in the scenario directory. you may use functions from different scenarios as long as u paste and copy them in your scenario script and they still have a correct meaning (eg suppose your scenario as a map 30x30 all hexes indication must be in that range).
hope this may help you, good luck

If you want to implement a LUA script for your scenario scenario it must be named as the current scenario and included in the scenario directory. you may use functions from different scenarios as long as u paste and copy them in your scenario script and they still have a correct meaning (eg suppose your scenario as a map 30x30 all hexes indication must be in that range).
hope this may help you, good luck
Re: Lua modules
The whole point of using modules is to avoid the copy & paste, which creates an untenable maintenance problem once there are 139 or more .lua files that have to be checked and possibly modified the exact same way to make the exact same change ...cicciopastic wrote: ↑Fri Apr 09, 2021 3:04 pm you may use functions from different scenarios as long as u paste and copy them in your scenario script
This works:
In scenario file (such as Seville.lua):
Code: Select all
lib = require "shared" -- file shared.lua in campaign directory ../AO0Spain
...
function OnCaptureVillage(action)
if lib.IsItemInTable(Village, action.flag) then
lib.AddEquipment(player, unit, amount, Captured)
...
end
end
...
-
- Administrative Corporal - SdKfz 232 8Rad
- Posts: 173
- Joined: Mon Oct 26, 2015 9:01 pm
Re: Lua modules
ah ok ... didn't know! tks a lot!
Re: Lua modules
Looks interesting!
The question is whether a central LUA library is easier to control than a separate LUA file for each individual scenario. So far, the developers have also opted for the separate LUA files - do you have better error control here?
The question is whether a central LUA library is easier to control than a separate LUA file for each individual scenario. So far, the developers have also opted for the separate LUA files - do you have better error control here?
Re: Lua modules
For some definition of "control."
As of the AO1941East DLC, there are 139 .lua files. Most of them have the same copy & paste, some of which are not even needed in a given scenario file (benign latent defects). The error potential, when making a change, is updating some but not all of the places where the identical code has been repeated. That error potential increases as more .lua files are added in subsequent DLCs, using the same (or subtly different) copy & paste. Consolidating the copied & pasted code into a shared library file (or, at least, one per campaign), reduces the error potential by two orders of magnitude (139 -> 4). Basic software engineering.
Consider some of the changes discussed elsewhere in this forum: such as changing the EnemyHero() and/or PlayerHero() functions to randomize traits, with the latter not duplicating attributes on Hero instances generated previously in the campaign. Currently, there are 274 Hero-related functions (although, to be fair, that number could be reduced significantly during refactoring via better parameterization). Editing so many places to update the logic is tedious and time-consuming (which probably explains why it hasn't happened). And that is without considering the similar-but-different "Nemesis" generation.
Re: Lua modules
For the stand-alone scenarios in Content/Scenarios, the path is: ../../../PanzerCorps2/Content/Script/?.lua, a directory that does not exist. (Keep this in mind if moving a campaign's scenario to the stand-alone directory.)
Creating the Script/ directory and putting any shared library .lua file(s) in it means that all stand-alone scenarios can share and re-use the same set of utility functions (similar to how all the scenario scripts of a campaign can share).
Re: Lua modules
As a baseline, here are the .lua files after slight clean-up and commenting:
Line and word counts as reported by wc. Original files in attached .zip file.
Code: Select all
Lines Words File
40 146 AO0Spain/script.lua
365 1852 AO0Spain/01Seville/Seville.lua
418 2001 AO0Spain/02Antequera/Antequera.lua
225 948 AO0Spain/03Merida/Merida.lua
104 360 AO0Spain/04Toledo/Toledo.lua
374 1638 AO0Spain/05EarlyMadrid/EarlyMadrid.lua
369 1629 AO0Spain/06CorunnaRoad/CorunnaRoad.lua
81 274 AO0Spain/07Malaga/Malaga.lua
223 836 AO0Spain/08Brunete/Brunete.lua
248 1237 AO0Spain/09Zaragoza/Zaragoza.lua
114 381 AO0Spain/10Bilbao/Bilbao.lua
166 695 AO0Spain/11Gijon/Gijon.lua
356 1532 AO0Spain/12Teruel/Teruel.lua
110 359 AO0Spain/13Aragon Offensive/AragonOffensive.lua
425 1893 AO0Spain/14Battle of the Ebro/BattleoftheEbro.lua
86 289 AO0Spain/15Catalonia/Catalonia.lua
158 613 AO0Spain/16Madrid1939/Madrid1939.lua
46 174 AO1939/script.lua
258 1141 AO1939/01Czechoslovakia/Czechoslovakia.lua
448 1901 AO1939/02Sarreguemines/Sarreguemines.lua
269 1452 AO1939/03WarndtForest/WarndtForest.lua
235 931 AO1939/04Orenthal/Orenthal.lua
160 675 AO1939/05Forbach/Forbach.lua
345 1780 AO1939/06Saarbrucken/Saarbrucken.lua
305 1540 AO1939/07Bzura/Bzura.lua
90 455 AO1939/08Modlin/Modlin.lua
75 429 AO1939/09BrestLitovsk/BrestLitovsk.lua
86 448 AO1939/10Lvov/Lvov.lua
74 416 AO1939/11Wlodawa/Wlodawa.lua
342 1622 AO1939/12Warsaw39/Warsaw.lua
181 692 AO1939/13RaateRoad/RaateRoad.lua
201 1004 AO1939/14Taipale/Taipale.lua
92 444 AO1939/15Denmark/Denmark.lua
74 308 AO1940/script.lua
405 1604 AO1940/01Fornebu/Fornebu.lua
132 777 AO1940/02UndisclosedLocationCZ/UndisclosedLocationCZ.lua
167 690 AO1940/03ValkenburgRaid/ValkenburgRaid.lua
218 1017 AO1940/04Grebbeberg/Grebbeberg.lua
130 484 AO1940/05EbenEmael/EbenEmael.lua
324 1477 AO1940/06Hannut/Hannut.lua
322 1510 AO1940/07Sedan/Sedan.lua
394 2062 AO1940/08Arras/Arras.lua
201 806 AO1940/09Lille/Lille.lua
278 1386 AO1940/10Dunkirk/Dunkirk.lua
402 2161 AO1940/11Abbeville/Abbeville.lua
218 911 AO1940/12Neufchateau/Neufchateau.lua
106 548 AO1940/13ChannelIslandTraining/ChannelIslandTraining.lua
189 831 AO1940/14Dover/Dover.lua
332 1516 AO1940/15Brighton/Brighton.lua
406 2029 AO1940/16Epsom/Epsom.lua
191 805 AO1940/17Portsmouth/Portsmouth.lua
164 641 AO1940/18Pindus/Pindus.lua
289 1449 AO1940/19Valona/Valona.lua
99 354 AO1941East/script.lua
541 2309 AO1941East/01Zagreb/Zagreb.lua
185 759 AO1941East/02Yugoslavia/Yugoslavia.lua
114 433 AO1941East/03Thessaloniki/Thessaloniki.lua
288 1258 AO1941East/04Thermopylae1941/Thermopylae1941.lua
411 2024 AO1941East/05OperationMercury/OperationMercury.lua
540 2947 AO1941East/06UndisclosedLocationPO/UndisclosedLocationPO.lua
417 1901 AO1941East/07Raseiniai/Raseiniai.lua
357 1473 AO1941East/08StalinLine/StalinLine.lua
158 670 AO1941East/09Tallinn/Tallinn.lua
442 1734 AO1941East/10ApproachingLeningrad/ApproachingLeningrad.lua
297 1203 AO1941East/11Minsk1941/Minsk1941.lua
268 1146 AO1941East/12Smolensk1941/Smolensk1941.lua
274 1389 AO1941East/13YelnyaOffensive/YelnyaOffensive.lua
144 535 AO1941East/14Gomel/Gomel.lua
316 1292 AO1941East/15Lokhvitsa/Lokhvitsa.lua
192 788 AO1941East/16Kiev1941/Kiev1941.lua
199 902 AO1941East/17Bryansk/Bryansk.lua
200 838 AO1941East/18MozhaiskLine/MozhaiskLine.lua
416 1945 AO1941East/19BattleofMoscow/BattleofMoscow.lua
360 1471 AO1941East/20Klin/Klin.lua
- Attachments
-
AOCampaigns0.zip
- (221.28 KiB) Downloaded 78 times
-
- Administrative Corporal - SdKfz 232 8Rad
- Posts: 173
- Joined: Mon Oct 26, 2015 9:01 pm
Re: Lua modules
I reread your posts ... luckily i work on a single scenario, so i really don't need any script management. Anyway i find your point very interesting and don't understand current LUA script management by the designer.
Re: Lua modules
One very important caveat:
Due to a defect in the UE4 Lua plugin, re-loading does not re-load required .lua files.
As a work-around, the library module needs to:
- set the module table as global, not local
- for each function attached to the module table (and hence callable from scenario scripts), include a "re-load guard"
For example:
Code: Select all
-- shared.lua - utility function module for scenario scripting
-- Usage:
-- Use lib. prefix for utility and support functions:
-- lib = require "shared" -- file shared.lua in parent campaign directory
Mshared = {} -- Module table (needs to be a global, for re-loads ... defect in UE4 Lua plugin)
-- UE4 Lua plugin work-around: re-loads do not re-load "require"d modules, so each module function has a re-load guard for that case
-- Also, the Mshared variable can _not_ be local, because the re-load failure causes a nil _ENV (preventing use of global functions)
----------------------------------------------------
-- Utility functions: generic Lua table searching --
----------------------------------------------------
function Mshared.FindItemInTable(atable, item) -- returns integer index of item in table, or -1 if not found
if (not package.loaded["shared"]) then Mshared = require "shared" end -- re-load guard
for index,value in pairs(atable) do
if (value == item) then return index end -- found
end
return -1 -- not found
end
Re: Lua modules
Line and word counts as reported by wc -l -w (not a perfect SLOC count, but close enough) for the original (commented and slightly cleaned up) AO* .lua files:
- 18,229 82,170
- 12,194 62,966
- 33.11% 23.37%
The attached file has the raw data.
- Attachments
-
Comparison.zip
- (8.21 KiB) Downloaded 66 times
Re: Lua modules
The attached file contains the revised Lua scripts used in the above comparison. The additional comments inflated the counts slightly.

Note that the shared.lua library module is duplicated in each of the campaign directories.
This redundancy could be removed if you want to take the trouble to override the UE4 Lua plugin setting to set package.path to a value reflecting the location of the shared file.
(The default is currently ../../../PanzerCorps2/Content/Campaigns/campaign-name/?.lua for each scenario script.)
- Attachments
-
AOCampaignsRevised.zip
- AO campaign .lua scripts and shared library module
- (200.8 KiB) Downloaded 70 times