jdog5000
Revolutionary
Tech Cost Mod
Version .5
By jdog5000
The goal:
In many of my games, I start to pull away with a large tech lead in the Renaissance. Sometimes Mansa Musa can hang with me, but otherwise the game is effectively over. Instead of just raising the difficulty, I decided to experiment with dynamic tech costs. The idea is that technology diffuses, particularly in the modern era, and that should lower the cost for civs catching up.
How it works:
Basically, whenever a civ acquires a new technology, the cost of that technology decreases for all the other civs. The formula is scaled linearly by tech era, with no effect on ancient techs but cost of techs in the modern era can decrease up to 40%. Future techs are never discounted. Currently, the maximum discount is multiplied by the fraction of civs who have discover the tech to the 1.6 power. So when one civs learns the tech, the cost only drops a small amount. Once half the world knows it, the cost for the laggers is much lower. There is also a factor that reduces when there are a small number of civs (when 1 of 3 civs know (barbarians count), the effect is much smaller than when 6 of 18 know). In the mod folder is a excel spread sheet that models the effect of the reduction for all the eras and % who know, with the variables used in the mod easy to manipulate and then change in TechCost.py.
Why a DLL?
Certainly doing whatever is possible in Python alone is a noble cause, but I don't believe all that I'm aiming for can be acheived in Python. The issue was that there's no method for modifying the cost of a tech, and clearly a changing tech cost was not part of the Civ 4 setup. Many functions retrieve tech cost directly from the c++ side of the game, for example in the TechConquest Mod, Bhruic uses the following lines:
pNewTeam = gc.getTeam(city.getOwner())
iTechCost = pNewTeam.getResearchCost(lTechDiff[iRandTech])
Or, in the tech chooser popup:
szTechString += str(gc.getPlayer(g_civSelected).getResearchTurnsLeft(i, ( gc.getPlayer(g_civSelected).getCurrentResearch() == i )))
I believe for these to return the proper result, the value returned by the C++ getResearchCost function has to be modified.
That being said, you could acheive most of the results by simply giving civs free beakers when they start a tech that many people already have. However, the appropriate costs won't be displayed when choosing techs, and this may affect the choices of the AI. Plus, it would be hard to handle the case where you researched a tech for one turn, then switched for a long time, then came back after many others had gotten it.
What the DLL does:
Creates one new member variable for CvTechInfo, the modified research cost. Changes getResearchCost() to return this variable, and creates setModResCost(int) and getOrigResCost(). All of the modifications to tech cost occur in Python. Since the modified research cost is initialized to the original, if you never modify it the cost never changes.
Potential mod side effects:
With this model, costs decrease for civs that have never met. While the decrease doesn't start until the classical era, and then is never more than ~8%, it seems this would decrease the potential tech divide when you find a "new world." Future versions may attempt to take into account the time since first discovery, which would also help solve the next issue.
While unlikely, there is potential for a strange race condition with the current implementation. If several civs finish a tech at nearly the same time, the cost for the last will be significantly lower for the last civ even if the others just got it the turn before. While unlikely in a game that starts in the Ancient Era, this could cause issues for games starting in the Middle Ages or later and is therefore not recommended for those situations.
Finally, the effect of this on the state of Barbarian research is unknown. They don't do normal research, but it could mean non-obsolete units on say a Terra map. Results similar to sugar pill.
Installation:
Unzip TechCost.zip and move to your Mods folder. The new DLL will load instead of the original one. Haven't tried putting it in the My Documents one, don't know if there are issues with that.
Note to fellow modders:
Python events handled using Dr_Elmer_Jiggles custom event handler. All changes in the C++ source code are commented with // ------ TECH_COST_MOD start ----------
and // ------ TECH_COST_MOD end ----------
Sources are attached.
TechCost.zip
View attachment TechCost_sources.zip
Version .5
By jdog5000
The goal:
In many of my games, I start to pull away with a large tech lead in the Renaissance. Sometimes Mansa Musa can hang with me, but otherwise the game is effectively over. Instead of just raising the difficulty, I decided to experiment with dynamic tech costs. The idea is that technology diffuses, particularly in the modern era, and that should lower the cost for civs catching up.
How it works:
Basically, whenever a civ acquires a new technology, the cost of that technology decreases for all the other civs. The formula is scaled linearly by tech era, with no effect on ancient techs but cost of techs in the modern era can decrease up to 40%. Future techs are never discounted. Currently, the maximum discount is multiplied by the fraction of civs who have discover the tech to the 1.6 power. So when one civs learns the tech, the cost only drops a small amount. Once half the world knows it, the cost for the laggers is much lower. There is also a factor that reduces when there are a small number of civs (when 1 of 3 civs know (barbarians count), the effect is much smaller than when 6 of 18 know). In the mod folder is a excel spread sheet that models the effect of the reduction for all the eras and % who know, with the variables used in the mod easy to manipulate and then change in TechCost.py.
Why a DLL?
Certainly doing whatever is possible in Python alone is a noble cause, but I don't believe all that I'm aiming for can be acheived in Python. The issue was that there's no method for modifying the cost of a tech, and clearly a changing tech cost was not part of the Civ 4 setup. Many functions retrieve tech cost directly from the c++ side of the game, for example in the TechConquest Mod, Bhruic uses the following lines:
pNewTeam = gc.getTeam(city.getOwner())
iTechCost = pNewTeam.getResearchCost(lTechDiff[iRandTech])
Or, in the tech chooser popup:
szTechString += str(gc.getPlayer(g_civSelected).getResearchTurnsLeft(i, ( gc.getPlayer(g_civSelected).getCurrentResearch() == i )))
I believe for these to return the proper result, the value returned by the C++ getResearchCost function has to be modified.
That being said, you could acheive most of the results by simply giving civs free beakers when they start a tech that many people already have. However, the appropriate costs won't be displayed when choosing techs, and this may affect the choices of the AI. Plus, it would be hard to handle the case where you researched a tech for one turn, then switched for a long time, then came back after many others had gotten it.
What the DLL does:
Creates one new member variable for CvTechInfo, the modified research cost. Changes getResearchCost() to return this variable, and creates setModResCost(int) and getOrigResCost(). All of the modifications to tech cost occur in Python. Since the modified research cost is initialized to the original, if you never modify it the cost never changes.
Potential mod side effects:
With this model, costs decrease for civs that have never met. While the decrease doesn't start until the classical era, and then is never more than ~8%, it seems this would decrease the potential tech divide when you find a "new world." Future versions may attempt to take into account the time since first discovery, which would also help solve the next issue.
While unlikely, there is potential for a strange race condition with the current implementation. If several civs finish a tech at nearly the same time, the cost for the last will be significantly lower for the last civ even if the others just got it the turn before. While unlikely in a game that starts in the Ancient Era, this could cause issues for games starting in the Middle Ages or later and is therefore not recommended for those situations.
Finally, the effect of this on the state of Barbarian research is unknown. They don't do normal research, but it could mean non-obsolete units on say a Terra map. Results similar to sugar pill.
Installation:
Unzip TechCost.zip and move to your Mods folder. The new DLL will load instead of the original one. Haven't tried putting it in the My Documents one, don't know if there are issues with that.
Note to fellow modders:
Python events handled using Dr_Elmer_Jiggles custom event handler. All changes in the C++ source code are commented with // ------ TECH_COST_MOD start ----------
and // ------ TECH_COST_MOD end ----------
Sources are attached.
TechCost.zip
View attachment TechCost_sources.zip