-Locals Variant-

This scene contains 2 events that atm run every minute (oviously in real life change the trigger timer to something more like hour or two or every 24hr.).  It demos two little self-contained 'local' scripts in the 2 events to do the following:

a) One script process a list of loadouts you want added to a bunch of specific units in whatever quantities you want (within reason), so long as those units still exist at time of execution, ie are not destroyed, or their muniton storage is not destroyed.

 

b) The other script processes a list of units where you wan their mags filled up, and allows the user to specify how they want those units' mags filled. a) all mags, all weapon records in order up to the magazine capacity limits. b) only a specific mag... up to the limits. c) only a specific weapon record up to the limits of it's containig mag.  d) modifiy a specific record(s) and set them to a specific amounts, which is handy when mag capacity is limited for whatever reason and you want 20 of these, and 12 of that other thing to stay under say a 32 cap.   This all presumes said units, said mags, and said wpn records still exist at time of execution....if they've been destroyed, that's ok, the script should just log a failure and continue on its way working it's way through the rest of the list.

The Refilling of unit Mags action script has a table at the very top, this is where you add or remove what you want done. Tables are pretty simple {} <- is a table, {{name=123},{name=456}} <-is a table with two records, both tables themselves.  

from the script:

{name='SAM Bn S-400 #2', guid='4FH7PU-0HMNDPRJL99BD',comment="attempts maxcap fill all mags on unit"}, 
These are the only things you need to add\remove\comment out (--) or change, you need to give your entry a name, the guid of the unit to act on (ctrl-c, paste will provide that for you), and that's all you need for it to try to re-fill all weapons on all mags in numerical order.

You will see in the sample table definition addition examples with additional fields like:

quantity=24 - this means instead of trying to fill each weapon record to it's max, you want it set to this number, not added or subtracted but set to this number.  If provided the script will attempt that, provided the cap is not exceeded.

specific_magguid="guid-here", - include this when you want this entry to only operate on a specific magazine that you have snooped out head of time. The script will ignore all other mags on a unit that don't match this mag_guid.  

specific_wpnrecguid="guid-here", - include this when you want this entry to only operate on a very specific weapon record that exists in some mag on the unit. The script will ignore all other wpn records on a unit that don't match this wpn_guid.  Usually when using this you'll want to provided the specific_magguid option too, if you don't it'll still work just fine, it's just the code will go searching in all mags (places it doesn't needed too -slower), but it'll eventually find it.

How do you find a mag guid or weapon record guid?  Good question you pop into the lua console and print the unit's magazines , and comb though looking for the mag_guid that matches the one you want.  I put a sample in the special actions here that you copy and paste into the console, just changing the unit guid at the top.  You're looking for mag_guid and wpn_guid entries in the table that at the same level share the mag_name or wpn_name you see in the gui etc.

 

The sample scene starts out as follows, and with the following things to sort of watch for after the trasition from start into the next minute marker:  

The DDG:  The helocopter mag starts with 4 of each item,a fter the 1st minute they should be full. The Torpedo Magazine starts with 32/34 Mk54 LHT Mod0's, after the first minute it should only have 24/34, because it's table entry say that's what we want exactly (it's not an addition), that said if you put it to 34 it will fail because the mag itself is capped at 34 and there is 2 used up to start by the mk46's. You dig?  Magazine caps are a big part of managing maniputlation outside of the airbase loadout filler routines things can't break the limits - but if you try my scripts will log the issue as best it can so you know what to go look at when that happens.  Anyway let's move on.  The DDG also has a generic munitions mag(has 10k cap), in it are some extra rim-174a's, in a 1/64 weapon record, after the first minute this will be filled to 64, you can set it to whatever you want, every cycle it'll get maxed out to 64.  

The Two s-400 sites each have additional generic 10k cap munitions entries added, each with an 10k entry for sa-21b's.  One starts at 0/10k, the other at like 1234/10k, both will get filled to 10k on each cycle because their table entry say to attempt to maxout all mags, all weapon records.  They each have their standard sa-21a/b Bn mag as well, each with different starting number in their x/48 entry for the 21b's.  They will get filled up after the first minute. HOWEVER you will get warnings in your \logs\lua_history_date.txt logs about something being wrong with the SA-21a weapon records. That's because the mag has a cap of 48, and the first entry gets filled first with 48, no more room for second entry.  Now that may not be a problem for you, it's actually how these s-400 come stock.  BUT if was, you could create two table entries to replace the original,  one specifically for the sa\21b instance and set it at say 24, and one for the second table entry specific to sa21a's, you of course will then need to query the unit to grab those specific wpn_guids like you see in the DDG table sample entries for the MK54's.  ...or could just remove the dam thing and use the generic munitions, but I'm trying to explain it for cases where you don't want that.

 Now onto the loadouts and airbases..

This script works similar to the more complicated mag refilling, but all you need here are a unit guid, a loadoutid, a quantity, and a name, the name doesn't have to match the unit but it's a good idea and does need to be in the entry for logging purposes.  mydesc= does not need to exist, I just have it there to help me know what the heck 26461 might mean, rename mydesc whatever you want like hint="", or remove it entirely, just make sure name,guid,loadout and quantity exist. 

Anyway this is primarly meant for authors who are just trying fill stuff up initally during development, or maybe you have special action that grants the user extra stuff, or they unlock loadouts at certain bases, or you're spawning airbases on-the-fly where guids can't be determined ahead of time (or you don't have the lua knowledge to find them on the fly etc), whatever it maybe, this is the quick and dirty method that so long as the unit and 1 mag exists will always work.  The downside is it only works for aircraft loadouts.    

 {name='SUA_1', guid='4FH7PU-0HMNDPRJL928I',loadoutid=26461, quantity=50,mydesc="f22 aim 260 loadout"}, 


That says add 50 instances of loadoutid 26461 to this unit, plain and simple and script will do that on ever execution, if the mag gets filled to the brim, welp that's ok the developers let the particular command invoved keep inserting them regardless of magcaps. That doesn't mean you can or should add stuff up to the limits of 32bit intergers... I just tell you it so you know why it can end up exceeding the mag-cap, where as the other script isn't allowed to do so. 

Besides you can always use the mag refiller to edit specific records at these air bases anyway, though in that case you do gotta stay within mag-cap of each mag.  How do you find the loadoutid, you look on the aircraft's database viewer page and note the number that has the munitions you want.  Yes other aircraft can use the munitions once placed, it doesn't really matter which aircraft loadoutid you use so long as you get the muniton entries you want\need.

Did you even read all the way down here? Why am I still typing? Well cause...

Q: "What if I want to have a whole bunch of different timers doing different units on different schedules or based on other events etc.. ?"

A: Not a problem, even if you don't know much about lua, just copy and paste all the code into each of the event actions involved, tweak the table contents as need in each copy (just make sure there is always at least 1 entry in the table).  Is this a ok thing....till once you get to like 10 copies, but for a few, sure it's some unneeded bloat, but it's whatever.

Q: "Where is the logging being done?"

A: Always to your INSTALLPATH\Logs\LuaHistory_todaysdate.txt file, and yet it rolls over at midnight even if you're still in the game.  

Q: "What do some of the log entries look like?"

A: Similar to this:

topUpUnitsMags(): Adding weapons to weapon record SA-21a Growler [48N6DM] on mag SA-21a/b Bn on unit SAM Bn S-400 #1 may have failed, likely because the mag itself reached its cap of 48
TopUpAllExistingMags(): Finished processing entry DDG 125 #1 helocoptermountonly  # of mags processed: 1 # of wpns processed: 2
TopUpAllExistingMags(): Finished processing entry DDG 125 #1 mk54LHT to 24 only  # of mags processed: 8 # of wpns processed: 1
TopUpAllExistingMags():  Done.
Total entries processed was 2, total successfully was 2
Total mags processed was 9, total weapon records touched was 3


The format you will see is function name doing the printing func():  message, except for the last bit about totals.

You see the first line, it's an error worth telling you about, but not really an error per say, remember all those magazine capacity issues I kept mentioning with the short hand of "mag cap", well these are what I print out to you when I think I detect that instance. That way you have some explaination of why things are not working if you bother to look at the log, instead of saying the script doesn't work - it worked fine, you (and I in this sample) told it to do something it technically can't.

Q: "I don't like all this print to the log, doesn't it also cost a few ms for each print statement?"

A: You know what, I kinda don't either, but better you know whats going on instead of trying to tell me it's not working, when it probably is and the log is probably telling why something is the way it is or that something doesn't exit cause you typo'd a guid or forgot a comma or something, or a unit in your list is destroyed or you deleted it and re-added it and forgot to update the list for the new guid. 

As for perf... YOU ARE NOT WRONG, string concats and writes to io are pricey in CMO lua scripting (less so with ssd), it's not bad bad, but yeah if you run this on the every minute mark, well every minute that particular in-game second may take 2 or 3 depending on how long your table lists are - dozens like in the sample is a nothing burger, 100's (I've used) are nothing burger in small scene. 1000's will totally work in large or small scene, but expect things to chug for few seconds when that executes.

As for a no logging option, well my friend you can simply comment out the (put -- in front of ) print lines where even you want, though please leave the ones that are more serious alerts to problems, like units missing or invalid params\parameter validation. 

Q: Can I rename these functions?  

A: Sure go right ahead...especially the fn="blabla(): " as those tell the print statement what to use, ie if you just need to better ID which copy of similar event code is running seperately at the same time. BUT if you're really gonna rename the admittedly dumb function names, know what you're doing and make sure you change the other code to match the new names. 

Q: What is this accounting\total stuff in the log?

A: I though it was useful to have some idea when processing long table lists, how many entries were processed, how many seemed successful, how many mags were processed\scanned and weapons recs processed\scanned per-entry, as well as a collective total of how many mags were touched\processed and weapon recs touched\processed without clear errors.  This helps you debug a little bit in small lists, or noticed changes from one run to the next (even this sample will produce different numbers from minute 1 vs minute 2).  ALSO if you come to me and say you stuff is running slow and I see 10,000 mags processed and 80,000 wpn records in the log you provided.  Yeah...well I'm immediately gonna know to tell you yeah - those amounts will take awhile to process.  Also you can get an idea of failures at a glance if you know you have 50 entries and only 40 are reporting successful, it doesn't even mean you need to fix something, maybe things got destroyed, maybe guids are wrong, but at a glance you have some idea if things are running as expected.

Q: Why did I not make these function in global startup script... and just call the functions in the action luascripts?  

A: Well actually that's how I do it myself, but I un-did all that to try to make this a copy paste, edit a little, GO friendly.  That way a user doesn't have to understand what a global vs local function is, or doesn't wonder why when they make a change the trigger fires next why their change wasn't seen because it was a global table and was only read once at startup,etc,etc.  This form is copy event code, past into yours, tweek the table entries, press play, something doesn't work well edit table again and next trigger will be working with the changes.  So what if they copy 10 copies of the code into different events, whats some file bloat to them, so long it works?  Now if you're plan to copy this to 20 or 100 different events... yeah don't do that, contact me or someone else in the Lua Legion area and we'll show you a better way.

Btw if you want that sample...well I included it too with -Globals.scen in the file name.

Q: What's the pros cons of using centralized global methods?

A: 

Pros:

- One copy of core code functions resident in memory that doesn't have to be recompiled on every event execution.

- Centralized and once place to edit\tweak core script function code.

- Progromatically update or manipulate your global tables from other events, yes you can add and subtract from the lists from other events, great for long running scenes with dynamic additions. HOWEVER, you should know how to stringify tables and save that to a key (and I don't mean tostring() ), and also how to manage reloading and unstringifying said tables as part of 'OnSceneLoad' so that dynamic changes are not lost, or at least very minimized during a reload of a save days, months later.  Ask me on the forums about this. It takes some work, but ain't as scary as it might seem and I can provide you some 'state' saving functions to use that take some of the work out of it.

Cons:

- One copy of code, if you want to make custom edits for some darn reason for different event needs you'll need to copy pasta, change related function names so there are no dupes, or extended the original with params and logic to meet you needs. idk..is this really a con?

- Core functions are only loaded\reloaded into memory OnSceneLoad. So if you make a change you gotta save and reload.  (hint: or do your work in the editor to overwrite the already memory copies with updated ones)

- If placing your tables in OnSceneLoad, same problem as the last, you will need to save and reload scene to see the changes. This can be pita during testing. so... hybrid could be best option. See -Hybrid.scne, this is where the core code is global but the table input is local to each event. 

- When you go to load up and play another map, the globals you already loaded since starting command.exe are still in ram, and they're still globals in the next scene.  locals per event are dead second after execution.

This is why prefixing your global function names to something personallized and more than 1 char but probably less then 6 is a good idea OR putting them in their own namespace\table with said prefix so there is a decent chance they will not conflict with anyone elses code still in memory.  

For instance in proper you'll see have claimed use of gKH = {} namespace, I know Whicker used to use W_ prefix or gW={}.  I use it for and to help organize most my libary code.  You don't need to fully understand the concept except to know that my stuff under gKH... ain't likely to ever collide with anything else that is not from my library, short of some samples here and there I copy pasta like this to the forums or in '-Globals.scen sample'.  You could change it to gXYZ={}, so long as you change it everywhere needed code will run just the same. 
