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. CurtSibling

    CurtSibling ENEMY ACE™ SLeague Staff Supporter

    Joined:
    Aug 31, 2001
    Messages:
    29,280
    Gender:
    Male
    Location:
    Innsmouth
    Amazing, sir - Thanks - Your help is invaluable. :)
     
  2. CurtSibling

    CurtSibling ENEMY ACE™ SLeague Staff Supporter

    Joined:
    Aug 31, 2001
    Messages:
    29,280
    Gender:
    Male
    Location:
    Innsmouth
    @Prof. Garfield
    One more thing to ask - In "eventsTriggers",
    I'm using the "onCityTaken" function, I want to emulate this macro:

    Code:
    @IF
    CityTaken
    city=AnyCity
    attacker=Soviet Union
    defender=German Reich
    @THEN
    JUSTONCE
    TEXT
    ^
    ^^ Stalin has daringly unleashed a concerted strike upon German
    ^^ positions. He hopes to dislocate any action from the fascists.
    ^^ An inspired move, or potential disaster? Time will tell...
    ^
    ENDTEXT
    PlayWaveFile
    RUS.wav
    @ENDIF
    The code I have so far is Below...What I want to change is instead of Paris, I would like that any city can be taken, and it will trigger the message...

    Code:
    function triggerEvents.onCityTaken(city,defender)
        context[getContext()]["onCityTaken"](city,defender)
        universal["onCityTaken"](city,defender)
        legacy.doCityTakenEvents(city,defender)
       
    if city == object.cParis and city.owner == object.tGermany then
    civ.ui.text("^^ Stalin has daringly unleashed a concerted strike upon German positions. He hopes to dislocate any future aggression from the fascists. An inspired move, or potential disaster? Time will tell...")
    civ.playSound("RUS.wav")
    end
    
    end 
    If I can crack this, it enables me to clone lots of macro events into Lua.
     
  3. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    Just omit the check for the city. That is:

    Code:
    if defender == object.tGermany then
    
    Then, this code will run any time a city is captured from Germany. Note the use of defender instead of city.owner. I'm 99% sure that when the trigger is run, city.owner is now the tribe that just captured the city, and defender is the tribe that lost it (but I can't double check just now).
     
  4. CurtSibling

    CurtSibling ENEMY ACE™ SLeague Staff Supporter

    Joined:
    Aug 31, 2001
    Messages:
    29,280
    Gender:
    Male
    Location:
    Innsmouth
    Thanks, sir - I should have said it is a specific justonce event for when the Russians take a city...(it's a Soviet surprise attack)

    The defender line is perfect, but is there a way to make this event only fire once when the Russsians take a city?

    The flow of how I am doing this in Lua:

    1-Russians research a tech - Working.
    2-Units are spawned - Working.
    3-State of war begins - Working.
    4-Russians take a city - Where I am at.
    5-Invasion goes on - AI will take things from here. :)

    No rush, I am calling it a night for some sleep - 100% appreciate all the help, man.
     
  5. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    "Wrap" your code inside of a gen.justOnce.

    Code:
       gen.justOnce("UniqueJustOnceString", function ()
            -- put your code here
        end) -- the end here is for the function we defined inside of gen.justOnce, the ) is to close gen.justOnce
    
    Then, even though the if statement will be true multiple times, the code inside the justOnce will only execute once. Remember that the string must be unique. If 2 justOnce events share the same justOnce 'key' (first argument), then only one of them will happen. (That could be a useful trick, but you don't want to do it by accident.)
     
  6. CurtSibling

    CurtSibling ENEMY ACE™ SLeague Staff Supporter

    Joined:
    Aug 31, 2001
    Messages:
    29,280
    Gender:
    Male
    Location:
    Innsmouth
  7. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    4,506
    I'm curious if one of our more advanced coders thinks something like this is possible for two interesting issues that might be solved by using a similar strategy:


    1.
    Is there a way for the AI to be directed towards the location of certain human units? Specifically, I'm curious if I had a unit, such as the Bismarck, that was attempting to break out into the Atlantic, if it would be possible to:

    1. Acquire the location of this unit (it's the only one out there so this should be possible)
    2. Then redirect certain units in an area to that location (for example, maybe British ships out of Scapa Flow try to intercept it).

    So basically, I need a location that can change at any given turn to be fed into a goto

    How would I go about capturing Bismarck's location? I think I know how to feed it to other units with a forloop that only looks at certain units in a coordinate box (so I don't have battleships in Alexandria abandoning their post to chase the Bismarck).

    2.
    What does everyone think about this as a way to solve the AI's inability to use aircraft carriers?

    -On the AI turn, when a carrier activates, it "senses" if there are human naval units within a range of the carrier.
    -If so, AI air units are created on the carrier's tile, their value/unique id is captured, and given a goto command to the human naval units' tile
    -Then, at the start of the human player's turn, the air units with that value/unique id are deleted (so the human has to go kill the carrier to get the air attacks to stop).

    #1 would make the scenario I'm building much more fun and #2 is my best stab at getting AI carriers to work as they currently don't.

    I think #1 is possible, I'm not sure about #2 given the value but thought I'd open it up for discussion.

    Thanks all,
     
  8. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    Disclaimer: all this code is untested.
    Code:
    local bismark = nil -- This is deliberately outside the function
    local function getBismark()
        if bismark and bismark.type == object.uBismark then
            return bismark
        end
        if bismark == false then
            return nil  -- return nil if no Bismark unit found
        end
        for unit in civ.iterateUnits() do
            if unit.type == object.uBismark then
                bismark = unit
                return unit
            end
        end
        bismark = false -- set to false, so we don't always look for a nonexistent Bismark
        return nil -- return nil if no Bismark unit found
    end
    
    Saving the Bismark unit in a variable isn't strictly necessary, but it saves going through all the units in the game every time you need the Bismark (in principle, you will only have to check when the game loads). However, this won't find the Bismark if it doesn't exist at the start of the scenario, at least until you reload the game.

    Code:
    local function chaseBismark(hunterUnit)
        local bismarkUnit = getBismark()
        if bismarkUnit and bismarkUnit.location then
            hunterUnit.gotoTile = bismark.location
        end
    end
    
    You would have to run this code every turn for each hunterUnit, to update the goto destination.

    If you have trouble with units not navigating around Great Britain properly, let me know and I can help you get better navigation (I did this for trains in OTR).

    This seems like it should work, although I don't think you can actually force a unit to attack. You would probably find gen.nearbyUnits useful when trying to find human units. If you're going to delete the aircraft on the human turn, you might as well delete them by event once they attack (don't make them missile units, or the AI won't use them properly).
     
  9. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    Has anyone written a working alpha centauri arrival event? I tried to write one this evening in order to test a change to the Lua Scenario Template, and couldn't get it to work, even if I tried to use civ.scen.onCentauriArrival in the console to make an event. Since I'm not running Civ II on Windows, there is a chance the problem is with my setup, so I'd like a second opinion.

    It isn't a serious problem for me either way (and I didn't care enough to test this particular event before). All I'm doing is writing a file where a designer can work with most kinds of events in a single file, and leaving this event out of the list isn't a big deal. However, if there is a bug with the event, it would be good to know.
     
  10. Knighttime

    Knighttime Prince

    Joined:
    Sep 20, 2002
    Messages:
    336
    I've never tried using this trigger before, but you made me curious so I had to try it out. I agree that this doesn't seem to fire for me either, at least in an Original game (where arrival on Alpha Centauri automatically ends the game). Did you try testing this in an Extended Original, SciFi, or Fantasy game? I wonder if that would make a difference.
     
    Last edited: Aug 22, 2021
  11. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    Just tested in an extended original game, and the event does trigger. Interestingly, if I don't use the console to write an event, the game ends. However, if I do write an event (even just a text box event), the game continues and a few units appear on the next map.
     
  12. Knighttime

    Knighttime Prince

    Joined:
    Sep 20, 2002
    Messages:
    336
    Well, that's progress at least :thumbsup: and thanks for testing this. Glad to know the event isn't entirely broken, but maybe there are still bugs undocumented features to be discovered. Too bad that most of the event triggers don't have official documentation.
     
  13. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    OK, if I start the game as an extended original game, but move it out of that folder, the Centauri event can still happen. The Centauri event availability will persist even after saving as a scenario.
     
  14. Knighttime

    Knighttime Prince

    Joined:
    Sep 20, 2002
    Messages:
    336
    I think civ.game.gameType is an undocumented field that contains the value of byte 982 in Catfish's saved game file structure. But I've always wondered at the values:
    • 0x00 Original
    • 0x01 Sci-Fi
    • 0x02 Fantasy
    There isn't a separate value for Extended Original? Is that just coded as Original and then detected by the presence of more than 1 map?
     
  15. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    I just tried starting an 'original' game, and adding a second map, and the centauri arrival event didn't trigger.
     
  16. Knighttime

    Knighttime Prince

    Joined:
    Sep 20, 2002
    Messages:
    336
    :dunno: Hmm. Well, if you ever figure out how to tell whether a saved game was created as Original vs. Extended Original, please post the details!

    For that matter, how did you add a second map to an Original game? By editing Rules.txt in the folder where the saved game was stored, to add a @SECONDARY_MAPS section, and then reloading? I never realized you could change the number of maps once a game was underway.
     
    Last edited: Aug 25, 2021
  17. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    I just started on a premade world, and used the cheat menu to import the same map again. Maybe there is a more subtle two map requirement. My main concern was simply to avoid providing a broken event in the template, by at least testing a text box event. This is an interesting mystery, but unless someone has a specific use for this event, I'm not intending to delve further into the mystery at the moment. We went a couple years without noticing the issue with this event.
     
    Knighttime likes this.
  18. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    4,506
    Is anyone willing to write a small script for me? I think other designers would find it useful.

    I want certain units (in my case, generals: object.uGuderian, object.uModel, object.uRommel, object.uManstein) to be able to press a button (might as well use "k") while standing on terrain that has the road improvement, and change it to the railroad improvement. In exchange, there is a 1,000 gold deduction, and the general's MP is reduced by 3 (there doesn't need to be a check to see how many MP the general starts with meaning I'm fine with them doing this if they only have 1 MP, I'm simply trying to reduce the number of times a general can do this to 2x per turn and they have 6 MP).

    Reason I need it: I have an established road network for a scenario that I would like the player to be able to upgrade, but I want it to be costly so that it is used sparingly. Further, I don't want "new" roads to be constructed - there should simply be an ability to upgrade them. I would think this would be a useful script that could be used in many scenarios.

    While I could probably handle a portion of this event myself, trying to figure out if there is a road on a tile is a bit beyond my grasp. Many thanks to anyone who is willing to help.
     
  19. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,818
    Location:
    Ontario
    Disclaimer: Untested code follows.

    This is the data that goes before the event. Maybe some of this should be in the parameters file.
    Code:
    local railBuilders = {}
    railBuilders[object.uGuderian.id] = true
    railBuilders[object.uModel.id] = true
    railBuilders[object.uRommel.id] = true
    railBuildres[object.uManstein.id] = true
    local railUpgradeMoneyCost = 1000
    local railUpgradeMoveCost = 3
    
    This part goes in the onKeyPress event, after determining that the appropriate key has been pressed.

    Code:
    local activeUnit = civ.getActiveUnit()
    if activeUnit and railBuilder[activeUnit.type.id] and gen.hasRoad(activeUnit.location) and
        not gen.hasRailroad(activeUnit.location) and activeUnit.owner.money >= railUpgradeMoneyCost then
        local menuOptions = {[1]="No, do not place railroad.", [2]="Yes, spend "..text.money(railUpgradeMoneyCost).." to upgrade this road to a railroad."}
        local menuText = text.substitute("Our %STRING1 unit can place a railroad at the cost of %STRING2 and %STRING3 movement points.  Shall we proceed?",
        {activeUnit.type.name, text.money(railUpgradeMoneyCost),railUpgradeMoveCost})
        local menuTitle = "Place Railroad"
        local choice = text.menu(menuOptions,menuText,menuTitle)
        if choice == 2 then
            activeUnit.moveSpent = activeUnit.moveSpent + totpp.movementMultipliers.aggregate*railUpgradeMoveCost
            activeUnit.owner.money = activeUnit.owner.money - railUpgradeMoneyCost
            gen.placeRailroad(activeUnit.location)
        end
    end
    
    In parameters.lua, there is a line with text.setMoney, where you can change how text.money displays money. (If text.money gives you an error, let me know, since that means you have an older version of the template than I thought.)

    That's why I wrote the flag functions for the General Library. (There are some new ones for the recent TOTPP version that I haven't added to the documentation yet.)
     
    JPetroski likes this.
  20. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    4,506
    You rock!
     

Share This Page