[MOD] MagisterModmod

Yes, I checked and it worked fine (at least first couple of turns).

Maybe there are some path problems? Like non-latin characters in path or something? Just in case, I tested it on steam version.
 
Do you install it on vanilla FFH?
Ah, this may be the issue - I imagine I need a fresh folder? I've found it hard to juggle with MNAI, but will try this.
 
Ah, this may be the issue - I imagine I need a fresh folder? I've found it hard to juggle with MNAI, but will try this.
I haven't tried it myself but i think it's ready-to-play mod. Extract it to the new folder and launch.
 
I haven't tried it myself but i think it's ready-to-play mod. Extract it to the new folder and launch.
This is what I initially tried, and has been crashing. I also tried creating a vanilla FFH2 folder and extracting the contents to it, but no dice.

Zub, I'd be surprised - the mod launches fine, and its in the same folder as my normal FFH2 (or MMM save). It just can't cope with launching a game. I'm not sure what I'm missing?
 
This is what I initially tried, and has been crashing. I also tried creating a vanilla FFH2 folder and extracting the contents to it, but no dice.

Zub, I'd be surprised - the mod launches fine, and its in the same folder as my normal FFH2 (or MMM save). It just can't cope with launching a game. I'm not sure what I'm missing?
Well you've baited me to try myself and i can say that it works fine(as i thought it's really ready-to-play thing) so i'll explain step by step just in case
1 dl the mod
2 extract it to your mods folder
3 DO NOT RENAME downloaded mod's folder (if you have another version installed just rename it before extracting)
4 Launch the mod and enjoy seeing the mod date 4 october 2016

I'm not sure about renaming but i had issues with this before or with other mod i don't remember so that's the steps that i've done and played this mod ver. for 50 turns with no problems at all
 
Well you've baited me to try myself and i can say that it works fine(as i thought it's really ready-to-play thing) so i'll explain step by step just in case
1 dl the mod
2 extract it to your mods folder
3 DO NOT RENAME downloaded mod's folder (if you have another version installed just rename it before extracting)
4 Launch the mod and enjoy seeing the mod date 4 october 2016

I'm not sure about renaming but i had issues with this before or with other mod i don't remember so that's the steps that i've done and played this mod ver. for 50 turns with no problems at all
I've tested some more and I can get the game to work, but seemingly only if I play a map without ocean(???). So Rainforest launches okay, but Pangaea crashes before the first turn.
 
Is this mod still being worked on @MagisterCultuum?
What is the state of the mod these?
I would love play this mod, since I think it is the best of the FFH2 modmods, but last time I played I had stop my rather long running game because I hit end of turn crash that I could not "fix".
Also how are the end of turn times?
 
Hello! Yesterday I posted a selection of religious music for a fashion mod from Magister. Please download, evaluate and suggest what music to add and what to remove. Have a good game)


This pack adds for each (almost) new religion in MagisterModMod.

Below are the current state of religions and links to playlists where you can listen to music that you like separately.

To install, copy the folder from the archive to the "Mods" folder with the merge confirmation

1. Brotherhood of Wardens - https://www.youtube.com/playlist?list=PLKGQ_InTqoDDae7TuNI_6EnSzrETQNnWU/

2. Ringgiver - https://www.youtube.com/playlist?list=PLKGQ_InTqoDBfYe-CPYYCkReYE1m-cle1

3. Unblemished - https://www.youtube.com/playlist?list=PLKGQ_InTqoDAshZHHS3ppI8lemU3WY47g

4. House of Plenty - https://www.youtube.com/playlist?list=PLKGQ_InTqoDBshZDCtBE4KaTxXoU7TBly

5. Eternal Cabal - https://www.youtube.com/playlist?list=PLKGQ_InTqoDAJexzdGHgWCvq7_h1IYBob

6. Laeran Cord - https://www.youtube.com/playlist?list=PLKGQ_InTqoDAWT3OZOd6KRSAD65hgLUw0

7. Foxman - https://www.youtube.com/playlist?list=PLKGQ_InTqoDC_1oRIVFVeLUbbZeQcv-Oi

8. White Hand - https://www.youtube.com/playlist?list=PLKGQ_InTqoDDfvjp2GcopTA_JYAr5NOh-

9. Stewards of Inequity - https://www.youtube.com/playlist?list=PLKGQ_InTqoDDt5HrF-e6To_OX5JtxVRJG

10. Sons of Discord - https://www.youtube.com/playlist?list=PLKGQ_InTqoDAVcqqKaD4fqyi7gO4iNI3X

11. Anointed - https://www.youtube.com/playlist?list=PLKGQ_InTqoDCmR6dJeZYY_CGz5BNFAy1p

12. Ember Legion - https://www.youtube.com/playlist?list=PLKGQ_InTqoDAhU0byjLtHcS5bW7zpo7Ki

13. Coven - https://www.youtube.com/playlist?list=PLKGQ_InTqoDDZdRkN4AB-7qptiBbpMO0X

14. Empyrean(There is nothing new, but you can add your own music and I will add it later) - https://www.youtube.com/playlist?list=PLKGQ_InTqoDAAczv-mjN5NYAoDJ2wdmTA

15. Order (There are some new tracks, but not enough to add in pack) - https://www.youtube.com/playlist?list=PLKGQ_InTqoDAg7uDXlGjT69ZQ6H31xeAx

16. Fellowship of Leaves (There are some new tracks, but not enough to add in pack) - https://www.youtube.com/playlist?list=PLKGQ_InTqoDASq0UbgspVtrSOvxbPwexx

17. Matronae (There are some new tracks, but not enough to add in pack) - https://www.youtube.com/playlist?list=PLKGQ_InTqoDDfK3BrDxRBnEVkRfd9KVfG

18. Children of the One (I could not understand the main theme of this religion, I would be VERY grateful if you send musical compositions that you think are suitable for it.) - https://www.youtube.com/playlist?list=PLKGQ_InTqoDCqRCVTxFHTX3OXIs2MABBl

19. Cult of the Dragon (I could not understand the main theme of this religion, I would be VERY grateful if you send musical compositions that you think are suitable for it.) -https://www.youtube.com/watch?v=TKzLHshYGxU&list=PLKGQ_InTqoDBEnIvuYZLWAi2-yq4efNjR&index=1

20. Grey Council - (There are some new tracks, but not enough to add in pack) - https://www.youtube.com/playlist?list=PLKGQ_InTqoDCYOHTFOPGpDKKYGu_bKqZQ

21. Octopus Overlords (There is nothing new, but you can add your own music and I will add it later) - https://www.youtube.com/playlist?list=PLKGQ_InTqoDBbPg0bC_YN8UStHVBrmYBb

22. Council of Esus (There are some new tracks, but not enough to add in pack) - https://www.youtube.com/playlist?list=PLKGQ_InTqoDBDxF1uyMp6Lo4qpkO9K_J9

23. Ashen Veil (There are some new tracks, but not enough to add in pack) - https://www.youtube.com/playlist?list=PLKGQ_InTqoDB1WO3KbAyiKWSqEdnsgmJ_

24. Runes of Kilmorph (There is nothing new, but you can add your own music and I will add it later) - https://www.youtube.com/playlist?list=PLKGQ_InTqoDDTb3sFoffFDfQGJmh0R47V



P.s. As you have already read, some religions do not have the proper amount of music to add to the pack. I would be very grateful if you help with the expansion of this music pack.
 
So is there a way to fix the AI not expanding? I see after I have come back from however long it's been some AI stick with one city for like the longest time.
 
Dear Magister,

Thanks for your excellent modmod! With all this new lore implemented, it's like an old dream coming true.

I'm writing to propose the solutions to a couple of game-breaking bugs I encountered.

1. When playing as Order or Death Cabal, the game locks up whenever the player researches Fanaticism.

I tracked this problem down to the potential infinite loops present in lines 13066 to 13139 in CvSpellInterface.py:

Python:
def reqDivineRetribution(pCaster, eSpell=-1):
    if not pCaster.isHuman():
        iTeam = pCaster.getTeam()
        eTeam = gc.getTeam(iTeam)
        if eTeam.getAtWarCount(True) < 2:
            return False

    iDemon = gc.getInfoTypeForString('PROMOTION_DEMON')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if loopUnit.isImmuneToSpell(pCaster, eSpell):continue
                    iRace = loopUnit.getRace()
                    if iRace  == iDemon:
                        return True
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

    return False

def spellDivineRetribution(pCaster, eSpell=-1):
    iDemon = gc.getInfoTypeForString('PROMOTION_DEMON')
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if loopUnit.isImmuneToSpell(pCaster, eSpell):continue
                    iRace = loopUnit.getRace()
                    if iRace  == iDemon:
                        loopUnit.doDamage(70, 100, pCaster, iHoly, False)
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

def reqRequiem(pCaster, eSpell=-1):
    if not pCaster.isHuman():
        iTeam = pCaster.getTeam()
        eTeam = gc.getTeam(iTeam)
        if eTeam.getAtWarCount(True) < 2:
            return False
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if loopUnit.isImmuneToSpell(pCaster, eSpell):continue
                    iRace = loopUnit.getRace()
                    if iRace  == iUndead:
                        return True
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)
    return False

def spellRequiem(pCaster, eSpell=-1):
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if loopUnit.isImmuneToSpell(pCaster, eSpell):continue
                    iRace = loopUnit.getRace()
                    if iRace == iUndead:
                        loopUnit.doDamage(70, 100, pCaster, iHoly, False)
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

Here, if the unit is immune to the world spell, then the loop counter will not move and the loop will get stuck. I fixed the bug by replacing with the following code:

Python:
def reqDivineRetribution(pCaster, eSpell=-1):
    if not pCaster.isHuman():
        iTeam = pCaster.getTeam()
        eTeam = gc.getTeam(iTeam)
        if eTeam.getAtWarCount(True) < 2:
            return False

    iDemon = gc.getInfoTypeForString('PROMOTION_DEMON')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        CvUtil.pyPrint("reqDivineRetribution")
        CvUtil.pyPrint(str(iPlayer))      
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if not loopUnit.isImmuneToSpell(pCaster, eSpell):
                        iRace = loopUnit.getRace()
                        if iRace  == iDemon:
                            return True
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

    return False

def spellDivineRetribution(pCaster, eSpell=-1):
    iDemon = gc.getInfoTypeForString('PROMOTION_DEMON')
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if not loopUnit.isImmuneToSpell(pCaster, eSpell):
                        iRace = loopUnit.getRace()
                        if iRace  == iDemon:
                            loopUnit.doDamage(70, 100, pCaster, iHoly, False)
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

def reqRequiem(pCaster, eSpell=-1):
    if not pCaster.isHuman():
        iTeam = pCaster.getTeam()
        eTeam = gc.getTeam(iTeam)
        if eTeam.getAtWarCount(True) < 2:
            return False
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if not loopUnit.isImmuneToSpell(pCaster, eSpell):
                        iRace = loopUnit.getRace()
                        if iRace  == iUndead:
                            return True
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)
    return False

def spellRequiem(pCaster, eSpell=-1):
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if not loopUnit.isImmuneToSpell(pCaster, eSpell):
                        iRace = loopUnit.getRace()
                        if iRace == iUndead:
                            loopUnit.doDamage(70, 100, pCaster, iHoly, False)
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

2. The Lord of the Balors scenario won't load (I lose immediately on startup). I tracked the problem down to the following (unique) code chunk in "Lord of the Balors.CivBeyondSwordWBSave":


Code:
    BeginUnit
        UnitType=UNIT_BHALL_ORC, UnitOwner=50
        Damage=0
        Level=1, Experience=0
        PromotionType=PROMOTION_ZEAL
        PromotionType=PROMOTION_LAIR_GUARDIAN
        FacingDirection=4
        UnitAIType=UNITAI_RESERVE
    EndUnit

After removing this block, the scenario loaded just fine. The turns, however, feel extremely slow -- maybe there is a potential to speed them up?
 
Last edited:
@MagisterCultuum: In Beneath the Heel scenario, it seems that currently there is no way to hire units. The code that brings up the popup message is removed.


Here's my makeshift fix: replace the implementation of doTurnBeneathTheHeel in ScenarioFunctions.py by

Python:
    def doTurnBeneathTheHeel(self):
        iPlayer = 0
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.getGold() >= 80:
            pCity = pPlayer.getCapitalCity()
            iEvent = CvUtil.findInfoTypeNum(gc.getEventTriggerInfo, gc.getNumEventTriggerInfos(),'EVENTTRIGGER_RECRUIT_MERCENARY')
            triggerData = pPlayer.initTriggeredData(iEvent, true, -1, pCity.getX(), pCity.getY(), iPlayer, pCity.getID(), -1, -1, -1, -1)
        eTeam = gc.getTeam(3) #Calabim
        iTeam2 = 0 #Hippus
        if eTeam.isAlive():
            if eTeam.AI_getAtPeaceCounter(iTeam2) > 50:
                if eTeam.isHasMet(iTeam2):
                    if eTeam.getAtWarCount(True) == 0:
                        eTeam.declareWar(iTeam2, False, WarPlanTypes.WARPLAN_TOTAL)
        pCity = gc.getPlayer(1).getCapitalCity() #Illians
        pPlot = pCity.plot()
        bWin = False
        iBarnaxus = gc.getInfoTypeForString('EQUIPMENT_PIECES_OF_BARNAXUS')
        iPromBarnaxus = gc.getInfoTypeForString('PROMOTION_PIECES_OF_BARNAXUS')
        for i in xrange(pPlot.getNumUnits()):
            pUnit = pPlot.getUnit(i)
            if pUnit.getUnitType() == iBarnaxus:
                bWin = True
            if pUnit.isHasPromotion(iPromBarnaxus):
                bWin = True
        if bWin:
            gc.getGame().setWinner(pPlayer.getTeam(), 2)

Now since the mercenary hiring costs are doubled compared to vanilla FfH2, the scenario feels much more difficult. Perhaps the balance could be tipped a bit by giving Tasunke another unit? A beefed-up Horse Archer or a nerfed Magnadine. Maybe also Currency.
 
Last edited:
Also The Cult scenario won't start---apparently because BUILDING_WYRMHOLD_ACHERON was replaced by BUILDING_WYRMHOLD.
Here's the offending block in The Cult.CivBeyondSwordWBSave
Code:
    BeginCity
        CityOwner=50
        CityPopulation=3
        Player50Culture=300
        BuildingType=BUILDING_WYRMHOLD_ACHERON
        ReligionType=RELIGION_CULT_OF_THE_DRAGON
        HolyCityReligionType=RELIGION_CULT_OF_THE_DRAGON
    EndCity

Changing BuildingType=BUILDING_WYRMHOLD_ACHERON to BUILDING_WYRMHOLD fixes the problem.
 
Lately I have been too busy with work, with some family issues, and having a lot of computer trouble, but today I did my first modding in months.

(After replacing my old laptop's battery, the screen started flickering for a week and then failed completely. I was able to connect it to a TV via HDMI but the resolution didn't seem as good and my neck hurt from turning to look at the TV instead of straight ahead at the laptop when laying in bed like I was used to doing most of the time. The keyboard randomly became completely unresponsive some days but worked fine on others. The charger hadn't been great at maintaining a connection, but got worse last week. Even when plugged in all the time, if the computer was on it would discharge faster than it charged. I had to turn the device off for several hours to be able to use it for half that long.)

Thursday I went ahead and bought myself a new laptop, a 16 inch Levovo Yogi 7i which was on sale $400 off the normal price and has better stats than anything I could find for under $1k. With a 12th generation Intel Evo Platform Core i7-1260P, 16GB LPDDR5, and 512GB SSD, it greatly outperforms my old device. The battery life is nowhere near the 15 hours the manufacturer claims, but still better than my previous laptops.

I got an external harddrive enclosure for my old laptop's 2tb harddrive and have transferred the important files and set up the important programs.

I was rather confused at first when I tried to get back to modding because Windows 11 saves everything in different locations. It put the mods within the user's AppData and the saves, logs etc on OneDrive. I suspect this will cause problems for the installer. I may need to only release an archive version for my next release.


Dear Magister,

Thanks for your excellent modmod! With all this new lore implemented, it's like an old dream coming true.

I'm writing to propose the solutions to a couple of game-breaking bugs I encountered.

1. When playing as Order or Death Cabal, the game locks up whenever the player researches Fanaticism.

I tracked this problem down to the potential infinite loops present in lines 13066 to 13139 in CvSpellInterface.py:

Python:
def reqDivineRetribution(pCaster, eSpell=-1):
    if not pCaster.isHuman():
        iTeam = pCaster.getTeam()
        eTeam = gc.getTeam(iTeam)
        if eTeam.getAtWarCount(True) < 2:
            return False

    iDemon = gc.getInfoTypeForString('PROMOTION_DEMON')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if loopUnit.isImmuneToSpell(pCaster, eSpell):continue
                    iRace = loopUnit.getRace()
                    if iRace  == iDemon:
                        return True
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

    return False

def spellDivineRetribution(pCaster, eSpell=-1):
    iDemon = gc.getInfoTypeForString('PROMOTION_DEMON')
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if loopUnit.isImmuneToSpell(pCaster, eSpell):continue
                    iRace = loopUnit.getRace()
                    if iRace  == iDemon:
                        loopUnit.doDamage(70, 100, pCaster, iHoly, False)
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

def reqRequiem(pCaster, eSpell=-1):
    if not pCaster.isHuman():
        iTeam = pCaster.getTeam()
        eTeam = gc.getTeam(iTeam)
        if eTeam.getAtWarCount(True) < 2:
            return False
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if loopUnit.isImmuneToSpell(pCaster, eSpell):continue
                    iRace = loopUnit.getRace()
                    if iRace  == iUndead:
                        return True
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)
    return False

def spellRequiem(pCaster, eSpell=-1):
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if loopUnit.isImmuneToSpell(pCaster, eSpell):continue
                    iRace = loopUnit.getRace()
                    if iRace == iUndead:
                        loopUnit.doDamage(70, 100, pCaster, iHoly, False)
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

Here, if the unit is immune to the world spell, then the loop counter will not move and the loop will get stuck. I fixed the bug by replacing with the following code:

Python:
def reqDivineRetribution(pCaster, eSpell=-1):
    if not pCaster.isHuman():
        iTeam = pCaster.getTeam()
        eTeam = gc.getTeam(iTeam)
        if eTeam.getAtWarCount(True) < 2:
            return False

    iDemon = gc.getInfoTypeForString('PROMOTION_DEMON')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        CvUtil.pyPrint("reqDivineRetribution")
        CvUtil.pyPrint(str(iPlayer))     
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if not loopUnit.isImmuneToSpell(pCaster, eSpell):
                        iRace = loopUnit.getRace()
                        if iRace  == iDemon:
                            return True
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

    return False

def spellDivineRetribution(pCaster, eSpell=-1):
    iDemon = gc.getInfoTypeForString('PROMOTION_DEMON')
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if not loopUnit.isImmuneToSpell(pCaster, eSpell):
                        iRace = loopUnit.getRace()
                        if iRace  == iDemon:
                            loopUnit.doDamage(70, 100, pCaster, iHoly, False)
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

def reqRequiem(pCaster, eSpell=-1):
    if not pCaster.isHuman():
        iTeam = pCaster.getTeam()
        eTeam = gc.getTeam(iTeam)
        if eTeam.getAtWarCount(True) < 2:
            return False
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if not loopUnit.isImmuneToSpell(pCaster, eSpell):
                        iRace = loopUnit.getRace()
                        if iRace  == iUndead:
                            return True
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)
    return False

def spellRequiem(pCaster, eSpell=-1):
    iUndead = gc.getInfoTypeForString('PROMOTION_UNDEAD')
    iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
    for iPlayer in xrange(gc.getMAX_PLAYERS()):
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.isAlive():
            (loopUnit, iter) = pPlayer.firstUnit(False)
            while(loopUnit):
                if not loopUnit.isDead(): #is the unit alive and valid?
                    if not loopUnit.isImmuneToSpell(pCaster, eSpell):
                        iRace = loopUnit.getRace()
                        if iRace == iUndead:
                            loopUnit.doDamage(70, 100, pCaster, iHoly, False)
                (loopUnit, iter) = pPlayer.nextUnit(iter, False)

2. The Lord of the Balors scenario won't load (I lose immediately on startup). I tracked the problem down to the following (unique) code chunk in "Lord of the Balors.CivBeyondSwordWBSave":


Code:
    BeginUnit
        UnitType=UNIT_BHALL_ORC, UnitOwner=50
        Damage=0
        Level=1, Experience=0
        PromotionType=PROMOTION_ZEAL
        PromotionType=PROMOTION_LAIR_GUARDIAN
        FacingDirection=4
        UnitAIType=UNITAI_RESERVE
    EndUnit

After removing this block, the scenario loaded just fine. The turns, however, feel extremely slow -- maybe there is a potential to speed them up?

Also The Cult scenario won't start---apparently because BUILDING_WYRMHOLD_ACHERON was replaced by BUILDING_WYRMHOLD.
Here's the offending block in The Cult.CivBeyondSwordWBSave
Code:
    BeginCity
        CityOwner=50
        CityPopulation=3
        Player50Culture=300
        BuildingType=BUILDING_WYRMHOLD_ACHERON
        ReligionType=RELIGION_CULT_OF_THE_DRAGON
        HolyCityReligionType=RELIGION_CULT_OF_THE_DRAGON
    EndCity

Changing BuildingType=BUILDING_WYRMHOLD_ACHERON to BUILDING_WYRMHOLD fixes the problem.

@MagisterCultuum: In Beneath the Heel scenario, it seems that currently there is no way to hire units. The code that brings up the popup message is removed.


Here's my makeshift fix: replace the implementation of doTurnBeneathTheHeel in ScenarioFunctions.py by

Python:
    def doTurnBeneathTheHeel(self):
        iPlayer = 0
        pPlayer = gc.getPlayer(iPlayer)
        if pPlayer.getGold() >= 80:
            pCity = pPlayer.getCapitalCity()
            iEvent = CvUtil.findInfoTypeNum(gc.getEventTriggerInfo, gc.getNumEventTriggerInfos(),'EVENTTRIGGER_RECRUIT_MERCENARY')
            triggerData = pPlayer.initTriggeredData(iEvent, true, -1, pCity.getX(), pCity.getY(), iPlayer, pCity.getID(), -1, -1, -1, -1)
        eTeam = gc.getTeam(3) #Calabim
        iTeam2 = 0 #Hippus
        if eTeam.isAlive():
            if eTeam.AI_getAtPeaceCounter(iTeam2) > 50:
                if eTeam.isHasMet(iTeam2):
                    if eTeam.getAtWarCount(True) == 0:
                        eTeam.declareWar(iTeam2, False, WarPlanTypes.WARPLAN_TOTAL)
        pCity = gc.getPlayer(1).getCapitalCity() #Illians
        pPlot = pCity.plot()
        bWin = False
        iBarnaxus = gc.getInfoTypeForString('EQUIPMENT_PIECES_OF_BARNAXUS')
        iPromBarnaxus = gc.getInfoTypeForString('PROMOTION_PIECES_OF_BARNAXUS')
        for i in xrange(pPlot.getNumUnits()):
            pUnit = pPlot.getUnit(i)
            if pUnit.getUnitType() == iBarnaxus:
                bWin = True
            if pUnit.isHasPromotion(iPromBarnaxus):
                bWin = True
        if bWin:
            gc.getGame().setWinner(pPlayer.getTeam(), 2)

Now since the mercenary hiring costs are doubled compared to vanilla FfH2, the scenario feels much more difficult. Perhaps the balance could be tipped a bit by giving Tasunke another unit? A beefed-up Horse Archer or a nerfed Magnadine. Maybe also Currency.

I just implemented the suggested code changes and am about to test them.

I'm thinking the most appropriate extra unit to give Tasunkamay be a Condottiero, the mounted mercenary who can recruit more mercenaries and serves as a religious champion for the Stewards of Inequity. of course, since that unit currently has the bAbandon tag, it would necessitate giving Tasunke Stewards of Inequity as his state religion, but that seems canonically appropriate anyway.


I still plan to make more extensive changes to the scenarios but want to get some other things settled first. When last I was modding months ago I was focused on some improvements to the Foxmen religion which I hadn't fully tested yet. I added a temple called the Trailhead, a disciple called the Vagrant that upgrades to a priest called the Drifter, which can use the airdrop ability. (unfortunately the game only allows airdrops from within cities or superforts, when it would fit the theme better to let them use such abilities far from civilization.) I based its art on the paratrooper because I liked the parachute animation and have not been able to get that to work with any other models. I was playing around with letting players of the Foxmen religion train Adventurers (as national units) directly instead of a normal religious hero or the previous special promotion, but the python code to check for other upgraded adventurers to prevent them from building too many was too inefficient.
 
Greetings Magister! Congratulations on buying a new laptop and getting back into modding after a short break! During your absence, I have had a desire to add musical accompaniment / discovery / distribution to your modification for almost every new religion relative to the original FFH II. Can you personally evaluate this collection? For convenience, each of the religions was folded into a separate playlist for it on YouTube. The most easily unlocked religions of the new ones are ready (Children of the One, Matrons, Dragon Cult have not yet been made), and there is a small list for expanding old religions. If you like everything, then I could suggest that you build my music set into your modification on a permanent basis. Or, as an option, leave it as before with distribution as a separate pack, but with your evaluative view. You could also offer your own musical compositions, which I will gladly add. https://www.moddb.com/games/civiliz...ligions-in-magistermodmodjune-6-2022-changes#
 
Great to hear that you have a chance to get back to modding now, Magister! Hope my suggestions could be helpful.

Couple comments about The Radiant Guard scenario:

1. We start with a Wind Knight (called 'Nikis'), on the first turn. But since we're not Foxmen, this Wind Knight leaves us immediately on the first term. Also, a regular Knight called Nikis joins us after we take Bastradam. Is this intended behavior?

2. The scenario now feels much more difficult compared to the original version. Balors, Beasts of Agares, and Iras start showing up almost immediately. I recall that in the original version we had a bit weaker enemies going in the first waves, with Beasts of Agares appearing a bit later.
 
Can I request that Badb and the Wandering Castle be toned down and/or be reworked somewhat? I just had two runs ended 50-ish turns in (epic speed) because they showed up and there's literally nothing that I can do to stop them from murdering every single one of my units w/ their passive cold aura and leave my capital undefended to whatever Goblin wanders by. Its *very* frustrating and I'm now resorting to removing it w/ the world-editor. With stuff like Orthus appearing nearby its possible to survive with a strong enough defense, but there doesn't seem to be anything you can do about the death castle casually wiping out every one of your units.
 
Greetings Magister! Congratulations on buying a new laptop and getting back into modding after a short break! During your absence, I have had a desire to add musical accompaniment / discovery / distribution to your modification for almost every new religion relative to the original FFH II. Can you personally evaluate this collection? For convenience, each of the religions was folded into a separate playlist for it on YouTube. The most easily unlocked religions of the new ones are ready (Children of the One, Matrons, Dragon Cult have not yet been made), and there is a small list for expanding old religions. If you like everything, then I could suggest that you build my music set into your modification on a permanent basis. Or, as an option, leave it as before with distribution as a separate pack, but with your evaluative view. You could also offer your own musical compositions, which I will gladly add. https://www.moddb.com/games/civiliz...ligions-in-magistermodmodjune-6-2022-changes#

I listened to a few of them. The songs seem fine on their own but for most I couldn't figure out what connection they had to a particular faith. I normally play with the game muted while listening to YouTube or something, so including more music is not a high priority for me. Are these songs in the public domain? I don't philosophically agree with copyright, and have used some art for buttons and popups that might technically violate it, but I think the risks of getting in legal trouble may be higher for including popular music. I find it particularly hard to justify making the download almost 10x larger just to include the music.
Great to hear that you have a chance to get back to modding now, Magister! Hope my suggestions could be helpful.

Couple comments about The Radiant Guard scenario:

1. We start with a Wind Knight (called 'Nikis'), on the first turn. But since we're not Foxmen, this Wind Knight leaves us immediately on the first term. Also, a regular Knight called Nikis joins us after we take Bastradam. Is this intended behavior?

2. The scenario now feels much more difficult compared to the original version. Balors, Beasts of Agares, and Iras start showing up almost immediately. I recall that in the original version we had a bit weaker enemies going in the first waves, with Beasts of Agares appearing a bit later.
The name "Nikis" is given to the first knight to appear, as an easter egg for the Civ FanaticsForum member NikisKnight who used to be active here as was on the FfH2 design team. It has nothing to do with the scenario per se, it was just automatically given when I first added a knight or wind knight back when Wind knights were a Hippus version of the Knight. I just changed that unit back to a Knight, with the Horselord promotion.

Looking through the scenario file, there is only one Beast of Agares. The problem is that I made the unit type not only stronger but considerably faster, so it is running towards the Mercurian city much faster. I decided to move it back to the Infernal capital and give it the Bound By the Compact promotion so it cannot leave hell terrain.

I also gave the player a few more units, including Paladins.


Can I request that Badb and the Wandering Castle be toned down and/or be reworked somewhat? I just had two runs ended 50-ish turns in (epic speed) because they showed up and there's literally nothing that I can do to stop them from murdering every single one of my units w/ their passive cold aura and leave my capital undefended to whatever Goblin wanders by. Its *very* frustrating and I'm now resorting to removing it w/ the world-editor. With stuff like Orthus appearing nearby its possible to survive with a strong enough defense, but there doesn't seem to be anything you can do about the death castle casually wiping out every one of your units.

Yeah, I definitely agree it needs to be toned down. I thought I had already made it so that the improvement will not spawn Babd directly, but he may be added through python in much the same way as Orthus only later. I was wondering why he still showed up so soon. This morning I checked and found I'd forgotten to edit CIV4ImprovementInfos.xml to stop him from spawning the normal way. I did so, and also changed the term on which he can spawn in Python from turn 200 to 500 (both adjusted to game speed).


I also decided to give him a small chance of spawning from exploring the Wandering Castle if he had not spawned any other way yet. The exploring unit would have to be at least level 6 before it even becomes possible though. I also changed it so that exploring the Wandering castle has about a 50% chance of making the castle move, with the explorer sometimes moving with it.

I also made it so that entering the Wandering Castle's tile gives a unit the Slow promotion.

In the process I found some code in the onMoveBadbsBlizzard that I moved to onMoveBlizzard, as I am pretty sure I had originally intended it so go there instead. It generates Hollow Men defenders in White Hand lands in much the same way that Ancient Forests generate Treants in Fellowship of the Leaves lands.
 
Last edited:
Back
Top Bottom