Mod-Modders Guide to Fall Further

Just an update to say that my bUniqueCult is working great, finally!
Thanks a lot, xienwolf :D
 
Had a bug reported today that has to do with loading savegames. When you start a game in my mod, everything is fine. You save, exit and reload and then you can't research religious techs anymore, they are red in the tech tree. I think it may have something to do with a value being misread when loading...

Edit: And it seems it screws up religion adopting too. I think it has to do with the bUniqueCult and bIntolerant tags I added. I modded the DLL so that, like bAgnostic(), they don't allow to do religion and it seems to think that some leaders are either intolerant or uniqueCult on loading. I wonder why.
 
Quite possibly. Affects all players, or only certain leaders? Anyway, I would check the ::read and ::write functions in CvPlayer to make sure you didn't copy/paste to do your new fields and then forget to rename what you pasted. That sounds like the most likely problem (hence would only affect the few leaders who use a value in whatever was copied). If you had flat out forgotten to set up a read/write (just one, not both) then the save wouldn't load at all.
 
Ah, I found it! I had:
Code:
pStream->Write(&m_bUniqueCult);
I saw that I don't need the "&" here.

Could I bother you and ask what is that "&"? What is its purpose in the code?
 
Ah, I found it! I had:
Code:
pStream->Write(&m_bUniqueCult);
I saw that I don't need the "&" here.

Could I bother you and ask what is that "&"? What is its purpose in the code?

Don't ask that... That way madness lies... Pointers and references of doom!

====

&m_bUniqueCult is a memory pointer to the variable m_bUniqueCult. That means instead of actually passing the data itself, it's passing the memory address where the data is kept. The advantage here is that you are passing a memory address (small) rather than the data (potentially large).

The Write function then looks up the relevant data and writes it.

The real madness comes when you realize that & is just one of many pointerish symbols &var, int* var, int* foo = &bar etc...

Spoiler Spawn of the Overlords :
Code:
int j = 5 // Normal int
int *i;  // i is a pointer to an int

i = &j; // i now points to j

*i == 5;


int &k = j; // k is a reference to j (C++ only)
k == 5;

int *i, j;  // i is a pointer to an int. j isn't! is just an int.

FAQ on the topic

Yes - I learned to code with Java and so pointers scare me.
(technically it was AmigaBasic, but we don't talk about that)
 
Ok, I wrote a Module under this new system myself to test things out, and I wanted to put out some notes on how to do it. Much of this might seem like gibberish until you actually get a chance to make one for yourself, but hopefully it is a handy reference when that time comes for someone.

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

MLF Files. These are the "Master Load Files" and their purpose is to control the order in which the Modules are loaded. Remember in the old system that you couldn't modify the same <Type> in the same file with 2 different modules. Whichever module loaded up last would be the only one read. This was REALLY bad for files where you had to include the entire thing (like an improvementinfos file which included an improvement which can upgrade), since then only the last file would be used at all.

There are a few ways to use the MLF:

First, you can just NOT use it. Then the loading is done in whatever order the DLL decides to grab them in (generally alphabetical by folder depth). The downside of this is that you will get an error message when you launch Civ from the desktop saying that it cannot find the MLF file. The error can be ignored though as it won't actually effect anything.


Second: You can use them to block modules completely by listing all of the folders EXCEPT the one you no longer desire to use.

Third: You can use them to control the loading order of each module. This is the INTENDED use. What order they are listed in is the order they will load in. You can make multiple configurations if you want, but swapping from one to another requires that you edit the MLF anyway, so I am not sure why that function was programmed other than because it was possible.


The downside of using them (remember the downside of NOT using them was that annoying little error message): If you use an MLF file in a folder to control the load order of the subfolders, then each subfolder must ALSO include an MLF. This can potentially cause you some issues someday if you forget it.

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

Refreshing:

There seems to be a small issue with the refreshing of the Text files in modules. I am still trying to figure out precisely what is going on with it, but it would seem that the text is cached when first read and then never looked at again, possibly if I could remember where the cache was I could clear it and be fine, but I have 2 text keys which simply don't seem to be getting read, and they are the 2 I added after the first time I launched the module.

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

Partial edits:

The flat out coolest feature of the entire new system, you can change a single line of any <Type> with just that type and the one line you want to change in your module. This means you are even LESS likely to need to update a module when a new patch comes out. As an example (which doesn't matter for FF, but would for Orbis) you can modify your favorite GameOptions to always be on by just stating the name of the option and the default value you would like.

Here would be the complete file you would need for my example:
Code:
<Civ4GameOptionInfos xmlns="x-schema:CIV4GameInfoSchema.xml">
	<GameOptionInfos>
		<GameOptionInfo>
			<Type>GAMEOPTION_RAGING_BARBARIANS</Type>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_BARBARIAN_WORLD</Type>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_AI_NO_BUILDING_PREREQS</Type>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_AI_NO_MINIMUM_LEVEL</Type>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_NEW_RANDOM_SEED</Type>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_DOUBLE_EVENTS</Type>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_ALL_UNIQUE_IMPROVEMENTS</Type>
			<bDefault>1</bDefault>
		</GameOptionInfo>
	</GameOptionInfos>
</Civ4GameOptionInfos>

And now those options would be selected at the start of each game for you. If more options are added in the future, everything updates just fine, the important thing is just that these options don't get renamed/deleted :) To avoid even having to update at that time, you could modify things slightly to read:

Code:
<Civ4GameOptionInfos xmlns="x-schema:CIV4GameInfoSchema.xml">
	<GameOptionInfos>
		<GameOptionInfo>
			<Type>GAMEOPTION_RAGING_BARBARIANS</Type>
			<bTypeDependency>1</bTypeDependency>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_BARBARIAN_WORLD</Type>
			<bTypeDependency>1</bTypeDependency>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_AI_NO_BUILDING_PREREQS</Type>
			<bTypeDependency>1</bTypeDependency>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_AI_NO_MINIMUM_LEVEL</Type>
			<bTypeDependency>1</bTypeDependency>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_NEW_RANDOM_SEED</Type>
			<bTypeDependency>1</bTypeDependency>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_DOUBLE_EVENTS</Type>
			<bTypeDependency>1</bTypeDependency>
			<bDefault>1</bDefault>
		</GameOptionInfo>
		<GameOptionInfo>
			<Type>GAMEOPTION_ALL_UNIQUE_IMPROVEMENTS</Type>
			<bTypeDependency>1</bTypeDependency>
			<bDefault>1</bDefault>
		</GameOptionInfo>
	</GameOptionInfos>
</Civ4GameOptionInfos>

What bTypeDependency does is it says "If this <Type> doesn't already exist, then ignore what I am doing here..." Which is a good thing because this is one XML file you do NOT want to add items to on accident :)

At this point, the little module which loads your favorite gameoptions is 100% immune to needing updated for any future patches (well, unless a new gameoption appears that you also want to set as default ON... ;))

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

Graphics:

OK, Monsterous Creatures Module had an issue where the promotions showed up as HUGE pink boxes on mouseover of the unit. I said it was due to a space in the filename of the DDS, and I was right, just not COMPLETELY right. If there is a space ANYWHERE in the file PATH then this happens. So you can name your folder whatever you want, just don't use spaces if you will be including promotion buttons (or any automatically resized button for that matter)
 
Modder should make them in general so the players don't have to bother, but that only works while there aren't very many modules in the world. Since it has to list all modules being used, the player will have to be involved in it, or specially request one which includes X, Y and Z modules active.

Two which will be included with distribution will be:

Code:
<Civ4ModularLoadControls xmlns="x-schema:CIV4ModularLoadingControlsSchema.xml">
	<DefaultConfiguration>Modules_Main_1</DefaultConfiguration>
	<ConfigurationInfos>
		<ConfigurationInfo>
			<Type>Modules_Main_1</Type>
			<Description>Initialize ALL Modules by using the MLF file structure</Description>
			<Modules>
				<Module>
					<Directory>NormalModules</Directory>
					<bLoad>1</bLoad>
				</Module>
				<Module>
					<Directory>LoadOrderVitalModules</Directory>
					<bLoad>1</bLoad>
				</Module>
			</Modules>
		</ConfigurationInfo>
	</ConfigurationInfos>
</Civ4ModularLoadControls>

and

Code:
<Civ4ModularLoadControls xmlns="x-schema:CIV4ModularLoadingControlsSchema.xml">
	<DefaultConfiguration>Modules_Vital_Load_Order</DefaultConfiguration>
	<ConfigurationInfos>
		<ConfigurationInfo>
			<Type>Modules_Vital_Load_Order</Type>
			<Description>Initialize ALL Modules by using the MLF file structure</Description>
			<Modules>
				<Module>
					<Directory>FirstLoad</Directory>
					<bLoad>1</bLoad>
				</Module>
				<Module>
					<Directory>SecondLoad</Directory>
					<bLoad>1</bLoad>
				</Module>
				<Module>
					<Directory>ThirdLoad</Directory>
					<bLoad>1</bLoad>
				</Module>
				<Module>
					<Directory>FourthLoad</Directory>
					<bLoad>1</bLoad>
				</Module>
			</Modules>
		</ConfigurationInfo>
	</ConfigurationInfos>
</Civ4ModularLoadControls>


At one point I had things where I thought you would load every module in a folder if there wasn't an MLF in that folder, regardless of there having been one in the previous folder. That is why I set things up like this, then if order didn't matter at all, you made your module to load into NormalModules. But if the order did matter (modular mod of a modular mod) you used the First/Second/Third/Fourth folders. I'll be playing with the code sometime when I have a chance to see if I can make that possible again, because then as long as this folder structure exists and nobody need to be later than fourth, players will not have to touch the MLF files (and if you need later than fourth you just stick to the pattern and increment to whatever you need, players remain able to leave things alone)


note that the DefaultConfiguration of each one matches the <Type> listed just after that. And that those <Type> fields are different than each other. Those are 2 of the important things to remember.
 
Ok, I played with things a bit to see if I could make it as easy on the modders and players as I could and found a small loophole in the code we can use till I sort things out better. If I leave an MLF in the folder which lists no Default Configuration, then it loads every folder it finds deeper in that particular directory. So now things work quite nicely.


Instead of making Modules with the intention of placing them in Assets/Modules, people need to plan on putting them in Assets/Modules/NormalModules. So anyone who has a module mod existing already, change all your art references accordingly and you should be ready for the new patch. No MLF will be required for 98% of all Module makers.
 
2 more tags I just added when their value become obvious during some final testing, both in SpellInfos:

<PrereqIsNOTMinion> - Spell can only be cast if the unit has no Commander Unit it is attached to

<PyHelp> - Allows you to add Help Text using Python to indicate certain things which the DLL might not be able to pick up (mostly those which are situational to your spell, like targetting data). Available fields are the spell being cast and the unit who is currently selected (Or possibly the leader of the group which the unit currently selected belongs to, not QUITE certain on that one...), as typically that is the caster.


The second of those probably being the most important for future use and development.
 
Where is all the info about leaders kept? I am planning make alcinus a leader, with Mad, Arcane, Summoner, and Angonistic. With mad being insane but with calcinating on all arcane. :goodjob:
 
What should I change in order for trade routes to be displayed as decimal instead of integer in the city view? Well, I think it needs more than that, like a revamp of the trade routes system (integer?) to decimal. I'm a bit worry that there will be many many changes and many I could overlook... Any guideline about this?
 
You'll be needing changes in tons of places most likely, yes. Probably best to approach it similar to the Decimal XP System and inflate trade route yields by 100x, then everywhere it is actually put to use divide it by 100 to process things.

I am pretty sure it has been done before for BtS, so you could check out the MODCOMP section for someone who still uses it and borrow from their code. Kael hasn't done much to change trade routes so it'd be a fairly straightforward merge.
 
Top Bottom