No GP Icon for unit 9

Le Sage

Emperor
Joined
Apr 24, 2009
Messages
1,522
Location
Digging up your garden
I get the No GP Icon for Unit 9 error message displayed in late games. This annoying message is displayed for all players whether they have logging activated or not.

I've added the three special great generals I've created into the GPUtil.py, but I still et the message.

Spoiler :
PHP:
## GPUtil
##
## Utilities for dealing with Great People.
##
## MODDERS
##
##   There are four places where you must add information about your new great people.
##   This is also necessary if you assign GP points to buildings that don't normally get them,
##   for example GG points to Heroic Epic.
##
##     1. Unit Type
##     2. Named constant
##     3. Color
##     4. Icon (font glyph or string)
##
## Notes
##   - Must be initialized externally by calling init()
##
## Copyright (c) 2007-2009 The BUG Mod.
##
## Author: EmperorFool

from CvPythonExtensions import *
import BugUtil
import FontUtil
import PlayerUtil

gc = CyGlobalContext()

# Generic GP icon
g_gpIcon = None

# Unit Type of each great person that can gain GP points
g_gpBarList = (
	"UNIT_GREAT_SPY",
	"UNIT_ENGINEER",
	"UNIT_MERCHANT",
	"UNIT_SCIENTIST",
	"UNIT_ARTIST",
	"UNIT_PROPHET",
	"UNIT_KING",
	"UNIT_ROYAL_PRINCE",
	"UNIT_CRYSTALKING",
# MOD: specify the unit type (XML key) for each new great person (1)
	#"UNIT_DOCTOR",
)

# Named constants for each great person and total number of GP types
# These must be in the exact same order as the list above
NUM_GP = len(g_gpBarList)
(
	GP_SPY,
	GP_ENGINEER,
	GP_MERCHANT,
	GP_SCIENTIST,
	GP_ARTIST,
	GP_PROPHET,
	GP_KING,
	GP_ROYAL_PRINCE,
	GP_CRYSTALKING,
# MOD: define a constant for each new great person in same order as above (2)
	#GP_DOCTOR,
) = range(NUM_GP)

# Map each GP type to unit ID, color, and icon to show in GP Bar
g_gpUnitTypes = None
g_gpColors = None
g_unitIcons = None


# Information

def init():
	global g_gpIcon
	g_gpIcon = FontUtil.getChar("greatpeople")
	
	global g_gpUnitTypes
	g_gpUnitTypes = [None] * NUM_GP
	for i, s in enumerate(g_gpBarList):
		g_gpUnitTypes[i] = gc.getInfoTypeForString(s)
	
	global g_gpColors
	g_gpColors = [None] * NUM_GP
	g_gpColors[GP_SPY] = gc.getInfoTypeForString("COLOR_WHITE")
	g_gpColors[GP_ENGINEER] = gc.getYieldInfo(YieldTypes.YIELD_PRODUCTION).getColorType()
	g_gpColors[GP_MERCHANT] = gc.getInfoTypeForString("COLOR_YELLOW")
	g_gpColors[GP_SCIENTIST] = gc.getInfoTypeForString("COLOR_RESEARCH_STORED")
	g_gpColors[GP_ARTIST] = gc.getInfoTypeForString("COLOR_CULTURE_STORED")
	g_gpColors[GP_PROPHET] = gc.getInfoTypeForString("COLOR_BLUE")
	g_gpColors[GP_KING] = gc.getInfoTypeForString("COLOR_RED")
	g_gpColors[GP_ROYAL_PRINCE] = gc.getInfoTypeForString("COLOR_BLACK")
	g_gpColors[GP_CRYSTALKING] = gc.getInfoTypeForString("COLOR_WHITE")
	# MOD: specify color for each new great person (3)
	#g_gpColors[GP_DOCTOR] = gc.getInfoTypeForString("COLOR_WHITE")
	
	global g_unitIcons
	g_unitIcons = {}
	g_unitIcons[g_gpUnitTypes[GP_SPY]] = FontUtil.getChar(FontSymbols.COMMERCE_ESPIONAGE_CHAR)
	g_unitIcons[g_gpUnitTypes[GP_ENGINEER]] = FontUtil.getChar(FontSymbols.YIELD_PRODUCTION_CHAR)
	g_unitIcons[g_gpUnitTypes[GP_MERCHANT]] = FontUtil.getChar(FontSymbols.COMMERCE_GOLD_CHAR)
	g_unitIcons[g_gpUnitTypes[GP_SCIENTIST]] = FontUtil.getChar(FontSymbols.COMMERCE_RESEARCH_CHAR)
	g_unitIcons[g_gpUnitTypes[GP_ARTIST]] = FontUtil.getChar(FontSymbols.COMMERCE_CULTURE_CHAR)
	g_unitIcons[g_gpUnitTypes[GP_PROPHET]] = FontUtil.getChar(FontSymbols.RELIGION_CHAR)
	g_unitIcons[g_gpUnitTypes[GP_KING]] = FontUtil.getChar(FontSymbols.GREAT_GENERAL_CHAR)
	g_unitIcons[g_gpUnitTypes[GP_ROYAL_PRINCE]] = FontUtil.getChar(FontSymbols.GREAT_GENERAL_CHAR)
	g_unitIcons[g_gpUnitTypes[GP_CRYSTALKING]] = FontUtil.getChar(FontSymbols.GREAT_GENERAL_CHAR)
	# MOD: specify icon (font glyph) for each new great person (4)
	#g_unitIcons[g_gpUnitTypes[GP_DOCTOR]] = FontUtil.getChar(FontSymbols.HEALTHY_CHAR)

def getUnitType(gpType):
	return g_gpUnitTypes[gpType]

def getColor(gpType):
	return g_gpColors[gpType]

def getUnitIcon(iUnit):
	try:
		return g_unitIcons[iUnit]
	except:
		BugUtil.warn("no GP icon for unit %d", iUnit)
		return u"%c" % CyGame().getSymbolID(FontSymbols.GREAT_PEOPLE_CHAR)


# Getting Progress

def getDisplayCity():
	"""
	Returns the city to display in the progress bar.
	"""
	pHeadSelectedCity = CyInterface().getHeadSelectedCity()
	if (pHeadSelectedCity and pHeadSelectedCity.getTeam() == gc.getGame().getActiveTeam()):
		city = pHeadSelectedCity
		iTurns = getCityTurns(city)
	else:
		city, iTurns = findNextCity()
		if not city:
			city, iGPP = findMaxCity()
			iTurns = None
	return (city, iTurns)

def findNextCity():
	iMinTurns = None
	iTurns = 0
	player = gc.getPlayer(gc.getGame().getActivePlayer())
	iThreshold = player.greatPeopleThreshold(False)
	bestCity = None
	for city in PlayerUtil.playerCities(player):
		iRate = city.getGreatPeopleRate()
		if (iRate > 0):
			iProgress = city.getGreatPeopleProgress()
			iTurns = (iThreshold - iProgress + iRate - 1) / iRate
			if (iMinTurns is None or iTurns < iMinTurns):
				iMinTurns = iTurns
				bestCity = city
	return (bestCity, iMinTurns)

def findMaxCity():
	iMaxProgress = 0
	player = gc.getPlayer(gc.getGame().getActivePlayer())
	bestCity = None
	for city in PlayerUtil.playerCities(player):
		iProgress = city.getGreatPeopleProgress()
		if (iProgress > iMaxProgress):
			iMaxProgress = iProgress
			bestCity = city
	return (bestCity, iMaxProgress)

def getCityTurns(city):
	if (city):
		player = gc.getPlayer(city.getOwner())
		iThreshold = player.greatPeopleThreshold(False)
		iRate = city.getGreatPeopleRate()
		if (iRate > 0):
			iProgress = city.getGreatPeopleProgress()
			iTurns = (iThreshold - iProgress + iRate - 1) / iRate
			return iTurns
	return None

def calcPercentages(city):
	# Calc total rate
	iTotal = 0
	for iUnit in g_gpUnitTypes:
		iTotal += city.getGreatPeopleUnitProgress(iUnit)
	# Calc individual percentages based on rates and total
	percents = []
	if (iTotal > 0):
		iLeftover = 100
		for iUnit in range(gc.getNumUnitInfos()):
#			iUnit = getUnitType(gpType)
			iProgress = city.getGreatPeopleUnitProgress(iUnit)
			if (iProgress > 0):
				iPercent = 100 * iProgress / iTotal
				iLeftover -= iPercent
				percents.append((iPercent, iUnit))
		# Add remaining from 100 to first in list to match Civ4
		if (iLeftover > 0):
			percents[0] = (percents[0][0] + iLeftover, percents[0][1])
	return percents


# Displaying Progress

def getHoverText(eWidgetType, iData1, iData2, bOption):
	city, iTurns = getDisplayCity()
	if (not city):
		# no rate or progress in any city and no city selected
		return BugUtil.getText("TXT_KEY_MISC_GREAT_PERSON", (0, PlayerUtil.getActivePlayer().greatPeopleThreshold(False)))
	iThreshold = gc.getPlayer(city.getOwner()).greatPeopleThreshold(False)
	iProgress = city.getGreatPeopleProgress()
	iRate = city.getGreatPeopleRate()
	szText = BugUtil.colorText(city.getName(), "COLOR_HIGHLIGHT_TEXT")
	szText += u"\n"
	szText += BugUtil.getText("TXT_KEY_MISC_GREAT_PERSON", (iProgress, iThreshold))
	if (iRate > 0):
		szText += u"\n%d%s%s " % (iRate, g_gpIcon, BugUtil.getPlainText("TXT_KEY_PER_TURN"))
		szText += BugUtil.getText("INTERFACE_CITY_TURNS", (iTurns,))
	
	percents = calcPercentages(city)
	if (len(percents) > 0):
		percents.sort()
		percents.reverse()
		szText += u"\n"
		for iPercent, iUnit in percents:
#			iUnit = getUnitType(gpType)
			szText += u"\n%s%s - %d%%" % (getUnitIcon(iUnit), gc.getUnitInfo(iUnit).getDescription(), iPercent)
	return szText

def getGreatPeopleText(city, iGPTurns, iGPBarWidth, bGPBarTypesNone, bGPBarTypesOne, bIncludeCityName):
	sGreatPeopleChar = u"%c" % CyGame().getSymbolID(FontSymbols.GREAT_PEOPLE_CHAR)
	if (not city):
		szText = BugUtil.getText("INTERFACE_GREAT_PERSON_NONE", (sGreatPeopleChar, ))
	elif (bGPBarTypesNone):
		if (iGPTurns):
			if (bIncludeCityName):
				szText = BugUtil.getText("INTERFACE_GREAT_PERSON_CITY_TURNS", (sGreatPeopleChar, city.getName(), iGPTurns))
			else:
				szText = BugUtil.getText("INTERFACE_GREAT_PERSON_TURNS", (sGreatPeopleChar, iGPTurns))
		else:
			if (bIncludeCityName):
				szText = BugUtil.getText("INTERFACE_GREAT_PERSON_CITY", (sGreatPeopleChar, city.getName()))
			else:
				szText = sGreatPeopleChar
	else:
		lPercents = calcPercentages(city)
		if (len(lPercents) == 0):
			if (iGPTurns):
				if (bIncludeCityName):
					szText = BugUtil.getText("INTERFACE_GREAT_PERSON_CITY_TURNS", (sGreatPeopleChar, city.getName(), iGPTurns))
				else:
					szText = BugUtil.getText("INTERFACE_GREAT_PERSON_TURNS", (sGreatPeopleChar, iGPTurns))
			else:
				if (bIncludeCityName):
					szText = BugUtil.getText("INTERFACE_GREAT_PERSON_CITY", (sGreatPeopleChar, city.getName()))
				else:
					szText = sGreatPeopleChar
		else:
			lPercents.sort()
			lPercents.reverse()
			if (bGPBarTypesOne or len(lPercents) == 1):
				iPercent, iUnit = lPercents[0]
				pInfo = gc.getUnitInfo(iUnit)
				if (iGPTurns):
					if (bIncludeCityName):
						szText = BugUtil.getText("INTERFACE_GREAT_PERSON_CITY_TURNS", (pInfo.getDescription(), city.getName(), iGPTurns))
					else:
						szText = BugUtil.getText("INTERFACE_GREAT_PERSON_TURNS", (pInfo.getDescription(), iGPTurns))
				else:
					if (bIncludeCityName):
						szText = BugUtil.getText("INTERFACE_GREAT_PERSON_CITY", (pInfo.getDescription(), city.getName()))
					else:
						szText = unicode(pInfo.getDescription())
			else:
				if (iGPTurns):
					if (bIncludeCityName):
						szText = BugUtil.getText("INTERFACE_GREAT_PERSON_CITY_TURNS", (sGreatPeopleChar, city.getName(), iGPTurns))
					else:
						szText = BugUtil.getText("INTERFACE_GREAT_PERSON_TURNS", (sGreatPeopleChar, iGPTurns))
				else:
					if (bIncludeCityName):
						szText = BugUtil.getText("INTERFACE_GREAT_PERSON_CITY", (sGreatPeopleChar, city.getName()))
					else:
						szText = sGreatPeopleChar + u":"
				szTypes = ""
				for iPercent, iUnit in lPercents:
					szNewTypes = szTypes + u" %c%d%%" % (getUnitIcon(iUnit), iPercent)
					szNewText = szText + u"<font=2> -%s</font>" % szTypes
					if (CyInterface().determineWidth(szNewText) > iGPBarWidth - 10):
						# Keep under width
						break
					szTypes = szNewTypes
				if (len(szTypes) > 0):
					szText += u"<font=2> -%s</font>" % szTypes
	return szText

I have also added buildings that add to Great People generation and the GPUtil states that I have to add those as well in there. But where and how?

Edit: I removed the error message for now, but I'd really want to get things right with this...
 
Just a small question. I noticed this declaration in the Python file you posted:

Code:
[COLOR=#000000][COLOR=#DD0000]"UNIT_CRYSTALKING"[/COLOR][COLOR=#007700][/COLOR][/COLOR]

I'm wondering if you declared it this way in the XML:

Code:
[COLOR=#000000][COLOR=#DD0000]"UNIT_CRYSTAL_KING"[/COLOR][COLOR=#007700][/COLOR][/COLOR]

Like the normal unit naming convention (the way UNIT_ROYAL_PRINCE is declared), and have just forgotten to put the underscore into the Python functions? That way, the Python functions will try to load a non existent unit and thus show no icon.

I'll look more deeply, but this stood out right away, and it's something that I often do in my excitement of getting something written.

-LM
 
The PythonErr log is completely empty. That's the fun part with this one. The error message only pops up in the World News string where it says that your city is about to become unhappy and that your knights have won a battle against enemy spearmen. Suff like that.

Yeah, Lemon Merchant. Crystalking (in one word) is what is used in the XML as well. It is really a female version of the Great General.
 
You can find the problem unit using the Python console or examining the CIV4UnitInfos.xml file for the 10th unit (they start with #0).

Code:
print gc.getUnitInfo(9).getDescription()

You enter the console using the tilde key (~).

Ah, this is a warning instead of an exception. The message will appear in PythonDbg.log, but really you just need to figure out which unit is #9 and go from there. Is it possible there's a 10th great person type?
 
Ah. Thanks! I'll get to it at once. No, I haven't a tenth GP.

You are always very helpful, EmperorFool. You should have the Lion Order of the Kingdom of Angleeye for that. My game is ten times better because of BUG. Just so you know. :goodjob:
 
Thank you, I truly appreciate the feedback. Helping other modders make better mods more easily is precisely why I put the time into BUG that I do. :D
 
Yeah, Lemon Merchant. Crystalking (in one word) is what is used in the XML as well. It is really a female version of the Great General.
Oh bummer. I thought I might have been helpful for a change. :lol:

Better luck next time, I suppose.

And my game is ten times better because of BUG, too. I'm EF's biggest fan-grrrl, but I don't mind sharing him with the boys. :D
 
Back
Top Bottom