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

MNAI-U: unofficial build & bugfixes

Discussion in 'More Naval AI Modmod' started by lfgr, May 15, 2019.

  1. lfgr

    lfgr King

    Joined:
    Feb 6, 2010
    Messages:
    715
    Not a bad idea as such, but I try to stay away from non-bugfixing stuff as much as possible, at least in MNAI-U.

    AC 40 is currently a requirement for Pit Beast, Death Knight and Balor to spawn.

    Agreed. As for teams, I lean towards allowing only human players to explore lairs in teammates' territory.
    The AI is currently the main problem. There is no dedicated lair exploration code, but instead a marker for certain improvements (lairs, but also e.g. cages) that the AI should visit with units. Units will explore lairs they're standing on with some different code.

    Nothing too ambitious from a player's perspective. Fix bugs, polish, quality of life improvements, basically continue what Tholal did. At some point I want to scavenge the "new" AI mods like AdvCivs for AI improvements. The only thing I might put a bit more creativity into (at some point) is the revolutions component, which is still quite rough and not well integrated into FfH lore.
    The way I see the MNAI descendants is basically that MNAI-U is for stability, MagisterModMod is for new features, and EMM is for balance and a bit of both.
     
  2. lfgr

    lfgr King

    Joined:
    Feb 6, 2010
    Messages:
    715
    There are actually two BUG events for this, combatRetreat (when the attacker flees) and combatWithdrawal (when the attacker withdraws after dealing maximum damage, like catapults); see BUG/BugEventManager.py. I've added combatDefenderRetreat (for when the defender flees) for the next release. Let me know if you need help setting up the BUG event handlers.

    EDIT:
    I have implemented a <iMiscastChance> tag for promotions. However, the way it currently works, if a unit has a positive overall miscasting chance, it can miscast every spell, including e.g. world spells. Is that what you want? If not, I'm thinking of making a <bCanMiscast> tag that would have to be added to all spells that can be miscast.
     
    Last edited: Oct 6, 2019
  3. lfgr

    lfgr King

    Joined:
    Feb 6, 2010
    Messages:
    715
    New release: mnai-2.8.1u. Should be compatible with 2.8.0u savegames.
    Thanks to Devils_Advocate, MagisterCultuum, OKSleeper and westamastaflash for bug reports.

    Download
    Please extract into "Mods/Fall from Heaven 2" (not into the Assets folder!)

    This release again contains a lot of smaller bug fixes. Other changes include:
    • As discussed earlier in this thread, I took some measures to reduce early civ deaths. Lair bosses are now not as strong early on, the mistform event requires sorcery, and barbarian spectres cannot upgrade to wraiths before barbarians have sorcery (i.e. many players have sorcery or a few have had it for some time).
    • The sevopedia and several advisor screens can now set to full-screen via the "Advisors" tab in the BUG option window. The other advisor screens will follow suit in the next few versions.
    • I overhauled the Dynamic civ names component. The way Tholal set up the system, it can generate a wide variety of interesting names, but also sometimes results in somewhat wacky ones. However, I think DNC is quite useful in any case to distinguish between multiple players of the same civilization. So I added two more conservative options. "Minimal" doesn't do anything except when multiple players share the same civ, where all get the name "Realm of <leader>". "Medium" tries to be a bit more creative. In particular, it uses the capital city in the name of vassal players that share a civilization with some other players. For example, a Bannor player and its Bannor vassal might get the names "Bannor Empire" and "Duchy of Vallus". You can switch between these options in the "Scoreboard" tab of the BUG option window (the names will be immediately updated).
    • The performance of the AI unit evaluation was improved via caching. The savings in my two test games were considerable, but I only tested the non-optimized version of the DLL, so the actual improvement might be less noticeable. Still, I'm hoping to make similar improvements in some other ares in the future.

    See here or the file changelog.md included in the download for a full changelog.
     
    Last edited: Nov 3, 2019
  4. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,102
    Location:
    Kael's head
    Thanks for the update!

    It is already possible to make spells so that should never miscast by giving them a <iMiscastChance>-1000</iMiscastChance> modifier, so a <bCanMiscast> tag is not really necessary but might be nice if only to reduce clutter in the spell mouseovers.

    It might be easier though to only have a spell miscast if something is listed in its <PyMiscast> tag. You could just put something like <PyMiscast>False </PyMiscast> for spells that simply fail when miscast rather than doing anything special.

    In my initial texts am noticing a lot more units than I would like miscasting currently, but I can probably fix that by adjusting some values with tags already in place.

    I started to complain about several missing TXT_KEYs, but just before submitting I realized that when merging your mod with mine I'd forgotten to check "Show Left Unique Items: in Winmerge, which meant I had overlooked and forgot to include the new file Spells.xml.

    I think I would like some pointers on setting up the BUG event handlers. I have never bothered with any BUG files before and don't want to mess things up.

    Can I just treat BugEventManager.py like CvEventManager.py and put the code there directly, or do I need to put thins in other files.

    What I want to do is basically just make this code from def onCombatResult(self, argsList): apply also when a unit manages to retreat (perhaps only if they land some hit to do a little damage.


    Spoiler :
    Code:
    
                   iGodslayer = gc.getInfoTypeForString('PROMOTION_GODSLAYER')
                   iAvatar = gc.getInfoTypeForString('PROMOTION_AVATAR')
    
                   iCaveaAngelorum = gc.getInfoTypeForString('PROMOTION_ANGELORUM_CAVEA')
                   iCaptusAngelorum = gc.getInfoTypeForString('PROMOTION_CAPTUS_CAVEAE_ANGELORUM')
    
                   iCaveaSawol = gc.getInfoTypeForString('PROMOTION_SAWOL_CAVEA')
                   iCaptusSawol = gc.getInfoTypeForString('PROMOTION_CAPTUS_CAVEAE_SAWOL')
    
                   iNetherblade = gc.getInfoTypeForString('PROMOTION_NETHER_BLADE')
                   iNBind = gc.getInfoTypeForString('PROMOTION_NETHERBIND')
    
                   iCustos = gc.getInfoTypeForString('PROMOTION_CUSTOS_JUDICII')
                   iCarcer = gc.getInfoTypeForString('PROMOTION_INCARCERATUS_JUDICII')
    
                   if pWinner.isHasPromotion(iGodslayer):
                       cf.makeMortal(pLoser)
                       if pLoser.isHasPromotion(iAvatar):
                           pLoser.setHasPromotion(iAvatar, False)
                           gc.getPlayer(iPlayerL).AI_changeAttitudeExtra(iPlayerW,-12)
                           pLoser.kill(True, iPlayerW)
                   elif pLoser.isHasPromotion(iGodslayer):
                       cf.makeMortal(pWinner)
                       if pWinner.isHasPromotion(iAvatar):
                           pWinner.setHasPromotion(iAvatar, False)
                           gc.getPlayer(iPlayerW).AI_changeAttitudeExtra(iPlayerL,-12)
                           pWinner.kill(True, iPlayerL)
    
                   if pWinner.isHasPromotion(iNetherblade):
                       pLoser.setHasPromotion(iNBind, True)
                       cf.makeMortal(pLoser)
                       if isWorldUnitClass(pLoser.getUnitClassType()):
                           gc.getPlayer(iPlayerL).AI_changeAttitudeExtra(iPlayerW,-7)
                           pLoser.kill(True, iPlayerW)
                   elif pLoser.isHasPromotion(iNetherblade):
                       cf.makeMortal(pWinner)
                       if isWorldUnitClass(pWinner.getUnitClassType()):
                           pWinner.setHasPromotion(iNBind, True)
                           gc.getPlayer(iPlayerW).AI_changeAttitudeExtra(iPlayerL,-7)
                           pWinner.kill(True, iPlayerL)
    
    
    
                   if pWinner.isHasPromotion(iCaveaAngelorum):
                       if pLoser.getRace() in [gc.getInfoTypeForString('PROMOTION_DEMON'),gc.getInfoTypeForString('PROMOTION_ANGEL')]:
    
                           pLoser.setHasPromotion(iCaptusAngelorum, True)
                           cf.makeMortal(pLoser)
                           if isWorldUnitClass(pLoser.getUnitClassType()):
                               gc.getPlayer(iPlayerL).AI_changeAttitudeExtra(iPlayerW,-7)
                           pLoser.kill(True, iPlayerW)
                       elif pLoser.isHasPromotion(gc.getInfoTypeForString('PROMOTION_DEMON_POSSESSED')):
                           pLoser.setHasPromotion(gc.getInfoTypeForString('PROMOTION_DEMON_POSSESSED'), False)
    
    
                   elif pWinner.isHasPromotion(iCustos):
                       if pLoser.isHasPromotion(gc.getInfoTypeForString('PROMOTION_DEMON')):
                           pLoser.setHasPromotion(iCarcer, True)
                           cf.makeMortal(pLoser)
                           if isWorldUnitClass(pLoser.getUnitClassType()):
                               gc.getPlayer(iPlayerL).AI_changeAttitudeExtra(iPlayerW,-7)
                           pLoser.kill(True, iPlayerW)
                       elif pLoser.isHasPromotion(gc.getInfoTypeForString('PROMOTION_DEMON_POSSESSED')):
                           pLoser.setHasPromotion(gc.getInfoTypeForString('PROMOTION_DEMON_POSSESSED'), False)
    
                   iX = pWinner.getX()
                   iY = pWinner.getY()
    
    
    
                   if pLoser.isAlive():
    
                       if pWinner.isHasPromotion(gc.getInfoTypeForString('PROMOTION_VILE_TOUCH')):
                           pLoser.setHasPromotion(gc.getInfoTypeForString('PROMOTION_WITHERED'), True)
                       if pWinner.getDamageTypeCombat(gc.getInfoTypeForString('DAMAGE_POISON')) > 0:
                           if pLoser.getDamage() > 0:
                               if not pLoser.isHasPromotion(gc.getInfoTypeForString('PROMOTION_POISONED')):
                                   if pLoser.getDamageTypeResist(gc.getInfoTypeForString('DAMAGE_POISON')) < 100:
                                       if CyGame().getSorenRandNum(100,"Poisoned") >= pLoser.getDamageTypeResist(gc.getInfoTypeForString('DAMAGE_POISON')):
                                           pLoser.setHasPromotion(gc.getInfoTypeForString('PROMOTION_POISONED'), True)
    
    
    
                       if pWinner.isHasPromotion(iCaveaSawol):
    
                           pLoser.setHasPromotion(iCaptusSawol, True)
                           cf.makeMortal(pLoser)
                           if isWorldUnitClass(pLoser.getUnitClassType()):
                               gc.getPlayer(iPlayerL).AI_changeAttitudeExtra(iPlayerW,-7)
                           pLoser.kill(True, iPlayerW)
                       else:
    
                           iRavenous = gc.getInfoTypeForString('PROMOTION_RAVENOUS')
                           iWerewolf = gc.getInfoTypeForString('PROMOTION_WEREWOLF')
                           lImmuneLycanthropy = [   iWerewolf,
                                   gc.getInfoTypeForString('PROMOTION_WEREWOLF_SLAYING'),
                                   gc.getInfoTypeForString('PROMOTION_IMMUNE_DISEASE'),
                                   gc.getInfoTypeForString('PROMOTION_SPIRIT3'),
                                   gc.getInfoTypeForString('PROMOTION_AFFINITY_SPIRIT'),
                                   gc.getInfoTypeForString('PROMOTION_ILLUSION'),
                                   gc.getInfoTypeForString('PROMOTION_DARK_REFLECTION')
                                   ]
    
    
                           if pWinner.isHasPromotion(iRavenous):
                               if not pLoser.isImmortal():
                                   if not iUnitCombatLoser in lBeasts:
                                       pWinner.setHasPromotion(iRavenous, False)
    
    
                           if pLoser.isHasPromotion(iWerewolf):
                               if pWinner.isAlive() and pWinner.getDamage() > 0:
                                   if not pWinner.getUnitCombatType() in lBeasts:
                                       for iProm in lImmuneLycanthropy:
                                           if pWinner.isHasPromotion(iProm):
                                               break
                                       else:
                                           iChance = pLoser.getLevel() - pWinner.getLevel()
                                           if iTypeLoser == gc.getInfoTypeForString('UNIT_DUIN'):
                                               iChance += 5
                                           elif iTypeLoser == gc.getInfoTypeForString('UNIT_GREATER_WEREWOLF'):
                                               iChance += 3
                                           elif iTypeLoser == gc.getInfoTypeForString('UNIT_WEREWOLF'):
                                               iChance += 2
                                           elif iTypeLoser == gc.getInfoTypeForString('UNIT_RAVENOUS_WEREWOLF'):
                                               iChance += 1
                                           if iChance > 0:
                                               if CyGame().getSorenRandNum(200, "Spread Lycanthropy"  + str(pWinner.getName()) + ' slayer of '+ str(pLoser.getName())) < iChance:
                                                   sName = pWinner.getName()
                                                   CyInterface().addMessage(iPlayerW,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_SPREAD_LYCANTHROPY",(sName,)),'AS2D_FEATUREGROWTH',1,'Art/Interface/Buttons/Promotions/Werewolf.dds',ColorTypes(7),iX,iY,True,True)
                                                   CyInterface().addMessage(iPlayerL,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_SPREAD_LYCANTHROPY",(sName,)),'AS2D_FEATUREGROWTH',1,'Art/Interface/Buttons/Promotions/Werewolf.dds',ColorTypes(8),iX,iY,True,True)
                                                   newUnit = pPlayerW.initUnit(gc.getInfoTypeForString('UNIT_RAVENOUS_WEREWOLF'), iX, iY, UnitAITypes.UNITAI_ATTACK, DirectionTypes.NO_DIRECTION)
                                                   cf.makeMortal(pWinner)
                                                   pWinner.setHasPromotion(gc.getInfoTypeForString('PROMOTION_DARK_REFLECTION'), True)
                                                   newUnit.convert(pWinner)
                                                   newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_DARK_REFLECTION'), False)
    
                           if pWinner.isHasPromotion(iWerewolf):
                               if pLoser.isAlive():
                                   if not iUnitCombatLoser in lBeasts:
                                       for iProm in lImmuneLycanthropy:
                                           if pLoser.isHasPromotion(iProm):
                                               break
                                       else:
                                           iChance = pWinner.getLevel() - pLoser.getLevel()
                                           sName = pLoser.getName()
                                           if iTypeWinner == gc.getInfoTypeForString('UNIT_DUIN'):
                                               iChance += 5
                                           elif iTypeWinner == gc.getInfoTypeForString('UNIT_GREATER_WEREWOLF'):
                                               iChance += 3
                                               if pWinner.isHasPromotion(gc.getInfoTypeForString('PROMOTION_CANNOT_CAST')):
                                                   pWinner.setHasPromotion(gc.getInfoTypeForString('PROMOTION_CANNOT_CAST'), False)
                                                   CyInterface().addMessage(iPlayerW,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_WEREWOLF_CAN_CAST",(sName,)),'AS2D_FEATUREGROWTH',1,'Art/Interface/Buttons/Promotions/Werewolf.dds',ColorTypes(8),iX,iY,True,True)
    
                                           elif iTypeWinner == gc.getInfoTypeForString('UNIT_WEREWOLF'):
                                               iChance += 2
                                           elif iTypeWinner == gc.getInfoTypeForString('UNIT_RAVENOUS_WEREWOLF'):
                                               iChance += 1
                                           iChance *= 10
                                           if iChance > 0:
                                               if CyGame().getSorenRandNum(100, "Spread Lycanthropy "  + str(pWinner.getName()) + ' slayer of '+ str(pLoser.getName())) < iChance:
                                                   sName = pLoser.getName()
                                                   CyInterface().addMessage(iPlayerL,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_SPREAD_LYCANTHROPY",(sName,)),'AS2D_FEATUREGROWTH',1,'Art/Interface/Buttons/Promotions/Werewolf.dds',ColorTypes(7),iX,iY,True,True)
                                                   CyInterface().addMessage(iPlayerW,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_SPREAD_LYCANTHROPY",(sName,)),'AS2D_FEATUREGROWTH',1,'Art/Interface/Buttons/Promotions/Werewolf.dds',ColorTypes(8),iX,iY,True,True)
                                                   newUnit = pPlayerW.initUnit(gc.getInfoTypeForString('UNIT_RAVENOUS_WEREWOLF'), iX, iY, UnitAITypes.UNITAI_ATTACK, DirectionTypes.NO_DIRECTION)
                                                   newUnit.setScenarioCounter(iTypeLoser)
                                                   newUnit.setLevel(pLoser.getLevel())
                                                   newUnit.setExperience(pLoser.getExperience(), -1)
                                                   newUnit.setName(sName)
                                                   newUnit.setReligion(pLoser.getReligion())
                                                   newUnit.setDamage(pLoser.getDamage()/2, pWinner.getOwner())
                                                   newUnit.finishMoves()
                                                   for iCount in xrange(gc.getNumPromotionInfos()):
                                                       if pLoser.isHasPromotion(iCount) and not gc.getPromotionInfo(iCount).isEquipment():
                                                           newUnit.setHasPromotion(iCount, True)
                                                   cf.makeMortal(pLoser)
                                                   pLoser.setHasPromotion(gc.getInfoTypeForString('PROMOTION_DARK_REFLECTION'), True)
    
    


    Could you make it so that the pedia entries for equipment show the date for the unit as well as the promotion? Or maybe just let promotions have Pedia entries that do not show up in mouseovers?

    I added Kael's recently released story of Basium and the Boiling Sea to the pedia entry for the equipment he uses to trap demons, but found it did not show up anywhere when it is there for the unit. Using a 6 page story as a help string that appears in the mouseovers of a promotion would be insane.
     
    Last edited: Nov 4, 2019
  5. Tielby

    Tielby Prince

    Joined:
    Sep 23, 2007
    Messages:
    313
    Location:
    The sacred and free citadel of mind

    WHERE DID YOU FIND THIS?... Ahem. Sorry. I mean, I wasn't aware Kael was still releasing FfH-related anything. Is there a forum or blog where he dumps this stuff?
     
    DarkLunaPhantom likes this.
  6. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,102
    Location:
    Kael's head
    Kael has been active on Reddit recently. Last month he released an entry on one character per day, some of which cover lore he had never revealed before. Some stuff was recently reconnected as only this year did he decide the course that history should take during the Age of Invention, after the Crucible robs the world of Magic and the worship of the old gods is replaced by the Matronae. Who the Matronae are was a secret he saved for the Halloween entry on Basium and the Boiling Sea.
     
    DarkLunaPhantom and Tielby like this.
  7. lfgr

    lfgr King

    Joined:
    Feb 6, 2010
    Messages:
    715
    You shouldn't put it into BugEventManager.py. The idea of the BUG architecture is that each component has their own files, which is nice to make them easier to merge. A component can register its functions as event handlers. I made a small example that should serve as a template for you:

    In the Assets/Config directory, you put the file Magister.xml:
    Code:
    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <!--
       MagisterModMod EventHandlers
     
       DESCRIPTION HERE
    -->
    <mod id="MagisterEvents"
        name="Magister Events"
        author="Magister Cultuum"
        version="..."
        date="..."
        url="...">
       <event type="combatWithdrawal" module="MagisterEvents" function="onCombatWithdrawal"/>
       <event type="combatRetreat" module="MagisterEvents" function="onCombatRetreat"/>
       <event type="combatDefenderRetreat" module="MagisterEvents" function="onCombatDefenderRetreat"/>
    </mod>
    
    Most of that should be self-explanatory. The important part is the <event ... /> tags, where you bind e.g. the combatWithdrawal event to the onCombatWithdrawal function in the MagisterEvents module. Consequently, you need a MagisterEvents.py file in Assets/python that could look like this:
    Code:
    # MagisterModMod Events
    
    from CvPythonExtensions import *
    
    
    def onCombatWithdrawal(argsList):
       """Fired when an attacker withdraws from combat after doing maximum damage."""
       pAttacker, pDefender = argsList
       CyInterface().addImmediateMessage( str("TEST - %s withdraws from %s" % ( pAttacker.getName(), pDefender.getName() ) ), "" )
    
    def onCombatRetreat(argsList):
       """Fired when an attacker retreats from combat, escaping death."""
       pAttacker, pDefender = argsList
       CyInterface().addImmediateMessage( str( "TEST - %s retreats from %s" % ( pAttacker.getName(), pDefender.getName() ) ), "" )
    
    def onCombatDefenderRetreat(argsList):
       """Fired when a defender retreats from combat, escaping death."""
       pAttacker, pDefender = argsList
       CyInterface().addImmediateMessage( str( "TEST - defender %s retreats from %s" % ( pDefender.getName(), pAttacker.getName() ) ), "" )
    
    Finally, you need to tell BUG to load your component by specifying
    Code:
        <load mod="Magister"/>
    
    in Assets/Config/init.xml, e.g. after the <load mod="BUFFY"/> line.
    I attached the example files.

    I'll look into it.
     

    Attached Files:

  8. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,102
    Location:
    Kael's head
    Thanks.

    When I first tried using your template with a bit of my code it did not work, but then I realized it was because I had referenced another file I had not imported nor did I need.

    I have tested it and found it working for the Runewyn's ability to remove magic with a single tough. I have not yet tested how well it works with the code to spread Lycanthropy or pass on poisoned or withered. I have not yet tested code that could kill a unit.


    I have gotten these asserts after merging your mod with mine:
    Spoiler :
    Code:
    Assert Failed
    
    File:  CvUnit.cpp
    Line:  3833
    Expression:  canMoveInto(pPlot, true)
    Message:
    
    ----------------------------------------------------------
    
    Assert Failed
    
    File:  CvCityAI.cpp
    Line:  4463
    Expression:  (MAX_INT / 1000) > iValue
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlot.cpp
    Line:  8644
    Expression:  getStolenVisibilityCount(eTeam) >= 0
    Message:
    
    ----------------------------------------------------------
    
    Assert Failed
    
    File:  CvUnit.cpp
    Line:  14594
    Expression:  eIndex >= 0
    Message:  eIndex is expected to be non-negative (invalid Index)
    
    ----------------------------------------------------------
    
    Assert Failed
    
    File:  CvCity.cpp
    Line:  7755
    Expression:  getBonusGoodHealth() >= 0
    Message:  getBonusGoodHealth is expected to be >= 0
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvInfos.cpp
    Line:  2674
    Expression:  i > -1
    Message:  Index out of bounds
    
    
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvCity.cpp
    Line:  8340
    Expression:  getBonusBadHappiness() <= 0
    Message:
    
    ----------------------------------------------------------
    
    
    
    Assert Failed
    
    File:  CvGlobals.cpp
    Line:  1865
    Expression:  eGoodyNum > -1
    Message:
    
    ----------------------------------------------------------
    
    
    
    Assert Failed
    
    File:  CvCity.cpp
    Line:  7753
    Expression:  getBonusGoodHealth() >= 0
    Message:
    
    
    ----------------------------------------------------------
    (When miscasting Floating Eye)
    Assert Failed
    
    File:  CvUnit.cpp
    Line:  3833
    Expression:  canMoveInto(pPlot, true)
    Message:
    
    ----------------------------------------------------------
    (when attacking barbarian floating eye from miscasting
    Assert Failed
    
    File:  CvUnit.cpp
    Line:  1093
    Expression:  getAttackPlot() == NULL
    Message:  The current unit instance's attack plot is expected to be NULL
    
    ----------------------------------------------------------Assert Failed
    
    File:  CvUnit.cpp
    Line:  1081
    Expression:  !isCombat()
    Message:  isCombat did not return false as expected
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvUnit.cpp
    Line:  12849
    Expression:  getMoves() >= 0
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvUnit.cpp
    Line:  3833
    Expression:  canMoveInto(pPlot, true)
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvTeam.cpp
    Line:  3153
    Expression:  !(AI_isSneakAttackPreparing((TeamTypes)iI))
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  d:\dev\civ\repos\mnai\cvgamecoredll\CvPlayerAI.h
    Line:  25
    Expression:  ePlayer != NO_PLAYER
    Message:  Player is not assigned a valid value
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvUnitAI.cpp
    Line:  61
    Expression:  AI_getUnitAIType() != NO_UNITAI
    Message:  AI_getUnitAIType() is not expected to be equal with NO_UNITAI
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvArea.cpp
    Line:  861
    Expression:  eIndex2 >= 0
    Message:  eIndex2 is expected to be >= 0
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvArea.cpp
    Line:  851
    Expression:  eIndex2 >= 0
    Message:  eIndex2 is expected to be >= 0
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvArea.cpp
    Line:  864
    Expression:  getNumAIUnits(eIndex1, eIndex2) >= 0
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17653
    Expression:  eIndex >= 0
    Message:  eIndex is expected to be non-negative (invalid Index)
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17645
    Expression:  eIndex >= 0
    Message:  eIndex is expected to be non-negative (invalid Index)
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17656
    Expression:  AI_getNumAIUnits(eIndex) >= 0
    Message:
    
    ----------------------------------------------------------
    
    Assert Failed
    
    File:  CvCity.cpp
    Line:  8328
    Expression:  getBonusGoodHappiness() >= 0
    Message:
    
    ----------------------------------------------------------
    
    Assert Failed
    
    File:  CvArea.cpp
    Line:  864
    Expression:  getNumAIUnits(eIndex1, eIndex2) >= 0
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17653
    Expression:  eIndex >= 0
    Message:  eIndex is expected to be non-negative (invalid Index)
    
    ----------------------------------------------------------Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17645
    Expression:  eIndex >= 0
    Message:  eIndex is expected to be non-negative (invalid Index)
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17656
    Expression:  AI_getNumAIUnits(eIndex) >= 0
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvInfos.cpp
    Line:  2674
    Expression:  i > -1
    Message:  Index out of bounds
    
    ----------------------------------------------------------Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  12973
    Expression:  eUnitAI != NO_UNITAI
    Message:  UnitAI is not assigned a valid value
    
    ----------------------------------------------------------Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  2374
    Expression:  false
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvCity.cpp
    Line:  9180
    Expression:  getOccupationTimer() >= 0
    Message:
    
    ----------------------------------------------------------
    
    Assert Failed
    
    File:  CvCity.cpp
    Line:  8468
    Expression:  getHurryAngerTimer() >= 0
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvTeam.cpp
    Line:  7510
    Expression:  eTeam < MAX_CIV_TEAMS
    Message:  eTeam is expected to be within maximum bounds (invalid Index)
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvUnit.cpp
    Line:  12849
    Expression:  getMoves() >= 0
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvGlobals.cpp
    Line:  3764
    Expression:  strcmp(szType, "NONE")==0 || strcmp(szType, "")==0
    Message:  info type PROJECT_ASCENSION not found, Current XML file is: (None)
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvUnit.cpp
    Line:  3972
    Expression:  canMoveOrAttackInto(pPlot) || isMadeAttack()
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvGame.cpp
    Line:  5821
    Expression:  eIndex >= 0
    Message:  eIndex is expected to be non-negative (invalid Index)
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  d:\dev\civ\repos\mnai\cvgamecoredll\CvPlayerAI.h
    Line:  25
    Expression:  ePlayer != NO_PLAYER
    Message:  Player is not assigned a valid value
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvUnitAI.cpp
    Line:  61
    Expression:  AI_getUnitAIType() != NO_UNITAI
    Message:  AI_getUnitAIType() is not expected to be equal with NO_UNITAI
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvArea.cpp
    Line:  861
    Expression:  eIndex2 >= 0
    Message:  eIndex2 is expected to be >= 0
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvArea.cpp
    Line:  851
    Expression:  eIndex2 >= 0
    Message:  eIndex2 is expected to be >= 0
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvArea.cpp
    Line:  864
    Expression:  getNumAIUnits(eIndex1, eIndex2) >= 0
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17653
    Expression:  eIndex >= 0
    Message:  eIndex is expected to be non-negative (invalid Index)
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17645
    Expression:  eIndex >= 0
    Message:  eIndex is expected to be non-negative (invalid Index)
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17656
    Expression:  AI_getNumAIUnits(eIndex) >= 0
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvGlobals.cpp
    Line:  3764
    Expression:  strcmp(szType, "NONE")==0 || strcmp(szType, "")==0
    Message:  info type BUILDING_LION_CAGE not found, Current XML file is: xml\Units/CIV4UnitInfos.xml
    
    ----------------------------------------------------------
    

    I got had couple asserts I did not include because I easily tracked them down to two typos in python referencing equipment promotions.

    Those looked a lot like the BUILDING_LION_CAGE or PROJECT_ASCENSION asserts, which I have not tracked down to any source and which have happened only once each.

    The Lion Cage one was particularly strange because it happened when loading a saved game but did not happened after I closed the same and loaded that same saved mane without changing any code.


    I realized my earlier issue with everything miscasting was due to the code I added to help the Nullstone Citadel and Nullstone Golems interfere with casters nearby. It was supposed to add a promotion that gives a +100 miscast chance only when within range of the Nullstone Golem or Citadel and otherwise remove it, but I got True and False switched so it was always giving the promotion to every unit, This would have been obvious had I not set the promotion as its own next level in order to hide it from view.
     
    Last edited: Nov 6, 2019
  9. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,102
    Location:
    Kael's head
    I am pretty much ready to release a new update, but I keep getting some odd asserts when loading a saved game or sometimes when starting a new game.

    The asserts claim that some info type that cannot be read. Usually it is a building, but never the same building twice, even when loading the same saved game. Sometimes it stops a file like CIV4UnitInfos.xml from loading correctly, but usually causes no problems. Reloading the saved game tends to return no such assert, or sometimes a similar assert for a different info type.

    Sometimes the asserts show the info type as containing a missing Unicode character box.

    What is going on here?


    Spoiler :
    Code:
    Assert Failed
    
    File:  CvArtFileMgr.cpp
    Line:  175
    Expression:  false
    Message:  get##name##ArtInfo: ART_DEF_UILDING_WYRMHOLD_VAULT was not found
    (It did not copy paste right but there was a box for the missing character where a B should be.)
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvGlobals.cpp
    Line:  3764
    Expression:  strcmp(szType, "NONE")==0 || strcmp(szType, "")==0
    Message:  info type BUILDING_HIPPODROME not found, Current XML file is: xml\Units/CIV4UnitInfos.xml
    
    ----------------------------------------------------------
    
    Assert Failed
    
    File:  CvGlobals.cpp
    Line:  3764
    Expression:  strcmp(szType, "NONE")==0 || strcmp(szType, "")==0
    Message:  info type BUILDING_TEMPLE_OF_LEAVES not found, Current XML file is: xml\Units/CIV4UnitInfos.xml
    
    ----------------------------------------------------------
    
    
    Assert Failed
    
    File:  CvGlobals.cpp
    Line:  3764
    Expression:  strcmp(szType, "NONE")==0 || strcmp(szType, "")==0
    Message:  info type BUILDING_PANTHER_CAGE not found, Current XML file is: xml\Units/CIV4UnitInfos.xml
    
    ----------------------------------------------------------
    
    
    Assert Failed
    
    File:  CvGlobals.cpp
    Line:  3764
    Expression:  strcmp(szType, "NONE")==0 || strcmp(szType, "")==0
    Message:  info type CIVILIZAION_BALSERAPHS not found, Current XML file is: xml\Units/CIV4SpellInfos.xml
    (It did not copy paste right but there was a box for the missing character where a T should be.)
    ----------------------------------------------------------
     
  10. lfgr

    lfgr King

    Joined:
    Feb 6, 2010
    Messages:
    715
    Looks like memory corruption. Can you upload your mod files?
     
  11. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,102
    Location:
    Kael's head
    Which files would you like me to upload? Should I just go ahead and release the mod as it is now?

    I just used Winmerge to delete the untouched FfH2 files put the rest in the .zip and .exe like I usually do. The setup is 55 mb and the archive almost 77 mb this time, larger than previous versions because I included a little more art (mostly copies of buttons that do not have spaces in the name so they so not show up as pink squares in mouseovers, and course 21 species of Dragon) and lot of longer pedia entries (such as including all of Kael's "Fideism" and "Ashes of Brigdarrow" stories, which are respectively 56 and 77 pages long.)

    Edit: I just uploaded the new version of my modmod. When I follow the links from my signature they say there are not currently any available mirrors for downloading, but that should change within a few hours. (I expected this and so use tomorrow's date instead of today's as the version identifier.)
     
    Last edited: Nov 8, 2019
  12. lfgr

    lfgr King

    Joined:
    Feb 6, 2010
    Messages:
    715
    I tried a bit of autoplay and save/reload, but I did not get the asserts. Do you have a savegame where you get them more or less reliably?
     
  13. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,102
    Location:
    Kael's head
    Oddly enough, I am not getting any such asserts anymore either. After running the installer that I posted the game seems much less sluggish too. I have no idea why, but I'm not complaining.
     
  14. lfgr

    lfgr King

    Joined:
    Feb 6, 2010
    Messages:
    715
    I think the default DLL in the installer is actually the non-assert release DLL (contrary to what you wrote in the MagisterModMod thread). Did you really test the assert DLL? The release DLL should run somewhat faster than the assert DLL.
     
  15. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,102
    Location:
    Kael's head
    I am pretty sure the default dll in the installer is the assert DLL, both because it is larger than the one I remaned CvGameCoreDLL_normal.dll and because when I just added the Sawol Cavea equipment in worldbuilder I still got these asserts:
    Spoiler :
    Code:
    Assert Failed
    
    File:  CvUnitAI.cpp
    Line:  61
    Expression:  AI_getUnitAIType() != NO_UNITAI
    Message:  AI_getUnitAIType() is not expected to be equal with NO_UNITAI
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvArea.cpp
    Line:  861
    Expression:  eIndex2 >= 0
    Message:  eIndex2 is expected to be >= 0
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvArea.cpp
    Line:  851
    Expression:  eIndex2 >= 0
    Message:  eIndex2 is expected to be >= 0
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvArea.cpp
    Line:  864
    Expression:  getNumAIUnits(eIndex1, eIndex2) >= 0
    Message:
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17653
    Expression:  eIndex >= 0
    Message:  eIndex is expected to be non-negative (invalid Index)
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17645
    Expression:  eIndex >= 0
    Message:  eIndex is expected to be non-negative (invalid Index)
    
    ----------------------------------------------------------
    Assert Failed
    
    File:  CvPlayerAI.cpp
    Line:  17656
    Expression:  AI_getNumAIUnits(eIndex) >= 0
    Message:
    
    ----------------------------------------------------------
    

    I thought I remembered getting those asserts whenever any piece of equipment was created, but the first several items that I just tried adding did not give me any asserts. I think it may only be those with <DefaultUnitAI/> instead of <DefaultUnitAI>UNITAI_UNKNOWN</DefaultUnitAI>

    edit: I just replaced every instance of <DefaultUnitAI/> with <DefaultUnitAI>UNITAI_UNKNOWN</DefaultUnitAI> and then tried adding every unit listed under Items in worldbuilder. None give me any asserts anymore.

    Now that I think of it I don't believe I ran any test games using the release DLL, as I renamed them as soon as I copied them into my modmod at the start of the merging process.
     
    Last edited: Nov 9, 2019
  16. lfgr

    lfgr King

    Joined:
    Feb 6, 2010
    Messages:
    715
    I see, maybe I messed something up when installing. Anyway, good to know it works now. I'll look into the DefaultUnitAI problem.
     
    Tielby likes this.
  17. jackal1234

    jackal1234 Chieftain

    Joined:
    Jul 11, 2010
    Messages:
    96
    Location:
    127.0.0.0
    thanks for the continued updates. giving it a spin now
     

Share This Page