How do Settler costs work? Looking into the unit XML they have iCost set to 0, but clearly they do not cost nothing. I checked CvPlayer::getProductionNeeded and there does not seem to be any custom code to handle settler cost. Where can I change it?
int CvPlayer::getNewCityProductionValue() const
{
int iValue = 0;
for (int iJ = 0; iJ < GC.getNumBuildingClassInfos(); iJ++)
{
BuildingTypes eBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iJ)));
if (NO_BUILDING != eBuilding)
{
if (GC.getBuildingInfo(eBuilding).getFreeStartEra() != NO_ERA)
{
if (GC.getGameINLINE().getStartEra() >= GC.getBuildingInfo(eBuilding).getFreeStartEra())
{
iValue += (100 * getProductionNeeded(eBuilding)) / std::max(1, 100 + getProductionModifier(eBuilding));
}
}
}
}
iValue *= 100 + GC.getDefineINT("NEW_CITY_BUILDING_VALUE_MODIFIER");
iValue /= 100;
iValue += (GC.getDefineINT("ADVANCED_START_CITY_COST") * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent()) / 100;
int iPopulation = GC.getDefineINT("INITIAL_CITY_POPULATION") + GC.getEraInfo(GC.getGameINLINE().getStartEra()).getFreePopulation();
for (int i = 1; i <= iPopulation; ++i)
{
iValue += (getGrowthThreshold(i) * GC.getDefineINT("ADVANCED_START_POPULATION_COST")) / 100;
}
return iValue;
}
........
if (!GC.getGameINLINE().isOption(GAMEOPTION_WARLORD_SETTLER_COST))//2.32q
{
iProductionNeeded += getUnitExtraCost(eUnitClass);//This is the default line
}
else if (GC.getUnitInfo(eUnit).isFound())
{
int iFixedSettlerCost;
iFixedSettlerCost = GC.getDefineINT("BTG_WARLORD_SETTLER_COST" ) * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent();
iProductionNeeded += iFixedSettlerCost / 100;
}
I have some knowledge of coding, so that shouldn't be too much of a problem ^^ (and in fact, thanks, I didn't realize that so much of the code was simply freely available in CvGameCoreDLL )@Akka
this is quite complicated. its a code that lies in the unit cpp under resolvecombat code.
need kits of background knowledge.
Changed in BTS.
Settlers are "isFound()" in the C++
in CvPlayer::Init you'll find this :
setUnitExtraCost((UnitClassTypes)iI, getNewCityProductionValue());
Code:int CvPlayer::getNewCityProductionValue() const { int iValue = 0; for (int iJ = 0; iJ < GC.getNumBuildingClassInfos(); iJ++) { BuildingTypes eBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iJ))); if (NO_BUILDING != eBuilding) { if (GC.getBuildingInfo(eBuilding).getFreeStartEra() != NO_ERA) { if (GC.getGameINLINE().getStartEra() >= GC.getBuildingInfo(eBuilding).getFreeStartEra()) { iValue += (100 * getProductionNeeded(eBuilding)) / std::max(1, 100 + getProductionModifier(eBuilding)); } } } } iValue *= 100 + GC.getDefineINT("NEW_CITY_BUILDING_VALUE_MODIFIER"); iValue /= 100; iValue += (GC.getDefineINT("ADVANCED_START_CITY_COST") * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent()) / 100; int iPopulation = GC.getDefineINT("INITIAL_CITY_POPULATION") + GC.getEraInfo(GC.getGameINLINE().getStartEra()).getFreePopulation(); for (int i = 1; i <= iPopulation; ++i) { iValue += (getGrowthThreshold(i) * GC.getDefineINT("ADVANCED_START_POPULATION_COST")) / 100; } return iValue; }
This is to balance the cost of Settlers for Eras Start (medieval onwards) where you have a starting buildings, factor in the traits etc. in those cases.
If you only do Ancient start you can bin all this and write your number
For the little story, apparently this was added in the last days of production of BTS, untested by the beta-tester, as a results of top MP players destroying a Firaxis team in late era start by making super fast super numerous cities,
Hence Firaxis finding a way to make cities very expensive in those scenarios.
Thanks! That's some funny additional context.To complement my answer to Leoreth on the Settler cost,
Here is how I (more easily) circumvented the issue.
Via an option and Via a Constant that I declared in XML
in...
int CvPlayer::getProductionNeeded(UnitTypes eUnit) const
Code:........ if (!GC.getGameINLINE().isOption(GAMEOPTION_WARLORD_SETTLER_COST))//2.32q { iProductionNeeded += getUnitExtraCost(eUnitClass);//This is the default line } else if (GC.getUnitInfo(eUnit).isFound()) { int iFixedSettlerCost; iFixedSettlerCost = GC.getDefineINT("BTG_WARLORD_SETTLER_COST" ) * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent(); iProductionNeeded += iFixedSettlerCost / 100; }
From what I've gathered in the code, the result of the fight is calculated quickly, and then the animations are scripted in a mostly random way, but with the results taken into account to ensure consistency (for example, the unit losing the fight must be the last losing a character in the animation).I was under the impression the animations had something to do with how hits themselves are resolved, but perhaps that's incorrect.
<FeatureDoubleMoves>
<FeatureDoubleMove>
<FeatureType>FEATURE_MYSTPLACE</FeatureType>
<bFeatureDoubleMove>1</bFeatureDoubleMove>
</FeatureDoubleMove>
<FeatureDoubleMove>
<FeatureType>FEATURE_VRES</FeatureType>
<bFeatureDoubleMove>1</bFeatureDoubleMove>
</FeatureDoubleMove>
</FeatureDoubleMoves>
elif(inputClass.getNotifyCode() == NotifyCode.NOTIFY_CLICKED and inputClass.getFunctionName() == "MapPreviewButton"):
CvMapPreviewScreen.CvMapPreviewScreen().showMapReviewPopup()
elif(inputClass.getNotifyCode() == NotifyCode.NOTIFY_CLICKED and inputClass.getFunctionName() == "MapPreviewButton"):
#2.37i
popupInfo = CyPopupInfo()
popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON_SCREEN)
popupInfo.setText(u"showMapPreviewScreen")
#popupInfo.addPopup(iPlayer)
popupInfo.addPopup(0)
popupInfo.addPopup(1)
def showMapReviewPopup(self):
popup = PyPopup.PyPopup(-1, EventContextTypes.NO_EVENTCONTEXT, True)
.......
popup.launch(True, PopupStates.POPUPSTATE_IMMEDIATE)#
thanks for your availability.USE_UNIT_CANNOT_MOVE_INTO_CALLBAC
That'll only enable the call to Python, you'd still need to write Python code that does the same thing as the C++ code I linked to except that it doesn't make an exception for tile ownership. The DLL-to-Python call should reach unitCannotMoveInto in Assets\Python\EntryPoints\CvGameInterface.py. From there, if it's a BUG-based mod, it'll be forwarded to BugGameUtils.py, otherwise to CvGameUtils.py. I never figured out how exactly BUG handles Python callbacks; presumably you could just place your code directly in CvGameInterface.py. But it sounds like that's not really workable – if you're totally unfamiliar with Python.