Page 1 of 1
Lua modules
Posted: Fri Apr 09, 2021 12:17 am
by n0b0dy007
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.
Re: Lua modules
Posted: Fri Apr 09, 2021 3:04 pm
by cicciopastic
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
Re: Lua modules
Posted: Sat Apr 10, 2021 12:12 pm
by n0b0dy007
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
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 ...
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
...
The single, shared definitions of functions
IsItemInTable(),
AddEquipment(),
&c can be moved to the library file
shared.lua.
Re: Lua modules
Posted: Sat Apr 10, 2021 1:45 pm
by cicciopastic
ah ok ... didn't know! tks a lot!
Re: Lua modules
Posted: Sat Apr 10, 2021 5:18 pm
by asuser
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?
Re: Lua modules
Posted: Sat Apr 10, 2021 6:54 pm
by n0b0dy007
asuser wrote: ↑Sat Apr 10, 2021 5:18 pm
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?
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
Posted: Sun Apr 11, 2021 1:24 pm
by n0b0dy007
n0b0dy007 wrote: ↑Fri Apr 09, 2021 12:17 am
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
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
Posted: Sun Apr 18, 2021 12:31 am
by n0b0dy007
As a baseline, here are the .lua files after slight clean-up and commenting:
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
Line and word counts as reported by
wc. Original files in attached .zip file.
Re: Lua modules
Posted: Wed Apr 21, 2021 9:30 pm
by cicciopastic
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
Posted: Sat Apr 24, 2021 12:25 pm
by n0b0dy007
n0b0dy007 wrote: ↑Sat Apr 10, 2021 12:12 pm
The single, shared definitions of functions
IsItemInTable(),
AddEquipment(),
&c can be moved to the library file
shared.lua.
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"
The latter tests the
package.loaded table and re-
requires the library module if missing.
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
Posted: Sat Apr 24, 2021 12:36 pm
by n0b0dy007
n0b0dy007 wrote: ↑Sun Apr 18, 2021 12:31 am
As a baseline, here are the .lua files after slight clean-up and commenting:
. Original files in attached .zip file.
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:
After moving the copied & pasted duplicates into a common
shared.lua library (and more clean up):
Even though the same copy of the module file exists in each AO campaign directory, the overall savings are:
Plus the time saved not having to find and fix the same defect in each & every copied and pasted (and sometimes slightly modified) piece of code.
The attached file has the raw data.
Re: Lua modules
Posted: Sat Apr 24, 2021 12:49 pm
by n0b0dy007
n0b0dy007 wrote: ↑Sat Apr 24, 2021 12:36 pm
After moving the copied & pasted duplicates into a common
shared.lua library (and more clean up):
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.)