Modmodding Q&A Thread

Because of the first loop, areas with only barbarians, natives or independents are prioritized of being resurrected. You will lose that prioritization when you merge the loops.
How so? I thought that DoResurrection made the civ resurrect. Is that incorrect?

Ah, it's because of the return after the first DoRessurrection, isn't it? What if I changed that to continue?

EDIT: But as it currently is it seems like only one civ can ressurrect per turn. I'm confused now, how does merging the loops remove prioritization?
 
Moderator Action: Moved discussion to this thread.
 
How so? I thought that DoResurrection made the civ resurrect. Is that incorrect?

That is correct. This code determines which civ should be resurrected.

Ah, it's because of the return after the first DoRessurrection, isn't it? What if I changed that to continue?

If you change the return statement, more civs can ressurrect at once. In this case, removing the return statement has the same effect as replacing it with a continue.

EDIT: But as it currently is it seems like only one civ can ressurrect per turn. I'm confused now, how does merging the loops remove prioritization?

If you merge them, the check which is currently in the second loop (enough cities to respawn with some rgn) will occur immediately after the check in the first loop (only non-major civ cities). That means that only if both checks are NOT met, it will go to the next iteration. That means it is possible that a civ can resurrect if its respawn area has non-major civ cities, even if there are civs with only non-major civ cities.

The first loop ensures that civs with only non-major civ cities in the respawn area have a higher priority than civs with major civ cities in the respawn area, even if the second one died earlier.
 
In CvCity.cpp in void CvCity::doCulture() there is this bit of code:

Code:
    if     (getCommerceRate(COMMERCE_CULTURE) <= 4)
    {
        changeCultureTimes100(getOwnerINLINE(), getCommerceRateTimes100(COMMERCE_CULTURE), false, true);
        return;
    }

Can anyone tell me what its purpose is? All I know is that if I don't change that 4 to a 0, culture won't be counted towards Golden Age progress in my modmod if a city produces less than 4 culture per turn.
 
In Barbs.py, what's the difference between checkSpawn and checkLimitedSpawn exactly?
 
I try to change the 600AD scenario starting date, but when I change the turn catapult even it deactivated. How can I fix this?
 
So after working a bit more I think my main issue is that I have zero idea what to do so that the health from specialists are enabled by buildings. Where would be the best place to put such a check? I assume I need a variable in CvCity.cpp for the amount of health given to specialists in each city, then some place in said file run through what buildings the city has and for each one add the specialist health to the variable, and the rest is pretty much the specialist yield XML implementation.

Am I wrong? Where should I put the building check?
 
Make it a separate attribute of the city, change it with processBuilding, then apply it when city health is calculated.
 
change it with processBuilding
How do I ensure that the variable doesn't grow out of control? I haven't tried there, but if I just go and change the value in process building, wouldn't the value increase every time the function is called? Where do I set the specialist health value to 0?

Also, should I have use AI_setAssignWorkDirty(true) and setInfoDirty(true) in my change health function like CvCity::changeBuildingGoodHealth does? What do those statements do exactly?
 
Attribute? As in a class wide variable? Or something else?
Instance variable, but yes.

How do I ensure that the variable doesn't grow out of control? I haven't tried there, but if I just go and change the value in process building, wouldn't the value increase every time the function is called? Where do I set the specialist health value to 0?

Also, should I have use AI_setAssignWorkDirty(true) and setInfoDirty(true) in my change health function like CvCity::changeBuildingGoodHealth does? What do those statements do exactly?
Sorry, maybe I have assumed too much prior work/knowledge.

processBuilding is called every time a building is added (with iChange = 1) or removed (with iChange = -1), if your new effect is a CvBuildingInfo attribute as it should be, you can just mimic what is already there. The initial value of course needs to be set to 0 in the constructor.

AI_setAssignWorkDirty makes the AI reevaluate the worked city tiles selection, which is a good idea for changed health (the AI may be working food heavy tiles because the city is in negative health). setInfoDirty just tells the interface to be redrawn which you definitely want.
 
In CMC, when Egypt spawns, despite their Capital's culture only growing by 2 and Nwt-Rst's being 36, at the end of the first turn every plot around the capital and the marble 2 tiles away flips to Egypt. What code is causing this?
 
I've found a workaround for the last issue, but I've just noticed that Ninua does not flip to the Persians in CMC, it's normally controlled by the Babylonians by the Persian spawn, it's within the flip zone, and usually has at least 150 Babylonian Culture. Does anyone have an idea as to why it's not flipping?
 
In case anyone's interested, I've written a script for a 32-bit Notepad++ Python scripting plugin to automate the addition of new civs to a scenario file:

Code:
from Npp import *
import re

start = 3 - 1
end = 54
for i in range(start, end):
    ii = end + start - i
    editor.rereplace(r"(Owner=|Reveal=|Player|,|Team=|TeamID=)" + "(" + str(ii) + ")([^1234567890])", r"($1)" + str(ii+1) + "($3)")

This takes references to civs between start and end, both inclusively, and increases them by 1.

Aforementioned Python Scripting Plugin: http://npppythonscript.sourceforge.net/
 
Last edited:
That's great!
 
Quick Update: My last script caused the first character after the civ's number to be deleted. I've updated the OP.
 
Thanks. This is really useful.

EDIT:
I made 2 small modifications. The first is a popup, in which you can type the number of the new civ. (So you don't have to open the script to edit it)
The second an undo-action, which will undo the whole script when Ctrl-Z is pressed.

Code:
from Npp import *
import re

start = int(notepad.prompt(notepad, 'Number of the new civ', "")) - 1
end = 54

editor.beginUndoAction()
for i in range(start, end):
    ii = end + start - i
    editor.rereplace(r"(Owner=|Reveal=|Player|,|Team=|TeamID=)" + "(" + str(ii) + ")([^1234567890])", r"($1)" + str(ii+1) + "($3)")
editor.endUndoAction()
 
Last edited:
I'm trying to figure out how to grant research through Python, as I can't seem to find a DLL equivalent to StoredData.getWonderBuilder, but my code doesn't seem to work.

Code:
def onCityAcquired(iPlayer, iOwner, city, bConquest):

   # Library of Ashurbanipal effect
   if (bConquest == true and data.getWonderBuilder(iAshurbanipalLibrary) == iPlayer):
       team = getTeam(iPlayer)
       culture = city.getCulture(iOwner)
       team.changeResearchProgress(team.getCurrentResearch(), culture, iPlayer)
 
Why go through wonder builder at all? Can't the wonder change hands so the effect goes to the new owner? But changeResearchProgress should do it, are you sure this line is called? Also, you don't need to check equality with true for booleans.
 
Back
Top Bottom