Foreign Trade Routes

Gedemon

Modder
Super Moderator
Joined
Oct 4, 2004
Messages
12,823
Location
France
Allow one trade routes per city with another civilization's city if they are connected by road, river, coast or ocean and you have an open border agreement (or at least friendly relation for a city-state trade route)

installation :

- download the civ5mod file to your mod folder (..\My Documents\My Games\Sid Meier's Civilization 5\MODS).
- launch civ5, go to the mod browser and click "install mod"
- find the "Foreign trade Routes" line and activate the mod.
- from the mod section, go to single player and set up a game


Credits & thanks

Whys, Onni, whoward69


Screenshoots

Spoiler :
(click for full screen)
 
(reserved)
 
This is amazing. I'm assuming this works with even large civilizations, not just city-states?
 
Yes, I'll need to put more details in the OP ;)

It works with any civilization that have an open border treaty with you (the treaty could be one-sided BTW), which means other players (human/AI) with OB and friendly/allied city-states.

ATM the routes are recalculated at each new turns, I'll see what can be done if it's impact performance too much, but ATM it's ~1 sec/turn in the middle of a standard (map/speed) game on my computer.

Here are the type of route :
River : 2 cities along the same river, yield 50% of normal income (based on vanilla calculation for city-capital route), one of the civ must have researched sailing.
Coastal : 2 cities linked by coast tiles, both with harbor (meaning both civ have optic), yield 75% of normal income.
Road : 2 cities linked by road, yield 100% of normal income.
Ocean : 2 cities linked by ocean, both must have harbor, one of the civ must have Astronomy, yield 125% of normal income.

When linking cities, the biggest (most populated) ones choose first, trying to make a route with another big city.

You'll find infos on your trade routes in the economic overview and on the gold tooltip (see screens)
 
Yes, I'll need to put more details in the OP ;)

It works with any civilization that have an open border treaty with you (the treaty could be one-sided BTW), which means other players (human/AI) with OB and friendly/allied city-states.

ATM the routes are recalculated at each new turns, I'll see what can be done if it's impact performance too much, but ATM it's ~1 sec/turn in the middle of a standard (map/speed) game on my computer.

Here are the type of route :
River : 2 cities along the same river, yield 50% of normal income (based on vanilla calculation for city-capital route), one of the civ must have researched sailing.
Coastal : 2 cities linked by coast tiles, both with harbor (meaning both civ have optic), yield 75% of normal income.
Road : 2 cities linked by road, yield 100% of normal income.
Ocean : 2 cities linked by ocean, both must have harbor, one of the civ must have Astronomy, yield 125% of normal income.

When linking cities, the biggest (most populated) ones choose first, trying to make a route with another big city.

You'll find infos on your trade routes in the economic overview and on the gold tooltip (see screens)


Alright, awesome! Does the AI use this too? And is there any way to discourage the AI from backstabbing you or attacking you if they can benefit financially from this (diplomacy modification, I guess)?
 
Yes, the AI will benefit from trade routes too. I won't make balance change with this mod component, but I may add an override for worker AI so it may build international road.

I don't know how many mods there are that modify the AI diplomatic behavior, but one who reduce the penalty from close land and raise the willingness to offer OB would be a good complement.

edit : but anyway, we can't make the AI aware that backstabbing could cost it the trade route money ATM.
 
Yes, the AI will benefit from trade routes too. I won't make balance change with this mod component, but I may add an override for worker AI so it may build international road.

I don't know how many mods there are that modify the AI diplomatic behavior, but one who reduce the penalty from close land and raise the willingness to offer OB would be a good complement.

edit : but anyway, we can't make the AI aware that backstabbing could cost it the trade route money ATM.


Ah, I see, well at least they make use of it too! Now if only there were some good diplomacy behavior mods outside of the WWGD mod (which is now part of VEM, which I have no interest in...).
 
This looks fantastic. You certainly have been busy creating mod comps lately :)!

This has been one of my biggest pet peeves with CiV. I thought that international trade routes should have been an integral part of the game from day one. I am glad that someone is implementing it however. My only concern would be the AI willingness to build routes since the current system discourages development there.

Are you planning to combine all of your mod comps into a big modpack eventually?
 
Yes, international trade routes is something I'v waited for, too. Thx for your time again, Gedemon. But unfortunately I'v to report a bug:

Runtime Error: [string "C:\Users\MyUserName\Documents\My Games\Sid Me..."]:50: attempt to call method 'GetForeignTradeRoutesGoldTimes100' (a nil value)

It occured several times, I'v attached the complete log of my first game session (just a few turns). The result is the toppanel tooltip not working (sometimes turning the toppanel into a bunch of "?").

Maybe InitializePlayerFunctions() in which you extend the metatable of the activePlayer "object" is not called correctly?

The second log is a completely new game session. This time a ran ListAttrib(Players[0]) from your Debug.lua file at the beginning of my 3rd turn. The ForeignTradeRoute function was not present in the metatable.

Update: After changing player:GetForeignTradeRoutesGoldTimes100 to GetForeignTradeRoutesGoldTimes100(player) in ForeignTradeRoutesUIFunctions.lua the mod works just fine.

I hope you found this report usefull :).
 

Attachments

Maybe InitializePlayerFunctions() in which you extend the metatable of the activePlayer "object" is not called correctly?
bingo !

It was called only when loading a game, not on a new game initialization... Not the first time I made this mistake, as I tend to start a new game for a new mod, save, quit, add function to the mod, reload, test, save, quit, etc...

that function was added in the middle of the process, and I didn't test a new game... :blush:

Update: After changing player:GetForeignTradeRoutesGoldTimes100 to GetForeignTradeRoutesGoldTimes100(player) in ForeignTradeRoutesUIFunctions.lua the mod works just fine.
But it won't show you the correct value on the toppanel/economic overview (gold gained per turn especially)

I hope you found this report usefull :).
Very usefull, thanks :goodjob:

bugfix soon...
 
New version

v.2 (May 2, 2012):
- bugfix : bad initialization on new game
 
Are you planning to combine all of your mod comps into a big modpack eventually?
Eventually.

But even if they are designed to work together (and some will be mandatory to others, like Cultural Diffusion for Revolution), I prefer to release them separated.

The "big picture", the mod for which I'm making this components is a dynamic history mod, if I were to release a modpack, it would be the base of it. Yet I may release it separately, still pondering... What I feel from the development version of RFC for civ5 is that the vanilla game lacks depth in gameplay for a dynhist mod comparatively to civ4, so more mechanisms must be added to keep the player busy while waiting for other civs to spawn... And not only barbarian invasion, instability, revolution...

I really hope that G&K will be a better base on that point.


Edit: sorry for triple post and going a bit OT here, I just realized I was thinking aloud :D
 
I'm sorry, but yet another bug ;)

Loading a game directly from within the game session causes this:

Runtime Error: [string "C:\Users\MyUserName\Documents\My Games\Sid Me..."]:305: attempt to call global 'LoadData' (a nil value)
Runtime Error: [string "C:\Users\MyUserName\Documents\My Games\Sid Me..."]:305: attempt to call global 'LoadData' (a nil value)
Runtime Error: [string "C:\Users\MyUserName\Documents\My Games\Sid Me..."]:297: attempt to call global 'LoadData' (a nil value)
Runtime Error: Error loading Assets/UI/InGame/TopPanel.lua.
[snip]
ForeignTradeMain: ---------------------------------------------------------------------------------------------------------------
ForeignTradeMain: -------------------------------- Foreign Trade Routes Script : loaded ! ---------------------------------------
ForeignTradeMain: ---------------------------------------------------------------------------------------------------------------
Runtime Error: [string "C:\Users\MyUserName\Documents\My Games\Sid Me..."]:295: stack overflow


Maybe it is the same bug that caused Thalassicus to disable the "Load Game" entry from the ingame menu altogether for CivUP+VEM (I forgot what that was about)?

Exiting to the Main Menu and loading the save from there works perfectly. LoadData() is available again.

Edit: ChangeLog of VEM 1.10: Disabled the load game button on the ingame menu (loading from within an active game breaks all mods with lua code). It seems globals do not get re-initialized correctly because of a bug within the games caching mechanisms (http://forums.civfanatics.com/archive/index.php/t-442597.html).

Edit2: On second thought my wild guess would be that it has nothing to do with the cache directly but something with the UI ToolTipHandlers and when the game registers the callbacks. Maybe in a loaded game from the Main Menu the Callback will be registered only after ForeignTradeMain.lua was processed. In a game loaded from within a game session the callbacks are still present even before ForeignTradeMain.lua is processed. Therefore none of the globals needed are present.
 
It's the same global bug, yes.

What happens here is a load order problem that I hadn't anticipated.

Vanilla Lua files (or their override if a mod use any with the VFS) are loaded before the entry point of modded Lua file.

In a new game (or when loading from main menu), the following specific initializations related to that bug are made in order:
1- vanilla TopPanel.Lua is loaded
2- The top panel infos are then updated, vanilla pPlayer:CalculateGoldRate() is called
3- SaveUtils.lua is loaded from the mod (LoadData is initialized here)
4- Foreign trade Routes functions are initialized, specifically CalculateGoldRate() is replaced with the mod custom function, that use LoadData
5- top panel infos are updated again, the new pPlayer:CalculateGoldRate() is called with success as LoadData as previously been initialized.


Now when reloading from inside a game, the global lua variables are not reinitialized as Thalassicus pointed out, and the custom functions (including CalculateGoldRate) attached to one of them (here player metatable) are not deleted... While the mod lua variables (including LoadData) are.

So when pPlayer:CalculateGoldRate() in step 2 is called when reloading from inside a game, it's still the CalculateGoldRate() from step 4, and it still refers to the non-existent LoadData, as step 3 has not occurred yet...

On top of that, step 4 reinitialize CalculateGoldRate() again, and this function include a reference to the old one, causing the stack overflow error.


...


So, yep, I'll disable the ingame load button, I could prevent the calling of a nil function, but not the "stack overflow" error...
 
What about not using the metatables at all? Can we define functions inside of a function? Something like..

Code:
function GoldTipforFTRHandler( control )
    include("SaveUtils.lua")
    include("ForeignTradeUtils.lua")

    local iGoldPerTurnFromForeignTradeRoute = GetForeignTradeRoutesGoldTimes100(pPlayer) / 100
end
 
What about not using the metatables at all? Can we define functions inside of a function, something like..

Code:
function GoldTipforFTRHandler( control )
    include("SaveUtils.lua")
    include("ForeignTradeUtils.lua")

    local iGoldPerTurnFromForeignTradeRoute = GetForeignTradeRoutesGoldTimes100(pPlayer) / 100
end

I need the metatable so I don't have to override all the vanilla files that calls the player gold rate function. It would break compatibility with mods editing the same files (like VEM or NIGHT for TopPanel.Lua)

And I'm not a programmer, but I suppose that having an include in a function that's called multiple times each turn will have consequence on memory usage.
 
Nonetheless a great mod, thank you! Proximity to other empires or city states does matter now. I like it. Any ideas on how to balance it further? Imo I got too much gold connecting to nearby city states. Maybe making the income also depend on City State Influence and diplomatic relationship with major civilizations?
 
Income per relation is planned, yes, as adding 1 or 2 trade routes in cities with specific building or tech... We can also lower the global income from foreign routes, that would be needed anyway when more routes per city are allowed.

ATM a road trade route with a foreign city use the same formula as the gold income from one of your city connected to your capital, maybe this should be lowered to 75% and that value would be reached only with a DoF or for an allied City State.
 
Back
Top Bottom