How popular is this mod in 2019?

FFH2 not much popular anymore... but still super great and still a few hundred people worldwide playing a game now and then... and liking it enough to check the forums now and then.

A good check would be to see how many view you'll get in a few months... (but as I posted, the 72 people that have already looked at your thread might re-check to see the content of the new post to the thread).

as a counter-test I posted in february a couple photos of lego that I had to make for my kids that wanted some FFH2 legos.
I don't expect that people went to see it more than once or twice... (it's not great lego construction... even I didn't go to see it more than twice) and it still went up 1100 view in 8 months.
So my estimate is between 300-500 people navigating the forums.

but it could be 100 or 2000 ... what do you think ?
(for civ4 as a whole, it might be orders of magnitude greater... but FFH2 really is 1.5-2 generations of civ in advance)
 
Well, I see at the download page that every day about 15 people install it. So, it's not dead, at least
 
My friend and I love FFH, we regularly try to play sit down for a session of 4 or more hours at least twice a week. We've experimented with many of the modmods abound and are currently enjoying MagisterModmod. Seems like we can never escape from OOS errors however at random points in our games.
 
I don't wan't to start a new thread but, can someone tell me, how could I make a world spell in which all evil aligned units suffer about 35-50% holy damage
 
In the future, please do start a new thread for unrelated questions like this.
As for your question, you'll need both XML in python code. Do you know both of these? You can look at entries with <bGlobal>1</bGlobal> in Units/CIV4SpellInfos.xml for world spell templates. The python code goes to entrypoints/CvSpellInterface.py.
 
Did xml, tried python but got bad.
What's wrong with this one:
Code:
def spellDivineRetribution1(caster):
    for iPlayer in range(gc.getMAX_PLAYERS()):
        player = gc.getPlayer(iPlayer)
        if player.isAlive():
            if player.getAlignment() == gc.getInfoTypeForString('ALIGNMENT_GOOD'):
                py = PyPlayer(iPlayer)
                for pUnit in py.getUnitList():
                    if (pUnit.getRace() == iDemon or pUnit.getRace() == iUndead):
                        pUnit.doDamage(50, 100, caster, gc.getInfoTypeForString('DAMAGE_HOLY'), false)
 
Did xml, tried python but got bad.
What's wrong with this one:
Code:
def spellDivineRetribution1(caster):
    for iPlayer in range(gc.getMAX_PLAYERS()):
        player = gc.getPlayer(iPlayer)
        if player.isAlive():
            if player.getAlignment() == gc.getInfoTypeForString('ALIGNMENT_GOOD'):
                py = PyPlayer(iPlayer)
                for pUnit in py.getUnitList():
                    if (pUnit.getRace() == iDemon or pUnit.getRace() == iUndead):
                        pUnit.doDamage(50, 100, caster, gc.getInfoTypeForString('DAMAGE_HOLY'), false)
It does not appear that you have defined iDemon or iUndead anywhere in this function. Those are not globals defined for the whole file, so they need to be declared within this definition or you will get errors..

You could replace iUndead with gc.getInfoTypeForString('PROMOTION_UNDEAD') and iDemon with gc.getInfoTypeForString('PROMOTION_DEMON') in place, but it wastes some resources to keep looking up those values for each and every unit so it is better to do so once at the top. (Similarly, defining holy over again every time it deals damage is a bit wasteful.)

Personally I would prefer to put them in a list and then check each unit's race once and see if that is in the list rather than check it twice and compare it with both promotions.

I also like to be more consistent and always use pCaster instead of caster, pPlayer instead of Player, and always use True/False instead or true/false (that does not matter for the CivIV game engine but they need to be capitalized for PyScritper to recognize them as booleans instead of variables when I use it to debug files).

This code should work to damage all Demons or Undead units owned by Good players, if that is what you wanted.
Code:
def spellDivineRetribution1(pCaster):
   iHoly = gc.getInfoTypeForString('DAMAGE_HOLY')
   lTargetRaces = [gc.getInfoTypeForString('PROMOTION_UNDEAD'), gc.getInfoTypeForString('PROMOTION_DEMON')]
   for iPlayer in range(gc.getMAX_PLAYERS()):
       pPlayer = gc.getPlayer(iPlayer)
       if pPlayer.isAlive():
           if pPlayer.getAlignment() == gc.getInfoTypeForString('ALIGNMENT_GOOD'):
               py = PyPlayer(iPlayer)
               for pUnit in py.getUnitList():
                   if pUnit.getRace() in lTargetRaces:
                       pUnit.doDamage(50, 100, pCaster, iHoly, False)
This would not make "all evil aligned units suffer about 35-50% holy damage." It would deal an average of 50% damage, with random factors and the promotions of the target and caster modifying it, and possibly kill the unit. The second parameter, 100, is the maximum damage it can deal, and 100 means it can kill. 50 would mean maximum 50% damage.

If you don't want the caster's own strength/promotions to effect things, you'd instead use pUnit.doDamageNoCaster(35, 50, iHoly, False)

Are demons and undead units owned by good players the only ones you want to damage? I would have assumed you meant units belonging to evil players, or with evil religions, or promotions like Death 2 or Unholy Taint.

In my modmod I made a cf.getUnitAlignment(pUnit) function that you could use, but in the base mod you'd have to check promotions, religions, or player alignments separately.
 
It appears i hasted too much when posting, I forgot to change alignment and I forgot to remove that with demons, here is new code:
Code:
def spellDivineRetribution1(caster):
    for iPlayer in range(gc.getMAX_PLAYERS()):
        player = gc.getPlayer(iPlayer)
        if player.isAlive():
            if player.getAlignment() == gc.getInfoTypeForString('ALIGNMENT_EVIL'):
                py = PyPlayer(iPlayer)
                for pUnit in py.getUnitList():
                        pUnit.doDamage(50, 100, caster, gc.getInfoTypeForString('DAMAGE_HOLY'), false)
 
it seems that your code would target all units of Evil-aligned civs.
 
You probably need to adjust the indentations. That last line is still indented an extra time from when it was within another conditional statement. Also, I would recommend using tabs instead of spaces. If you are consistent with spaces Python will interpret them like tabs, but it is easier to make mistakes and 4 spaces do take up a little more memory than 1 tab.
 
1. Click your mouse and drag to select the blank space characters in your code.
2. Hit the delete key on your keyboard.
3. Hit the tab key on your keyboard until you get the indentation you want.

Repeat this process for each line of code.
 
What editor are you using?

I usually use either PyScripter or Notepad++.

In either case you want to make sure you have selected the "Show All Characters" option, a toggle button that looks like this: ¶

When that is active, a space will appear as a little dot and a tab as a small arrow pointing towards the right.

PyScripter allows you to run a debug option that would find all the syntax errors (like improper indentation) for you, if you have the right version of python installed and configured properly.

Notepad++ has a better find/replace function and does not require such configuration.

I would start by using Notepadd++ to replace every " " (for spaces, not including the quotation marks) with "\t" (making sure that search mode is set not to "normal" but "extended") so that you are using tabs consistently instead of spaces.
You would then want to go back to the line pUnit.doDamage(50, 100, caster, gc.getInfoTypeForString('DAMAGE_HOLY'), false) and press delete or backspace once to eliminate one excess indentation.

(I believe there was one file where Kael used 8 spaces for each tab, which is ok if you are consistent, but usually he used 4 spaces per tab or else just used tabs. Using only tabs is preferable because it makes files smaller and does not cause problems if you accidentally but in 5 instead of 4 tabs somewhere and cannot easily see where on a simple visual inspection.)
 
I fixed it and now it works!
Here is the code:
Code:
def spellDivineRetribution1(caster):
    for iPlayer in range(gc.getMAX_PLAYERS()):
        player = gc.getPlayer(iPlayer)
        if player.isAlive():
            if player.getAlignment() == gc.getInfoTypeForString('ALIGNMENT_EVIL'):
            py = PyPlayer(iPlayer)
            for pUnit in py.getUnitList():
                pUnit.doDamage(50, 100, caster, gc.getInfoTypeForString('DAMAGE_HOLY'), false)
Thank you so much!
 
Top Bottom