Quick Modding Questions Thread

Add the isHasReligion() line and it should work.
Code:
        if iNewReligion == gc.getInfoTypeForString("RELIGION_XXXX"):
            for pCity in PyPlayer(iCiv).getCityList():
                city = pCity.GetCy()
                if city.isHasReligion(iNewReligion):
                    iBuilding = gc.getInfoTypeForString("BUILDING_WALLS")
                    if not city.isHasBuilding(iBuilding):
                        city.setNumRealBuilding(iBuilding, 1)
 
merijn_v1 :

At first that didn't work, but then I noticed you'd replaced iPlayer with iCiv in the second line and thought that might have been a mistake, so I replaced iCiv with iPlayer and then it worked perfectly! I tested it under a bunch of different situations and it worked every time!

Thank you so much!

Doing this little project reminded me of my college days . . . long, long ago . . . when I took a couple of computer programming classes and really enjoyed coding. I ended up not going into that field, but I'd like to try my hand at playing around with this sort of thing some more. Can you recommend some newbie-friendly resources?
 
I copied that line from some other code. The previous code snippet I did notice it and change it, but the last time I forgot. Good to see yourself what cause that problem and fixed it by yourself.

I never really got programming classes myself. I learned all by doing little things like this. I started doing minor things in RFC mods. Back then, I did know that e.g. iPlayer.getGold() didn't work and gc.getPlayer(iPlayer).getGold() did. Or in this case why iPlayer does work but iCiv doesn't. But I had no clue why. But by just doing I learned what works and also (more or less) how it works.

What you obtain from gc.getPlayer(iPlayer) probably has a technical name, but I don't know which one. In fact, many things have formal names I don't know because I never learned them by a class. I know they exist, what they do and how they work, but I don't know how it is called.

Programming is not my mian field either, although I quite often use it to automate certain calculations. It's really nice that because of my hobby I have a little more knowledge about that. So I don't really have any good sources. But my advise, just do it. IMO you learn most by doing and make mistakes.
 
So I modded the protective trait to give the promotions to melee units and I modified the promotion info to allow them to take higher tier Drill/City Garrison promotions, but when I go to promote the option for Drill II/ CG II is not there and I'm not sure why? Any help would be appreciated.
 
I could use some instructions on how to add a new building to Civ4 BTS. I don't need to add any new graphics. I don't care what the building looks like; it can look like any other building in the game or it can even be invisible. All I care about is the effects of the building. I tried adding a building to CIV4BuildingClassInfos.xml and CIV4BuildingInfos.xml by copying, pasting, and slightly tweaking the XML code for monument/obelisk, but this just produces tons of errors when loading the game.
 
I could use some instructions on how to add a new building to Civ4 BTS. I don't need to add any new graphics. I don't care what the building looks like; it can look like any other building in the game or it can even be invisible. All I care about is the effects of the building. I tried adding a building to CIV4BuildingClassInfos.xml and CIV4BuildingInfos.xml by copying, pasting, and slightly tweaking the XML code for monument/obelisk, but this just produces tons of errors when loading the game.
Can you upload those 2 moded xml files so we can have a look?
 
I actually solved the problem with the error messages; it was a typo in one of the files. So now my question is: how do I change the name of the new building so it shows up as "Test Building" in-game instead of "Monument"?

I've uploaded the files. The new building is listed at the top of both files and is named TEST_BUILDING. It's just a copy/paste from obelisk/monument. The only difference (just to see if it worked) is that it generates 2 culture per turn instead of 1.

EDIT: OK, I figured it out. In CIV4BuildingInfos.xml, I just changed:

<Description>TXT_KEY_BUILDING_MONUMENT</Description>

to:

<Description>Test Building</Description>

It took me forever because it was way too easy. I assumed TXT_KEY_BUILDING_MONUMENT must refer to a notation in another file that contained the name of the building. I spent hours looking for the damn thing and couldn't find it. Then, in an act of frustration, I just typed "Test Building" into the Description field assuming it would just crash the game, but, instead, it worked.
 

Attachments

Last edited:
You can find the text files in the XML/Texts folder. If it is not in the BTS/XML/Text folder, search in the XML/Text (vanilla game) or Warlords/XML/Text folder.
 
It's Beyond the Sword/Assets/XML/Text and Warlords/Assets/XML/Text, to be precise.
 
Thank you! I did check all but one of those locations, which is where I found just found TXT_KEY_BUILDING_MONUMENT. It's in C:\Program Files (x86)\2K Games\Firaxis Games\Sid Meier's Civilization 4 Complete\Warlords\Assets\XML\Text\CIV4GameText_Warlords.xml. I never would have thought to look there since I'm not playing Warlords.

It's not in any file that's located in the C:\Program Files (x86)\2K Games\Firaxis Games\Sid Meier's Civilization 4 Complete\Assets\XML\Text folder or the C:\Program Files (x86)\2K Games\Firaxis Games\Sid Meier's Civilization 4 Complete\Beyond the Sword\Assets\XML\Text folder.
 
Yes, the way it works is that if you play Beyond the Sword or a BtS mod, it uses text files from the base game and both mods, which is somewhat annoying when you want to change something and don't know where it's coming from.
 
I use the Notepad++ search in files for this. Then you only need to search at most 3 folders. It is much quicker than manual search anyway.

EDIT:
I quickly wrote a small Notepad++ plugin that automatically searches for the TXT_KEY in all 3 folders. Simply select the key and run the plugin.

Code:
import os
import sys
from Npp import *
import re


def searchForText(text):
    if text == "": return
    
    vanillaTextPath = "C:\Program Files (x86)\Steam\steamapps\common\Sid Meier's Civilization IV Beyond the Sword\Assets\XML\Text"
    warlordsTextPath = "C:\Program Files (x86)\Steam\steamapps\common\Sid Meier's Civilization IV Beyond the Sword\Warlords\Assets\XML\Text"
    BTSTextPath = "C:\Program Files (x86)\Steam\steamapps\common\Sid Meier's Civilization IV Beyond the Sword\Assets\XML\Text"
    lPaths = [BTSTextPath, warlordsTextPath, vanillaTextPath]

    text = editor.getSelText()

    for path in lPaths:
        for root, dirs, files in os.walk(path):
            for fn in files:
                notepad.open(root + "\\" + fn)
                pos = editor.findText(FINDOPTION.WHOLEWORD, 0, editor.getTextLength(), str(text))
                if pos is None or pos == (0, 0):
                    notepad.close()
                else:
                    editor.gotoPos(pos[0])
                    return

searchForText(editor.getSelText())
 
I did something similar (+1 production per angry citizen), but it requires DLL changes. Angry citizens aren't really specialists even though they are presented as such in the interface. You can use CvCity::angryPopulation() to implement it.
 
I did something similar (+1 production per angry citizen), but it requires DLL changes. Angry citizens aren't really specialists even though they are presented as such in the interface. You can use CvCity::angryPopulation() to implement it.
Ahh... DLL is far out of my reach :sad:
Thank you for the answer though :thumbsup:
 
I'm having a weird issue with siam's African unit pack.I'm sourcing elements for a mod with civ-specific artstyles and while the Chariot and Cavalry work fine in-game, their pedia pages break as if the models can't be read. They do have a shader NIF without a plain NIF, but that shouldn't matter since the other units are coded the same way and the ones I've used work fine.

Files attached for review.
 

Attachments

Not sure, but since the info is shown in cityscreens and ciityinfo, I think it should be accessible from
I'm having a weird issue with siam's African unit pack.I'm sourcing elements for a mod with civ-specific artstyles and while the Chariot and Cavalry work fine in-game, their pedia pages break as if the models can't be read. They do have a shader NIF without a plain NIF, but that shouldn't matter since the other units are coded the same way and the ones I've used work fine.

Files attached for review.
iirc I had problems with the chariot as well, and had to remove it.
 
Hopefully someone here can help :)

A while ago I implemented the bfc strategy overlay mod (circled in blue) into my mod, and want to add it as a button (red circle is where'ish it should be).
I also wanted to change the keyboard shortcuts (alt+x for editing and Ctrl+x for toggling it), though I cannot find it (my python skills are extremely limited)
I think I have seen a mod adding the button, but cant remember which, and even if i find it, i would have trouble locating and transferring it :(

Any help is much appreciated :)
 

Attachments

  • Civ4ScreenShot0013.png
    Civ4ScreenShot0013.png
    2.2 MB · Views: 204
Does anyone know where in the DLL source is the behaviour implemented that wakes threatened workers? Not even sure if it's from BUG or if it was already in the base game.
 
Does anyone know where in the DLL source is the behaviour implemented that wakes threatened workers? Not even sure if it's from BUG or if it was already in the base game.
Could it be
PHP:
void CvSelectionGroup::autoMission()
{
    FAssert(getOwnerINLINE() != NO_PLAYER);

    if (getNumUnits() > 0)
    {
        if (headMissionQueueNode() != NULL)
        {
            if (!isBusy())
            {
                bool bVisibleHuman = false;
                if (isHuman())
                {
                    for (CLLNode<IDInfo>* pUnitNode = headUnitNode(); pUnitNode != NULL; pUnitNode = nextUnitNode(pUnitNode))
                    {
                        CvUnit* pLoopUnit = ::getUnit(pUnitNode->m_data);
                        if (!pLoopUnit->alwaysInvisible())
                        {
                            bVisibleHuman = true;
                            break;
                        }
                    }
                }

                if (bVisibleHuman && GET_PLAYER(getOwnerINLINE()).AI_getPlotDanger(plot(), 1) > 0)
                {
                    clearMissionQueue();
                }
                else
                {
                    if (getActivityType() == ACTIVITY_MISSION)
                    {
                        continueMission();
                    }
                    else
                    {
                        startMission();
                    }
                }
            }
        }
    }

    doDelayedDeath();
}


if (bVisibleHuman && GET_PLAYER(getOwnerINLINE()).AI_getPlotDanger(plot(), 1) > 0)
 
Back
Top Bottom