View Full Version : HOW TO: Isolate Crashes
Kael Jun 21, 2006, 12:44 PM [tab]Okay, you have finally done it. After many long hours you have the mod you always wanted to make. But then you, or someone else, try to play and it crashes. What do you do?
Isolation and Resolution
[tab]There are two steps to fixing problems, isolating to find out what piece of code is causing the problem and changing that code to resolve the issue. This article will only deal with isolation. Resolution is going to be specific to your code so I can’t offer general advice. The hardest part of fixing problems is isolating the issue, typically if you can do that resolution is easy.
The Changelog
[tab]Before we start talking through the steps it is important that you keep a changelog of the changes you are making between versions. Players will often give you a good indication of what was going on during the crash and if you have a good changelog you will be able to drill into the issue right away.
[tab]Changelogs become even more important as you start writing new functions. In these cases crashes may not be a problem in the function that crashes so much as in “bad” data passed to them. It is extremely frustrating to be working on a new crash in a function that hasn’t changed in forever and to have forgotten that you made a change to a related module that passed data to it.
Special note, the SDK changelog:
[tab]The changelog is good advice for modding, but if you are going to be making SDK changes it is mandatory. Not only is it required to help troubleshoot issues but you will need the changelog to convert all of your changes into the next SDK when Firaxis releases future patches.
[tab]The following is the format I use for SDK changes:
So that civs with the Scorched Earth Trait auto-raze cities (unless they created them)
Version: 0.12
CvPlayer.cpp CvPlayer::acquireCity()
if (bConquest)
{
//FfH: Modified by Kael 05/31/2006
// if (((pOldCity->getHighestPopulation() == 1) && !(GC.getGameINLINE().isOption(GAMEOPTION_NO_CITY_R AZING))) ||
// ((GC.getGameINLINE().getMaxCityElimination() > 0) && !(GC.getGameINLINE().isOption(GAMEOPTION_NO_CITY_R AZING))) ||
// (GC.getGameINLINE().isOption(GAMEOPTION_ONE_CITY_C HALLENGE) && isHuman()))
if (((pOldCity->getHighestPopulation() == 1) && !(GC.getGameINLINE().isOption(GAMEOPTION_NO_CITY_R AZING))) ||
((GC.getGameINLINE().getMaxCityElimination() > 0) && !(GC.getGameINLINE().isOption(GAMEOPTION_NO_CITY_R AZING))) ||
(GC.getGameINLINE().isOption(GAMEOPTION_ONE_CITY_C HALLENGE) && isHuman()) ||
(hasTrait((TraitTypes)GC.getInfoTypeForString("TRAIT_SCORCHED_EARTH")) && pOldCity->getOriginalOwner() != getID()))
//FfH: End Modify
{
[tab]It’s pretty self explanatory. It contains why the change was made, the version it was checked into, the file and function that was changed and the actual code. Notice when the code is changed the original code is always left in but commented out. I never remove “real” code, it is too important as a reference.
Step 1: Get a save
[tab]To fix a problem you are going to need a save game right before a reproduceable crash. Load up the save and verify that the crash occurs consistently. If the crash doesn’t happen then we can’t go any further. We will talk about intermittent issues later in this article.
The Little Hammer
[tab]Once we have a reproducible crash you can begin to isolate exactly what is going on in the save that is triggering the crash. I usually go through the following steps:
1. Remove all players except the player and one other in the Worldbuilder. See if the crash still occurs. If the Crash still occurs go to 2, if it doesn’t go to step 3.
2. If the crash still occurs with only the player and one other, we will need to delete more stuff. Remove all players except the player and one other again, but this time remove all of the units and cities for two existing players except for an empty city each. Make sure neither of these cities is finishing production the turn the crash occurs. If the crash still occurs go to the next section on ‘The Big Hammer’. If the crash doesn’t occur go to step 3.
3. Now that we have a save game where we can stop the crashes by removing a certain portion of the environment we have only to add pieces back until the crash happens again. This can get time consuming but I typically reload and only delete half of what I did the previous time (when the crash didn’t occur) and see of the crash still doesn’t happen. If it doesn’t repeat this step but delete even less. If it does repeat this step but only delete half of what I just added back in until I narrow down on the specific unit/action/city/etc that is causing the issue.
The Big Hammer
[tab]The Little Hammer doesn’t always work. Sometimes you can remove just about everything in the save game and it still crashes. The Big Hammer is another method of isolation that works at the mod level instead of within the save game. It is very useful for isolating python and SDK issues.
[tab]As above you will need a reproducible crash to test with.
1. If you are using an SDK mod rename the ‘CvGameCoreDLL.dll’ to ‘CvGameCoreDLL old.dll’. If the crash still occurs then you can assume that the problem isn’t in the SDK modified sections. If the crash no longer occurs then you have an SDK issue. You will have to go through your changelog (you do have a changelog right!) and review the changes that have been made in your latest version.
[tab]I keep all of the old CvGameCoreDLL.dll files from my versions so I can walk back through the changes until I find the first CvGameCoreDLL.dll that is broken, review the changes that were checked into that one and I should have my issue isolated.
2. If you aren’t using an SDK mod or removing the CvGameCoreDLL.dll didn’t fix your problem your next suspect is python. To rule out a python issue rename your python directory to ‘python.old’ then reload your save and see if the crash still occurs.
[tab]If it still occurs with your CvGameCoreDLL.dll and your python directory out of your way then you have to be looking at an XML issue and you should probably go back to the Little Hammer section and see what is still around to delete.
[tab]Assuming renaming the python directory keeps the crash from occurring you can start adding python file back until the crash returns and then see what changed in the last python file added since the last version. You could also swap in python directories from older version of your mod to see if those have the same issue (to prove if this crash is a new issue or if it has been around before).
Intermittent Issues
[tab]Intermittant issues are the worst! If they are extremely intermittent then they are almost impossible to trap because they may happen on only 1 out of 20 times. You may make a change that you think will fix it and load the save 40 times without a problem and you still wont know if you actually did anything to help with the issue or if you just got lucky.
[tab]Fortunatly since Civ4 saves the random generator these issues are less common. Even “random” events will occur exactly as before if no one consumes a random number they didn’t in the original.
[tab]For example I had a reproduceable crash that occured if I fortified my unit and ended the turn. If I used the unit to attack and kill a nearby barbarian the crash wouldn’t happen. So I spent hours trying to figure out what was up with that barbarian or the attacking unit that could have anything to do with the error. Then I tried to attack another unit with one of mine, again there was no crash. All I was doing with the attack was eating up some of the random numbers so that the actual random event that caused the crash didn’t occur. The lesson I learned from this was, if you have crashes related to random functions you need to make sure your actions are identical each time you reload the save, or your results won’t be meaningful.
Practice makes Perfect
[tab]I hope this helps. I plan on updating this article with me information and suggestions as I come across them. But don’t wait for me, post your own tips and tricks for isolating issues with mods in this thread!
Red Door Jun 21, 2006, 01:13 PM Wow! Nice job Kael, should help out a lot of mod-makers.
Kael Jun 21, 2006, 06:26 PM Wow! Nice job Kael, should help out a lot of mod-makers.
Thanks, I know to some of the community this will be information they already know but I think it may be of value to new modders.
Shqype Jun 21, 2006, 09:08 PM Thanks, I know to some of the community this will be information they already know but I think it may be of value to new modders.
True, but some of us already know because you've helped us out in the past ;)
Chalid Jun 27, 2006, 05:20 PM For locating problems i usually add some code in the SDK.
I have a log message that reports when the program enters a major part of the code and it reports back when it leaves the code.
Eg. It reports when AI player 1 begins the turn, then it reporte when the cities are all worked, when the cities are finished, then when it starts doing units, when the units are finished, ..., and finally when the entire player has finished its turn. Then the same thing for the next player.
This way i simply can look which action was begin but was not finished. That often gives a good clue where to look for your bug.
Kael Jun 27, 2006, 08:10 PM Could you provide some example code?
Chalid Jun 28, 2006, 03:13 AM I'll post some code sniplets this evening.
talchas Jul 10, 2006, 12:01 PM This is my logging function that I use in the SDK. Just stick this at the top of the cpp file after all of the #include statements to use it. Also, if you use it in multiple files, you need to give it a different name for each file (or do it properly and give it a header file that is included, but this is simpler, especially if each file uses its own logfile).
void logMsg(char* format, ... )
{
static char buf[2048];
_vsnprintf( buf, 2048-4, format, (char*)(&format+1) );
gDLL->logMsg("ai.log", buf);
}
This would log the messages that use this function to "Documents and Settings\<username>\My Documents\My Games\<whatever your civ4 dir is called>\logs\ai.log" not "program files\Firaxis Games\Civ4\anything".
you would call this exactly like printf - logMsg("message to log"); or logMsg("log:%d",aNumber);
Also, instead of using a changelog like Kael's, you might want to use version control if you can deal with it. It would allow you to save all the versions of the files so you know exactly what changes you made. I personally use Subversion for the spells code I wrote for FFH.
wotan321 Aug 04, 2006, 08:21 AM Could you shed some light on what the .log files tell us? How do we use the log files to isolate errors?
Thanks for this valuable thread, btw.
talchas Aug 04, 2006, 10:10 AM Well, its the standard printf method of debugging - you go to the area where you think the program is crashing + insert log statements like this:
someMethod(){
log("1");
<code>
log("2");
<code>
log("3");
...
}
where <code> is a few lines of the actual code. Then, after it crashes, you can go look at the log file. If the log shows
1
2
or even
1
2
3
1
2
3
...
1
2
you know that the CTD is occurring between the log("2") statement and the log("3") statement. (this is where java-style stacktraces, with line numbers would be really nice). However, this doesn't tell you exactly what the problem is (however, its almost certainly a null reference, the trick is finding out where and why), for that you need to do more debugging. You can print out a number like this: log("my number is:%d", mynumber) and it'll print something like this: "my number is:14". To print a string use %s instead of %d (for more info google for printf). If you want to tell if a given pointer is null you do one of these two things: either log("my pointer is this:%d", myPointer), which will print out 0 if it is null and some large number otherwise, or more properly log("my pointer is null:%d", myPointer==NULL), which will print "my pointer is null:1" if it is null and "my pointer is null:0" otherwise. However, even checking for nulls may not be enough as you might access a deleted object (this should rarely happen, as you should generally set any deleted references to NULL unless you are sure you don't have to). Then the best you can do is to try something like this:
someMethod(){
...
log("before");
log("%d", myPointer->someVariable); //or myPointer->someMethod();
log("after");
...
}
if it prints both "before" and "after" then the pointer is (probably) valid and the crash is somewhere else.
Isn't C++ debugging w/o a debugger fun? :crazyeye:
Lord Olleus Aug 31, 2006, 10:24 AM A simpler way of logging is to use gDLL->messageControlLog(char *), which prints to the MPLog. However, this only accepts char*and not wchar* which is what civ uses most of the time and converting one to the other can lead to some problems.
Jeckel Aug 31, 2006, 11:23 AM Instead of printing values and checks to the log, I have then print on screen in the game and to the ingame event log. That way you can see it right there without having to alt-tab and open the log file.
talchas Aug 31, 2006, 11:48 AM Only problem with that is that only so many messages will show up, and if one shows up, but then the program crashes immediately afterward, you may not see the message. Also, you can always run Civ in windowed mode, and have the file open in the background.
Houman Sep 12, 2006, 12:34 AM Thanks Kael for this wonderful thread.
And Many thanks talchas for your logging function. This is exactly where we at Total Realism are stuck. It is really hard to debug the SDK.
Regarding your code
void logMsg(char* format, ... )
What should the ... mean? More parameters?
Many thanks
Houman
talchas Sep 12, 2006, 05:11 AM That is one of the ways to define a variable argument list in C/C++ - I copied it from somewhere else in the SDK.
Kael Sep 12, 2006, 06:31 AM Thanks Kael for this wonderful thread.
And Many thanks talchas for your logging function. This is exactly where we at Total Realism are stuck. It is really hard to debug the SDK.
Np, if you get some time you should write a how-to on building an automated installed for a mod. Yours is really cool since it creates an icon on the desktop, adds an entry to add/remove programs and allows the player to select options during the install. I would love to know how to do all that.
Houman Sep 12, 2006, 02:24 PM Thanks Kael,
Yeah definitely its worth an artikel. I will publish it as soon as I fix these CTDs and prepare the Warlord release. Right now the community is close to throwing rotten eggs at us. :)
Houman Sep 14, 2006, 03:39 PM Gys,
I have problems: Some of the files are fine with the debugger function, others say:
cannot convert 'this' pointer from 'const Unit' to 'Unit &
I.e.:
bool CvUnit::isNukeVictim(const CvPlot* pPlot, TeamTypes eTeam) const
{
CvPlot* pLoopPlot;
int iDX, iDY;
// Dale - MAD: don't declare war on self
logMsg("CvUnit.cpp - 16");
if(getTeam() == eTeam)
{
return false;
}
.
.
.
I have already declared the method in each header file:
void logMsg(char* format, ... );
WHat shall I do please?
talchas Sep 14, 2006, 05:28 PM Try making that const void logMsg...
Houman Sep 17, 2006, 10:10 AM Try making that const void logMsg...
Ok by making the function itself to const void logMsg(...)
how do I call a const function from code?
Because now it says:
'CvUnit::logMsg' : cannot convert 'this' pointer from 'const CvUnit' to 'CvUnit &'
Thanks
Houman
Mexico Sep 17, 2006, 01:23 PM Np, if you get some time you should write a how-to on building an automated installed for a mod. Yours is really cool since it creates an icon on the desktop, adds an entry to add/remove programs and allows the player to select options during the install. I would love to know how to do all that.
Just for short info: we are using NSIS installer script (nsis.sf.net) for cerating this.
After releasing warlord Total realism mod, i found some time to write how-to with samples about this.
Of course, you can find all scripts (for our installers) in subversion repository of our mod
talchas Sep 17, 2006, 05:20 PM Whats odd is that logMsg shouldn't be associated with any class - it shouldn't be CvUnit::logMsg (unless you want it to be). Of course, its entirely possible that I've made it be that somehow given that my knowledge of C++ is mostly based on java knowledge + a bunch of fiddling.
When you stick logMsg in the headers, do you stick it inside the "class CvUnit {...}" section? If so, that may be why its thinking that it is defined in the object.
Lord Olleus Sep 30, 2006, 03:09 AM I can't seem to get logMsg (the one in CvDLLUtilityIFaceBase.h) to work in warlords. Has anybody figured out a way of debuging warlords?
Houman Sep 30, 2006, 03:41 AM Actually I have figured out a way, or better to say Mexico told me ;) ,
Delete all Logmsg() methods in all classes and set it only once in Defines.ccp and set only once its definition un Defines.h.
Thats it, now you can use it frm all classes without any problem.
Regards
Houman
Jean Elcard Jul 04, 2007, 06:38 AM Actually I have figured out a way, or better to say Mexico told me ;) ,
Delete all Logmsg() methods in all classes and set it only once in Defines.ccp and set only once its definition un Defines.h.
Thats it, now you can use it frm all classes without any problem.
Regards
Houman
Could you please be more specific about this? Can't find the file defines.cpp. Do I have to create it first?
Shqype Jan 03, 2008, 08:22 AM . .. .. .. .. .Okay, you have finally done it. After many long hours you have the mod you always wanted to make. But then you, or someone else, try to play and it crashes. What do you do?
Isolation and Resolution
. .. .. .. .. .There are two steps to fixing problems, isolating to find out what piece of code is causing the problem and changing that code to resolve the issue. This article will only deal with isolation. Resolution is going to be specific to your code so I can’t offer general advice. The hardest part of fixing problems is isolating the issue, typically if you can do that resolution is easy.
The Changelog
. .. .. .. .. .Before we start talking through the steps it is important that you keep a changelog of the changes you are making between versions. Players will often give you a good indication of what was going on during the crash and if you have a good changelog you will be able to drill into the issue right away.
. .. .. .. .. .Changelogs become even more important as you start writing new functions. In these cases crashes may not be a problem in the function that crashes so much as in “bad” data passed to them. It is extremely frustrating to be working on a new crash in a function that hasn’t changed in forever and to have forgotten that you made a change to a related module that passed data to it.
Special note, the SDK changelog:
. .. .. .. .. .The changelog is good advice for modding, but if you are going to be making SDK changes it is mandatory. Not only is it required to help troubleshoot issues but you will need the changelog to convert all of your changes into the next SDK when Firaxis releases future patches.
. .. .. .. .. .The following is the format I use for SDK changes:
. .. .. .. .. .It’s pretty self explanatory. It contains why the change was made, the version it was checked into, the file and function that was changed and the actual code. Notice when the code is changed the original code is always left in but commented out. I never remove “real” code, it is too important as a reference.
Step 1: Get a save
. .. .. .. .. .To fix a problem you are going to need a save game right before a reproduceable crash. Load up the save and verify that the crash occurs consistently. If the crash doesn’t happen then we can’t go any further. We will talk about intermittent issues later in this article.
The Little Hammer
. .. .. .. .. .Once we have a reproducible crash you can begin to isolate exactly what is going on in the save that is triggering the crash. I usually go through the following steps:
1. Remove all players except the player and one other in the Worldbuilder. See if the crash still occurs. If the Crash still occurs go to 2, if it doesn’t go to step 3.
2. If the crash still occurs with only the player and one other, we will need to delete more stuff. Remove all players except the player and one other again, but this time remove all of the units and cities for two existing players except for an empty city each. Make sure neither of these cities is finishing production the turn the crash occurs. If the crash still occurs go to the next section on ‘The Big Hammer’. If the crash doesn’t occur go to step 3.
3. Now that we have a save game where we can stop the crashes by removing a certain portion of the environment we have only to add pieces back until the crash happens again. This can get time consuming but I typically reload and only delete half of what I did the previous time (when the crash didn’t occur) and see of the crash still doesn’t happen. If it doesn’t repeat this step but delete even less. If it does repeat this step but only delete half of what I just added back in until I narrow down on the specific unit/action/city/etc that is causing the issue.
The Big Hammer
. .. .. .. .. .The Little Hammer doesn’t always work. Sometimes you can remove just about everything in the save game and it still crashes. The Big Hammer is another method of isolation that works at the mod level instead of within the save game. It is very useful for isolating python and SDK issues.
. .. .. .. .. .As above you will need a reproducible crash to test with.
1. If you are using an SDK mod rename the ‘CvGameCoreDLL.dll’ to ‘CvGameCoreDLL old.dll’. If the crash still occurs then you can assume that the problem isn’t in the SDK modified sections. If the crash no longer occurs then you have an SDK issue. You will have to go through your changelog (you do have a changelog right!) and review the changes that have been made in your latest version.
. .. .. .. .. .I keep all of the old CvGameCoreDLL.dll files from my versions so I can walk back through the changes until I find the first CvGameCoreDLL.dll that is broken, review the changes that were checked into that one and I should have my issue isolated.
2. If you aren’t using an SDK mod or removing the CvGameCoreDLL.dll didn’t fix your problem your next suspect is python. To rule out a python issue rename your python directory to ‘python.old’ then reload your save and see if the crash still occurs.
. .. .. .. .. .If it still occurs with your CvGameCoreDLL.dll and your python directory out of your way then you have to be looking at an XML issue and you should probably go back to the Little Hammer section and see what is still around to delete.
. .. .. .. .. .Assuming renaming the python directory keeps the crash from occurring you can start adding python file back until the crash returns and then see what changed in the last python file added since the last version. You could also swap in python directories from older version of your mod to see if those have the same issue (to prove if this crash is a new issue or if it has been around before).
Intermittent Issues
. .. .. .. .. .Intermittant issues are the worst! If they are extremely intermittent then they are almost impossible to trap because they may happen on only 1 out of 20 times. You may make a change that you think will fix it and load the save 40 times without a problem and you still wont know if you actually did anything to help with the issue or if you just got lucky.
. .. .. .. .. .Fortunatly since Civ4 saves the random generator these issues are less common. Even “random” events will occur exactly as before if no one consumes a random number they didn’t in the original.
. .. .. .. .. .For example I had a reproduceable crash that occured if I fortified my unit and ended the turn. If I used the unit to attack and kill a nearby barbarian the crash wouldn’t happen. So I spent hours trying to figure out what was up with that barbarian or the attacking unit that could have anything to do with the error. Then I tried to attack another unit with one of mine, again there was no crash. All I was doing with the attack was eating up some of the random numbers so that the actual random event that caused the crash didn’t occur. The lesson I learned from this was, if you have crashes related to random functions you need to make sure your actions are identical each time you reload the save, or your results won’t be meaningful.
Practice makes Perfect
. .. .. .. .. .I hope this helps. I plan on updating this article with me information and suggestions as I come across them. But don’t wait for me, post your own tips and tricks for isolating issues with mods in this thread!
Once again, this is a very helpful guide, Kael. But what does one do when he can identify when the crash occurs, but not what causes it?
BTS TAM (upgraded from Vanilla CIV 4) will give you a crash whenever a player advances to the Imperial Age via technology. Many users have come across this when they, or an AI player, discovers a technology from the Imperial Age. TAM has only 4 eras, Ancient, Bronze, Classical, and Imperial, all others were removed. The problem with this "CTD" is that the game never crashes, it just engages in an infinite loop and you're forced to shut down the game manually (thus no crash-to-desktop). It usually occurs during the AIs turn, and players find that the game hangs while "Waiting for other civilizations."
Similarly, if you gift yourself an Imperial Age tech/techs in the worldbuilder and then click on a city, you will get this infinite loop of python errors:
http://img263.imageshack.us/img263/4804/infiniteloopju9.th.jpg (http://img263.imageshack.us/my.php?image=infiniteloopju9.jpg)
The PythonErr.log shows this, repeatedly:
Traceback (most recent call last):
File "CvScreensInterface", line 705, in forceScreenRedraw
File "CvMainInterface", line 719, in redraw
File "CvMainInterface", line 1394, in updateSelectionButtons
RuntimeError: unidentifiable C++ exception
ERR: Python function forceScreenRedraw failed, module CvScreensInterface
It's obvious that the problem is with the Imperial Age, but it's difficult to find what is causing the infinite loop. Seven05 suggested to analyze the dump file, but because this is an infinite loop and not a CTD, there is no dump file to analyze. With Python and DLL removed, this still occurs.
In your experience and CIV 4 modding wisdom, what do you think could be causing this problem? And do you have any ideas how I could fix it?
Kael Jan 03, 2008, 08:59 PM Usually isolating the crash is the hard part, fixing it is easier (and hard to give general advice to since it depends on the cause).
In your case you probably have looping tech chain. Tech A requires Tech B which Requires Tech C which requires Tech A. When the AI considers what tech to research it walks down the tech line to see what they lead to. I suspect its walking through that looping tech chain forever which is causing the spinlock.
Check it out and see what you can find. If you don't see any issues post back here and send me another PM ping and I'll download TAM and take a look.
Shqype Jan 03, 2008, 09:07 PM Awesome Kael, thanks for your reply.
Only problem is, there was no such "bug" in vanilla TAM, and when I upgraded to BTS I didn't change the techs at all, save adding the necessary new tags that came with BTS.
Shqype Jan 08, 2008, 07:31 PM Kael, looking through CvPlayer.cpp I found the following which may be relevant to the issue TAM is having:
const TCHAR* CvPlayer::getUnitButton(UnitTypes eUnit) const
{
return GC.getUnitInfo(eUnit).getArtInfo(0, getCurrentEra(), (UnitArtStyleTypes) GC.getCivilizationInfo (getCivilizationType()).getUnitArtStyleType())->getButton();
}
And, perhaps more importantly, this:
void CvPlayer::setCurrentEra(EraTypes eNewValue)
{
CvCity* pLoopCity;
CvUnit* pLoopUnit;
CvPlot* pLoopPlot;
int iLoop;
int iI;
if (getCurrentEra() != eNewValue)
{
EraTypes eOldEra = m_eCurrentEra;
m_eCurrentEra = eNewValue;
if (GC.getGameINLINE().getActiveTeam() != NO_TEAM)
{
for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
{
pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
pLoopPlot->updateGraphicEra();
if (pLoopPlot->getRevealedImprovementType(GC.getGameINLINE().getA ctiveTeam(), true) != NO_IMPROVEMENT)
{
if ((pLoopPlot->getOwnerINLINE() == getID()) || (!(pLoopPlot->isOwned()) && (getID() == GC.getGameINLINE().getActivePlayer())))
{
pLoopPlot->setLayoutDirty(true);
}
}
}
}
// dirty all of this player's cities...
for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
{
if (pLoopCity->getOwnerINLINE() == getID())
{
pLoopCity->setLayoutDirty(true);
}
}
//update unit eras
for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
{
gDLL->getEntityIFace()->updateGraphicEra(pLoopUnit->getUnitEntity(), eOldEra);
}
//update flag eras
gDLL->getInterfaceIFace()->setDirty(Flag_DIRTY_BIT, true);
if (getID() == GC.getGameINLINE().getActivePlayer())
{
gDLL->getInterfaceIFace()->setDirty(Soundtrack_DIRTY_BIT, true);
}
if (isHuman() && (getCurrentEra() != GC.getGameINLINE().getStartEra()) && !GC.getGameINLINE().isNetworkMultiPlayer())
{
if (GC.getGameINLINE().isFinalInitialized() && !(gDLL->GetWorldBuilderMode()))
{
CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_PYTHON_SCREEN);
if (NULL != pInfo)
{
pInfo->setData1(eNewValue);
pInfo->setText(L"showEraMovie");
addPopup(pInfo);
}
}
}
}
}
Does this ring any bells in regards to the issue we are having? The techs and everything else seems fine, but when you enter the Imperial Era (which corresponds to and replaces the Renaissance Era), the game goes into an infinite loop where the AI is attempting to do something it cannot, or you get the python error messages when clicking on a city as noted a few posts above.
If you're able to look at TAM to give us a hand, TAM BTS v0.73 (http://forums.civfanatics.com/showthread.php?t=256196) is out.
Kael Jan 08, 2008, 08:42 PM I downloaded and took a look at the mod (great job by the way, I havent played TAM in ages and its even better than I remembered, I love the new icons). The CtD is coming from the worker unit, in your CIV4UnitArtStyleTypeInfos.xml you have the late era art definition of the workers set to ART_DEF_UNIT_WORKERMODERN, which doesn't exist in your art definitions.
You can either add that definition to your unit art definitions or change ART_DEF_UNIT_WORKERMODERN to be the same as the Early and Middle art definition.
Shqype Jan 08, 2008, 09:07 PM Kael has once again demonstrated his excellence in all things CIV 4. Many, many thanks Kael, on behalf of the TAM development team and TAM lovers everywhere!
woodelf Jan 09, 2008, 04:31 AM All Hail Kael. We can now play TAM for BtS!!!
Gaius Octavius Jan 10, 2008, 06:50 PM I downloaded and took a look at the mod (great job by the way, I havent played TAM in ages and its even better than I remembered, I love the new icons). The CtD is coming from the worker unit, in your CIV4UnitArtStyleTypeInfos.xml you have the late era art definition of the workers set to ART_DEF_UNIT_WORKERMODERN, which doesn't exist in your art definitions.
You can either add that definition to your unit art definitions or change ART_DEF_UNIT_WORKERMODERN to be the same as the Early and Middle art definition.
Believe it or not, I had an almost identical problem with a scenario I was doing. It was absolutely silly because I was worried about some kind of major error, and there were no usual "XML failed to load" kinds of messages. Crazy. :crazyeye:
Kailric Apr 04, 2008, 05:25 PM This is my logging function that I use in the SDK. Just stick this at the top of the cpp file after all of the #include statements to use it. Also, if you use it in multiple files, you need to give it a different name for each file (or do it properly and give it a header file that is included, but this is simpler, especially if each file uses its own logfile).
void logMsg(char* format, ... )
{
static char buf[2048];
_vsnprintf( buf, 2048-4, format, (char*)(&format+1) );
gDLL->logMsg("ai.log", buf);
}
This would log the messages that use this function to "Documents and Settings\<username>\My Documents\My Games\<whatever your civ4 dir is called>\logs\ai.log" not "program files\Firaxis Games\Civ4\anything".
you would call this exactly like printf - logMsg("message to log"); or logMsg("log:%d",aNumber);
Also, instead of using a changelog like Kael's, you might want to use version control if you can deal with it. It would allow you to save all the versions of the files so you know exactly what changes you made. I personally use Subversion for the spells code I wrote for FFH.
I put this in my CvUnits.cpp code and did all you said with adding logMsg.. but I am not finding a ai.log anywhere.. whats the deal?
Gaius Octavius May 10, 2008, 02:51 PM Here is an issue I've been experiencing as of late that might cause others undue trouble as well. I've been modding the SDK and testing it out in a modular scenario. Trouble is, whenever I try to load a saved game I get a weird crash almost immediately. New games load perfectly, however, and if I first start a new game from scratch, then reload the old saved game, it comes up fine. :crazyeye:
I went through my SDK changes and was stumped, since nothing appeared to be wrong. I finally switched from a modular to a regular mod, and the crash vanished. Since it was not an intermittent issue I have to assume it was caused somehow by the modular loading system, so I'd advise anyone with similar problems who is also using the modular system to convert to a regular mod and see if the crash still occurs. I don't know why this happens, but I've heard that it's happened to other people, too.
Am I wrong here, or is the modular system just prone to do these kinds of seemingly random things?
deanej Jun 20, 2008, 07:48 PM I have a crash that I can't really explain. When I play as the Borg civ (note: may actually be due to the leader I tested it on, not sure) in my Star Trek mod and select the IDIC tech to research, I immediately get a CTD. Researching IDIC with other civs works fine. As far as I know this did not occur prior to 3.17. Please advise.
|
|