Problems with mission' adding

Griffon.it

Chieftain
Joined
Feb 19, 2006
Messages
12
Hi to all
first of all sorry for my english. try to understand me :p

I have a problem when try to add a new "mission" for the great prophet. I want to found religion with this unit, not with tech discover (yes, there's already a mod that do it, True Prophet, but with sdk i would like to implement this feauter with mission, not with "built trick")

I'have opened the Assests/XML/Units/Civ4MissionInfos.xml, and i'have added a new <MissionInfo> tags, copy-paste from other great prophet mission (build the shirine in holy city):

Code:
		<MissionInfo>
			<Type>MISSION_JOIN</Type>
			<Description>TXT_KEY_MISSION_JOIN_CITY</Description>
			<Help>TXT_KEY_MISSION_JOIN_CITY_HELP</Help>
			<Waypoint>NONE</Waypoint>
			<EntityEventType>ENTEVENT_GREAT_EVENT</EntityEventType>
			<iTime>18</iTime>
			<bTarget>0</bTarget>
			<bBuild>0</bBuild>
			<bSound>0</bSound>
		</MissionInfo>
[B]		<MissionInfo>
			<Type>MISSION_FOUND_RELIGION</Type>
			<Description>TXT_KEY_FOUND_RELIGION</Description>
			<Help>TXT_KEY_FOUND_RELIGION_HELP</Help>
			<Waypoint>NONE</Waypoint>
			<EntityEventType>ENTEVENT_GREAT_EVENT</EntityEventType>
			<iTime>18</iTime>
			<bTarget>0</bTarget>
			<bBuild>0</bBuild>
			<bSound>0</bSound>
		</MissionInfo>[/B]
		<MissionInfo>
			<Type>MISSION_CONSTRUCT</Type>
			<Description>TXT_KEY_MISSION_CONSTRUCT</Description>
			<Help>TXT_KEY_MISSION_CONSTRUCT_HELP</Help>
			<Waypoint>NONE</Waypoint>
			<EntityEventType>ENTEVENT_GREAT_EVENT</EntityEventType>
			<iTime>18</iTime>
			<bTarget>0</bTarget>
			<bBuild>0</bBuild>
			<bSound>0</bSound>
		</MissionInfo>

At the header of this xml file i read "Changes must be reflected in CvEnums.h", so i'have opened this file in sdk and i'have added a new enumeration, in the same position of xml file (beetwen MISSION_JOIN and MISSION_CONSTRUCT):

Code:
	MISSION_JOIN,
	MISSION_FOUND_RELIGION,
        MISSION_CONSTRUCT,

Ok, then i have recompiled the core and i have launch the mod (i know that with this modding i don't change anything).
The mod init correctly, but if i try to start a new single player game, after loading, movie and intro popup, the game crash with the Windows dialog to send the log error to Microsoft.

I know tha in Documents/My Games/.../Logs folder i can find all the logs that civ4 generate, but in this log i don't find nothing that can help me with debug.

can someone help me?

thx :)
 
Griffon.it said:
Hi to all
first of all sorry for my english. try to understand me :p

Ok, then i have recompiled the core and i have launch the mod (i know that with this modding i don't change anything).
The mod init correctly, but if i try to start a new single player game, after loading, movie and intro popup, the game crash with the Windows dialog to send the log error to Microsoft.

I know tha in Documents/My Games/.../Logs folder i can find all the logs that civ4 generate, but in this log i don't find nothing that can help me with debug.

can someone help me?

thx :)

My guess would be that when your first unit gets selected, the core makes a check for all the actions that the unit can do. One of the actions it checks is your mission. Normally, it checks all the missions in a big switch statement, such as in CvSelectionGroup...

Spoiler :

Code:
bool CvSelectionGroup::canStartMission(int iMission, int iData1, int iData2, CvPlot* pPlot, bool bTestVisible)
{
	CLLNode<IDInfo>* pUnitNode;
	CvUnit* pTargetUnit;
	CvUnit* pLoopUnit;

	if (isBusy())
	{
		return false;
	}

	if (pPlot == NULL)
	{
		pPlot = plot();
	}

	pUnitNode = headUnitNode();

	while (pUnitNode != NULL)
	{
		pLoopUnit = ::getUnit(pUnitNode->m_data);
		pUnitNode = nextUnitNode(pUnitNode);

		switch (iMission)
		{
		case MISSION_MOVE_TO:
			if (!(pPlot->at(iData1, iData2)))
			{
				return true;
			}
			break;

		case MISSION_ROUTE_TO:
			if (!(pPlot->at(iData1, iData2)) || (getBestBuildRoute(pPlot) != NO_ROUTE))
			{
				return true;
			}
			break;

		case MISSION_MOVE_TO_UNIT:
			FAssertMsg(iData1 != NO_PLAYER, "iData1 should be a valid Player");
			pTargetUnit = GET_PLAYER((PlayerTypes)iData1).getUnit(iData2);
			if ((pTargetUnit != NULL) && !(pTargetUnit->atPlot(pPlot)))
			{
				return true;
			}
			break;

		case MISSION_SKIP:
			if (pLoopUnit->canHold(pPlot))
			{
				return true;
			}
			break;

[b]
.
.
....a whole bunch more missions snipped...
.
.
.[/b]

		case MISSION_BUILD:
			if (pLoopUnit->canBuild(pPlot, ((BuildTypes)iData1), bTestVisible))
			{
				return true;
			}
			break;

		case MISSION_BEGIN_COMBAT:
		case MISSION_END_COMBAT:
		case MISSION_AIRSTRIKE:
		case MISSION_SURRENDER:
		case MISSION_IDLE:
		case MISSION_DIE:
		case MISSION_DAMAGE:
		case MISSION_MULTI_SELECT:
		case MISSION_MULTI_DESELECT:
[b]		case MISSION_FOUND_RELIGION:
[/b]
			break;

		default:
			FAssert(false);
			break;
		}
	}

	return false;
}



Because it doesn't find your mission in that switch statement, it falls into the default. It runs that FAssert(false). Typically, in a final release build this is ignored, but it may be that it's causing the crash. Maybe try putting your found religion in with the other false's and see if it doesn't crash?

Without a good trace I'm not too sure, but that's my best guess.
 
Gerikes said:
[cut]

Because it doesn't find your mission in that switch statement, it falls into the default. It runs that FAssert(false). Typically, in a final release build this is ignored, but it may be that it's causing the crash. Maybe try putting your found religion in with the other false's and see if it doesn't crash?

Without a good trace I'm not too sure, but that's my best guess.

no, there is some else wrong. i have add a new case statement with the new enum, but it still crash.
a question: if game exit with the Windows dialog box with error info and "sent to microsoft" button, can i find in log files the line or files or something else about exact crash reason? i do this question beacuse i don't find anything in log folder... all the log are "clear", with no error coding...
 
Griffon.it said:
no, there is some else wrong. i have add a new case statement with the new enum, but it still crash.
a question: if game exit with the Windows dialog box with error info and "sent to microsoft" button, can i find in log files the line or files or something else about exact crash reason? i do this question beacuse i don't find anything in log folder... all the log are "clear", with no error coding...

I think the logs don't say anything because by the time the program needs to figure out what kind of error it is, the program already crashed. If you're using Visual Studio, your best bet is to make a debug build of the dll and use the debugger like that. Otherwise, perhaps find some c++ code that gives output to a log file, and put it at the beginning of a couple of functions, and see the last function that was started before the crash.

Short of writing your own logging function in c++, I'm not sure if the SDK code has their own logging functions, but you could try doing a generic event with python and then having a python event that prints for you.
 
NikG said:
A good idea when fiddling with the enums of the SDK, is to add the new ones, after the originals. I had the same problem, solved it with this. I think it has something todo with the SDK.

That's true. And now that you mention it, the python enumerators are probably out of sync, which could have been causing problems. Check out CyEnumsInterface.py and add yourself there too, making sure to be in the correct order (I would also recommend being at the end). If a python function is using the python enumerated list, it's missing yours, so everything after yours is off by one, which may put the code in a place it doesn't want to be.
 
thank u NicG, i have solved adding the new mission entry after all the originals in the xml file and after all the originals but before the NUM_MISSION_TYPES entry in CvEnums.h

thx all :D
 
i have an other problem, about the new mission.
Where do i find the code to insert in the interface the new button?
 
Griffon.it said:
i have an other problem, about the new mission.
Where do i find the code to insert in the interface the new button?

There's a mod-pack or two out there that allow for adding buttons, but I don't know how well they work with SDK changes such as this.


The way to do it that goes along with how they've set up buttons is as followed:

First off, don't think in terms of units, think in terms of SelectionGroups. Even if you have one unit selected, you're controlling a SelectionGroup, of which there is only one unit.

Next, in order for a SelectionGroup to have available it's mission, it needs to pass a test. The CvSelectionGroup::canStartMission is the test. Every time a SelectionGroup is selected, this function is run once for every mission available, sometimes more than once for each mission (checks to see if the MISISON_BUILD can build one of any number of improvements). If the function returns true, then the button is added. All the xml is what is needed to get the graphics set. Try putting your mission in the large switch statement in canStartMission and make it return true. This will be for any unit. if that works, then you can modify it to only be available to certain units.

I'm pretty sure that's how it works, but I could be wrong, so post back your results.
 
no, there's someelse wrong...
i'have add a new case statement that return always true in canStartMission function but with no result (a new game start but no unit have the mission button). I think that the core never call my mission...
 
Griffon.it said:
no, there's someelse wrong...
i'have add a new case statement that return always true in canStartMission function but with no result (a new game start but no unit have the mission button). I think that the core never call my mission...

I'm sure it can be done. I haven't added missions, but I have added automatizations, which are both checked almost the same way. To be more precise, before calling canStartMission for missions, there is one other function the core calls. CvGame::canHandleAction, which then upon determining that the action is a mission calls canStartMission. All missions, builds, automatizations, etc. are all collected into a category called actions, so hopefully yours is too.

One thing I just noticed is that your action doesn't have a button assigned to it. Try using one of the other missions (ones that look a bit longer and have a button at the end of them) as your guide, but keep everything else the same. I wonder if it's just because it doesn't have a button.

Otherwise, you might be able to help out your debugging by using the canHandleAction function, because this calls a python function that you can probably use to do some quick tests without recompiling (such as which actions are being checked for each unit, and using the gc.getActionInfo(iAction) functions to determine exactly what actions they are. Unfortunately the action numbers are generated, but you might be able to find yours by using gc.getActionInfo(iAction).getButton() to get the string of the button name.

I'm eventually going to have to do this too, so I'm hoping we can figure this out :P
 
i have copied-pasted a mission from someone that have a <Button> entry, but with some test i understand that the influent entry is <bVisible>: must be 1 :)
 
Back
Top Bottom