1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Bug Reports and Discussion

Discussion in 'More Naval AI Modmod' started by Tholal, Jan 3, 2013.

  1. jackal1234

    jackal1234 Chieftain

    Joined:
    Jul 11, 2010
    Messages:
    96
    Location:
    127.0.0.0
    end of turn hangs, will not complete. task manager at 0-1 % on the civ4 process, some kind of logic failure loop? game still responds otherwise. i looked in worldbuilder but didnt see anything unusual about to be completed anywhere. tried reloading 3 times on random seed no change. save attached
     

    Attached Files:

  2. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    Unable to load the save. What version of MNAI are you using?
     
  3. jackal1234

    jackal1234 Chieftain

    Joined:
    Jul 11, 2010
    Messages:
    96
    Location:
    127.0.0.0
    hey thanks for checking! i later noticed in my downloads folder a 2.53 alpha dll that had been posted(forgot about that one!), so maybe this may be part of my issue.. sorry for wasting troubleshooting time on this
     
  4. Horatius

    Horatius Prince

    Joined:
    Sep 30, 2006
    Messages:
    575
    In honor of my favorite unit, postCombatWolfRider should be like this:

    Code:
    def postCombatWolfRider(pCaster, pOpponent):
    	if (pOpponent.getUnitType() == gc.getInfoTypeForString('UNIT_WOLF') or pOpponent.getUnitType() == gc.getInfoTypeForString('UNIT_WOLF_PACK')):
                    pPlayer = gc.getPlayer(pCaster.getOwner())
                    if pOpponent.plot().getNumVisibleEnemyDefenders(pCaster) > 1:
                            newUnit = pPlayer.initUnit(gc.getInfoTypeForString('UNIT_WOLF_RIDER'), pCaster.getX(), pCaster.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
                            CyInterface().addMessage(pCaster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_WOLF_RIDER", ()),'',1,'Art/Interface/Buttons/Units/Wolf Rider.dds',ColorTypes(8),pCaster.getX(),pCaster.getY(),True,True)
    		else:   
                            newUnit = pPlayer.initUnit(gc.getInfoTypeForString('UNIT_WOLF_RIDER'), pOpponent.getX(), pOpponent.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
                            CyInterface().addMessage(pCaster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_WOLF_RIDER", ()),'',1,'Art/Interface/Buttons/Units/Wolf Rider.dds',ColorTypes(8), newUnit.getX(), newUnit.getY(),True,True)
    		newUnit.convert(pCaster)
    Finishmoves() could be a consideration. Just saying. Poor wolfie gets a beat down, has to carry a fat smelly goblin and still has 3 movement points? Hey, I understand, they are tough.

    EDIT: Btw, I don't think the second line below (and similar) is really necessary but I could be wrong (some elif could be used at that section of event manager as well):
    Code:
    if pPlayer.getStateReligion() == gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL'):
    			if pPlayer.getCurrentEra() != gc.getInfoTypeForString('ERA_VEIL'):
    				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_VEIL'))
    Removing that useless check at endplayerturn is also ok.

    Using elif at onBuildingBuilt could be better instead of checking always all the buildings mentioned (similar for unitbuilt, etc.)

    Code:
    if gc.getGame().getBuildingClassCreatedCount(gc.getInfoTypeForString("BUILDINGCLASS_SOUL_FORGE")) > 0: 
    should be used at the start of the code for the soul forge onunitkilled. There's no reason for the loop and those checks every time a unit is killed if the building was not created. Too many games that thing is never built.

    Code:
    for i in xrange(21):
    	pPlot2 = pCity.getCityIndexPlot(i) 
    can probably be used onCityDoTurn instead of
    Code:
    for iiX in range(iX-2, iX+3, 1):
    		for iiY in range(iY-2, iY+3, 1):
     
  5. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,118
    Location:
    Kael's head
    It appears that setCurrentEra(iEra) checks to make sure that the old and new era are not the same before it does much anyway, so those checks do seem unnecessary.

    Is there a need to check or change eras every turn anyway? Couldn't it be handled in def onPlayerChangeStateReligion(self, argsList): ?
     
  6. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    OK. I'll also consider adding a finishMoves() call.

    Right on both counts. Will do.

    The change civic popup?

    Sounds good. Added elif at a number of places.

    Also good.

    Not this though. pCity isn't defined yet. The code there is looking for nearby cities.
     
  7. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    Seems reasonable. Seems like we can just do a setCurrentEra() there directly without doing a check for each religion. Anyone want to write that bit of code for me?
     
  8. Horatius

    Horatius Prince

    Joined:
    Sep 30, 2006
    Messages:
    575
    Yes, well, why should that first line be checked for each player every turn? If this was not a slow mod in the late game, this was just being picky, but everything counts. Up to you, though.

    What do you mean? Isn't this correct?:

    Code:
    if pCity.getNumRealBuilding(gc.getInfoTypeForString('BUILDING_CITADEL_OF_LIGHT')) > 0:
    		eTeam = gc.getTeam(pPlayer.getTeam())
    		iBestValue = 0
    		pBestPlot = -1
    		for i in xrange(21):
    	                        pPlot2 = pCity.getCityIndexPlot(i)
    				bEnemy = false
    				bNeutral = false
    				iValue = 0
    				if pPlot2.isVisibleEnemyUnit(iPlayer):
                                                    etc
    
     
  9. Horatius

    Horatius Prince

    Joined:
    Sep 30, 2006
    Messages:
    575
    Code:
    	def onPlayerChangeStateReligion(self, argsList):
    		'Player changes his state religion'
    		iPlayer, iNewReligion, iOldReligion = argsList
    		pPlayer = gc.getPlayer(iPlayer)
    
    		if iNewReligion == gc.getInfoTypeForString('RELIGION_RUNES_OF_KILMORPH'):
    			pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_RUNE'))
    
    		elif iNewReligion == gc.getInfoTypeForString('RELIGION_FELLOWSHIP_OF_LEAVES'):
    			pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_LEAF'))
    
    		elif iNewReligion == gc.getInfoTypeForString('RELIGION_OCTOPUS_OVERLORDS'):
    			pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_OCTO'))
    
    		elif iNewReligion == gc.getInfoTypeForString('RELIGION_THE_EMPYREAN'):
    			pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_EMPY'))
    
    		elif iNewReligion == gc.getInfoTypeForString('RELIGION_COUNCIL_OF_ESUS'):
    			pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_COUN'))
    
    		elif iNewReligion == gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL'):
    			pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_VEIL'))
    
    		elif iNewReligion == gc.getInfoTypeForString('RELIGION_THE_ORDER'):
    			pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_ORDE'))
     
  10. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,118
    Location:
    Kael's head
    The above suggested code would leave the player with religious art styles if it goes to no state religion.

    I'd think he's want something more like this:
    Code:
    
    	def onPlayerChangeStateReligion(self, argsList):
    		'Player changes his state religion'
    		iPlayer, iNewReligion, iOldReligion = argsList
    
    		if iNewReligion != iOldReligion:
    
    			if iNewReligion == -1:
    				iCurrentEra = pPlayer.getCurrentEra()
    				iEra = iCurrentEra
    				if not (iCurrentEra == gc.getInfoTypeForString('ERA_ANCIENT') or iCurrentEra == gc.getInfoTypeForString('ERA_CLASSICAL') or iCurrentEra == gc.getInfoTypeForString('ERA_MEDIEVAL')):
    					iEra = gc.getGame().getStartEra()
    					pPlayer.setCurrentEra(iEra)
    			elif iNewReligion == gc.getInfoTypeForString('RELIGION_THE_ORDER'):
    				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_ORDE'))
    			elif iNewReligion == gc.getInfoTypeForString('RELIGION_THE_EMPYREAN'):
    				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_EMPY'))
    			elif iNewReligion == gc.getInfoTypeForString('RELIGION_RUNES_OF_KILMORPH'):
    				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_RUNE'))
    			elif iNewReligion == gc.getInfoTypeForString('RELIGION_FELLOWSHIP_OF_LEAVES'):
    				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_LEAF'))
    			elif iNewReligion == gc.getInfoTypeForString('RELIGION_OCTOPUS_OVERLORDS'):
    				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_OCTO'))
    			elif iNewReligion == gc.getInfoTypeForString('RELIGION_COUNCIL_OF_ESUS'):
    				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_COUN'))
    			elif iNewReligion == gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL'):
    				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_VEIL'))
    
    
    The thought comes to mind that the code might have been done per turn because it is possible for a player that a player could convert to a religion early and then loose the custom artwork when he researches technologies that make him advance to the classical or medieval eras.

    To get around this, there might also hve to be some code added to def onTechAcquired(self, argsList):

    Edit: I just played a game with the Ashen Veil state religion going from having no techs to having all of them, and never saw my era art stye change; I guess the tech issue is not a big deal.
     
  11. Horatius

    Horatius Prince

    Joined:
    Sep 30, 2006
    Messages:
    575
    Yep, forgot no state. Very nice. Well, I actually just assumed there must be a reason if Kael put the codes where they are but I'm stll suprised at it.

    Btw, and just curiosity, do the reqs for the world spells are checked for every unit every turn?
     
  12. Blakmane

    Blakmane Prince

    Joined:
    Feb 17, 2007
    Messages:
    447
    When using food to production civics/producing settlers or workers, the city plot AI doesn't take into account that production multipliers do not influence food-to-production hammers. This can cause some very sub-optimal tile decisions by the automated AI in these situations. This has probably existed since vanilla I'm sure.

    Easy to reproduce: get heroic epic and conquest in a city with some farms and mines. Watch as AI chooses farms over mines for production.
     
  13. platyping

    platyping Sleeping Dragon

    Joined:
    Oct 22, 2010
    Messages:
    4,626
    Location:
    Emerald Dreams
    You can use that religion code only if there are no votes which will force players to change religions, aka free religion civic in bts.

    Forced civics will not trigger those codes even though religion is changed.
     
  14. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,118
    Location:
    Kael's head
    The Taunt spell seems to cause a crash whenever its target units are in a group.

    I think the best way to get around this would be to cause any unit that does not resist the spell to become separated from its group before it attacks.

    In order to do this, you would need to expose the python code that causes a unit to leave or join a group. I'd really like you to do that anyway, so I could modify group membership in worldbuilder.
     
  15. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    OK. I'll look into it.

    It's already exposed -- void CyUnit::joinGroup(CySelectionGroup* pNewGroup)

    Use joinGroup(NULL) to force a unit to leave its group.
     
  16. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,118
    Location:
    Kael's head
    I don't think I can use NULL in python.

    When I use pUnit.joinGroup(NULL) I get this:

    Code:
    Traceback (most recent call last):
    
      File "CvSpellInterface", line 49, in cast
    
      File "<string>", line 0, in ?
    
      File "CvSpellInterface", line 8011, in spellTaunt
    
    NameError: global name 'NULL' is not defined
    ERR: Python function cast failed, module CvSpellInterface
    
    When I use pUnit.joinGroup(-1) I get this:
    Code:
    Traceback (most recent call last):
    
      File "CvSpellInterface", line 49, in cast
    
      File "<string>", line 0, in ?
    
      File "CvSpellInterface", line 8011, in spellTaunt
    
    ArgumentError: Python argument types in
        CyUnit.joinGroup(CyUnit, int)
    did not match C++ signature:
        joinGroup(class CyUnit {lvalue}, class CySelectionGroup *)
    ERR: Python function cast failed, module CvSpellInterface
    
     
  17. lfgr

    lfgr King

    Joined:
    Feb 6, 2010
    Messages:
    727
  18. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,118
    Location:
    Kael's head
    "None" doesn't work either.

    pUnit.joinGroup(gc.getPlayer(pUnit.getOwner()).getSelectionGroup(-1)) does seem to work for splitting up the groups.

    However, I'm thinking that the group may not have been the issue. I seem to be getting crashes now when it works to force multiple units (from different groups and even tiles) to attack too.

    I thought the issue could be that an attacking unit might leave the stack and change the index of the other units, but it didn't help when I changed the code to add applicable units to a list and then cycle through that after the cycling through the adjacent plots was done.

    Edit: I've come across the occasional crash even when only one unit is forced to attack, although is relatively rare.

    The crash is not causing anything to show up in PythonErr.log, but when I check BBAI.log I find that the last thing to occur always seems to be the unit that cast Taunt being slain in combat with one of the units that the spell caused to attack him.

    I'm fairly confident now that the crash to desktop is related to the caster being killed before the spell's code has fully run its course.
     
  19. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    It's related to that damned doDelayedDeath() function. This thing has caused me a lot of heartache.
     
  20. Mailbox

    Mailbox King

    Joined:
    Oct 6, 2007
    Messages:
    873
    In a game as the Balseraphs where I'm able to steal units with loyalty with Mind III's domination. They should die according to the tooltip for loyalty. This is with 2.52 but I didn't see a change with 2.53.
     

Share This Page