1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Modding help - lua for trade routes

Discussion in 'Community Patch Project' started by pineappledan, Sep 19, 2018.

  1. pineappledan

    pineappledan Deity

    Joined:
    Aug 9, 2017
    Messages:
    4,881
    Gender:
    Male
    Location:
    Alberta, Canada
    Hi there,

    I'm working on a compatibility patch for the Canadian civ, and I am getting a crash when using a code for their UA

    What it does:
    On move, Internal land trade routes claim tiles

    The Code:
    Code:
    function YorkFactoryExpress(iPlayer, iUnit, iX, iY)
        local pPlayer = Players[iPlayer]
        local pCapital = pPlayer:GetCapitalCity()
        local pUnit = pPlayer:GetUnitByID(iUnit)
        local iRouteIndex = pUnit:GetTradeRouteIndex()
        local pTrade = Game.GetTradeRoute(iRouteIndex)
    
        if pPlayer:GetCivilizationType() ~= iCanada then return end
        if (pUnit == nil or pUnit:IsDelayedDeath()) then return end
    
        if (pUnit:GetUnitType() == GameInfoTypes.UNIT_CARAVAN) then 
            local pPlot = pUnit:GetPlot()
            if (pTrade.ToCivilizationType == iCanada) then
                if pPlot:GetOwner() == -1 then
                    pPlot:SetOwner(pPlayer, pCapital, 1, 1)
                end
            end
        end
    end
    
    GameEvents.UnitSetXY.Add(YorkFactoryExpress)
    
    If I disable the parts of the code which check if the trade route is internal, (lines 5,6 and 13, the lines with GetTradeRouteIndex() and GetTradeRoute()), then the code works perfectly, but it works for international trade routes too.
    If I run the code as seen above, the game crashes as soon as I issue an order to any unit (UnitSetXY() triggers, cannot complete and crashes the game)

    This uses @whoward69's extra lua components to work (CustomModOptions 'API_LUA_EXTENSIONS' is enabled), so I can't understand why this shouldn't work.

    - Is the code wrong for what I want it to do? ie. am I misusing these functions?
    - Are GetTradeRouteIndex() and GetTradeRoute() not included in the DLL? Do I need to package the mod with some other part of Whoward's Pck'n'mix mods to get this lua to work?
     
  2. Kim Dong Un

    Kim Dong Un The One & Unly Supporter

    Joined:
    Dec 17, 2017
    Messages:
    605
    Gender:
    Male
    Location:
    Pyongyang
    Ohh no...

    I reckon Enginseer was flustered with the work he managed to complete, and now you're having problems as well. I really hope this hasn't been too much of a pain.
     
  3. Gazebo

    Gazebo Lord of the Community Patch Supporter

    Joined:
    Sep 26, 2010
    Messages:
    17,787
    Gender:
    Male
    Location:
    Little Rock
    Well, for one thing you do a nil check for pUnit (good) after already calling pUnit above (bad). You need to nest calls to pUnit within the nil check.

    G
     
  4. pineappledan

    pineappledan Deity

    Joined:
    Aug 9, 2017
    Messages:
    4,881
    Gender:
    Male
    Location:
    Alberta, Canada
    So it should look like this?
    Code:
    function YorkFactoryExpress(iPlayer, iUnit, iX, iY)
        local pPlayer = Players[iPlayer]
        local pUnit = pPlayer:GetUnitByID(iUnit)
    
        if pPlayer:GetCivilizationType() ~= iCanada then return end
        if (pUnit == nil or pUnit:IsDelayedDeath()) then return end
    
        local pCapital = pPlayer:GetCapitalCity()
        local iRouteIndex = pUnit:GetTradeRouteIndex()
        local pTrade = Game.GetTradeRoute(iRouteIndex)
    
        if (pUnit:GetUnitType() == GameInfoTypes.UNIT_CARAVAN) then
            local pPlot = pUnit:GetPlot()
            if (pTrade.ToCivilizationType == iCanada) then
                if pPlot:GetOwner() == -1 then
                    pPlot:SetOwner(pPlayer, pCapital, 1, 1)
                end
            end
        end
    end
    
    That's better, thanks, but it does not fix the crashes I am having
     
    Last edited: Sep 19, 2018
  5. Enginseer

    Enginseer Salientia of the Community Patch Supporter

    Joined:
    Nov 7, 2012
    Messages:
    3,217
    Gender:
    Male
    Location:
    Somewhere in California
    pCity =/= iCity.

    Using a City Object instead of a City ID will always CTD.

    Instead you need to use this variable for your line 16 to work.
    Code:
    local pCapital = pPlayer:GetCapitalCity():GetID()
    
    You're also using too many unnecessary variables for such a Lua intensive GameEvent, while you are asking to grab iRouteIndex and pTrade for all units that aren't caravans which should've raised some red flags in your lua.log.
    Code:
    function YorkFactoryExpress(iPlayer, iUnit, iX, iY)
        local pPlayer = Players[iPlayer]
        if pPlayer:GetCivilizationType() ~= iCanada then return end
        local pUnit = pPlayer:GetUnitByID(iUnit)
        if (pUnit == nil or pUnit:IsDelayedDeath()) or not (pUnit:GetUnitType() == GameInfoTypes.UNIT_CARAVAN) then return end
    --GameInfoTypes.UNIT_CARAVAN should be variabled.
            local pPlot = pUnit:GetPlot()
            if (Game.GetTradeRoute(pUnit:GetTradeRouteIndex()).ToCivilizationType == iCanada) then
                if pPlot:GetOwner() == -1 then
                    pPlot:SetOwner(pPlayer, pPlayer:GetCapitalCity():GetCityID(), 1, 1)
                end
            end
        end
    end
    
     
    Last edited: Sep 20, 2018
  6. pineappledan

    pineappledan Deity

    Joined:
    Aug 9, 2017
    Messages:
    4,881
    Gender:
    Male
    Location:
    Alberta, Canada
    That isn't the issue. The issue is these 2 lines:
    local iRouteIndex = pUnit:GetTradeRouteIndex()
    local pTrade = Game.GetTradeRoute(iRouteIndex)

    The script works fine if I comment them out
     
  7. Enginseer

    Enginseer Salientia of the Community Patch Supporter

    Joined:
    Nov 7, 2012
    Messages:
    3,217
    Gender:
    Male
    Location:
    Somewhere in California
    Did you not enable API_TRADEROUTES?
     
  8. Gazebo

    Gazebo Lord of the Community Patch Supporter

    Joined:
    Sep 26, 2010
    Messages:
    17,787
    Gender:
    Male
    Location:
    Little Rock
    Not all units have a trade route index, and the route index does not control for variables outside of it's scope. i.e., the index on a unit defaults to -1, and if you toss -1 into the
    Game.GetTradeRoute() function it may throw up CTD on you.

    I strongly recommend you download the DLL repo, build a local copy, drop that debug DLL into your CP, and then attach the debugger to civ while testing. It'll show you exactly where crashes are happening, and why. You can also use this to see what the lua functions do with their data. It's a bit of work to get setup, but it will save you innumerable headaches in the future.

    G
     
  9. pineappledan

    pineappledan Deity

    Joined:
    Aug 9, 2017
    Messages:
    4,881
    Gender:
    Male
    Location:
    Alberta, Canada
    I tried running a game with Enginseer's proposed lua. The CTD now occurs once Canada builds a caravan, but at least the civ is playable if you avoid trade routes, which means I can begin to test other things too.:sad:

    Even though it doesn’t completely solve the problem, moving those local defines back should really help performance, so thank you for pointing that out. For my own curiosity, what advantage does putting the caravan unit check into a then - return - end check have over using it in an if - then condition?
    I did not. I was not aware that was necessary. I have added it in now. Thank you.
    Which DLL is that on the github? CvGameCoreDLL, or all 3?

    In other news, the coureurs des bois spawning lua/event works well. I just found out the original mod didn't have a strategiv view icon for the voyageur/coureurs des bois, so I will have to create one.

    The avro arrow art files are all broken as well (the arrow is currently a pack of flying spearmen). This base mod is pretty ghetto; there’s as much designing new, balanced components as their is fixing broken stuff
     
    Last edited: Sep 20, 2018

Share This Page