Final Frontier: Problems & Issues (Post-3.13 Update Available)

This would be yet another FF bug...

I'm surprised this hasn't been noticed before, but I can't find any mention of it.

If a "city" is razed then the next colony to be founded in that same system can have problems. Specifically, the individual planets can claim to have buildings on them that the game DLL doesn't think exist. These phantom buildings can't be built on these planets since the python function cannotConstruct thinks they already exist on the planet so indicates that you cannot do so. You also may be unable to build any buildings that require the phantom buildings for the opposite reason: it appears that if you have not built one of the prereq buildings somewhere in the system then the DLL knows you don't have the prereq at all and won't let you build the building.

I noticed this after I settled in a system that had formerly been a colony of the Paradise civ until a pirate invasion ship killed the defending destroyer and razed the colony maybe 10 turns after it was settled. Since it was a Paradise colony, every planet in the system had a mag-lev system added to it when they colonized it. When I colonized it, the main building list on the left side of the city screen (which is built from data frmothe DLL, not the planets' building data) showed no mag-lev systems but 3 of the 6 planets were still showing mag-lev systems - I assume that the other 3 were wiped out by the random 50% chance for buildings to be destroyed that happens in the onCityAcquired callback.

Tha cause of this is that in the DLL when a city is razed all of the buildings are deleted. This makes sense because in the regular game you can't have buildings anywhere but in a city, no city = no buildings.

The solution is to add an onCityRazed callback to CvFinalFrontierEvents.py so that all of the planets in the system are actually cleared of all buildings when the "city"/colony is razed. Something like this:
Code:
	def onCityRazed(self, argsList):
		'City Razed'
		self.parent.onCityRazed(self, argsList)
		
		pCity, iPlayer = argsList
		
		# Wipe out all of the buildings on all of the planets in the system.
		# They will be destroyed by the DLL shortly after this returns (there's no way to avoid it - you can't
		# have buildings without a city for them to be in, from the DLL's perspective).
		
		pSystem = self.getSystemAt(pCity.getX(), pCity.getY())
		
		pSystem.aaiSingleBuildingLocations = [] # clear this list

		# Loop through all the planets in the system
		for iPlanetLoop in range(pSystem.getNumPlanets()):
			pPlanet = pSystem.getPlanetByIndex(iPlanetLoop)
			# Loop through all building types
			for iBuildingLoop in range(gc.getNumBuildingInfos()):
				# Set the planet to not have one of these
				pPlanet.setHasBuilding(iBuildingLoop, false)
				
		# There are now no buildings left in the system.

There may be a related bug when a system is nuked with a doomsday missile. A planet is disabled but the buildings on it are not removed, either from the planet data or in the DLL's data. I would have to guess that if there was, for example, a bank on the disabled planet it would still give the +25% bonus to money. (I have seen a very small number of doomsday missiles used, but never against a system. I've only ever seen them used against ships in open space.)
 
I've done a test, and it does not remove the requirement that there be a matching number of building and buildingclass entries. I guess garbage entries such as:
Code:
		<BuildingClassInfo>
			<Type>BUILDINGCLASS_DOM_UB</Type>
			<Description>TXT_KEY_BUILDING_BARRACKS</Description>
			<iMaxGlobalInstances>-1</iMaxGlobalInstances>
			<iMaxTeamInstances>-1</iMaxTeamInstances>
			<iMaxPlayerInstances>-1</iMaxPlayerInstances>
			<iExtraPlayerInstances>0</iExtraPlayerInstances>
			<bNoLimit>0</bNoLimit>
			<bMonument>0</bMonument>
			<DefaultBuilding>NONE</DefaultBuilding>
			<VictoryThresholds/>
		</BuildingClassInfo>
aren't going anywhere (at least if you want UBs).

I don't know what we're doing that is different, but I have no such entires and my UBs work just fine. I currently have 48 BuildingClassInfos and 58 BuildingInfos.

I have made some adjsutments to the python in my mod for the UBs, but that is only for specific things happening (or not happening) - they worked, more or less, in general (i.e. it didn't crash, and the expected bonuses and such worked) without the tweaks.

Well, except the attempt at a Capital Shipyard UB. That didn't work properly because the PrereqBuilding tag in the UnitInfo is a BuildingInfo not a BuildingClassInfo and you can specify only one so the UB version doesn't allow the ships to be built. There is a workaround, but it is a mess: also assign the civ UUs (which may be exactly identical to the non-UU except for the type string and PrereqBuilding) for all of the ships which normally requre the Capitol Shipyard, specifying the UB as the prereq instead of the regular building. This did not seem to be worth the effort so I gave that civ a less problematic UB. (The Squadron Factory leads to the same problem, by the way.)

Which, by the way, leads to another FF bug: in the CIV4UnitInfos.xml file the values specified in the PrereqBuilding tag are building classes instead of building types (BUILDINGCLASS_CAPITAL_SHIPYARD where it should be BUILDING_CAPITAL_SHIPYARD, and likewise for the squadron factory). As usual, this only works in the base FF mod because the two values are actually the same due to the matching number and order of the BuildingClassInfos and BuildingInfos.
 
I've been adding UBs just after the building they replace, as in default BtS. Many buildings have multiple UBs. I also probably have a LOT more of them than you do, as there aren't that many default FF civs. Additionally, I set the building limit to a number that is way above the number of buildings I have to avoid having to touch it.
 
So far, I have been adding mine to the end of the file.

If you add them anywhere else, you have to adjust the arrays at the end of CvSolarSystem.py for all the buildings from that point forward so they point at the right building. You also need to make sure that the python is using BuildingInfos where it should be, and not BuildingClassInfos. And vice-versa.

At some point I intend to rearrange the order all at once.
 
The only default FF buildings I use are the nutrition and mining facilities and the habitation center, all of which are at the beginning of the file right after the palace, so I don't think I have array issues.

Where are the python building/buildingclass infos? I didn't know the FF python even used buildingclass at all.
 
Buildings are used all over the place but the FF specific python doesn't use building classes anywhere, including the one place it ought to (see post 378). There are a couple of places where they are used in files inherited from the base BtS but modified in other ways for FF, in the screen related python files.

I was refering more to any python that you might have added, or changed...

I have changed mine to use building classes in several places, with the current civ's specific building being determined from the class, or the class being determined from the building. For example, in onCityAcquired instead of bothering with what UBs to enter into the "never capture" list, I made that list hold the building classes and compare the class of each building with the list. Now the 3 UBs (I think it's 3) I have that match classes in the list get wiped out without me having to add them to the list.

I have not completely converted everything to use the class. I still directly use the building type of some UBs in a few places where I could switch to using the class. So I have a few places where I do "if havebuilding1 or havebuilding2" where I added the check for 2 which is a UB of the same class as 1. It was just a smidge quicker and easier to add that way. If you don't switch things to use classes, you need to do this in a bunch of places - like the AI code, which would force the city to build the standard building if one of its overrides is triggered (a sports arena for happiness, or a mag-lef or satellites for commerce, etc.) instead of the approprite UB.

As noted at the end of post 382, the BUILDINGCLASS_x values are used in the UniInfos xml file for the prereq building that allows various units to be built, where it ought to be using the BUILDING_x values. Since you are probably not using those buildings or units this should not be a problem for you, unless you duplicated the mistake.
 
Guess I'm going to have to get more familiar with what buildingclasses are like in python. I never modified a lot of that code beyond putting my building entries in (except for a lot of stuff in CvAI which is quite complex); needless to say, I hate modifying buildings! I'll have to look into converting the stuff over.
 
If anyone is curious to read, we have a succession game going on with Final Frontier over here.

I found a pretty serious AI bug. At game start, the AI begins with its population unassigned to any planet. This causes immediate starvation for New Earth, and makes every AI capital do nothing at all (0 food and 0 hammers). The AIs stay that way until something happens to call CvAI::doCityAIUpdate (this is the only function that can do FF-aware AI planet assignment). Typically this is the expansion at 50 influence. So most AIs do nothing at all for 25 turns, and poor Halis does nothing for 50.

No wonder the player can always out-scout the AIs! To verify this, just start a game, and worldbuilder in a great spy to infiltrate each AI and watch them.

Other systems work OK when founded, it's only the capitals at game start. It's not exactly a bug in CvAI, it's that CvAI::doCityAIUpdate does not get called at game start. Any FF aficionados suggest a good place to insert a call to it? I'm thinking CvFinalFrontierEvents::onBeginGameTurn, if the game turn number = 1, then loop through each AI calling CvAI::doCityAIUpdate. I don't speak Python natively but will try to figure it out sometime soon.
 
Thanks deanej. It worked great. I had thought onGameStart wouldn't be suitable because the first cities didn't exist yet (which would be the case in standard Civ), but they do so it worked fine.

Here's the fixed CvFinalFrontierEvents.py attached. It goes in Beyond the Sword\Mods\Final Frontier\Assets\Python .
 

Attachments

  • CvFinalFrontierEvents.zip
    17.5 KB · Views: 219
Thanks to help from God-Emperor in the succession game thread, I put in a fix for another AI bug. If there is angry population and the happy cap increases (common with the starbase influence bug or war weariness), the formerly-angry population is left unassigned. It never gets reassigned until one of the rare events that causes a full system recalculation: the system gets a border expansion, conquered, or nuked.

See God-Emperor's post here for the details. In short, it just makes sure the AI always reassigns unassigned population every turn (there is already a function to do this for the human player.) It worked in a brief test (using worldbuildered great spies to infiltrate to monitor the AIs) and I'll continue playing with it.
 

Attachments

  • CvFinalFrontierEvents.zip
    17.6 KB · Views: 240
Bug?
FF319.
Research = 11*15 turns=165, but tehnolog.=202 ?
File:
 

Attachments

  • AS AD-2302-January_bug_research.rar
    30.5 KB · Views: 159
I see no production overfolow from buildings either. I don't know what the cause is. Currently I suspect the plot yield update that is done in the onBuildingBuilt python that is not done in onUnitBuilt, as this appears to tbe the only thing going on that is different than for regular BtS that looks like it might be able to cause this.
Well, is there any progres in dealing with the "no overflow from buildings" bug? Unfortunately I don't speeak Python and can't handle the files to fix it, just waiting till some good guy does this job.

Maybe other ideas abount origins of the bug?
 
It's cause buildings are built on specific planets. Final Frontier looks like a solid mod, but it's really a lot of stuff tacked on to regular civ. Hence, it breaks a lot of stuff. Most of what it breaks is not noticeable until you try to mod it. Building production overflow probably wasn't thought of, and is really difficult to notice when you don't keep track of things like production beyond what you can see on the main map (of course, it's quite easy to see if you look at things in detail in the city screen and micromanage).
 
Bug?
FF319.
Research = 11*15 turns=165, but tehnolog.=202 ?
File:

You get the 20% beaker bonus for knowing a prerequisite technology, Space Exploration is a prerequisite for Survivalism. You also always get 1 free beaker per turn. So 11 * 1.2 + 1 = 14.2 beakers. Rounded down to 14 beakers * 15 turns = 210 which is enough for your tech. This is all part of regular Civ, not new in FF.


Well, is there any progres in dealing with the "no overflow from buildings" bug? Unfortunately I don't speeak Python and can't handle the files to fix it, just waiting till some good guy does this job.

Maybe other ideas abount origins of the bug?

It's because the increased building cost is calculated before overflow. So you only get overflow if you have hammers beyond the cost of the _next_ copy of the building. Load a savegame with a capital that can produce 80 hammers, build a 40-hammer Intelligence Agency, and you will see overflow.

It's not easy to fix, since overflow calculation happens in the DLL but the increased building cost happens in Python, in CvFinalFrontierEvents::getBuildingCostMod. You'd either have to recompile the DLL with smarter overflow logic, or enhance getBuildingCostMod to somehow detect if it's being called for overflow purposes and return the cost of the previous building rather than the next.
 
I guess Chelovek wants just to know where the calcilation of the overflow occurs.

CvCity::popOrder() in the block inside "case ORDER_CONSTRUCT". That's in CvCity.cpp starting at line 10800.

Code:
setNumRealBuilding(eConstructBuilding, getNumRealBuilding(eConstructBuilding) + 1);

iProductionNeeded = getProductionNeeded(eConstructBuilding);
// max overflow is the value of the item produced (to eliminate prebuild exploits)
int iOverflow = getBuildingProduction(eConstructBuilding) - iProductionNeeded;
int iMaxOverflow = std::max(iProductionNeeded, getCurrentProductionDifference(false, false));
int iMaxOverflowForGold = std::max(iProductionNeeded, getProductionDifference(getProductionNeeded(), getProduction(), 0, isFoodProduction(), false));
iOverflow = std::min(iMaxOverflow, iOverflow);
if (iOverflow > 0)
{
	changeOverflowProduction(iOverflow, getProductionModifier(eConstructBuilding));
}

The problem is that setNumRealBuilding() comes before getProductionNeeded(). So getProductionNeeded() returns the cost of the *next* building after the cost increase. A solution might be as simple as reversing those two lines, though I haven't thought it through for side effects.
 
It doesn't look like there would be any side effect to moving the line - none of the lines in between appear to be affected by having the building added to the city. Though I don't know how those functions work, so this might be a sloppy solution if getBuildingCostMod is used for something other than increasing the cost of a building if it already exists in the city. It would work here though, and I'll be adding this fix to Star Trek.
 
Top Bottom