Bug Reports and Discussion

I am more curious about that chunk of terrain if statements lol.
Regardless of whether it is snow, desert, plains etc, you will always end up with grass, so why so troublesome.
 
Ya when i went throu and made my own genesis code i removed that huge list of variables since only 2 of them is actually needed more than once and added marsh and shallows to the list as well since the current code doesn't change them for the regular genesis or the illian version of it. There are actually quite a few places that make me wonder why they were written a certain way unless someone knows if there are commands that are slightly faster than others in the code:confused:

edit: also the current code completely ignores floodplains and oasis and would end up upgrading those plots as well
 
I just found this bug around line 358 of PyHelpers.py

NameError: global name 'i' is not defined

Thanks for the report! I'll check the fix into the repository tonight.

in CustomFunctions.py what do the last 2 lines of the genesis code actually do? Because it looks to me like all it does is set a feature that is already there.

Interesting. I have no idea really. It does look pretty useless.

I am more curious about that chunk of terrain if statements lol.
Regardless of whether it is snow, desert, plains etc, you will always end up with grass, so why so troublesome.

Think those succeeding if statements should be elif instead.

added marsh and shallows to the list as well since the current code doesn't change them for the regular genesis or the illian version of it.

Good catch! Marsh is the bastard stepchild of the terrains and often is missed in the various python calls. I'll add in some code for Marsh.

There are actually quite a few places that make me wonder why they were written a certain way unless someone knows if there are commands that are slightly faster than others in the code:confused:

Feel free to point them out!

also the current code completely ignores floodplains and oasis and would end up upgrading those plots as well

Oases are not a big deal. Regular terraforming spells can change their terrain. I think the Floodplains part was intentional. I'll have to see if I can dig up any old posts on the matter.
 
I'm still trying to work out how but a Baalseraphs cultist cast Inquistition on an Infernals plot, a plot that wasn't even a city there. Then I think moved a couple plots somehow and after casting (which failed and gave me an error) moved again reeeeally far away best I can tell. It's late so I'll finish hunting this all down after some sleep and update here. When I got the error popup I got a really weird audio get played that sounded like a woman's voice shouting at someone (I swear I'm not making this up).
 
I'm still trying to work out how but a Baalseraphs cultist cast Inquistition on an Infernals plot, a plot that wasn't even a city there.

From your description, it sounds like the Cultist started inquisitioning an Infernal city, then lost the Open Borders agreement which booted the Cultist out of Infernal territory but since he was in the middle of a multi-turn casting process he ended up finishing outside the city which then ends up throwing a python error.
 
nope he started it about 2 tiles away from a city to begin with, I happened to conquering the Infernals at the time and saw him but I just didn't really pay attention to what he was doing at the time. Just checked and those 2 still have an open borders agreement. i uploaded a copy of the PythonErr and BBAILog files at the time of the error.

edit: found the sound file for the Inquisition spell and it was the correct one being played, such an odd sound to be hearing thou in a FFH2 game lol. The requirement code for Inquisition also to me shouldn't allow him to cast that spell in any city that isn't owned by the caster's player.
Spoiler :
Code:
def reqInquisition(caster):
	pPlot = caster.plot()
	pCity = pPlot.getPlotCity()
	pPlayer = gc.getPlayer(caster.getOwner())
	StateBelief = pPlayer.getStateReligion()
	
	if pPlayer.canInquisition():
		if StateBelief == -1:
			if caster.getOwner() != pCity.getOwner():
				return False
		if (StateBelief != gc.getPlayer(pCity.getOwner()).getStateReligion()):
			return False
		for iTarget in range(gc.getNumReligionInfos()):
			if (StateBelief != iTarget and pCity.isHasReligion(iTarget) and pCity.isHolyCityByType(iTarget) == False):
				return True
	return False
also what exactly does "if pPlayer.canInquisition():" actually check because there is no def in any python file named "Inquisition" and since the xml tags for the spell include the very python code this is in wouldn't that end up being a circular dependancy? (unless maybe it ignores the PyRequirement tag when checking canInquisition?) Also now that I think about it the code that restricts the spell to only the caster's cities doesn't apply unless the caster doesn't have a state religion...
 

Attachments

In order to prevent division by zero errors in autologEventManager.py the "def onTechSelected(self, argsList):" needs to be changed to
Spoiler :
Code:
	def onTechSelected(self, argsList):
		if (AutologOpt.isLogTechnology()):
			iTechType, iPlayer = argsList
			if iPlayer == CyGame().getActivePlayer():
				researchProgress = gc.getTeam(gc.getPlayer(iPlayer).getTeam()).getResearchProgress(gc.getPlayer(iPlayer).getCurrentResearch())
				overflowResearch = (gc.getPlayer(iPlayer).getOverflowResearch() * gc.getPlayer(iPlayer).calculateResearchModifier(gc.getPlayer(iPlayer).getCurrentResearch()))/100
				researchCost = gc.getTeam(gc.getPlayer(iPlayer).getTeam()).getResearchCost(gc.getPlayer(iPlayer).getCurrentResearch())
				researchRate = gc.getPlayer(iPlayer).calculateResearchRate(-1)
				if researchRate < 1:
					researchRate = 1
				zTurns = (researchCost - researchProgress - overflowResearch) / researchRate + 1
				message = BugUtil.getText("TXT_KEY_AUTOLOG_RESEARCH_BEGUN", (PyInfo.TechnologyInfo(iTechType).getDescription(), zTurns))
				Logger.writeLog(message, vColor="Green")
 
In my current game with my modmod I am getting a crash to desktop whenever I capture Meresin's last city.

It seems that the problem was caused by the Meresin unit (which is Immortal) being loaded into a Galley which was stationed in the capital city.

The game did not let him (or the Longbowman who was also in the galley) defend the city from conquest, but automatically destroyed him with his ship when the city was captured. When he died without personally engaging in combat, I think the game tried to resurrect him even though he had no place to go.

I get the same bug when the city contains a regular Immortal on a Galley in the city when I capture it.

I have not tested in base MNAI yet, but imagine that there would be an identical problem.

----

This issue wouldn't matter in MNAI as there are no bAlwaysHostile units, but I really think you ought to do something about how units with that tag are treated.

As things currently stand, they are treated as enemies when they attack units outside of cities, but can enter rival cities peacefully. They cannot however leave those cities peacefully. That is considered an act of war.

The units can capture superforts without war, but again cannot leave them to enter rival plots without declaring war.

Normal units trying to enter cities owned by the same player cannot do so if a rival player has a bAlwaysHostile unit stationed there. The bAlways hostile unit is being treated as hostile and yet not hostile at the same time. It is like other units have to attack them in order to enter the tile, but are not permitted to attack them while in the city.

Those issues are extremely annoying for humans, and are almost guaranteed to cause an AI to get stuck in loops.

I currently used some rather inefficient code under def unitCannotMoveInto(self,argsList): in my modmod to stop bAlwaysHostile units from entering rival cities or forts without war, but it is an imperfect fix. It wouldn't handle situations where cities change hands, as through Basium's, Rantine's, or Loki's abilities, or cultural flipping.


I would really like it if you could make it so that bAlwaysHostile units are treated as if they had the bNoCapture tag when it comes to cities and superforts belonging to neutral players. They should be allowed to attack units there, but not capture any territory without a declaration of war. They should be vulnerable to attack while there, and should not have to declare war to leave.

(I'd also really like it if promotions could grant bAlwaysHostile status too, but that is clearly a feature request and not even arguably a bug fix.)
 
uploaded a copy of the PythonErr and BBAILog files at the time of the error.

A saved game from a few turns back would be helpful, except that it looks like you are playing one of the alternate versions and not MNAI itself.

The requirement code for Inquisition also to me shouldn't allow him to cast that spell in any city that isn't owned by the caster's player.

Right. Which means the unit was moved after it started casting. This can happen sometimes with multi-turn spells. Should probably just cancel the spell casting if a unit is moved.

Spoiler :
Code:
def reqInquisition(caster):
	pPlot = caster.plot()
	pCity = pPlot.getPlotCity()
	pPlayer = gc.getPlayer(caster.getOwner())
	StateBelief = pPlayer.getStateReligion()
	
	if pPlayer.canInquisition():
		if StateBelief == -1:
			if caster.getOwner() != pCity.getOwner():
				return False
		if (StateBelief != gc.getPlayer(pCity.getOwner()).getStateReligion()):
			return False
		for iTarget in range(gc.getNumReligionInfos()):
			if (StateBelief != iTarget and pCity.isHasReligion(iTarget) and pCity.isHolyCityByType(iTarget) == False):
				return True
	return False

also what exactly does "if pPlayer.canInquisition():" actually check because there is no def in any python file named "Inquisition"

It's a DLL call (pretty much anything referencing units, cities, players and teams will be accessing the DLL). There is an option in CivicInfos for a Civic to block the player from Inquisitioning. That tag is unused in MNAI but is there in case any modders want to use it.

Also now that I think about it the code that restricts the spell to only the caster's cities doesn't apply unless the caster doesn't have a state religion...

Right. That's for Agnostic civs to clear religions from their cities if they have units who can do so.

For religious civs, they can Inquisition cities of other players as long as those players are following the same State Religion.


In order to prevent division by zero errors in autologEventManager.py the "def onTechSelected(self, argsList):" needs to be changed

Thanks!

In my current game with my modmod I am getting a crash to desktop whenever I capture Meresin's last city.

It seems that the problem was caused by the Meresin unit (which is Immortal) being loaded into a Galley which was stationed in the capital city.

OK. I'll look into this. Sounds easy enough to replicate.

This issue wouldn't matter in MNAI as there are no bAlwaysHostile units, but I really think you ought to do something about how units with that tag are treated.

Fair enough. Sounds like the implementation of Always Hostile units was not fully fleshed out or it was intended just for a specific scenario. I'll add it to the list!

(I'd also really like it if promotions could grant bAlwaysHostile status too, but that is clearly a feature request and not even arguably a bug fix.)

To the list as well!
 
I'm playing with my personal mod of MNAI (added in a few things and tweak a few others to my personal taste) so I'm fairly certain a save game wouldn't be playable by you unless I gave you the files I changed as well. I'd like to suggest the following small changes to the inquisition req and cast, not big changes just imho a bit more seamless for the req part and adds in a call to double check the canInquisition part for the cast too.
Spoiler :
Code:
def reqInquisition(caster):
	pPlot = caster.plot()
	pCity = pPlot.getPlotCity()
	pPlayer = gc.getPlayer(caster.getOwner())
	StateBelief = pPlayer.getStateReligion()
	if pPlayer.canInquisition():
		if StateBelief == -1:
			if caster.getOwner() == pCity.getOwner():
				return True
		if (StateBelief == gc.getPlayer(pCity.getOwner()).getStateReligion()):
			for iTarget in range(gc.getNumReligionInfos()):
				if (StateBelief != iTarget and pCity.isHasReligion(iTarget) and pCity.isHolyCityByType(iTarget) == False):
					return True
	return False

def spellInquisition(caster):
	pPlot = caster.plot()
	pCity = pPlot.getPlotCity()
	pPlayer = gc.getPlayer(caster.getOwner())
	StateBelief = gc.getPlayer(pCity.getOwner()).getStateReligion()
	iRnd = CyGame().getSorenRandNum(4, "Bob")
	if pPlayer.canInquisition():
		if StateBelief == gc.getInfoTypeForString('RELIGION_THE_ORDER'):
			iRnd = iRnd - 1
		for iTarget in range(gc.getNumReligionInfos()):
			if (StateBelief != iTarget and pCity.isHasReligion(iTarget) and pCity.isHolyCityByType(iTarget) == False):
				pCity.setHasReligion(iTarget, False, True, True)
				iRnd = iRnd + 1
				for i in range(gc.getNumBuildingInfos()):
					if gc.getBuildingInfo(i).getPrereqReligion() == iTarget:
						pCity.setNumRealBuilding(i, 0)
		if iRnd >= 1:
			pCity.changeHurryAngerTimer(iRnd)
 
in CvSpellInterface.py for spellMarchOfTheTrees, spellMotherLode, spellSanctuary, spellWorldbreak the checks for "if pPlot.isOwned():" seem a bit redundant since the code also does a check to see if the plot is owned by the caster and most of any map is going to be owned by someone so most plots would pass the isOwned check anyhow.
 
in CvSpellInterface.py for spellMarchOfTheTrees, spellMotherLode, spellSanctuary, spellWorldbreak the checks for "if pPlot.isOwned():" seem a bit redundant since the code also does a check to see if the plot is owned by the caster and most of any map is going to be owned by someone so most plots would pass the isOwned check anyhow.

If you try to call if pPlot.getOwner() on a plot with no Owner, the game will throw an error. Thus, we check beforehand to make sure its owned. There's lots of code in Civ4 that works this way.
 
In ExtraModMod I have gotten many reports about Loki being too efficient in taking cities over. The biggest problem probably is that he seems to disregard distance (although I checked and the Loki AI code certainly includes a way to penalize distance). In my test games I have also seen him cross Large pangaea maps and steal two or three cities even if they are so far. I think that distance should penalize a lot more how Loki values city targets for Disrupt, or that the * 20 to their value should be reduced.
 
I'm not able to build the dll at revision 1800 or 1806. 1799 works.
Code:
1>CvCityAI.cpp(8087): error C2664: 'CvPlot::calculateNatureYield' : cannot convert parameter 2 from 'PlayerTypes' to 'TeamTypes'
1>          Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
 
I'm not able to build the dll at revision 1800 or 1806. 1799 works.
Code:
1>CvCityAI.cpp(8087): error C2664: 'CvPlot::calculateNatureYield' : cannot convert parameter 2 from 'PlayerTypes' to 'TeamTypes'
1>          Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)

Apologies. That line shouldn't have been included yet. That's an upcoming change that I wasn't quite ready to add to the repository (though I will probably expedite things now that I have some out of sync code). Just change the reference to Team ID from Payer ID in the offending line and the build should work.
 
I just noticed that GAMEOPTION_START_AS_MINORS is never defined in either CvEnums.h or CIV4GameOptionInfos.xml but is still referenced in python and other DLL source files.

In the DLL it is line 5016 of CvPlayerAI.cpp and lines 3519 and 3581 of CvTeam.cpp.

In python it is in lines 52 and 103 of Assets\python\Revolution\Gameready\StartAsMinors.py.

(It is also found commented out in line 143 of the same file and in lines 1207 and 1766 of Assets\python\Revolution\Gameready\BarbarianCiv.py and lines 165 and 228 of Assets\python\Revolution\RevolutionInit.py)

This code could probably use cleaning up a bit.
 
Gekko reported that Scorpion clan goblin archers wander off instead of guarding the lair in EMM, because they have UNITAI_CITY_DEFENSE. I confirmed that this happens also in MNAI. In both cases, the problem lies in the initUnit() function. It is passed UNITAI_LAIRGUARDIAN, but that parameter is in the end ignored by AI_reset(), if it is not defined in the XML:
Code:
if (eUnitAI != NO_UNITAI)
{
	if (!GC.getUnitInfo(getUnitType()).getUnitAIType(eUnitAI))
	{
		eUnitAI = (UnitAITypes)GC.getUnitInfo(getUnitType()).getDefaultUnitAIType();
	}
}

Lizardman f.e. are later assigned UNTAI_LAIRGUARDIAN (AI_setUnitAIType() has no such restriction), but goblin archers are not.

Either the restriction should be removed or all units that could spawn as lair guardians should get UNTAI_LAIRGUARDIAN as a possible UnitAI. If you do the latter, I think ignoring the given UnitAI should at least trigger an assert, as it would be obviously a bug.
 
I think that distance should penalize a lot more how Loki values city targets for Disrupt, or that the * 20 to their value should be reduced.

Fair enough. I'll try some tweaks in that regard.

I just noticed that GAMEOPTION_START_AS_MINORS is never defined in either CvEnums.h or CIV4GameOptionInfos.xml but is still referenced in python and other DLL source files.

All of the references are commented out, so it doesn't hurt anything to have them there (aside from making the code a little messier). I believe I left that code there because I thought it was an interesting idea but needed some changes to make it fit better with FFH. I'll make a note to take a look at it and either remove the code or put in a tracking issue for implementing it as an option.

Gekko reported that Scorpion clan goblin archers wander off instead of guarding the lair in EMM, because they have UNITAI_CITY_DEFENSE.

I have a fix for this that I just haven't gotten around to uploading. The initial unit created on the plot will always be set to UNITAI_LAIRGUARDIAN (not just Lizardmen). The real issue is that subsequent units keep their city defense AI and try and head for the nearest barbarian city. My fix was to allow Scorpion Clan Goblin Archers to use UNITAI_ATTACK so that they will move off to harass players instead. Edit: I see now. It's the initial spawn that is not being set correctly. Goblin Forts are a special case in python. I'll add UNITAI_LAIRGUARDIAN to their XML.


Note: I also saw your Puppet States fix/patch. Will try to merge that this week. Thanks!


On line 734 of CustomFunctions (in doHellTerrain), pPlayer is referenced before assignment. This was added as part as the new volcano on hell terrain feature.

CvPlayerAI::AI_getPuppetAttitude is being called at CvGameTextMgr::getAttitudeString, but it is not being called at CvPlayerAI::AI_getAttitudeVal. Therefore, I believe that the attitude change for puppet states is not being taken into account.

Thanks! I will fix both of these issues.
 
Back
Top Bottom