Quick Modding Questions Thread

@ The J: as it works now, health merely modifies food accumulation when it is below a minimum threshold; it has no effect (correct me if I'm wrong) when it exceeds that minimum threshold. As long as the health level of a city is greater than the unhealth level, the city will accumulate food. This I think is too simple and does not fully represent the role that health played in history. Past civs have used things like "plague" random events, and that was not particularly fun.

There is no difference in game play between a size 10 city with 10 health and 10 unhealth, than a size 10 city with 20 health and 10 unhealth. There should be a difference, arguably a sizeable one; the city with a larger variety of health should show better performance over history. People enjoy healthy food, and they thrive. Excess health could have impacts on all aspects of a cities functioning: hammers, happiness, food accumulation (positive not just negative modifier), great people production, effects of great people.

A simple application of this could be something like:
20% excess health = +1 hammer, +1 happiness, +1 food, +25% GP production rate, +25% GP effects
50% = +2 hammer, +2 happiness, +2 food, +45% GP production rate, +35% GP effects
75% = +3 hammer, +3 happiness, +3 food, +60% GP production rate, +45% GP effects
100% = +4 hammer, +3 happiness, +3 food, +70% GP production rate, +50% GP effects

In sum, nonlinear positive effects of excess health on other aspects of city functioning. This would make having more of a variety of health sources a strategic advantage, which it should be, but is not really in game at present (at least beyond a minimum threshold).

Not knowing the maths nor the code behind the scenes, I'm not sure how this sort of stuff could or could not be done.

BTW, anybody reading this: feel free to run with it and try and make it work! I mostly enjoy playing and my real interest in modding is just to play the changes!

If anyone does use any idea like this, please integrate it into HiTM so I can play it too :)
 
That's not so easy that someone could code it in a few minutes ;).
If you want to get it done, then you'll probably have to try it yourself ;).

Got this when i loaded scenario:
PHP:
Assert Failed

File:  CvGlobals.cpp
Line:  2428
Expression:  e > -1
Message:

Got this again after about 6 turns
PHP:
Assert Failed

File:  CvGlobals.cpp
Line:  1490
Expression:  e > -1
Message:

Take a look at both the functions in CvGlobals, what's their names?


Then it crashed a turn later. I also got a bunch of errors like the one i posted before, but you showed me how to fix those so they will be easy fixed. for both of the ones abouve, on that line it does say e > -1 So i tried changing it to e > 0 and e > 1 and neither worked, same erros came up, if you can give me any hints that could help!

...er...no idea what you tried to do with that, but it will not work in this way ;).
The error message says basically, that some code in the mentioned files got some invalid value. What you've now done is changing the error message, to consider other invalid values to be valid, so that doesn't make that much sense at the end ;).
 
That's not so easy that someone could code it in a few minutes ;).
If you want to get it done, then you'll probably have to try it yourself ;).



Take a look at both the functions in CvGlobals, what's their names?




...er...no idea what you tried to do with that, but it will not work in this way ;).
The error message says basically, that some code in the mentioned files got some invalid value. What you've now done is changing the error message, to consider other invalid values to be valid, so that doesn't make that much sense at the end ;).

Well that was my best guess:crazyeye:

Anyway when you ask what their names are im assuming you mean in the xml file?

This is what is says around 1490
PHP:
CvInfoBase& CvGlobals::getMonthInfo(MonthTypes e)
{
	FAssert(e > -1);
	FAssert(e < GC.getNumMonthInfos());
	return *(m_paMonthInfo[e]);
}

This is what it says around 2428
PHP:
CvString& CvGlobals::getArtStyleTypes(ArtStyleTypes e)
{
	FAssert(e > -1);
	FAssert(e < GC.getNumArtStyleTypes());
	return m_paszArtStyleTypes[e];
}

Thanks for the help really apreciate it:goodjob:
 
@dacubz - In both cases you have code that tries to access an array in an illegal index: An array in C++ starts at index 0, and that's why you have an assert "e > -1".

An assert is a piece of code intended to help a developer find out when something goes wrong. Instead of only crashing, it informs the developer that a mandatory condition was not met. In this case - it checks if the enum value (and therefor the index) is legal - at least 0.

An assert in itself is not a crash. When the value is illegal, it might cause a crash later, since the game will try to access a memory address it was not supposed to.

If the value is -1, it means it's NO_MONTH (for example). If it's another negative value, it probably means it was not initialized at all.

The best way to find the source of the problem is to debug the assert - when it happens, select retry or debug. You can only do that if you have Visual Studio (or another debugger) and you should have compiled it yourself (so you'll have the sources). But then you can look at the call stack (which function called which) to find the source of the bad value.

And again - sorry for bailing out on you.
 
This might not be a quick question, but I don't have much experience modding as you can guess from my post count...

When starting a new game on an age past Ancient, new cities are built with more than 1 citizen and some free buildings in them, more depending on which age you start. However this only applies because of the age you start the game in: All your new cities will always start with the same things than when you started the game, which in a game starting from the ancient age means 1 citizen and no free buildings, and makes late game expansion quite a pain unless you use the food/production corporations at a high cost.
I was wondering if this 'advanced city start' feature could be implemented dynamically through a mod into any game, no matter the starting age. So for example, after you hit the classical age, all your new cities would start with the free buildings and citizens from a game starting in the classical age, same when you hit medieval, renaissance...
 
@dacubz - In both cases you have code that tries to access an array in an illegal index: An array in C++ starts at index 0, and that's why you have an assert "e > -1".

An assert is a piece of code intended to help a developer find out when something goes wrong. Instead of only crashing, it informs the developer that a mandatory condition was not met. In this case - it checks if the enum value (and therefor the index) is legal - at least 0.

An assert in itself is not a crash. When the value is illegal, it might cause a crash later, since the game will try to access a memory address it was not supposed to.

If the value is -1, it means it's NO_MONTH (for example). If it's another negative value, it probably means it was not initialized at all.

The best way to find the source of the problem is to debug the assert - when it happens, select retry or debug. You can only do that if you have Visual Studio (or another debugger) and you should have compiled it yourself (so you'll have the sources). But then you can look at the call stack (which function called which) to find the source of the bad value.

And again - sorry for bailing out on you.
Yeah that didnt cause the crash, but one turn after the second error like that it crashed, so your right about that.

Im kind of confused on the rest thought, what does it mean when its no_month? i have no idea what NO_MONTH means. how do i debug the assert? Im using the debug dll, and ive really havent had to do this before, so im not sure what to do honustly:crazyeye: Thanks for the help tho, and no problem, completely understand :D
@#1: Can you play beyond that without modifying anything?

@#2: Well, that looks like if a city stile for one of the civs was missing/borked. Thie time at which it crashed should give you a hint for the era.

1: What do you mean? I can play about 6 more turns after the first error, but after the second error, the next time i press anything it crashed

2: I dont see how thats possible, like i said my mods all modern, and im pretty sure all modern cities are the same art, ill look into that anyway though, myabe ones art style is spelled wrong or something

Thanks for the help!
 
@1: Because it seems that there's something wrong with the dates, and that should normally lead to a crash, that's why i ask.
What year/month/whatever was displayed at that point, can you check that?

Spoiler :
Read the bottom first
Heres the timeline for how it crashes best i can
When it loads, the loading bar loads all the way, and stops once its full and i get this error
Spoiler :
Assert Failed

File: CvGlobals.cpp
Line: 2428
Expression: e > -1
Message:

----------------------------------------------------------

I press ignore, games fine, and it goes back up.
The starting thing that says "take control of your civ etc etc" i press continue, thats fine. Starting year is 1900, i can do w.e i want and no error, but as soon as my settler is clicked on (or once i move infantry its automatically chosen) game gives me this error
Spoiler :
Assert Failed

File: CvPlayer.cpp
Line: 5249
Expression: GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(eBuildingClass) == eBuilding
Message:

----------------------------------------------------------

Click on game, everything appears to be fine again, found city, start to build workboat, click enter for next turn, get this error
Spoiler :

Assert Failed

File: CvPlayer.cpp
Line: 5134
Expression: GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(eUnitClass) == eUnit
Message:

----------------------------------------------------------

Choose Tech, sleep infantry, borders expand (1905), found random religion (1906), finish building workboat, start building training area (1908) sleep workboat. after 1910, turns go 5 months at a time. Expanded borders (1912)


Read First
Wait nevermind, i changed the starting date from 4000BC to 1900, and i got no crashes for 40 some turns that i played, idk why, i still got the errors i said above, but still no crashes :D thanks, hopefully my other scenarios work to, im sure they wont (just my luck) and ill be posting here shortly again:crazyeye:
 
What exactly is a python callback?

In the DLL there a bunch of places where it calls a Python function in order to allow modders to change how things work. These are the Python callbacks.

In some cases, if the callback returns a value other than -1 then that value is used instead of what the DLL's calculations would use. In other cases it is a simple True/False and if the function returns True then the DLL does that thing regardless of what it's own tests would indicate. Others just return a value (no "use if not -1", these are always used, there is no calculation for the value in the DLL) like the getExperienceNeeded function, which is used to determine how many XP a unit needs to go up a level.

In order to get most of the callbacks to work, you have to enable them in the PythonCallbackDefines.xml. This is done to make the game run faster since the simple act of calling a Python function, even if it does nothing, takes time (a lot of time compared to calling another function in the DLL) - the check to see if each callabck is enabled or not takes very little time.

Examples:

1) The getUnitCostMod callback can be used to change the amount of production a unit takes to build. If a value other than -1 is returned then that value modifies the cost of the unit. Returning a 50 makes the unit cost 50% of the normal cost. Returning a 125 makes it cost 125% of the usual number of hammers to build.

2) There are a pair of callback functions called canConstruct and cannotConstruct. Both of these callbacks happen in the DLL's canConstruct function for the CvCity object. The canConstruct callback is called near the beginning of the function and if it returns True then the DLL's function exits immediately with a return value of True, skipping it's own checks. The cannotConstruct callback is called at the end of the DLL's function, after all of it's own tests - if it failed any of the tests the function would not get to it since it would already have returned False, but if all of the DLL's tests have been passed, meaning the building can be built, then it checks the callback and if the cannotConstruct callback returns True then the building cannot be constructed and the DLL's function returns Fals (overriding it's own determination that it could be built).
 
So you could say that the C++ code in the Core Game Engine DLL file is outsourcing some calls to Python. This is simply to accommodate easy access scripting for modders. So its possible to intersect the game at a number of junctures and make it run your own scripts. Basically all of these things could be done directly in the SDK, but Python has some advantages making it easier to work with for some things. (No speed advantages, obviously. :rolleyes:)
 
Im kind of confused on the rest thought, what does it mean when its no_month? i have no idea what NO_MONTH means. how do i debug the assert? Im using the debug dll, and ive really havent had to do this before, so im not sure what to do honustly:crazyeye:

There are many enumerations in the code (enum in C++). An enumeration is a collection of integer values into a group. The value -1 is used across the Civ code to mark a 'NONE' value. For many enumerations, the values are generated dynamically when reading the XML. For each 'XXXInfo' in the XML you have a matching enumeration.

For example: For the UnitInfos you have an enum called UnitTypes. It has a hard-coded value of NO_UNIT=-1, and all the other values are actually the indices of the infos in Civ4UnitInfos.xml (starting from 0). So the value of the first unit (I think UNIT_LION) is 0, the next one is 1 etc.

MonthInfos are also part of this, so NO_MONTH is -1 and the other values are determined by their order in the XML.

Debugging is a bit more complicated than simply replacing the DLL and requires some preparations (and installing Visual Studio). There's a tutorial in my signature if you're interested.
 
There are many enumerations in the code (enum in C++). An enumeration is a collection of integer values into a group. The value -1 is used across the Civ code to mark a 'NONE' value. For many enumerations, the values are generated dynamically when reading the XML. For each 'XXXInfo' in the XML you have a matching enumeration.

For example: For the UnitInfos you have an enum called UnitTypes. It has a hard-coded value of NO_UNIT=-1, and all the other values are actually the indices of the infos in Civ4UnitInfos.xml (starting from 0). So the value of the first unit (I think UNIT_LION) is 0, the next one is 1 etc.

MonthInfos are also part of this, so NO_MONTH is -1 and the other values are determined by their order in the XML.

Debugging is a bit more complicated than simply replacing the DLL and requires some preparations (and installing Visual Studio). There's a tutorial in my signature if you're interested.

Found my problem, realized the thing accidently started in 4000 BC, and my timeline goes by months, for w.e reason in BC you cant go by months, (im assuming BC but atleast that early you can)

@ the J or Asaf, you said (the j) that i should check the UB when i get that problem, what exactly am i looking for? i checked that all the actuall UB and UU are the ones in the xml files, and that all matech (but one and i fixed htat) and i still get errors, what exactly would the problem be? Would it be the problem with the actuall Unit or building, or would it be the connection between wich UB goes to which civ?
 
Two more questions:

1) Is there a method in the SDK to get the found date of a religion?

If not:

2) I have a variable in python that stores the found date of a certain religion. Is there any way to import it into SDK?
 
@Anthropoid: You'd need to learn to do SDK changes to do most of the stuff you've listed. (Perhaps python could be used for some if it, if you found good ways to fiddle with things.), check the link in Asaf's signature to get a start on that, alsolook for Xeienwolf's DLL (or SDK) tutorial, which should also provide some good info for getting started.

The health changes are relatively simple to do if you figure out some SDK modding. (I've added similar changes to a mod I'm working on, though haven't tested them yet as I'm working really slowly at the moment), The functions you'd need to change are in the CvCity.cpp folder. Most variables are named pretty effectively, so if you look for some sort of GreatPerson, GetYield, or such, you should be able to find the ones you need to change relatively quickly. You'll also need to adjust the textManager file in the DLL if you want ot display the effects properly. Some AI changes might be useful as well, although I'm not sure how someone would go about doing those.
 
Two more questions:

1) Is there a method in the SDK to get the found date of a religion?

If not:

2) I have a variable in python that stores the found date of a certain religion. Is there any way to import it into SDK?

You don't need to store it yourself since the game already knows (it has to, it shows the founded date on the religion screen).

In Python you can get the turn it was founded on via the CyGame.getReligionGameTurnFounded(eReligion) function. You can convert the turn to a date via a CyGameTextMgr function. This is taken directly from line 187 of CvReligionScreen.py:
Code:
szFounded = CyGameTextMgr().getTimeStr(gc.getGame().getReligionGameTurnFounded(i), false)

The method of doing it in the SDK's C++ code would be similar.
 
Back
Top Bottom