bool CvPlot::isVisibleEnemyUnit(const CvUnit* pUnit) const
{
return (plotCheck(PUF_isEnemy, pUnit->getOwnerINLINE(), [COLOR="Blue"]pUnit->isAlwaysHostile(this)[/COLOR], NO_PLAYER, NO_TEAM, PUF_isVisible, pUnit->getOwnerINLINE()) != NULL);
}
for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
{
if (m_aiUnitClassWeights[iI] > 0)
{
UnitTypes eUnit = (UnitTypes)GC.getUnitClassInfo((UnitClassTypes)iI).getDefaultUnitIndex();
-> m_aiUnitCombatWeights[GC.getUnitInfo(eUnit).getUnitCombatType()] += m_aiUnitClassWeights[iI];
}
}
int ctype = 0;
for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
{
if (m_aiUnitClassWeights[iI] > 0)
{
UnitTypes eUnit = (UnitTypes)GC.getUnitClassInfo((UnitClassTypes)iI).getDefaultUnitIndex();
ctype = GC.getUnitInfo(eUnit).getUnitCombatType();
// FAssert(ctype >= 0 && ctype < GC.getNumUnitCombatInfos());
if (ctype >= 0 && ctype < GC.getNumUnitCombatInfos())
m_aiUnitCombatWeights[ctype] += m_aiUnitClassWeights[iI];
}
}
CvCommerceInfo* CyGlobalContext::getCommerceInfo(int i) const
{
return (i>=0 && i<NUM_COMMERCE_TYPES) ? &GC.getCommerceInfo((CommerceTypes) i) : NULL;
}
CvCommerceInfo* CyGlobalContext::getCommerceInfo(int i) const
{
if (GC.getCommerceInfo().size() == 0) return NULL;
return (i>=0 && i<NUM_COMMERCE_TYPES) ? &GC.getCommerceInfo((CommerceTypes) i) : NULL;
}
Nuclear plants blowing up still doesn't.Version 1.30 changes:
- CvPlot::doFeature - Plot feature (Forest/jungle) appearance now scales by game speed
- CvPlot::doImprovement - Bonus appearance in mines now scales by game speed
[COLOR="Green"]/************************************************************************************************/
/* UNOFFICIAL_PATCH jdog5000 */
/* */
/* Gamespeed scaling */
/************************************************************************************************/
/* original bts code[/COLOR]
[COLOR="DimGray"] if (GC.getBuildingInfo((BuildingTypes)iI).getNukeExplosionRand() != 0)
{
if (GC.getGameINLINE().getSorenRandNum(GC.getBuildingInfo((BuildingTypes)iI).getNukeExplosionRand(), "Meltdown!!!") == 0)
{[/COLOR]
[COLOR="Green"]*/[/COLOR]
int iOdds = GC.getBuildingInfo((BuildingTypes)iI).getNukeExplosionRand();
iOdds *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent();
iOdds /= 100;
if( iOdds > 0 )
{
if( GC.getGameINLINE().getSorenRandNum(iOdds, "Meltdown!!!") == 0)
{
[COLOR="Green"]/************************************************************************************************/
/* UNOFFICIAL_PATCH END */
/************************************************************************************************/[/COLOR]
void CvPlayer::removeBuildingClass(BuildingClassTypes eBuildingClass)
{
CvCity* pLoopCity;
BuildingTypes eBuilding;
int iLoop;
eBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(eBuildingClass)));
if (eBuilding != NO_BUILDING)
{
for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
{
if (pLoopCity->getNumRealBuilding(eBuilding) > 0)
{
pLoopCity->setNumRealBuilding(eBuilding, [B][COLOR="Red"]pLoopCity->getNumRealBuilding(eBuilding) - 1[/COLOR][/B]);
break;
}
}
}
}
if (pPlot->isWater())
{
bValid = false;
...
if ([B][COLOR="Red"]!bValid &&[/COLOR][/B] pPlot->isWater())
{
...
[B]// lResult is 0 here[/B]
if(GC.getUSE_CAN_FOUND_CITIES_ON_WATER_CALLBACK())
{
... [B]// and gets set to 1 if the callback says it's okay[/B]
}
if (lResult == 1)
{
bValid = true;
}
else
{
[B]// if the callback is disabled or returns False, cannot found on water[/B]
if (pPlot->isWater())
{
return false;
}
}
// Circumvents second crash bug in simultaneous turns MP games
if( eCivic == NO_CIVIC )
{
return 1;
}
/************************************************************************************************/
/* UNOFFICIAL_PATCH 10/21/09 jdog5000 */
/* */
/* Bugfix */
/************************************************************************************************/
/* orginal bts code
iValue += (getNumCities() * 6 * AI_getHealthWeight(isCivic(eCivic) ? -kCivic.getExtraHealth() : kCivic.getExtraHealth(), 1)) / 100;
*/
iValue += (getNumCities() * 6 * AI_getHealthWeight(kCivic.getExtraHealth(), 1)) / 100;
/************************************************************************************************/
/* UNOFFICIAL_PATCH END */
/************************************************************************************************/
for each adjacent tile
if it has ice or snow
bValid = true
break
[COLOR="Green"]/************************************************************************************************/
/* UNOFFICIAL_PATCH 10/22/09 jdog5000 */
/* */
/* Gamespeed scaling */
/************************************************************************************************/
/* original bts code[/COLOR]
[COLOR="Silver"]if (GC.getImprovementInfo(getImprovementType()).getImprovementBonusDiscoverRand(iI) > 0)
{
if (GC.getGameINLINE().getSorenRandNum(GC.getImprovementInfo(getImprovementType()).getImprovementBonusDiscoverRand(iI), "Bonus Discovery") == 0)
{[/COLOR]
[COLOR="Green"]*/[/COLOR]
int iOdds = GC.getImprovementInfo(getImprovementType()).getImprovementBonusDiscoverRand(iI);
int iResearchPercent = GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent();
[B]iOdds = static_cast<int>([U]math::round[/U](1.0 / (1.0 - (math[I]::[/I]pow((1.0 - (1.0 / iOdds)),(100.0 / iResearchPercent))))));[/B]
if( iOdds > 0 )
{
if( GC.getGameINLINE().getSorenRandNum(iOdds, "Bonus Discovery") == 0)
{
[COLOR="Green"]/************************************************************************************************/
/* UNOFFICIAL_PATCH END */
/************************************************************************************************/[/COLOR]
I bet the argument went something like this:
If the assumed logic of 1 is correct, then the change is actually a fix. If not, it's a gameplay change and doesn't belong in the UP. Since we cannot know if 1 is correct, I'd err on the side of caution and remove it from the UP.
- Assume the choice by Firaxis to remove features was
- Settling in forests and jungles gives an uncounterable +50% defense.
- This is not fair/realistic/whatever.
- Remove features when settling.
- Problem solved.
- Flood plains don't provide a defense bonus.
- Therefore Firaxis didn't mean to remove them.
- It's a bug; fix it!
I'm all for it being in PIG, however since that is what PIG is about: small gameplay changes designed to improve the game.
If you do leave it in, I recommend removing all features that add a defensive bonus rather than special-casing Flood Plains.
No (other feature that provides defence but forest and jungle) in vanilla, but it's always nice to consider the modding community when adding features, especially in this case where you'd need to exchange one line of code for another.
Code:if (pPlot->getFeatureType() != NO_FEATURE && GC.getFeatureInfo(pPlot->getFeatureType()).getDefenseModifier() != 0)
Now, what is up with extra player instances? The Palace is 1 but all the national wonders are 0 (all of those have 1 max). What is this field used for? It seems that by passing in extra player instances to isBuildingClassMaxedOut() which adds extra and max for comparison, it's a wash.
Ah, does this control allowing a building with a max to be replaced by building it elsewhere? canConstruct() passes in the default 0 for iExtra which allows the Palace to be built in another city but not a national wonder. So extraPlayerInstances seems to say how many you can add to city queues once you've maxed out the class.
I submitted a fix for the canFoundCitiesOnWater() callback, but I see that the code is different from what I submitted. As it is now, if the checks above make the plot valid for a city, the plot being water will no longer make it invalid as it did in the original code. This will happen if the callback is disabled (as it is by default) or if it returns False.
The bug in the original code was that it ignored the result of the callback, but the fix in 1.4 actually makes water plots valid locations for cities by default. Is this intended?
Here's the start of my patch:
Code:if (pPlot->isWater()) { bValid = false; ...
Here is 1.4:
Code:if ([B][COLOR="Red"]!bValid &&[/COLOR][/B] pPlot->isWater()) { ...
And for comparison, here is the original code:
Code:[B]// lResult is 0 here[/B] if(GC.getUSE_CAN_FOUND_CITIES_ON_WATER_CALLBACK()) { ... [B]// and gets set to 1 if the callback says it's okay[/B] } if (lResult == 1) { bValid = true; } else { [B]// if the callback is disabled or returns False, cannot found on water[/B] if (pPlot->isWater()) { return false; } }
So while the original code ignores isWater() if the callback returns True, it correctly blocks founding on water otherwise.
Given the checks above the code it probably won't come up in practice, but it might affect mods that allow founding on water or add more rules above this check.
Edit: Meh, I'm not really sure which way it should go. The three checks above are of the style "if it's not okay but if the terrain makes it okay, it's okay." As soon as one check says it's okay, the other checks are ignored. Leaving the !bValid check in as 1.4 has it matches that form. But 1.4 definitely differs from vanilla 3.19. That there's a definite bug in 3.19 makes it harder to pick a winner.
if (pPlot->isWater())
{
if(GC.getUSE_CAN_FOUND_CITIES_ON_WATER_CALLBACK())
{
bValid = false;
CyArgsList argsList2;
argsList2.add(iX);
argsList2.add(iY);
lResult=0;
gDLL->getPythonIFace()->callFunction(PYGameModule, "canFoundCitiesOnWater", argsList2.makeFunctionArgs(), &lResult);
if (lResult == 1)
{
bValid = true;
}
}
}
Minor nitpick: In the fix at the start of CvPlayer::canDoCivics() there's a check and early return.
Code:// Circumvents second crash bug in simultaneous turns MP games if( eCivic == NO_CIVIC ) { return 1; }
The function returns bool, though, so I recommend putting true there instead of 1. Yes, it's the same, but I did say it was a nitpick.
As long as I'm nit-picking, my name doesn't have a space in it.
for (iI = 0; iI < MAX_PLAYERS; iI++)
{
if (GET_PLAYER((PlayerTypes)iI).isAlive())
{
for (iJ = 0; iJ < NUM_MEMORY_TYPES; iJ++)
{
if (AI_getMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ)) > 0)
{
if (GC.getLeaderHeadInfo(getPersonalityType()).getMemoryDecayRand(iJ) > 0)
{
if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getMemoryDecayRand(iJ), "Memory Decay") == 0)
{
AI_changeMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ), -1);
}
}
}
}
}
}
Gamespeed scaling again: The current way of scaling works fine for all events that can happen multiple times per tile, for those that can only happen once (doImprovement: a mine can only once pop a resource, right?) things are a bit more complicated.
Code:[COLOR="Green"]/************************************************************************************************/ /* UNOFFICIAL_PATCH 10/22/09 jdog5000 */ /* */ /* Gamespeed scaling */ /************************************************************************************************/ /* original bts code[/COLOR] [COLOR="Silver"]if (GC.getImprovementInfo(getImprovementType()).getImprovementBonusDiscoverRand(iI) > 0) { if (GC.getGameINLINE().getSorenRandNum(GC.getImprovementInfo(getImprovementType()).getImprovementBonusDiscoverRand(iI), "Bonus Discovery") == 0) {[/COLOR] [COLOR="Green"]*/[/COLOR] int iOdds = GC.getImprovementInfo(getImprovementType()).getImprovementBonusDiscoverRand(iI); int iResearchPercent = GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent(); [B]iOdds = static_cast<int>(1.0 / (1.0 - (math[I]::[/I]pow((1.0 - (1.0 / iOdds)),(100.0 / iResearchPercent)))));[/B] if( iOdds > 0 ) { if( GC.getGameINLINE().getSorenRandNum(iOdds, "Bonus Discovery") == 0) { [COLOR="Green"]/************************************************************************************************/ /* UNOFFICIAL_PATCH END */ /************************************************************************************************/[/COLOR]
I imagine the error from not doing it this way is pretty small though, I don't know if single precision is enough here or how much more CPU this would cost, trading 2 integer operations for 5 floating point operations plus math::pow() and a few type casts .. but yeah, I thought I should still mention it.
Floodplains handling suggestion from EF whichI think belongs here: