1. Firaxis celebrates the "Asian American and Pacific Islander Heritage Month", and offers a give-away of a Civ6 anthology copy (5 in total)! For all the details, please check the thread here. .
    Dismiss Notice
  2. We have selected the winners of the Old World random draw and competition. For the winning entries, please check this thread.
    Dismiss Notice

Lua Scripting Possibilities

Discussion in 'Civ2 - General Discussions' started by JPetroski, Jan 21, 2018.

  1. PlutonianEmpire

    PlutonianEmpire Socially Awkward Goofball

    Joined:
    Mar 11, 2004
    Messages:
    4,797
    Gender:
    Male
    Location:
    MinneSNOWta
    Didn't Catfish provide an in depth look at the formula once? I vaguely remember something like that from years ago when Fertility was first being discussed for ToTPP. Other than that, the actual fertility calculation is beyond my knowledge too, unfortunately. ;_;
     
    Last edited: Jan 2, 2019
  2. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    The most I found in a search was a post from 2005 that gave a formula that may or may not have been entirely correct, or was at least incomplete. (The person who did the work lost interest once they figured out 'most' of what was happening.) With the lua console, doing further research should be relatively easy, since it no longer involves hex editing.

    For me, solving this particular mystery is a low priority. If someone else wants to give it a go, and needs some code to make the job easier, I'm willing to help with that.
     
  3. PlutonianEmpire

    PlutonianEmpire Socially Awkward Goofball

    Joined:
    Mar 11, 2004
    Messages:
    4,797
    Gender:
    Male
    Location:
    MinneSNOWta
    Alrighty cool.

    Also, the map scripts work great. :D Thank you :)
     
    Last edited: Jan 3, 2019
  4. Knighttime

    Knighttime Prince

    Joined:
    Sep 20, 2002
    Messages:
    336
    I'm not quite sure what you mean by "formula", but in the TOTPP launcher, TheNamelessOne's notes for the Fertility patch say this:
    (That's abbreviated, you can check out that section for the complete notes plus examples.)

    Is that helpful? @PlutonianEmpire it looks like you're not providing any coefficients, so you'd be using those default values.
     
  5. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    What I mean is that if I take a tile, I want to compute what the fertility value 'should' be, based on that tile and the tiles surrounding it. My (rather limited) search has not turned up any complete explanation of this, and I'm not interested in this topic enough to put together the available information myself, and check if it is complete. The food vs shields vs trade weighting gives part of the picture, but not all of it. I think I found somewhere that production is weighted more highly for the tile itself than for the adjacent tiles, and in turn, the adjacent tiles have higher weight than the ones two squares away. All the necessary information might be
     
  6. Manuel Re

    Manuel Re Chieftain

    Joined:
    Feb 25, 2019
    Messages:
    1
    Gender:
    Male
    Hello dear admirers and fans of the wonderful game Civilization,

    this is my first posting here, I've always been a silent reader. I think it's great and it motivates me that there are still fans of this game who exchange so wonderfully creative and with such great results.
    For a long time I have been working and tinkering with a good friend on a Civ2 scenario, which deals with the eastern front in the Second World War. The scenario shall be playable for two human players against each other.

    Among other things, we want to show the encircling battles and retreat battles so typical for warfare at that time. The encirclement of Stalingrad, but also the tactical retreat battles of the Wehrmacht in the years 1943-44 should be made as realistic as possible.

    As you all know, the problem with Civ has always been that an attacking unit is either destroyed itself or survives and destroys the attacked unit. This is historically unrealistic because a unit that attacks itself usually has the ability to stop the attack if it does not succeed before it is destroyed. At the same time, an attacked unit usually had the possibility to retreat backwards - if it has not been encircled.

    Therefore, with the help of LUA, we want to differentiate these CIV laws somewhat and the question is whether LUA can represent the following:

    1.) A unit attacks itself, but the attack fails and it is destroyed. But a random generator should give it the chance to flee and be recreated on a neighboring square in its own territory - strongly weakened.

    2.) A unit is attacked and destroyed from a certain direction. However, a random generator gives it the possibility to "evade" in the opposite direction by recreating it on a neighboring field - strongly weakened, of course.

    3.) This avoidance before the enemy attack is only possible if there is no other enemy unit in the back of the attacked unit. Otherwise, the attacked unit is considered "encircled".

    4.) Units that are in certain areas or cities can be cut off from their supply base by intercepting an enemy unit - this has been discussed in previous postings, hasn't it? Is that really representable?

    5.) If in CIV 2 land units attack cities, they destroy the planes stationed there at the same time. This is historically totally illogical, of course, because airplanes flew off in the real danger of a conquest of their airfield and changed location. Can LUA be used to program the game in such a way that the aircraft are rebuilt in their previous, specific combat strength (green/yellow/red) in a precisely defined city or position in the hinterland (e.g. capital) so that they can be used again from there in the next round?

    If I understood the previous discussion in this thread correctly, all this could be possible with LUA, wouldn't it?

    For me, this raises further questions:

    6.) The ability of the units to evade and escape after failed attacks will be randomized by a random generator. But this should then be made dependent on the number of a certain unit in your own army, a unit called "General" or "Field Marshal". This is to illustrate the great importance of qualified command personnel in the army's general staff. The more generals the player has, the greater the probability that his own units can act flexibly enough.

    7.) It would be best if the proximity of the positioned generals to the units in combat, i.e. their proximity to the front line, could play a role in the effectiveness of the generals.

    I think that's the most difficult thing to do: With LUA, you can define the proximity of two units to each other in order to define effects on the units. This could also be done with a kind of supply unit, a truck or a headquarters, which must always be close to certain units, because otherwise the quality of these defined units would decrease. Is this possible?

    8.) To further differentiate the idea, it would be nice if the remaining combat strength of the respective unit (green/yellow or red) could also be included in the random calculations. For example, it makes little sense if a totally weak unit, after being attacked and destroyed, can dodge and be rebuilt. Therefore, it would be more realistic to give these dodge abilities only to units that are fully operational at the beginning of the turn.

    Does all this go beyond the limits of LUA or is all this theoretically actually programmable?

    Those were quite a few questions. But unfortunately I'm not a programming expert and can't estimate what's feasible from the eight key points I mentioned. Any help or advice from you would be very welcome.

    Very big and dear greetings to you,

    Manuel
     
    Last edited: Mar 4, 2019
  7. Knighttime

    Knighttime Prince

    Joined:
    Sep 20, 2002
    Messages:
    336
    Hi Manuel,

    Great to see more interest in Lua events in these forums!

    Everything you've listed here does seem possible with Lua, including your #6, #7, and #8. Unfortunately that doesn't mean these events would be simple or easy to write. There's quite a bit of complexity here, and it would take plenty of time and many lines of code to accomplish everything you have in mind. So it's a little more difficult for me to assess the degree to which you might consider it feasible or practical.

    All Lua interaction with the game is based around a fixed set of what I call "triggers" -- situations or actions that take place within the game that cause it to interact with the events.lua file, and provide you with an opportunity to inject Lua code which will run at precisely that point in time. Two key ones for your needs are probably going to be civ.scen.onResolveCombat() and civ.scen.onUnitKilled(). The first of these runs once for every "round" of a battle, but unfortunately doesn't give you the ability to stop a battle partway through (leaving both units alive) -- one unit will always be destroyed. At that point, after the battle, the second of these triggers runs. It seems to me that many of your event actions will take place during the second trigger, after the battle is over, but may require information that needs to be gathered prior that point, either during the first of those triggers or else (perhaps) at the beginning of that turn.

    For example, within onUnitKilled(), if the attacking unit was defeated, it doesn't seem to be possible to determine what tile it was on when it launched the attack. So I think you'd need to determine this and store it in memory while the battle is active, during onResolveCombat(). Similarly, since for some of your events you need to know how many hit points the losing unit had at the start of a battle, you'd have to document this in memory ahead of time, in order to be able to reference it after the battle ends.

    For some of your events involving encirclement or proximity, you might benefit from using the Supply Lines module that I wrote and released here. I'm a little unsure whether that's going to be the best solution, though, without more information such as whether or not you expect enemy units to exert a zone of control, what you envision for encirclement "distance" (how tight a blockading circle needs to be), and how these affect the ability to evade or dodge.

    You may have done the following things already, but to anyone who's interested in learning how to write Lua events for Civ 2 and has limited programming experience, my recommendation would be:

    1) Start with @Prof. Garfield 's tutorial, Get Started With Lua Events. This is a very helpful guide to learning how to program in Lua that uses examples directly from Civ 2 (unlike other Lua guides you may find on the web). It's not complete yet -- there are more lessons still to be written -- but even what's there now represents a great foundation. I'd encourage you to make it interactive by actually typing out and running all of the code examples, rather than just reading the guide.

    2) Download all of the recent scenarios that use Lua: Caesar's Gallic Wars, Napoléon I, and Over the Reich. The Lua files in those scenarios are very large, but see if you can start picking apart what each section does, and how it works. Having lots of examples of working code to review can be a big help in putting together your own events.

    3) Start small and simple with an events.lua file for your own scenario. Some of your proposed events could require a hundred lines of code or more, but it's unrealistic to think that anyone would be able to write that top-to-bottom in one shot. Instead, focus on smaller building blocks that might form the foundation of several events. For example, write an event that runs when a battle begins and simply prints some data to the Lua console, such as the tile coordinates of the attacker and defender and how many hit points each one has. Then build on this by storing that data in memory and only displaying it later, after the battle completes and one unit has been destroyed. You get the idea. In general, always use the Lua console to print a lot of status messages and display the values of variables, as you're working on new events, so you can see what's working and what's providing unexpected results.

    4) Feel free to post questions or sections of code to this forum if something just isn't coming together for you, or you're not sure how to break a big problem into more manageable pieces. The more you can narrow a question down to a specific issue, the easier it will be for someone to give you practical ideas that might work for you.

    Good luck and have fun!
     
    Last edited: Mar 6, 2019
  8. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    Does anyone have a way of checking if the map is flat or round? I don't have an immediate need for this, but I'm probably going to write code for a library at some point that will depend on whether the map is flat or round.

    We can make it standard for there to be a global variable in events.lua with the world shape, and that could then be accessed by other modules as needed. However, it would probably be preferable to find a "direct" way of determining the world shape, as long as it is not too difficult.
     
  9. Knighttime

    Knighttime Prince

    Joined:
    Sep 20, 2002
    Messages:
    336
    @Prof. Garfield I've run into this problem as well but I haven't been able to find a solution, unfortunately. In my supplyLines module, I added the variable
    local CUSTOMIZE_RULES_FLAT_WORLD = true
    which the implementer should switch to false if they are applying the module to a scenario using a round world. (For pathfinding code, this is obviously a critical issue.)

    I suppose a global variable defined at the base events.lua level would be appropriate, if there truly is no programmatic way to determine this, and as long as it's clearly identified as a precondition for using the relevant library or external module.
     
  10. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    @Knighttime
    The only thing I can think of is to create 2 cities on either side of the date line, then create a unit, see which city it becomes supported by, and use that to determine the world shape. I think creating cities to determine this is going too far.

    My thought is to have a global variable in the events.lua (especially in a sample events.lua that is distributed), and in the General Library have gen.isWorldFlat() check that global variable. If it doesn't exist, then put up a message asking the player the shape of the world, and reminding them to make the change in events.lua. Then, when TNO returns, we update gen.isWorldFlat() to use a technique that he provides.

    I suppose under this arrangement that the scenario designer could simply change the gen.isWorldFlat() function, but I would kind of prefer not to have end users make scenario specific changes directly to libraries or "off the shelf" modules. If for no other reason, that means they can be easily replaced with new versions, and equivalently, any bug fixes can easily be provided back to everyone by simply uploading the changed module.
     
  11. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    4,506
    I wanted to throw out there that @Prof. Garfield has implemented payload as well as carrier rearm functionality in Over the Reich.

    Basically, as bombers are 0 attack units that carry munitions, they can only call up or use munitions if they have a home city other than "NONE." Using the munition resets the bomber's home city to "NONE."

    You normally have to rehome it in a city when it returns to base but he's also made it so it will automatically rehome to a certain city if it activates on the same square as an aircraft carrier.

    This opens up different possibilities. For example, replace "aircraft carrier" with "baggage train," or "supply mule."

    It's pretty exciting stuff if you ask me! It neatly solves the issue of bombers attacking over multiple turns at least.
     
  12. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    Something interesting I discovered today is that AI units seem to trigger the OnActivation event every square they move. This has a few implications.

    First is that it might be wise to put some on activation code only applicable to humans in an if statement, so that it doesn't run several times per unit when the AI plays.

    Second is that it might be easier to get the AI to 'use' munitions than I previously thought. Basically, on activation, if the unit can use munitions, check if there is a target in range. If so, and if the unit qualifies to fire, run the munition generation code (perhaps just the onkeypress function with appropriate keyid as input) and make the munition the active unit.

    Something else I noticed is that the effect of clearing goto orders when adjacent to an enemy unit seems to happen after the onActivateUnit event, so trying to give the unit an explicit order to either attack or flee might actually require a little work, such as, perhaps, teleporting the unit away a square if you want it to run away.
     
  13. SorFox

    SorFox Chieftain

    Joined:
    Aug 29, 2015
    Messages:
    16
    Location:
    somewhere in Central Europe
    First of all: Merry Christmas! :)

    I think this thread is again most appropriate to address my three Lua related questions.

    Topic:
    terrainType (get/set)
    tile.terrainType -> integer


    1. Is it possible to write a query in order to check for the presence of tiles with special resources? I am talking about the two tiles on the outermost right part of every line within the “Terrain1.bmp” (see attached screenshot). Example: If key “k” is hit then count special resource tiles (like Oasis, Buffalo, Coal, Gold, Peat, Fish, Desert Oil, Wheat, whatsoever) in square/region xyz.

    Something like
    Code:
    for __,location in ipairs(region.allBuffalos) do
              local tile = civ.getTile(location[1], location[2], location[3])
                    if tile.owner == nativeAmericans and
                       tile.terrainType & 0x40 ~= 0x40 then
                       numberOfBuffalos = numberOfBuffalos + 1
    I did go through all the Civ2 scenarios with Lua events currently available, but it seems that no one did such query before – maybe because it is simply not possible and only applicable for “standard” terrain tiles (0-15)…

    2. Is it possible by means of Lua to add ('set') the aforementioned special resource to a tile? How would the code look like? Am I right with the assumption that this is currently only possible in the phase of setting up the map manually?
    Ctrl-1 (resource #1) | Ctrl-2 (resource #2)

    3. Interestingly, I recognized that although it is possible to check for the presence of a river within a tile,
    Code:
    if civ.getTile(x,y,z).terrainType & 0x80 == 0x80 then
         civ.ui.text("River!")
    else
         civ.ui.text("NO river.")
    end
    or for forest terrain
    Code:
    if civ.getTile(x,y,z).terrainType & 0x03 == 0x03 then   -- original Terrain1.bmp + Rules.txt applied
    again it seems NOT possible to set a river by means of Lua on the map. Use case: Original map had no river on the tile, a water reservoir is created nearby, the tile should now gain a river.

    Even for a simple copy + paste procedure (source tile possess a river)
    Code:
    local source = civ.getTile(2,8,0).terrainType
    civ.getTile(3,1,0).terrainType = source
    this error message appears: "\Events.lua:716: `terrainType` value should be between 0 and 15."

    As one can see, I did even use 'bitwise operators' in tests and assignments as recommended by TNO and found on Catfish’s Cave but to no success. The only thing I can think of at the moment (if I am right with my findings) is a fix of the ‘civlua.lua’ file itself, like done in this case by Prof. Garfield. Any help, ideas, or suggestions are appreciated!
     

    Attached Files:

  14. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    I don't know of a way to get that information from the game itself.

    In principle, you could manually create a table that tells the location of all the special resources, then write a function to query that table to find out if the tile in question has a 'fish' special or a 'whale' special (maybe you need two tables, or the value is a string or something).

    You might be able to automate the compiling process by creating/teleporting a city near each square, setting the citizen to work the tile, and checking if production is higher than expected. Maybe edit the rules.txt so that specials produce 50 food/shields, so the difference is obvious. Say 'fish' specials produce 50 food, 'whale' specials produce 50 shields. Remember to change the terrain to something other than grassland for the test. And to put back all huts if you want them.

    For the 'standard' special allocation, it shouldn't be that difficult to input the map's resource seed and determine if a special is there, and, if so, what the special is. That probably just requires a little effort with the MGE map editor, but no one has done it yet.

    I don't know of a way to do this with Lua, so I think that you are correct that it has to be done manually.

    You are correct, rivers cannot be added. It looks like TNO tried to 'guard' against bad inputs when setting terrain, but overlooked the river issue.
     
  15. SorFox

    SorFox Chieftain

    Joined:
    Aug 29, 2015
    Messages:
    16
    Location:
    somewhere in Central Europe
    Thanks again, @Prof. Garfield!!

    I guessed this would be the answers but wanted to make sure my assumptions/finding were right. I will do it with the manually created table upfront you suggested, but with a much easier to realize solution than with the 'creating/teleporting a city' thing (although it’s a nice one). Simply checking changes of the basic terrain of the special resource at the table’ tiles and their ownership will already do the trick for my set-up.
     
  16. Civinator

    Civinator Blue Lion Supporter

    Joined:
    May 5, 2005
    Messages:
    7,617
    Gender:
    Male
    This defenitely sounds very interesting. :) Two questions:

    1. If an animated Civ2 ToT unit has the attack animation of that unit set as the default graphics of the defending 'amunition unit', can this graphically look as if the attacked unit would fire back (if the attack range is 1) ?

    2. Can the OnActivation event be used to trigger sound files while the unit is moving (p.e. footmarch sound for infantry units, jetsound for jetplanes, moving tanks sound for tanks and so on) ?
     
  17. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    I'm not familiar with TOT unit animations, and I don't fully understand the question. There doesn't seem to be a way to change the animation associated with a unit in the events, so you might be stuck having to have a custom munition for each munition firing unit. Beyond that, all I can do is say to set up some animation graphics on a couple units and try it out.

    Yes, but it probably wouldn't be very useful. The trigger wouldn't apply to human controlled units (except the first time they are activated), and the AI controlled units would play the sound even when they weren't moving on screen. You'd also need a check so that the sound only plays after the last sound has finished.

    I think we discussed changing the 'movement' sound based on the active unit in the past. The (relatively) straightforward way to do it would be to overwrite the movement sound file each time a new unit was activated. I did something similar for custom music.

    However, I'm still wary of changing the movement sound (or, for that matter, doing the batch file conversion by event). My reason is that such changes would rely on programatically determining where the file is (as opposed to hard coding where the files must be written), thereby increasing the chance for an error (or malicious person, though at the moment I think the risk is very low in our small community) to overwrite something unintended. Also, unlike custom music, this would require each scenario writer to provide the code, meaning more points of failure.

    Maybe I'm overly paranoid, and stopping a cool improvement. I don't really know.
     
  18. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    4,506
    I've been thinking about this a bit. If they trigger the OnActivation event every square they move, it should be possible to manipulate the AI in Hinge of Fate (or other scenarios) like so:

    -Use the "regions" code you made for OTR
    -OnActivation, check what region a unit is in
    -If an Allied Freighter is in the Red Box below on Map 1, then OnActivation triggers GoTo to send them to the yellow box
    -Once an Allied Freighter reaches the yellow box, assuming it has any movement points left, use OnActivation to teleport them to the yellow box on Map 2
    -Once on Map2, use the OnActivation to trigger GoTo to send them to the red box on Map 2 (coastal England)
    -When they reach coastal England, use OnActivation to delete the Allied freighter and create Allied bombers over Germany in the purple box, which seems a better place for them to be than wherever the AI would send them.

    Any flaws in my thinking or is this a solution that just might work?

    upload_2020-1-1_21-15-25.png

    upload_2020-1-1_21-16-22.png
     

    Attached Files:

  19. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    I think it would work. Certainly worth trying in any case.
     
  20. Knighttime

    Knighttime Prince

    Joined:
    Sep 20, 2002
    Messages:
    336
    @Prof. Garfield this is an interesting topic. Personally, I feel like using Lua events to dynamically change or swap files within the scenario directory itself (and any of its subdirectories) is "acceptable behavior", but doing so within any higher-level directory (such as the main TOT installation directory, or anywhere else on the user's computer) is strictly "off limits". Note that I'm basing this not on what I'd like to do as a designer in my own projects, but on how I feel about an appropriate boundary for someone else's scenario that I download, install, and run. I'm willing to give a designer control over his own scenario's folder, since bad decisions there would only affect his own work, but I feel pretty strongly that he has no "rights" outside of that.

    As many of us are probably aware, there are certain game files that can be customized for a scenario but which must be placed outside of the scenario directory in order to have an effect. Other than instructions for each user to follow manually, I believe that sticking with a batch file system for these, along with clear documentation, is the best approach -- unless someone else has a better suggestion.

    Unfortunately you're right that any Lua script opens up the possibility of error or malicious behavior, or someone not abiding by this boundary, which could have severe consequences. TNO added a warning popup about loading Lua events... I'm not sure if enforceable rules (to limit the power of Lua in this regard) are possible or not. I do agree that the risk is very low at the moment, but it's something to be mindful of if the community grows. If a technical limitation isn't feasible, eventually I could envision some sort of "certification" program in which one or more experienced Lua programmers, who are known to the community, review the code in a project and publicly confirm that it's safe for general usage.
     
    Last edited: Jan 7, 2020
    SorFox likes this.

Share This Page