Modding help - lua for trade routes

pineappledan

Deity
Joined
Aug 9, 2017
Messages
10,855
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?
 
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.
 
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?

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
 
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:
Plot:SetOwner(PlayerID newValue, int acquiringCityID, bool checkUnits = true, bool updateResources = true)
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:
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
 
Did you not enable API_TRADEROUTES?
 
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

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
 
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?
Did you not enable API_TRADEROUTES?
I did not. I was not aware that was necessary. I have added it in now. Thank 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.
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:
Back
Top Bottom