Quick Modding Questions Thread

Only via modding and recompiling the DLL. Have you done that before?
 
Only via modding and recompiling the DLL. Have you done that before?
I guess that means its not a quick modding question. I've edited python, xml, and I've got Visual C++ so I'm set up to recompile, just haven't given it a shot yet. But I haven't really tried to write code from scratch.
 
How do I move something from a trait or a civic to a building? (and vice versa?) I see there is the TradeYieldModifiers option for traits & civics, but I'd like to add it to buildings. How do I do that?
All the xml data is handled in CvInfo.cpp/.h. You copy a tag from one file to another by copying the variable, the get function and the read code in the Read function. Adding more tags is fairly simple once you know how to compile and have added a few tags. You also need to add the new tag to the xml schema file. If you add it with minOccur=0, then you don't have to fill out all the xml entries and they will get a default value if it's missing (makes life easier).

The problem is that adding a new tag to the info class will not actually change anything. You need to go through the source code and use the get function to do stuff in the right places.

I wrote a bit about adding xml tags/files at some point. It's for colonization, but it applies to BTS as well because the xml interface is the same.
https://github.com/We-the-People-civ4col-mod/Mod/wiki/Guide:-Add-an-xml-tag
https://github.com/We-the-People-civ4col-mod/Mod/wiki/Guide:-how-to-add-a-new-xml-file
 
I guess that means its not a quick modding question. I've edited python, xml, and I've got Visual C++ so I'm set up to recompile, just haven't given it a shot yet. But I haven't really tried to write code from scratch.
You wouldn't need to write code entirely from scratch, since what you want already exists for a civic or trait, so you only need to transfer it from there to a building. The challenge mostly comes from knowing where those parts go so the functionality is entirely implemented. So I would encourage you to give it a try, but as I said the first step is to set up the compiler.
 
I would like to read and parse data from an external file in Python, in particular a CSV file. The standard Python libraries for file I/O and csv parsing work in Civ4, what I am currently wondering is where can I best put these files (inside the mod directory) and how do I discover the dynamic file path to the mod directory in Python?
 
I use the following code in the map exporter of DoC:

Code:
IMAGE_LOCATION = os.getcwd() + "\Mods\\RFC Dawn of Civilization\\Export"

os.getcwd() is the working directory of the process, which is the BTS folder in program files.
 
Oh, interesting, looks like the Python process is running in the BtS folder. Looks like I have some options to try, thanks to both of you.
 
I use the following code in the map exporter of DoC:

Code:
IMAGE_LOCATION = os.getcwd() + "\Mods\\RFC Dawn of Civilization\\Export"

os.getcwd() is the working directory of the process, which is the BTS folder in program files.
That won't work if the player places the mod in my documents. Instead I will recommend asking the exe for the mod location.
PHP:
const char* CvDLLUtilityIFaceBase::getModName(bool bFullPath = true) const;
gDLL->getModName()
Expose this to python by adding gc.getModName() and you should have a reliable way of getting the mod root dir in python.

EDIT: based on experience some people have a tendency to rename mods. Don't ask me why, but people do that. Using getModName means the path will work even if the user renames the mod. It also allows the mod creator(s) to have multiple installs of the same mod, like one development and one stable release for (multiplayer) gaming.
 
Last edited:
Is it possible to play a movie when a certain event fires? I mean other than an "event built" building with a movie tag.
Did anyone ever create a python script for that?
If you are asking for how to play a movie, I would look at Assets\Python\Screens\CvWonderMovieScreen.py. Add another iMovieType type and add code to get the movie file based on that type. After that I think it will just be a matter of calling the movie popup like any other popup, like the vanilla code here:
PHP:
    def onProjectBuilt(self, argsList):
       'Project Completed'
       pCity, iProjectType = argsList
       game = gc.getGame()
       if ((not gc.getGame().isNetworkMultiPlayer()) and (pCity.getOwner() == gc.getGame().getActivePlayer())):
           popupInfo = CyPopupInfo()
           popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON_SCREEN)
           popupInfo.setData1(iProjectType)
           popupInfo.setData2(pCity.getID())
           popupInfo.setData3(2)
           popupInfo.setText(u"showWonderMovie")
           popupInfo.addPopup(pCity.getOwner())
The 2 is MOVIE_SCREEN_PROJECT. It's here you need to add your own type.

Please share your working code once you get it because I would like to see it. I haven't actually used movies myself.
 
Is there a way to make a mod that allows rebuilding of destroyed world wonders?
Looks like the proper way to do this is to edit CvGame to make it set m_paiBuildingClassCreatedCount to 0 for the wonder in question if it's destroyed. Vanilla only allows calling it to increment meaning you need to mod the DLL to allow resetting this counter.

For a non-dll approach, you might be able to make a callback to ignore this counter, but I don't like that approach as it sounds prone to consist of messy code and prone to bugs.

I don't know if there is an existing mod, which modded this. I only looked at vanilla code.
 
It's not really related to C&C but I figured it's most likely to find people who know the answer here.

After I've reinstalled Civ4, none of the savegames and WBsaves are associated with the game anymore. Of course I can instruct Windows to open them with the BeyondSword.exe but then it will just open unmodded BtS for saves and maps from mods, meaning e.g. the save will not actually be opened. I used to be able to just jump straight into a saved game with the correct mod loaded when opening a savegame file. Does anyone know how to configure Windows correctly to enable that?

I know that you can pass the mod you want to load as parameter to the exe but I don't know how to make the game infer that from the savegame or map file.

I'm on Windows 10 in case that matters.
 
I'm not sure whether this is a quick question, but I am curious about the doability of making a bot for taking screenshots from the mod during autoplay. Like the battle royale thing for Civ 5. Is it possible to programmatically take screenshots from the game? Because tbh I don't want to take them myself, that would take so much time.

If that's not possible making less detailed diagrams for the game seem like the best choice.
Imho it would be cool if this mod had a twitter bot for sharing screenshots.
 
I'm making a scenario and I need to know how do I make it so the starting location of the civs are defined, but not which civ/leader goes in that location. I want to be able to choose any leader/civ to play in any of the locations, and either pick your opponents on the game start screen or let the computer pick them randomly.
 
I'm making a new array class where you assign the size with templates, like ArrayClass<PlayerTypes, int> gives an int for each player, ArrayClass<UnitTypes, short> gives a short for each CvUnitInfo etc. It then contains code for memory allocation, length, savegames and whatever else can benefit from being a function for all arrays.

Can anybody think of a good name for such an array class?
Good coding practice is to pick names, which can be understood without comments. However all the names I can think of for this class fails this test.
 
I don't know the full answer to any of these, but here's my best shot:
[...] I know that you can pass the mod you want to load as parameter to the exe but I don't know how to make the game infer that from the savegame or map file.

I'm on Windows 10 in case that matters.
The attached screenshot shows how (I think) it works on Windows 8.1. That's all under HKEY_CLASSES_ROOT and was created by the installer. The start of "value data" that didn't fit in the box is just the full path ("C:\ ...") to the BtS EXE.
[...] Is it possible to programmatically take screenshots from the game? [...]
I don't see anything called "screenshot" or "printscreen" in the DLL. Shift+Print brings up a popup saying "Enter screen shot name". That instruction string is actually not in any of the game text files but is hardcoded in the EXE. This reinforces my suspicion that screenshots are handled (entirely) by the EXE. So my best bet would be to simulate a print key press through the DLL.
I'm making a scenario and I need to know how do I make it so the starting location of the civs are defined, but not which civ/leader goes in that location. I want to be able to choose any leader/civ to play in any of the locations, and either pick your opponents on the game start screen or let the computer pick them randomly.
The Vanilla Civ 4 Africa scenario appears to work this way. I'd try to imitate that. (Or perhaps someone else can describe how it's done specifically.)
I'm making a new array class where you assign the size with templates, like ArrayClass<PlayerTypes, int> gives an int for each player, ArrayClass<UnitTypes, short> gives a short for each CvUnitInfo etc. It then contains code for memory allocation, length, savegames and whatever else can benefit from being a function for all arrays.

Can anybody think of a good name for such an array class?
Good coding practice is to pick names, which can be understood without comments. However all the names I can think of for this class fails this test.
If I understand correctly*, this is a map that exploits that the keys are enum values from a fixed-size interval. "EnumMap"? Turns out that there is a Java SE class of that name.
* I'm not quite sure that I understand correctly. I'm assuming that ArrayClass<PlayerTypes,int> will have to allocate a new int[MAX_PLAYERS]. How does it know how many enum values there are? Through a constructor argument?
 

Attachments

  • regedit-screenshot.jpg
    regedit-screenshot.jpg
    121.2 KB · Views: 236
If I understand correctly*, this is a map that exploits that the keys are enum values from a fixed-size interval. "EnumMap"? Turns out that there is a Java SE class of that name.
* I'm not quite sure that I understand correctly. I'm assuming that ArrayClass<PlayerTypes,int> will have to allocate a new int[MAX_PLAYERS]. How does it know how many enum values there are? Through a constructor argument?
Thanks. EnumMap is precisely what this is, even down to the internal implementation.

The length is given like this (though I have an idea of how to make this more pretty/useful):
PHP:
inline unsigned int ArrayLength(PlayerTypes var)
{
   return MAX_PLAYERS;
}

This way I can "translate" templates into actual lengths without having to mention the length in the code where it's used. Just make an array (or EnumMap) of PlayerTypes and the code knows the length even without being told and without storing the length in a member variable. This allows using a default constructor, which is very useful for arrays of arrays. Add getLength() and suddenly you can write very generic code for the arrays, like one line savegame code. Add getting a default (like always 0) and the array can postpone allocation until you write a non-default value to it, which frequently is never.
It also prevents a number of bugs because if the programmer doesn't have to specify the length, then there isn't any risk that it's not the same length everywhere. If it's type strict, then you can't mix PlayerTypes with TeamTypes, UnitTypes with UnitClassTypes etc. No need to consider if the memory is allocated (just pretend that it is), the deconstructor frees the memory automatically. The list goes on and on about what is easier and less prone to bugs.

While I need to solve a few details, I pretty much have this figured out. I just got stuck with the name and the same goes for anybody I asked until I posted here.
 
Back
Top Bottom