Quick Modding Questions Thread

I get this: [...]
Oh. That's a crash in the EXE, without any helpful context. Unexpected for a crash that occurs in between turns. Well, I guess it's really at the start of the human turn. It seems that CvGame::doTurn still gets fully executed before the crash (because the autosave happens before the crash, and I've seen CvDeal::doTurn on the stack in your earlier screenshots). CvGame::doTurn should return to CvGame::update:
Spoiler :
Code:
		if (getNumGameTurnActive() == 0)
		{
			if (!isPbem() || !getPbemTurnSent())
				doTurn();
		}
		updateScore();
		updateWar();
		updateMoves();
		updateTimers();
		updateTurnTimer();
		AI_updateAssignWork();
		testAlive();
If any of those subsequent calls in the DLL were causing the crash, then they'd probably appear on the call stack when the crash occurs in the EXE. More likely, after loading the autosave, the EXE calls CvGame::update once or several times and the crash occurs at some point after such a call while graphics are being updated. To make sure that the crash isn't occurring within the context of the DLL after all (as it says in VS: the call stack may be "incorrect or missing" frames), I'd set a breakpoint at the call to updateScore, load the autosave (my understanding is that the crash will then happen without any further user input), continue (F5) if/when the breakpoint is hit to first see how often CvGame::update gets called before the crash, then, for the last time that the breakpoint gets hit, step (F10) over the rest of CvGame::update to verify that the crash only occurs after CvGame::update has returned control to the EXE. But this might be too complicated and too little promising.

If the crash happens while updating graphics, then my best bet would be to experiment (remove stuff through WorldBuilder) or to systematically undo recent changes (incl. artwork changes).

So, unless someone sees an angle that I'm missing, I don't think the whole dance with the debugger will bear fruit here. But it might still come in handy for future problems.
 
If the crash happens while updating graphics, then my best bet would be to experiment (remove stuff through WorldBuilder) or to systematically undo recent changes (incl. artwork changes).
So I few things I tried and didn't work:

1) Decreasing building level display:

<DefineName>SHOW_BUILDINGS_LEVEL</DefineName>
<iDefineIntVal>131</iDefineIntVal>

No, it didn't do anything.

2) Enabling viewports:
Now this one is more interesting. I had the regular alert about FAssertMsg but the game now loads fine. I get a diplo popup, select a city that finished a building and skip giving orders to some units. I even get to the end of the turn and can finish it. Now saving the game. Turn viewports off, quit and reload normal game...

EDIT:
Nah! Loading the game without viewports resulted in a CTD again :mad:
 
Last edited:
So this purely graphical setting does reliably prevent the crash upon loading the autosave; at least that would seem to confirm that the game/ AI logic isn't at fault. Still curious that it didn't crash during anarchy turns. Maybe some city production getting completed? Well, I really have no experience tracking down artwork-related issues. :/
 
Maybe some city production getting completed?
I don't think. I finished a building in a city and could enter that city. I have even finished that building a few times before and its using Courthouse graphics (though the icon is different).
What other thing can it be? Perhaps an improvement upgrading to a different one? After all those don't upgrade during Anarchy. But how to find it? :dunno:
 
Would be easy enough to change this condition to if(false) (or to comment out the whole block – if the compiler complains about unreachable code when checking for false). Have you tried any heavy-handed WorldBuilder action? E.g. delete some AI cities, your own cities, or maybe just declare a war before ending the turn – does it still crash? Well, but, either way, I wouldn't really know what to make of that.
 
delete some AI cities, your own cities,
Which ones? There are around 300 :lol:

or maybe just declare a war before ending the turn
Okay, that made a difference. I declared war an everyone and the game really did proceed to the next turn. But what's the next move?

Now I will try to declare war only to some civs or just one if possible.

EDIT:
Okay, that's strange.

Case #1:
I DW on Spain (3rd on score board). Civ far on the same continent, so no battles at all. --> CTD

Case #2:
DW on the Iroquois (2nd on score board). Civ is on an other continent, so no battles to expect, therefore I expect a CTD again... but no. The game proceeded to next turn. I wonder if I really can continue my turn...

EDIT2:
Viewports are off.
 
Last edited:
I guess I was hoping that it would still crash regardless of declared wars, due to some ... bucket having filled up in your empire that could be narrowed down. But this seems too chaotic. I suppose any earlier version of the mod wouldn't be able to load your current savegame(?) - so you wouldn't be able to verify this way that the bug was recently introduced.
 
I suppose any earlier version of the mod wouldn't be able to load your current savegame(?) - so you wouldn't be able to verify this way that the bug was recently introduced.
I think I can try that...
 
I guess I was hoping that it would still crash regardless of declared wars, due to some ... bucket having filled up in your empire that could be narrowed down. But this seems too chaotic. I suppose any earlier version of the mod wouldn't be able to load your current savegame(?) - so you wouldn't be able to verify this way that the bug was recently introduced.
Nah! My saves seem to be incompatible backwards :(
 
Nah! My saves seem to be incompatible backwards :(
Okay, I was wrong about that. I just didn't set up the earlier properly.

I went back a whole year and the dll from @Inthegrave with a date of 18.11.2021. still CTD at the same turn.
 
I went back a whole year and the dll from @Inthegrave with a date of 18.11.2021. still CTD at the same turn.
Probably some XML or artwork change then. XML changes often aren't save-compatible, but maybe artwork changes can be rolled back. Or, if you've already tried that - the conslusion being that the bug is older than a year -, then maybe it'll somehow be easier to diagnose if and when it occurs in another game at some point in the future.
 
the conslusion being that the bug is older than a year
It seems to me, that it is older than a year. Since than the dll was edited first by @keldath and later by me too.

maybe it'll somehow be easier to diagnose if and when it occurs in another game at some point in the future.
We'll see. I just really don't want to start a new game. I'm playing this one for about a year now (have little time).
 
We'll see. I just really don't want to start a new game. I'm playing this one for about a year now (have little time).
Maybe there is some less intrusive workaround than a DoW on the Iroquois. E.g. signing or canceling OB with them, or getting them to change civics/ religion ...
 
When compiling the DLL is there a way to add some sort of logging? And if so where would the logs be found?
Also, is it possible to do this without going all the way down the path of a full on Debug DLL?
 
Maybe there is some less intrusive workaround than a DoW on the Iroquois. E.g. signing or canceling OB with them, or getting them to change civics/ religion ...
Well, I tried that: Canceled OB with every civ, including my own vassals but it still ends with a CD.

So, I'm sorry Iroquois people but the time-continuum of our world needs this war...
 
@PPQ_Purple: The BtS DLL doesn't have any compile-time switch for logging; the settings in CivilizationIV.ini (LoggingEnabled, MessageLog, RandLog) always work – but don't have much coverage. RandLog (requires MessageLog) logs all generated random numbers. CvEventManager.py has some settings for Python event logging (to PythonDbg.log; requires LoggingEnabled in the ini). If you use K-Mod – or another BBAI-based mod –, then there's the LOG_AI preprocessor define in BetterBTSAI.h. But this only covers (some) AI decisions. Requires LoggingEnabled in the ini, can be used with any compiler options. K-Mod also adds a define LOG_COMBAT_OUTCOMES in CvUnit.cpp that writes combat outcomes to a logfile named combat.txt. And the DLL-internal profiler, technically, also writes a logfile (IFP log.txt); don't know how exactly to enable that in BtS or K-Mod.

All logs should be in My Games\Beyond the Sword\Logs. There might also be a shortcut to that folder in the BtS install dir. Well, ThemeParseLog.txt gets created in the BtS install dir - not in the Logs folder, but that's not a very relevant log.

Edit: The BUG mod also logs in Python. Settings for that are on the System tab of the BUG Options screen.
 
Last edited:
Thank you but what I need is basically a way to add my own debug log messages into the DLL and read them later. And it does not seem that this is possible from what you say.
 
Oh, I really did misunderstand. There's CvDLLUtilityIFaceBase::logMsg(logFileName, …), and the singleton instance of that EXE-to-DLL interface is named gDLL. The logfile in the first argument gets created in the Logs folder if it doesn't exist yet. But a proper logging system with a compile-time switch and various levels does not exist. The BBAI log kind of has that, so maybe you could use the global logBBAI function for logging. But it's of course confusing to use that function when not dealing with AI behavior. And obviously you could add your own preprocessor defines.
 
I don't need any complexity at all. I just need to print messages for when I am working on a feature. And than when it's done I would remove them all. Like, if I could get them to pop up in the game or something that would be even better.

I am basically still learning DLL work so I just need a crutch.

Like, how do I print those in game messages that pop up on the side?
 
Last edited:
Well, then
gDLL->logMsg("mylog.log", "my msg");
or
gDLL->MessageBox("my msg", "title of box");
– but these will need a string variable for formatted output, e.g.
Code:
int CvGlobals::getInfoTypeForString(const char* szType, bool hideAssert) const
{
	// ...
	CvString szError; // (derived from std::string)
	szError.Format("info type %s not found, Current XML file is: %s", szType,
			GC.getCurrentXMLFile().GetCString()); // GetCString does the same thing as c_str
	// ...
	gDLL->logMsg("xml.log", szError);
	// ...
}
Though this might also work:
Code:
gDLL->logMsg("mylog.log",
		CvString::format("info type %s not found, Current XML file is: %s",
		szType, GC.getCurrentXMLFile().c_str()));
Or, with LOG_AI defined in BetterBTSAI.h,
Code:
if (gCityLogLevel >= 2)
	logBBAI("      City %S uses barb choose worker 1", getName().GetCString());
Or an on-screen message:
Code:
gDLL->getInterfaceIFace()->addMessage(
		GC.getGame().getActivePlayer(), // player ID of recipient
		true, // display immediately
		10, // duration (seconds)
		szBuffer); // CvWString, which derives from std::wstring; e.g. L"Hallo World"
Like, how do I print those in game messages that pop up on the side?
On-screen messages also go into the Turn Log on the left. Or do you mean the popups on the right, e.g. for random events? Code for launching those would be rather verbose.
 
Back
Top Bottom