RFC Modding Central

Abbasids start with a settler + flip for historical reasons - 750 was the time of the Abbasid revolt and Baghdad was founded in 762. I really don't know what's causing these issues for you. Make sure that startingYear in CvRhyes.h is correct, and also tBirth in Consts.py is set to a special number (not the start date). In SoI it is 0. You can use -3000 BC but make sure the condition in setup method is changed from if tBirth[iLoopCiv] == 0: to ... == -3000; two similar changes have to be done in createEarlyStartingUnits.
 
yes that was exactly the problem. everything working now. thanks. hopefully the no-collapse was for the same reason. the only civs I have seen get really huge in the autoplay have been the Seleucids and Mauryans and they are both starting civs.
 
I'm having a problem with cities flipping to new civs. The cities flip but they don't receive defenders. I've looked over what I think is all the relevant code (convertSurroundingCities in RiseAndFall.py and flipUnitsInCityBefore and flipUnitsInCityAfter in RFCUtils.py), I understand how its supposed to work, creating the units in the designated flipping plot (and I checked the coordinates of the flipping plot), but I can't figure out what's stopping it.

here are the bits of code:

Spoiler :
Code:
convertSurroundingCities(self, iCiv, plotList, fBarbOnly = False):
			
			iConvertedCitiesCount = 0
			iNumHumanCities = 0
			cityList = []
			self.setSpawnWar(0)
			
			#collect all the cities in the spawn region
			for i in range(len(plotList)):
				pCurrent = gc.getMap().plot(plotList[i][0], plotList[i][1])
				if pCurrent.isCity():
					if pCurrent.getPlotCity().getOwner() != iCiv:
						if not fBarbOnly or pCurrent.getPlotCity().getOwner() == iBarbarian:
							cityList.append(pCurrent.getPlotCity())

			#print ("Birth", iCiv)
			#print (cityList)

			#for each city
			if len(cityList):
					for i in range(len(cityList)):
							loopCity = cityList[i]
							loopX = loopCity.getX()
							loopY = loopCity.getY()
							#print ("cityList", loopCity.getName(), (loopX, loopY))
							iHuman = utils.getHumanID()
							iOwner = loopCity.getOwner()
							iCultureChange = 0 #if 0, no flip; if > 0, flip will occur with the value as variable for utils.CultureManager()
							
							#case 1: barbarian/independent city
							if (iOwner >= iNumPlayers):
								#utils.debugTextPopup( 'BARB' )
								iCultureChange = 100
							#case 2: human city
							#elif (iOwner == iHuman and not loopCity.isCapital()): #exploitable
							elif (iOwner == iHuman and not (loopX == tCapitals[iHuman] and loopY == tCapitals[iHuman]) and not gc.getPlayer(iHuman).getNumCities() <= 1 and not (self.getCheatMode() == True and loopCity.isCapital())):
								
								#utils.debugTextPopup( 'HUMAN' )
	##							bForeigners = False
	##							cityPlot = gc.getMap().plot(cityList[i].getX(), cityList[i].getY())
	##							cityCulture = cityList[i].countTotalCulture()
	##							iCultureThreshold = 10
	##							for j in range(iNumPlayers+1):
	##								if (cityList[i].getCulture(j)*100 / cityCulture >= iCultureThreshold) and (j != iHuman):
	##									bForeigners = True
	##							humanCapital = gc.getPlayer(iHuman).getCapitalCity()
	##							iDistance = gc.getMap().calculatePathDistance(cityPlot, gc.getMap().plot(humanCapital.getX(),humanCapital.getY()))
	##							if (cityList[i].isOccupation()) or (cityList[i].isDisorder()) or (bForeigners == True) or (not cityPlot.getNumUnits()) or ((not cityList[i].isGovernmentCenter()) and (iDistance >= 8) and (gc.getPlayer(iHuman).getNumCities() >= 5)):
								if (iNumHumanCities == 0):
									iNumHumanCities += 1
									#iConvertedCitiesCount += 1
									#self.flipPopup(iCiv, plotList)
							#case 3: other
							elif (not loopCity.isCapital()):   #utils.debugTextPopup( 'OTHER' )
								if (iConvertedCitiesCount < 6): #there won't be more than 5 flips in the area
									#utils.debugTextPopup( 'iConvertedCities OK' )
									iCultureChange = 50
									if (gc.getGame().getGameTurn() <= getTurnForYear(tBirth[iCiv]) + 5): #if we're during a birth
										rndNum = gc.getGame().getSorenRandNum(100, 'odds')
										if (rndNum >= tAIStopBirthThreshold[iOwner]):
											print (iOwner, "stops birth", iCiv, "rndNum:", rndNum, "threshold:", tAIStopBirthThreshold[iOwner])
											if (not gc.getTeam(gc.getPlayer(iOwner).getTeam()).isAtWar(iCiv)):																		
												gc.getTeam(gc.getPlayer(iOwner).getTeam()).declareWar(iCiv, False, -1)
												if (gc.getPlayer(iCiv).getNumCities() > 0): #this check is needed, otherwise game crashes
													print ("capital:", gc.getPlayer(iCiv).getCapitalCity().getX(), gc.getPlayer(iCiv).getCapitalCity().getY())
													if (gc.getPlayer(iCiv).getCapitalCity().getX() != -1 and gc.getPlayer(iCiv).getCapitalCity().getY() != -1):
														self.createAdditionalUnits(iCiv, (gc.getPlayer(iCiv).getCapitalCity().getX(), gc.getPlayer(iCiv).getCapitalCity().getY()))
													else:
														self.createAdditionalUnits(iCiv, tCapitals[iCiv])
							
							if (iCultureChange > 0):
								#print ("flipping ", cityList[i].getName())
								utils.cultureManager((loopX, loopY), iCultureChange, iCiv, iOwner, True, False, False)
								#gc.getMap().plot(cityList[i].getX(),cityList[i].getY()).setImprovementType(-1)
								
								utils.flipUnitsInCityBefore((loopX, loopY), iCiv, iOwner)
								self.setTempFlippingCity((loopX, loopY)) #necessary for the (688379128, 0) bug
								utils.flipCity((loopX, loopY), 0, 0, iCiv, [iOwner])
								#print ("cityList[i].getXY", cityList[i].getX(), cityList[i].getY()) 
								utils.flipUnitsInCityAfter(self.getTempFlippingCity(), iCiv)

								#iEra = gc.getPlayer(iCiv).getCurrentEra()
								#if (iEra >= 2): #medieval
								#		if (loopCity.getPopulation() < iEra):
								#				loopCity.setPopulation(iEra) #causes an unidentifiable C++ exception
										#doesn't work (assigns UBs too)
										#for iLoopBuilding in range(iNumBuildingsPlague):
										#		if (gc.getBuildingInfo(iLoopBuilding).getFreeStartEra() >= 0):
										#				if (iEra >= gc.getBuildingInfo(iLoopBuilding).getFreeStartEra()):
										#						print (iEra, iLoopBuilding, gc.getBuildingInfo(iLoopBuilding).getFreeStartEra(), loopCity.canConstruct(iLoopBuilding, False, False, False))
										#						if (loopCity.canConstruct(iLoopBuilding, False, False, False)):
										#								if (not loopCity.hasBuilding(iLoopBuilding)):
										#										loopCity.setHasRealBuilding(iLoopBuilding, True)

								#cityList[i].setHasRealBuilding(iPlague, False)   #buggy
								
								iConvertedCitiesCount += 1
								print ("iConvertedCitiesCount", iConvertedCitiesCount)

			if (iConvertedCitiesCount > 0):
				if (gc.getPlayer(iCiv).isHuman()):
					CyInterface().addMessage(iCiv, True, iDuration, CyTranslator().getText("TXT_KEY_FLIP_TO_US", ()), "", 0, "", ColorTypes(iGreen), -1, -1, True, True)

			#print( "converted cities", iConvertedCitiesCount)
			return (iConvertedCitiesCount, iNumHumanCities)

Spoiler :
Code:
	def flipUnitsInCityBefore(self, tCityPlot, iNewOwner, iOldOwner):
		print ("tCityPlot Before", tCityPlot)
		plotCity = gc.getMap().plot(tCityPlot[0], tCityPlot[1])
		city = plotCity.getPlotCity()
		iNumUnitsInAPlot = plotCity.getNumUnits()
		j = 0
		for i in range(iNumUnitsInAPlot):
			unit = plotCity.getUnit(j)
			unitType = unit.getUnitType()
			if (unit.getOwner() == iOldOwner):
				unit.kill(False, con.iBarbarian)
				if (iNewOwner < con.iNumPlayers or unitType > con.iSettler):
					self.makeUnit(self.getBaseUnit(unitType, iNewOwner), iNewOwner, [con.iFlipX, con.iFlipY], 1) # edead
			else:
				j += 1


	# RiseAndFall
	def flipUnitsInCityAfter(self, tCityPlot, iCiv):
		#moves new units back in their place
		print ("tCityPlot After", tCityPlot)
		tempPlot = gc.getMap().plot(con.iFlipX, con.iFlipY)
		if (tempPlot.getNumUnits() != 0):
			iNumUnitsInAPlot = tempPlot.getNumUnits()
			#print ("iNumUnitsInAPlot", iNumUnitsInAPlot)
			for i in range(iNumUnitsInAPlot):
				unit = tempPlot.getUnit(0)
				unit.setXY(tCityPlot[0], tCityPlot[1], False, False, False)
		#cover plots revealed
		self.coverPlots(con.iFlipX, con.iFlipY, iCiv)
 
No guess here, many things could be happening. Try uncommenting the debug print messages and/or add your own and see what happens, action by action. Are the units created properly but not moved? Or are they not created at all? Debug messages should show why.
 
I added some debug messages like so:

Spoiler :
Code:
	# RiseAndFall
	def flipUnitsInCityBefore(self, tCityPlot, iNewOwner, iOldOwner):
		print ("tCityPlot Before", tCityPlot)
		plotCity = gc.getMap().plot(tCityPlot[0], tCityPlot[1])
		city = plotCity.getPlotCity()
		iNumUnitsInAPlot = plotCity.getNumUnits()
		[COLOR="Red"]print ("number of units", iNumUnitsInAPlot)[/COLOR]
		j = 0
		for i in range(iNumUnitsInAPlot):
			unit = plotCity.getUnit(j)
			unitType = unit.getUnitType()
			if (unit.getOwner() == iOldOwner):
				[COLOR="Red"]print ("old owner passed")[/COLOR]
				unit.kill(False, con.iBarbarian)
				if (iNewOwner < con.iNumPlayers or unitType > con.iSettler):
					self.makeUnit(self.getBaseUnit(unitType, iNewOwner), iNewOwner, [con.iFlipX, con.iFlipY], 1) # edead
					[COLOR="Red"]print ("unit made", iNewOwner, unitType)[/COLOR]
			else:
				j += 1


	# RiseAndFall
	def flipUnitsInCityAfter(self, tCityPlot, iCiv):
		#moves new units back in their place
		print ("tCityPlot After", tCityPlot)
		tempPlot = gc.getMap().plot(con.iFlipX, con.iFlipY)
		if (tempPlot.getNumUnits() != 0):
			iNumUnitsInAPlot = tempPlot.getNumUnits()
			print ("iNumUnitsInAPlot", iNumUnitsInAPlot)
			for i in range(iNumUnitsInAPlot):
				unit = tempPlot.getUnit(0)
				unit.setXY(tCityPlot[0], tCityPlot[1], False, False, False)
		[COLOR="Red"]else:
			print ("no units in temp plot")[/COLOR]
		#cover plots revealed
		self.coverPlots(con.iFlipX, con.iFlipY, iCiv)

and the debug log says this:

Spoiler :
birthInFreeRegion, FlipsDelay=2

('tCityPlot Before', (22, 38))

('number of units', 2)

old owner passed

('unit made', 10, 53)

old owner passed

('unit made', 10, 33)

PY:City Acquired Event: Mediolanum
('tCityPlot After', (22, 38))

no units in temp plot

('iConvertedCitiesCount', 1)

('tCityPlot Before', (24, 29))

('number of units', 1)

old owner passed

('unit made', 10, 19)

PY:City Acquired Event: Syracuse
('tCityPlot After', (24, 29))

no units in temp plot

('iConvertedCitiesCount', 2)

('tCityPlot Before', (25, 32))

('number of units', 4)

old owner passed

('unit made', 10, 53)

old owner passed

('unit made', 10, 33)

old owner passed

('unit made', 10, 19)

old owner passed

('unit made', 10, 19)

PY:City Acquired Event: Neapolis
('tCityPlot After', (25, 32))

no units in temp plot

('iConvertedCitiesCount', 3)


so it says it has created the units, but then it says they don't exist.
 
The way you placed "unit made" debug msg doesn't guarantee the unit was actually created. It's just called after makeUnit function is called, no matter if it was successful or not. Apparently it wasn't, and I think the culprit is in my getBaseUnit function which you should modify to fit your mod. You see by default it uses Delhi Sultanate's unit list to make sure all UUs are turned into basic units. And if that civ doesn't exist, then no units are created. You can either use another civ, or just get rid of the function (it doesn't exist in vanilla RFC, but I didn't like the fact that you could flip UUs and typically religious units).
 
I have some C++ trouble. I talked about a UP so that you just need 75 % :culture: than usual to expand cultural borders. I think i found the needed place in the code, so i coded that in (that's pretty much the same way i fixed the Jurchen UP, which grants defensive bonus for mounted units).

Code:
int CvCity::getCultureThreshold(CultureLevelTypes eLevel)
{
	if (eLevel == NO_CULTURELEVEL)
	{
		return 1;
	}
[COLOR="Red"]
	if (getOwner() == TANG) {//Tang UP
		return std::max(1, (GC.getGameINLINE().getCultureThreshold((CultureLevelTypes)(std::min((eLevel + 1), (GC.getNumCultureLevelInfos() - 1)))))*(3/4));
	}[/COLOR]

	return std::max(1, GC.getGameINLINE().getCultureThreshold((CultureLevelTypes)(std::min((eLevel + 1), (GC.getNumCultureLevelInfos() - 1)))));
	
}
And this is the error message i get:
Code:
1>CvCity.cpp(7681) : error C2352: 'CvCity::getOwner' : illegal call of non-static member function
I know too little C++ to get what that means:confused: I get the same error message with getOwnerINLINE() and even with a detour with its plot where i can't call getX() or getY().

EDIT: I just read that this is the wrong thread :blush:
 
@civ-addicted

1.
You can't call non-static functions from static ones, and getCultureThreshold(CultureLevelTypes eLevel) is static i.e. it belongs to the CvCity class, rather than to the city object created from it. In other words, this function is shared by all cities, so it cannot make any references to a particular city. The code can be placed in getCultureThreshold() above, since that function is non-static.

2.
Integer division problem: x*(3/4) = 0, so the result will always be 0 (or 1, in this case). Since you're operating with integers, you have to do it like this: (x*3)/4 (parentheses optional, but they show the order better)

Code:
int CvCity::getCultureThreshold() const
{
	// Tang UP start
	if (getOwnerINLINE() == TANG) {
		return (getCultureThreshold(getCultureLevel()) * 3) / 4;
	}
	// Tang UP end
	return getCultureThreshold(getCultureLevel());
}
 
Oh, alright. Thanks :)
 
suddenly my mod is not finding the art for regular city walls. this happened after I PAKed the art I think. I've never done anything to the walls art.

here's the building info:

Spoiler :
Code:
<BuildingInfo>
			<BuildingClass>BUILDINGCLASS_WALLS</BuildingClass>
			<Type>BUILDING_WALLS</Type>
			<SpecialBuildingType>NONE</SpecialBuildingType>
			<Description>TXT_KEY_BUILDING_WALLS</Description>
			<Civilopedia>TXT_KEY_BUILDING_WALLS_PEDIA</Civilopedia>
			<Strategy>TXT_KEY_BUILDING_WALLS_STRATEGY</Strategy>
			<Advisor>ADVISOR_MILITARY</Advisor>
			<ArtDefineTag>ART_DEF_BUILDING_WALLS</ArtDefineTag>

and the art define:

Spoiler :
Code:
<BuildingArtInfo>
			<Type>ART_DEF_BUILDING_WALLS</Type>
			<LSystem>LSYSTEM_WALLS</LSystem>
			<bAnimated>0</bAnimated>
			<fScale>1.0</fScale>
			<fInterfaceScale>0.4</fInterfaceScale>
			<NIF>Art/Structures/Buildings/Walls/Walls.nif</NIF>
			<KFM/>
			<Button>,Art/Interface/Buttons/Buildings/Wall.dds,Art/Interface/Buttons/Buildings_Atlas.dds,8,7</Button>
		</BuildingArtInfo>

and I get pink lines.

I tried adding the walls art folder to my mod but got the same result.
 

Attachments

  • walls.JPG
    walls.JPG
    249.1 KB · Views: 97
I'm trying to get the starting years in the civ selection screen to work properly. My mod is based on Sword of Islam, which starts in 750AD and so has no provision for starting years BCE. I've tried using bits of Rhye's code, which does have provision for BC/AD, but I don't know what I'm doing and it hasn't worked so far. Here are the 2 relevant bits of code:

my mod/SoI:

Spoiler :
Code:
// Rhye / edead: start Starting Year
		if (bDawnOfMan)
		{
			szBuffer.Format(SETCOLR L"%s: " ENDCOLR, TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), gDLL->getText("TXT_KEY_STARTING_YEAR").GetCString());
		}
		else
		{
			szBuffer.Format(NEWLINE SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT"), gDLL->getText("TXT_KEY_STARTING_YEAR").GetCString());
		}
		szInfoText.append(szBuffer);

		if (bDawnOfMan)
		{
			szBuffer.Format(L"%d ", GC.getCivilizationInfo(eCivilization).getStartingYear());
			szBuffer += gDLL->getText("TXT_KEY_AD");
			szText.Format(L"%s ", szBuffer.GetCString());
		}
		else
		{
			szBuffer.Format(L"%d ", GC.getCivilizationInfo(eCivilization).getStartingYear());
			szBuffer += gDLL->getText("TXT_KEY_AD");
			szText.Format(L"%s  %c%s", NEWLINE, gDLL->getSymbolID(BULLET_CHAR), szBuffer.GetCString());
		}
		szInfoText.append(szText);

		if (bDawnOfMan)
		{
			if (GC.getCivilizationInfo(eCivilization).isPlayable())
			{
				szBuffer = gDLL->getText("TXT_KEY_LOADING_TIME") + " " + GC.getCivilizationInfo(eCivilization).getLoadingTime() + " " + gDLL->getText("TXT_KEY_MINUTES");
				szBuffer += NEWLINE;
				szInfoText.append(szBuffer);
			}
			else
			{
				szInfoText.append(NEWLINE);
			}
		}

		// Rhye / edead: end

Rhye's:

Spoiler :
Code:
// Rhye / edead: start Starting Year
		if (bDawnOfMan)
		{
			szBuffer.Format(SETCOLR L"%s: " ENDCOLR, TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), gDLL->getText("TXT_KEY_STARTING_YEAR").GetCString());
		}
		else
		{
			szBuffer.Format(NEWLINE SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT"), gDLL->getText("TXT_KEY_STARTING_YEAR").GetCString());
		}
		szInfoText.append(szBuffer);

		if (bDawnOfMan)
		{
			szBuffer.Format(L"%d ", GC.getCivilizationInfo(eCivilization).getStartingYear());
			szBuffer += gDLL->getText("TXT_KEY_AD");
			szText.Format(L"%s ", szBuffer.GetCString());
		}
		else
		{
			szBuffer.Format(L"%d ", GC.getCivilizationInfo(eCivilization).getStartingYear());
			szBuffer += gDLL->getText("TXT_KEY_AD");
			szText.Format(L"%s  %c%s", NEWLINE, gDLL->getSymbolID(BULLET_CHAR), szBuffer.GetCString());
		}
		szInfoText.append(szText);

		if (bDawnOfMan)
		{
			if (GC.getCivilizationInfo(eCivilization).isPlayable())
			{
				szBuffer = gDLL->getText("TXT_KEY_LOADING_TIME") + " " + GC.getCivilizationInfo(eCivilization).getLoadingTime() + " " + gDLL->getText("TXT_KEY_MINUTES");
				szBuffer += NEWLINE;
				szInfoText.append(szBuffer);
			}
			else
			{
				szInfoText.append(NEWLINE);
			}
		}

		// Rhye / edead: end

I tried adding a set of booleans and a set of starting years without the minus sign on the BC ones, but I just got errors I couldn't understand.
 
Can you show us your code? I imagine it would work pretty straightforward.

Iirc, getStartingYear() gives you the the variables as defined in CvRhyes.cpp, i.e. positive for AD and negative for BC. It should be possible to simply include another fork with getStartingYear() >= 0 and then in the else case you use abs(getStartingYear()) and TXT_KEY_BC instead. Am I missing something?
 
sorry if I was unclear. the top example is my code, it is unchanged from Sword of Islam. I know this should be simple but I don't really know C++. usually I can figure out what to do by looking at different examples but in this case the 2 examples are written quite differently. I know its a question of a simple fork but I don't know how to write it. also I didn't know about the "abs" function.
 
Ah, okay. I was a little confused first because I couldn't find the difference between both examples, it seems you copied it twice by accident. Anyway, here's what I would do (didn't test it, however):
Spoiler :
Code:
// Rhye / edead: start Starting Year
		if (bDawnOfMan)
		{
			szBuffer.Format(SETCOLR L"%s: " ENDCOLR, TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), gDLL->getText("TXT_KEY_STARTING_YEAR").GetCString());
		}
		else
		{
			szBuffer.Format(NEWLINE SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT"), gDLL->getText("TXT_KEY_STARTING_YEAR").GetCString());
		}
		szInfoText.append(szBuffer);
		
		[color="red"]int iStartingYear = GC.getCivilizationInfo(eCivilization).getStartingYear();[/color]

		if (bDawnOfMan)
		{
			[color="red"]if (iStartingYear >= 0)
			{
				szBuffer.Format(L"%d ", iStartingYear);
				szBuffer += gDLL->getText("TXT_KEY_AD");
			}else
			{
				szBuffer.Format(L"%d ", abs(iStartingYear));
				szBuffer += gDLL->getText("TXT_KEY_BC");
			}[/color]
			szText.Format(L"%s ", szBuffer.GetCString());
		}
		else
		{
			[color="red"]if (iStartingYear >= 0)
			{
				szBuffer.Format(L"%d ", iStartingYear);
				szBuffer += gDLL->getText("TXT_KEY_AD");
			}else
			{
				szBuffer.Format(L"%d ", abs(iStartingYear));
				szBuffer += gDLL->getText("TXT_KEY_BC");
			}[/color]
			szText.Format(L"%s  %c%s", NEWLINE, gDLL->getSymbolID(BULLET_CHAR), szBuffer.GetCString());
		}
		szInfoText.append(szText);

		if (bDawnOfMan)
		{
			if (GC.getCivilizationInfo(eCivilization).isPlayable())
			{
				szBuffer = gDLL->getText("TXT_KEY_LOADING_TIME") + " " + GC.getCivilizationInfo(eCivilization).getLoadingTime() + " " + gDLL->getText("TXT_KEY_MINUTES");
				szBuffer += NEWLINE;
				szInfoText.append(szBuffer);
			}
			else
			{
				szInfoText.append(NEWLINE);
			}
		}

		// Rhye / edead: end
 
Great! :)
 
I have semi-successfully coded a UP for the Qin that gives reduced unhappiness from whipping. The results are a little different than what I thought I was doing, but it works. Here is the code:

Spoiler :
original:

Code:
int CvCity::getHurryPercentAnger(int iExtra) const
{
	if (getHurryAngerTimer() == 0)
	{
		return 0;
	}

	return ((((((getHurryAngerTimer() - 1) / flatHurryAngerLength()) + 1) * GC.getDefineINT("HURRY_POP_ANGER") * GC.getPERCENT_ANGER_DIVISOR()) / std::max(1, getPopulation() + iExtra)) + 1);
}

my mod:

Code:
int CvCity::getHurryPercentAnger(int iExtra) const
{
	int iAnger;
	if (getHurryAngerTimer() == 0)
	{
		return 0;
	}

	iAnger = ((((((getHurryAngerTimer() - 1) / flatHurryAngerLength()) + 1) * GC.getDefineINT("HURRY_POP_ANGER") * GC.getPERCENT_ANGER_DIVISOR()) / std::max(1, getPopulation() + iExtra)) + 1);
	if (getOwnerINLINE() == QIN) iAnger /= 2;  // srpt Qin UP
	return iAnger;
}

the results are: 1st whip produces no unhappiness, 2nd one about 5 turns. do you think there is a better way to do this?
as for the tooltip, it doesn't adjust automatically to display the reduced unhappiness. I looked around in CvGameTextMrg.cpp and CvDLLWidgetData.cpp, but got confused.
 
the results are: 1st whip produces no unhappiness, 2nd one about 5 turns. do you think there is a better way to do this?
return std::max(2, iAnger);
That should do the trick, if you want a minimum of 2 turns unhappines fe
 
Top Bottom