[MOD] MagisterModmod

So, the files exist where they're supposed to, I can see them. I copied FFH w/the O patch into a folder called "Magister Modmod for FfH2", then copied the zip over it, and overwrote the files. For some reason, it's not loading them, even though they exist.
Did you change launch options to be renamed the same as the folder/.lnk file? It might be bugging out and trying to launch base FFH instead, though i admit i don't know why it these specific xml files would be called out as being missing or wrong.
 
I'm getting the same issue after setting it up on Lutris. What file system are you running it on? My games are on an EXT4 partition, which might cause issues, maybe?
 
I have an EXT4 partition as well, so that shouldn't be the issue. Searching around for related issues all i can find is mention of missing msxml dependencies but that ought be an issue with base FFH & Civ4 as well.
 
iAirCombatLimit for the Ring-Giver Tank is set to to 0 in CIV4UnitInfos, so its ranged attack doesn't do anything.
 
Getting an error for CvSpellInterface.py when making an Artificer on a tile with golems in a Luchuirp game. I looked in there and reqRepair, helpRepair, and spellRepair functions do not define iRetrofit and the variable is not defined globally. However, the function they are missing from is reqRetrofitGolem which doesn't actually use the second optional parameter eSpell (and it is optional anyhow), so just deleting iRetrofit is probably OK in those three functions.

Relevant call in reqRepair, helpRepair, and spellRepair:

Python:
if reqRetrofitGolem(pUnit, iRetrofit):
    return True
 
Getting an error for CvSpellInterface.py when making an Artificer on a tile with golems in a Luchuirp game. I looked in there and reqRepair, helpRepair, and spellRepair functions do not define iRetrofit and the variable is not defined globally. However, the function they are missing from is reqRetrofitGolem which doesn't actually use the second optional parameter eSpell (and it is optional anyhow), so just deleting iRetrofit is probably OK in those three functions.

Relevant call in reqRepair, helpRepair, and spellRepair:

Python:
if reqRetrofitGolem(pUnit, iRetrofit):
    return True
Think that's the one that Magister posted corrected code for here:
 
Think that's the one that Magister posted corrected code for here:
Oh nice! Probably just hasn't been another mod update yet. Yep, that will work, or anything else really as the parameter isn't used in the reqRetrofitGolem function.
 
Last edited:
Rifleman also has iAirCombatLimit set to 0 in CIV4UnitInfos.xml, making their ranged attack not do any damage.
 
I decided to play a little with the neural network. I would call these drawings "The Magister thinks how to make his modmod better"
 

Attachments

  • Leonardo_Diffusion_Stone_dungeon_with_a_window_to_the_night_sk_0.jpg
    Leonardo_Diffusion_Stone_dungeon_with_a_window_to_the_night_sk_0.jpg
    618 KB · Views: 47
  • Leonardo_Diffusion_Stone_dungeon_with_a_window_to_the_night_sk_1.jpg
    Leonardo_Diffusion_Stone_dungeon_with_a_window_to_the_night_sk_1.jpg
    594 KB · Views: 46
So I’ve been playing this mod on and off for the last 10 years. More “off” in the last few years because I’m on a Mac, and was using Wine and some wine skins to run this but they broke somehow after multiple OS upgrades and I never got around to fixing them. But I am happy to say I got it working again on a Mac (M2 chip) using Crossover after making a fresh installation from my 15 or 20 year old Civ IV and then BTS disks. Really exciting! So, a few questions.

1. I’ve been reading the last few pages of comments here and wow is there a ton of additional content in the form of new religions, Arda, miscast chance, and a lot of very complicated middle and late game stuff. But it’s hard to piece together how it all is really supposed to work. eg “hostile” temples. I looked at the Civilopedia but it isn’t really explain there. possible to explain here or update the first page comment to give more of an overview of what is going on?
2. The unit promotion tree is very helpful but it’s still really hard to see what the actual potential unit promotion paths would be for a given unit because it’s so cluttered now. Any way to make this easier? I might take a hack at it, maybe even in some outside tool just parsing the XML files (I’ve tried in Civ IV itself before but the UI elements and coding around them are horrendous, could take days to just understand even what to call, and the online API reference is woefully inadequate.) Just curious if anyone else has experienced this.
3. Similar question about the promotion tree.
4. I built the Sylph Search, but not really sure what to do with the Foxmen at this point. I can’t build their unit until Guilds, which is waaaay down the tech tree. Besides just getting extra happiness for religion what else should I be doing?

Thanks so much again for this awesome modmod.
 
I want to give you some answers:
@1: hostile temples gives your city debuffs (like unhappiness for example) when existing in your cities, insteadf of buffs like normal temples.
@2 & @3: Learned some upgrade-ways by playing, but found no way of structuring the raw promotions-data into something easily understrandable.
@4: Foxmen just spreads around and froom time to time it will change its Holy City. Some units born in Foxmen-Religion cities can get ther "Light" Promotion, which gives +1 move and -30% strengh. Can be quiet usefull on the right units.
 
I think Foxmen, and some other religions too, have a mismatch between when they are founded and when you can benefit from them. Aside from the wonder there's no real benefit to Foxmen until you get to Guilds, unless you're looking for an easy alignment swap (i could imagine Sidar doing this to easily flip to Good or Evil if wanting to get another Eternal Cabal unit). In Magister's post a few pages back, he does mention a planned change expanding their units & buildings.

There are other religions that also have some odd tech behaviour; Anointed requiring you to tech all the way up to Rage before you can reliably found it, but then you have to jump to Alteration for their temple and for the Minotaurs. I haven't been able to seriously use their UU in any game, since by the time you can research Rage and Alteration you probably have access to Longbowmen or Crossbowmen via good research speed. Unblemished have this issue too, where you can get the Druid priests far quicker than their disciples, not to mention Hospitallers - again, they suffer from being a mid-to-late-game unit that requires a tech detour that you can usually only afford if you're already way ahead of your rivals (in which case it would often be more effective to instead beeline for things like Theology, Strength of Will or other game-changing techs.

Regarding Arda, miscasts and temples, in my games i often enjoy building the Aquae Sucellus and spreading the Unblemished, but in particular using their Druids to strategically terraform areas. How will the miscast chance look in the upcoming version? Since the Withour Arda mechanic was added, it often takes a whole squad of Druids to terraform the land around one city since they miscast so often, and i frequently get an issue where the Druid suddenly can't cast anymore once they should be done casting. It seems to me if you spread a non-state religion to all of your cities (especially if you have temples in all of them), the miscast chance should be substantially lowered.
 
I just went ahead and uploaded my latest version.

it will break saves.

I never managed to find the cause of some random crashes, but bugs are less common than in the last version and I figured it would be easier track down with the help of some playtesters who understand how to interpret dump files.
 
Magister, I've noticed that you've said you are/were helping Kael to curate a secret document with details about the setting. If Kael is still actively developing the setting and wanting to keep things secret, does that mean that he's looking at publishing something else in the setting at some point?

Second question: The "no world spells" option seems to be enabled by default. Is that correct, or is it a glitch on my end? If it's meant to be like that, why?
 
Last edited:
I just found my first post-release bug.
Code:
Traceback (most recent call last):
  File "BugEventManager", line 366, in _handleDefaultEvent
  File "CvEventManager", line 1327, in onBeginPlayerTurn
NameError: global name 'iEvil' is not defined

One change I made before the day before uploading was to copy the code which swaps out temples and hostile temples based on factors including alignments to make it run when the Foxmen religion makes one's alignment shift at random. I did not realize that the alignments themselves were not defined there like they were in onPlayerChangeStateReligion from where I copied that code from.

I'd suggest changing this (starting at line 1052 of Mods\Magister Modmod for FfH2\Assets\python\CvEventManager.py)
Code:
            if pPlayer.getStateReligion() == gc.getInfoTypeForString('RELIGION_FOXMEN'):
                if CyGame().getSorenRandNum(7, "Volatile Alignment") < 2:
                    lAlignments = [
                                    # gc.getLeaderHeadInfo(pPlayer.getLeaderType()).getAlignment(),#This does not seem to be exposed to python
                                    pPlayer.getAlignment(),
                                    pPlayer.getAlignment(),
                                    gc.getInfoTypeForString('ALIGNMENT_GOOD'),
                                    gc.getInfoTypeForString('ALIGNMENT_NEUTRAL'),
                                    gc.getInfoTypeForString('ALIGNMENT_NEUTRAL'),
                                    gc.getInfoTypeForString('ALIGNMENT_NEUTRAL'),
                                    gc.getInfoTypeForString('ALIGNMENT_EVIL')
                                    ]
                    iAlignment = lAlignments.pop(CyGame().getSorenRandNum(len(lAlignments), "Tali Fickle Alignment"))
                    if pPlayer.getAlignment() != iAlignment:
                        if pPlayer.isHuman():
                            sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_NEUTRAL", ())
                            if iAlignment ==gc.getInfoTypeForString('ALIGNMENT_GOOD'):
                                sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_GOOD", ())
                            if iAlignment ==gc.getInfoTypeForString('ALIGNMENT_EVIL'):
                                sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_EVIL", ())
                            cf.addPopup(CyTranslator().getText("TXT_KEY_MESSAGE_TALI_ALIGNMENT",(sAlignment,)), 'Art/Interface/Buttons/Religions/Foxmen.dds')
                        pPlayer.setAlignment(iAlignment)
to this
Code:
            if pPlayer.getStateReligion() == gc.getInfoTypeForString('RELIGION_FOXMEN'):
                if CyGame().getSorenRandNum(7, "Volatile Alignment") < 2:
                    iGood  = gc.getInfoTypeForString('ALIGNMENT_GOOD')
                    iNeutral = gc.getInfoTypeForString('ALIGNMENT_NEUTRAL')
                    iEvil = gc.getInfoTypeForString('ALIGNMENT_EVIL')
                    lAlignments = [
                                    # gc.getLeaderHeadInfo(pPlayer.getLeaderType()).getAlignment(),#This does not seem to be exposed to python
                                    pPlayer.getAlignment(),
                                    pPlayer.getAlignment(),
                                    iGood,
                                    iNeutral,
                                    iNeutral,
                                    iNeutral,
                                    iEvil
                                    ]
                    iAlignment = lAlignments.pop(CyGame().getSorenRandNum(len(lAlignments), "Tali Fickle Alignment"))
                    if pPlayer.getAlignment() != iAlignment:
                        if pPlayer.isHuman():
                            sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_NEUTRAL", ())
                            if iAlignment == iGood:
                                sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_GOOD", ())
                            if iAlignment == iEvil:
                                sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_EVIL", ())
                            cf.addPopup(CyTranslator().getText("TXT_KEY_MESSAGE_TALI_ALIGNMENT",(sAlignment,)), 'Art/Interface/Buttons/Religions/Foxmen.dds')
                        pPlayer.setAlignment(iAlignment)
 
I just found my first post-release bug.
Code:
Traceback (most recent call last):
  File "BugEventManager", line 366, in _handleDefaultEvent
  File "CvEventManager", line 1327, in onBeginPlayerTurn
NameError: global name 'iEvil' is not defined

One change I made before the day before uploading was to copy the code which swaps out temples and hostile temples based on factors including alignments to make it run when the Foxmen religion makes one's alignment shift at random. I did not realize that the alignments themselves were not defined there like they were in onPlayerChangeStateReligion from where I copied that code from.

I'd suggest changing this (starting at line 1052 of Mods\Magister Modmod for FfH2\Assets\python\CvEventManager.py)
Code:
            if pPlayer.getStateReligion() == gc.getInfoTypeForString('RELIGION_FOXMEN'):
                if CyGame().getSorenRandNum(7, "Volatile Alignment") < 2:
                    lAlignments = [
                                    # gc.getLeaderHeadInfo(pPlayer.getLeaderType()).getAlignment(),#This does not seem to be exposed to python
                                    pPlayer.getAlignment(),
                                    pPlayer.getAlignment(),
                                    gc.getInfoTypeForString('ALIGNMENT_GOOD'),
                                    gc.getInfoTypeForString('ALIGNMENT_NEUTRAL'),
                                    gc.getInfoTypeForString('ALIGNMENT_NEUTRAL'),
                                    gc.getInfoTypeForString('ALIGNMENT_NEUTRAL'),
                                    gc.getInfoTypeForString('ALIGNMENT_EVIL')
                                    ]
                    iAlignment = lAlignments.pop(CyGame().getSorenRandNum(len(lAlignments), "Tali Fickle Alignment"))
                    if pPlayer.getAlignment() != iAlignment:
                        if pPlayer.isHuman():
                            sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_NEUTRAL", ())
                            if iAlignment ==gc.getInfoTypeForString('ALIGNMENT_GOOD'):
                                sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_GOOD", ())
                            if iAlignment ==gc.getInfoTypeForString('ALIGNMENT_EVIL'):
                                sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_EVIL", ())
                            cf.addPopup(CyTranslator().getText("TXT_KEY_MESSAGE_TALI_ALIGNMENT",(sAlignment,)), 'Art/Interface/Buttons/Religions/Foxmen.dds')
                        pPlayer.setAlignment(iAlignment)
to this
Code:
            if pPlayer.getStateReligion() == gc.getInfoTypeForString('RELIGION_FOXMEN'):
                if CyGame().getSorenRandNum(7, "Volatile Alignment") < 2:
                    iGood  = gc.getInfoTypeForString('ALIGNMENT_GOOD')
                    iNeutral = gc.getInfoTypeForString('ALIGNMENT_NEUTRAL')
                    iEvil = gc.getInfoTypeForString('ALIGNMENT_EVIL')
                    lAlignments = [
                                    # gc.getLeaderHeadInfo(pPlayer.getLeaderType()).getAlignment(),#This does not seem to be exposed to python
                                    pPlayer.getAlignment(),
                                    pPlayer.getAlignment(),
                                    iGood,
                                    iNeutral,
                                    iNeutral,
                                    iNeutral,
                                    iEvil
                                    ]
                    iAlignment = lAlignments.pop(CyGame().getSorenRandNum(len/(lAlignments), "Tali Fickle Alignment"))
                    if pPlayer.getAlignment() != iAlignment:
                        if pPlayer.isHuman():
                            sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_NEUTRAL", ())
                            if iAlignment == iGood:
                                sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_GOOD", ())
                            if iAlignment == iEvil:
                                sAlignment = CyTranslator().getText("TXT_KEY_ALIGNMENT_EVIL", ())
                            cf.addPopup(CyTranslator().getText("TXT_KEY_MESSAGE_TALI_ALIGNMENT",(sAlignment,)), 'Art/Interface/Buttons/Religions/Foxmen.dds')
                        pPlayer.setAlignment(iAlignment)
There seems to be a glitch in that new code or something. When I make the change, everything breaks - my UI totally vanishes, I can't open the options menu from the main menu of the game, and probably other stuff too. Maybe there's a typo in the code, or saving it using Notepad++ doesn't work?
 
There seems to be a glitch in that new code or something. When I make the change, everything breaks - my UI totally vanishes, I can't open the options menu from the main menu of the game, and probably other stuff too. Maybe there's a typo in the code, or saving it using Notepad++ doesn't work?
I saved it with Notepad++ and it works fine for me. I'm guessing that when you copied and pasted it that you messed up the indentation. Python is very particular about how many tabs each line has, but when copying and pasting things it is easy to end up with extra tabs on the first line.
 
Back
Top Bottom