Lua Scripting Possibilities

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

  1. Pablostuka

    Pablostuka Prince

    Joined:
    Mar 27, 2002
    Messages:
    590
    Gender:
    Male
    Location:
    Galway, IRL
    Thanks for the reply, so yes, it's appaerently easy to force creation of specific wonders by event. This is just what i wanted :)

    I've also deleted my post in the reference thread to keep it clean.
     
  2. Pablostuka

    Pablostuka Prince

    Joined:
    Mar 27, 2002
    Messages:
    590
    Gender:
    Male
    Location:
    Galway, IRL
    Just my 2 cents in case anybody else needs to do the same (maybe it's been answered before, there are many posts on Lua that I haven't checked yet):

    How to move a city from one place to another:

    1st obtain the id of the city you want. You can open the city view, hit the Lua console and type this:

    Code:
    civ.getOpenCity().id
    This will return an integer which is ther internal id of the city.

    2nd close the city screen, go to the tile you want, ensure there's a road on it (shift + F8 to edit terrain) and then hit this in the Lua console:

    Code:
    civ.getCity(XX):relocate(civ.getCurrentTile())
    Where XX is the city id obtained in the previous step.

    How to paint a river on a tile:

    As you know, the cheat mode doesn't allow you to add rivers to tiles. This is the quickest option I was able to find, you only need to navigate to the tile you want the river and hit this in the Lua console:

    Code:
    civ.getCurrentTile().river = true
    That's it, If you want to remove a river, just change "true" to "false".

    Hope it helps.

    Pablo
     
  3. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,825
    Location:
    Ontario
    In TOTPP, CTRL+9 adds and removes rivers. Still, that's a useful example of using the tile.river property. I made links for both questions in the Great Lua Library thread.

    Per the extra terrain hotkeys patch description.
    Code:
    Adds keyboard shortcuts for changing terrain / tile improvements. In cheat mode, change terrain with 0 (Desert) to 9 (Jungle) and Ctrl-3 (Ocean) to Ctrl-8 (Extra terrain 5). Use Ctrl-9 to add/remove a river.
    For tile improvements, the following keys can be used in cheat mode when no unit is selected:
    r: Road
    o: Railroad
    i: Irrigation
    m: Mine
    l: Farmland
    f: Fortress
    e: Airbase
    p: Pollution
    
     
    Pablostuka likes this.
  4. Pablostuka

    Pablostuka Prince

    Joined:
    Mar 27, 2002
    Messages:
    590
    Gender:
    Male
    Location:
    Galway, IRL
    Thanks for that, as you can see I still have loads of stuff to catch up, big learning curve coming from MGE!!
     
  5. tootall_2012

    tootall_2012 King

    Joined:
    Feb 11, 2012
    Messages:
    800
    Hi Pablo,

    In case you don't have it, I've attached the TOTPP v0.18 PDF reference guide from the Scenario Creation Excel Sheet thread located here. The pdf contains all the features to be found within TNO's TOTPP project.
     

    Attached Files:

    Last edited: Feb 17, 2022
    Pablostuka likes this.
  6. Pablostuka

    Pablostuka Prince

    Joined:
    Mar 27, 2002
    Messages:
    590
    Gender:
    Male
    Location:
    Galway, IRL
    That link is pure gold, thanks!
     
    tootall_2012 likes this.
  7. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    4,509
    Can someone please help me out with a really stupid question? I have the below code (in after production) which aims to remove trade routes from cities that shouldn't have them, but really that's not what this code is doing obviously.

    What I want is to have any cities that are not in Japan to be precluded from trading with one another, with a penalty if it is attempted. What this say is simply that half of the trade route is always going to be removed (unless it happens to be between two Japanese mainland cities).

    Now, I think what i want to do is add another check between lines 4 and 5 below where I use the:

    from (get)
    traderoute.from -> city

    and

    to (get/set)
    traderoute.to -> city

    but I'm just drawing a blank of how I'd actually write this in the way that makes most sense. I'd really like to avoid having to go through and do one event for every single city that I don't want to be able to trade. Also I'm not totally certain how to write the actual line "traderoute.to (the -> city part is throwing me).

    Hopefully it's another one of my stupid "it's been a long day" questions that isn't too hard for one of our experts to explain :) Thank you all!

    Code:
    
    1if tribe == object.pJapanese then
      2  for city in civ.iterateCities() do 
        3        if city.owner == object.pJapanese and (city ~= object.cNagasaki and city ~= object.cKagoshima and city ~= object.cKumamoto and city ~= object.cUita and city ~= object.cKitakyushu and city ~= object.cHiroshima) then
          4          if city.tradeRoutes[0] then
            5        city:removeTradeRoute(0)
                    civ.ui.text("HOUSE RULES: You may only trade with Japan itself.  Any cities with a trade route on the mainland will have that route deleted each turn.  As you violated this house rule, a -25 gold penalty has been taken.")
                    object.pJapanese.money = object.pJapanese.money - 25
                    end
                    if city.tradeRoutes[1] then
                    city:removeTradeRoute(1)
                    civ.ui.text("HOUSE RULES: You may only trade with Japan itself.  Any cities with a trade route on the mainland will have that route deleted each turn.  As you violated this house rule, a -25 gold penalty has been taken.")
                    object.pJapanese.money = object.pJapanese.money - 25
                    end
                    if city.tradeRoutes[2] then
                    city:removeTradeRoute(2)
                    civ.ui.text("HOUSE RULES: You may only trade with Japan itself.  Any cities with a trade route on the mainland will have that route deleted each turn.  As you violated this house rule, a -25 gold penalty has been taken.")
                    object.pJapanese.money = object.pJapanese.money - 25
                    end
                end 
        end
    end 
    
    
     
  8. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,825
    Location:
    Ontario
    I haven't worked with the traderoute stuff yet, but I'm pretty sure this will work.

    Code:
    local function isNotInJapan(city)
        -- return true if a city is not in japan,
        -- and false otherwise
        return city ~= object.cNagasaki and city ~= object.cKagoshima and city ~= object.cKumamoto and city ~= object.cUita and city ~= object.cKitakyushu and city ~= object.cHiroshima
    end
    if tribe == object.pJapanese then
        for city in civ.iterateCities() do
            for tradeRouteID=2,0,-1 do
                if city.tradeRoutes[tradeRouteID] then
                    local route = city.tradeRoutes[tradeRouteID]
                    if isNotInJapan(route.from) or isNotInJapan(route.to) then
                        civ.ui.text("HOUSE RULES: You may only trade with Japan itself.  Any cities with a trade route on the mainland will have that route deleted each turn.  As you violated this house rule, a -25 gold penalty has been taken.")
                        object.pJapanese.money = math.max(object.pJapanese.money - 25,0)
                        city.removeTradeRoute(tradeRouteID)
                    end
                end
            end
        end
    end
    
    We check the 3 possible trade routes in reverse order, since removing a trade route shifts the IDs of the remaining routes. That is, if you remove route 0, route 1 now takes on the ID of 0. With a reverse order check, we don't need to worry about that.

    I also removed the trade route last, in case you want to use city names in the text. I'm not sure I would call this a "House" Rule when a penalty is levied in game.

    Let me know if you want more explanation, or if this doesn't work.
     
    Dadais likes this.
  9. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    4,509
    This threw up an issue with the last line before all the ends (city.removeTradeRoute(tradeRouteID) - looks like it wanted a city instead?

    Code:
    Enter console.commands() to see a list of keys in the console table.  Some give access to functions in modules, others will run event code.
    ...Scenario\1937-Japan Invades China\consolidatedEvents.lua:709: bad argument #1 to 'removeTradeRoute' (civ.city expected, got number)
    stack traceback:
        [C]: in field 'removeTradeRoute'
        ...Scenario\1937-Japan Invades China\consolidatedEvents.lua:709: in function 'consolidatedEvents.onCityProcessingComplete'
        ...est of Time\Scenario\1937-Japan Invades China\events.lua:444: in function <...est of Time\Scenario\1937-Japan Invades China\events.lua:436>
    
    I personally think this is one of the more interesting recent things... Sanctions, trade treaties and such are all now possible.
     
  10. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,825
    Location:
    Ontario
    No, I should have put a colon instead of a period.
    Code:
    city:removeTradeRoute(tradeRouteID)
    
    I think you get the "argument #1, civ.city" expected because the ':' operator puts the item to the left of the colon as the first argument of the function.

    I agree.
     
  11. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    4,509
    That did work to remove the traderoute. It's showing the text multiple times (one for each trade route) but when I have some time tomorrow I can play around with where to put that and the money cost to make sure it only fires once per turn. Thanks for your help!
     
  12. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,825
    Location:
    Ontario
    I've replied here, so we don't clutter the Function Reference Thread.

    Can you please post the relevant code? I quickly started a hotseat game, and tried this

    Code:
    function discreteEvents.onTurn(turn) 
        for i=0,7 do
            if not civ.getTribe(i).isHuman then
                civ.ui.text(civ.getTribe(i).name.." is not human.")
            end
        end
    end
    
    and it worked as expected.
     
  13. Dadais

    Dadais King

    Joined:
    Oct 20, 2010
    Messages:
    607
    Location:
    France
    Thx prof.

    Guess I understood the issue with the used code (from the "old" EpicCasualWWII" scenario) :

    Code:
           if civ.getPlayerTribe() ~= Nazi then
               LocationList = {{129,121,0},{135,115,0},{140,124,0}}
               civlua.createUnit(UnitTable.NazInf, Nazi, LocationList,{count = 21, randomize = true, homeCity = nil, veteran = false})
               civlua.createUnit(UnitTable.TanknM, Nazi, LocationList,{count = 12, randomize = true, homeCity = nil, veteran = false})
               civlua.createUnit(UnitTable.ArtillM, Nazi, LocationList,{count = 9, randomize = true, homeCity = nil, veteran = false})
           end
    
    As one of the player wasn't the nazi, it thus triggered the function.

    My first assumption was false (I believed I used the isHuman() function to code such a thing), revealing I changed the way I coded :)

    I stupidly didn't take time to check the code before asking. My deep mistake there.

    Sorry for eating some of your time ! I edited the question post so it won't bother anyone else.
     

Share This Page