Specialist slots

Xyth

History Rewritten
Joined
Jul 14, 2004
Messages
4,106
Location
Aotearoa
I know that I can add a free specialist to a city with something like:
Code:
city.changeFreeSpecialistCount(iSpecialist, 1)
Is there a function similar to this that I can use to instead add a specialist slot, like the Temple does?
 
Unfortunately, CvCity::changeMaxSpecialistCount(SpecialistTypes eIndex, int iChange) is not exposed to Python. One solution is to create a building that adds the specialist(s) you want and make it unbuildable (cost of -1 I think) and hidden. Then you can add the building via Python.
 
Doh. I'll try out the hidden building option, or something else entirely. Thanks for responding.
 
You can of course modify the SDK to create your own DLL that exposes that function, but I assume you're working in Python to avoid that.
 
On a Mac so SDK is sadly not an option.
 
Well I've got a fake building set up and working no problem. However is there someway of preventing it from displaying in Civilopedia, City Screen, etc? I'm using BUG.
 
There should be two places in the civilopedia files to prevent it from showing up.
In Python\Screens\CvPediaMain, after
Spoiler :

PHP:
	def placeBuildings(self):
		screen = self.getScreen()
		
		# Create and place a tech pane									
		list = self.pediaBuildingScreen.getBuildingSortedList(false)

		if gc.getDefineINT("CIVILOPEDIA_SHOW_ACTIVE_CIVS_ONLY") and gc.getGame().isFinalInitialized():
			listCopy = list[:]
			for item in listCopy:
				if not gc.getGame().isBuildingEverActive(item[1]):
					list.remove(item)

		nColumns = 4
		nEntries = len(list)
place this

Spoiler :
PHP:
		###invisible dummy building start part 1
		DoNotShow=0
		for item in list:
                        if gc.getBuildingInfo(item[1]).getType ()=="BUILDING_SOMETHING":
                                DoNotShow=DoNotShow+1
                nEntries = nEntries-DoNotShow
                ###invisible dummy building end part 1

and a bit more down, after
Spoiler :
PHP:
		iCounter = 0
		iNumRows = 0
		for item in list:
			iRow = iCounter % nRows
			iColumn = iCounter // nRows
			if iRow >= iNumRows:
				iNumRows += 1
				screen.appendTableRow(tableName)

place:
Spoiler :
PHP:
            if gc.getBuildingInfo(item[1]).getType ()=="BUILDING_SOMETHING":
                continue

This will hide the building in the overview.


In In Python\Screens\CvPediaBuilding, after
Spoiler :
PHP:
	def placeLinks(self, bRedraw):

		screen = self.top.getScreen()
        
		if bRedraw:
			screen.clearListBoxGFC(self.top.LIST_ID)

		listSorted = self.getBuildingSortedList(self.getBuildingType(self.iBuilding))
				
		iSelected = 0
		i = 0
		for iI in range(len(listSorted)):
			if (not gc.getBuildingInfo(listSorted[iI][1]).isGraphicalOnly()):
				if (not gc.getDefineINT("CIVILOPEDIA_SHOW_ACTIVE_CIVS_ONLY") or not gc.getGame().isFinalInitialized() or gc.getGame().isBuildingEverActive(listSorted[iI][1])):

place:
Spoiler :

PHP:
                                if gc.getBuildingInfo(listSorted[iI][1]).getType()=="BUILDING_SOMETHING":
                                        continue


Note: Haven't tested this here, but it works with some modifications for technologies, units and features.

And i know, hardcoding is ugly, but can't be done in another way here. I would have said, you could test, if iCost ==-1, but this is also true for the academy and all the corporations.


No idea about the city screen, haven't worked there yet.
 
You can just add it to the schema yourself. The existing code already takes care of the rest IIRC:

In Python\Screens\CvPediaBuilding:
if (not gc.getBuildingInfo(listSorted[iI][1]).isGraphicalOnly()):
 
I just tried adding <bGraphicalOnly>1</bGraphicalOnly> but it caused the BuildingInfos xml to be seen as broken. Mac BTS completely ignores schema files so I imagine this is the problem. I'll have to try hardcoding it.
 
You'll need to figure out exactly where in the XML it needs to go. The schema isn't needed by the game's parser to read the XML files, but it does demonstrate where the parser expects each element to go. If you can find a file that's using it already that should do, or maybe Maniac can tell you where it goes.
 
You'll need to figure out exactly where in the XML it needs to go. The schema isn't needed by the game's parser to read the XML files, but it does demonstrate where the parser expects each element to go. If you can find a file that's using it already that should do, or maybe Maniac can tell you where it goes.

That makes sense, I'll do some experimenting.
 
The only standard BTS xml files that seem to have <bGraphicalOnly> are Terrain and Improvements. I had a look at the FfH2 modder's guide and while they seem to have added it to Civs and Leaderheads I see no mention of it being added to Buildings. Are you certain Maniac? Finding out where it goes is going to take ages, there's a ton of tags for buildings ><

In the meantime does anyone know how I could port the code The J posted above for Sevopedia in BUG?
 
bGraphicalOnly is handled by the CvBaseInfo class which all other info classes extend. It's actually the first element to be parsed, before the item's type even:

Code:
bool CvInfoBase::read(CvXMLLoadUtility* pXML)
{
	CvString szTextVal;

	// Skip any comments and stop at the next value we might want
	if (!pXML->SkipToNextVal())
	{
		return false;
	}

	pXML->MapChildren();	// try to hash children for fast lookup by name

	// GRAPHICAL ONLY
	[B]pXML->GetChildXmlValByName(&m_bGraphicalOnly, "bGraphicalOnly");[/B]

	// TYPE
	pXML->GetChildXmlValByName(m_szType, "Type");

So you should be able to put it wherever you want in the schema. The TerrainInfos have it at the end. Oh wait, did you add it to all the existing buildings as well? If not, you need to make sure you make it optional in the schema.
 
bGraphicalOnly is handled by the CvBaseInfo class which all other info classes extend. It's actually the first element to be parsed, before the item's type even:

Code:
bool CvInfoBase::read(CvXMLLoadUtility* pXML)
{
	CvString szTextVal;

	// Skip any comments and stop at the next value we might want
	if (!pXML->SkipToNextVal())
	{
		return false;
	}

	pXML->MapChildren();	// try to hash children for fast lookup by name

	// GRAPHICAL ONLY
	[B]pXML->GetChildXmlValByName(&m_bGraphicalOnly, "bGraphicalOnly");[/B]

	// TYPE
	pXML->GetChildXmlValByName(m_szType, "Type");

So you should be able to put it wherever you want in the schema. The TerrainInfos have it at the end. Oh wait, did you add it to all the existing buildings as well? If not, you need to make sure you make it optional in the schema.

The problem is that Mac BTS completely ignores Schema and DLL files, it's all handled directly in the BTS application itself. So in order to add the bGraphicalOnly tag in the Buildings xml I need to know its exact default location - if it even exists. Otherwise it just won't load the file at all and changing the schema won't help.

That's why I'm asking if there's an alternate way by modifying the actual sevopedia files (similar to what The J wrote for the normal Civilopedia) cos I'm just having no luck whatsoever with bGraphicalOnly.


EDIT: After trying bGraphicalOnly in every possible position in the BuildingInfos.xml I can now conclude that bGraphicalOnly is impossible to use for buildings without an accompanying schema and/or DLL change.
 
Maybe I missed it, but did you try adding bGraphicalOnly to the schema? If not, how do you know that the Mac ignores schemas? If so, well, bummer.

So in Sevopedia there is a function that creates the list of all buildings in SevoPediaBuilding. It makes use of another function in that same module called getBuildingType(). This is where the building is checked to see if it is a national or world wonder. You could add to that to check for your graphical-only buildings.

Code:
def getBuildingType(self, iBuilding):
		if (isWorldWonderClass(gc.getBuildingInfo(iBuilding).getBuildingClassType())):
			return 2
		elif (isNationalWonderClass(gc.getBuildingInfo(iBuilding).getBuildingClassType())):
			return 1
[B]		elif (iBuilding in (gc.getInfoTypeForString("BUILDING_ADD_SCIENTIST_SLOT"), gc.getInfoTypeForString("BUILDING_ADD_MERCHANT_SLOT"), ...)):
			return 3[/B]
		else:
			return 0

Since Sevopedia will never ask for building type 3, these shouldn't show up in any of the lists.
 
That will drop the buildings from the pedia, but they'll still show up in the list in the city screen. It looks better if you at least give these "buildings" a name, since it avoids a blank line with hover data.
Incidentally, there's another way of dropping some buildings from the pedia implemented in Rhye's and Fall; it drops them from the list after building it, by hardcoded index.

I ran into this stuff when building my fix for the Mac version of Rhye's and Fall; I implemented one unique power as a pedia-invisible building that added research.

Oh, and the Mac ignoring schema/DLL? Pretty well known by everyone who's seriously tried modding that version. There is nothing you can do beyond XML and Python, short of rebuilding the whole application- and the only rebuilt applications out there are for the mods Road to War and Rhye's and Fall that were included with BTS. These are snapshots which can't be updated to the latest version, and can't really be used outside the intended scenarios. They're also hardcoded to specific paths within the game folder, so you can't clone the mod and have multiple slightly different versions available.
 
Top Bottom