question about the getCivics(CivicOptionTypes)

Kailric

Jack of All Trades
Joined
Mar 25, 2008
Messages
3,100
Location
Marooned, Y'isrumgone
I am trying to get this to work for Promotions where a certain Civic allows a promotion. The code compiles but I get a "infoclass was incorrect" if I add a civic to my CivicPrereq tag in my XML... then the promotion is always on. If I leave the CivicPrereq as NONE, the promotion is not allowed, but I get no erros. Somehow I am not getting the correct type of information transfered or something.

My code:
Code:
 if (GC.getPromotionInfo(ePromotion).getCivicPrereq() != NO_CIVIC)
	{    
         if (GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)6) != GC.getPromotionInfo(ePromotion).getCivicPrereq())
         {
            return false;
         }
         }

The FfH source code has this new option for units... how do I get it to work for promotions?
Example code:

Code:
//FfH Spell System: Added by Kael 07/23/2007
    int iI;
    CvPlot* pPlot = plot();
    if (m_pUnitInfo->isAbandon())
    {
        bool bValid = true;
		if (m_pUnitInfo->getPrereqCivic() != NO_CIVIC)
		{
            bValid = false;
            for (int iI = 0; iI < GC.getDefineINT("MAX_CIVIC_OPTIONS"); iI++)
            {
                [B]if (GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)iI) == m_pUnitInfo->getPrereqCivic())[/B]
                {
                    bValid = true;
                }
            }
            if (GET_PLAYER(getOwnerINLINE()).isAnarchy())
            {
                bValid = true;
            }
		}
		if (bValid == true)
		{
            if (m_pUnitInfo->getStateReligion() != NO_RELIGION)
            {
                bValid = false;
                if (GET_PLAYER(getOwnerINLINE()).getStateReligion() == m_pUnitInfo->getStateReligion())
                {
                    bValid = true;
                }
            }
		}
        if (bValid == false)
        {
            gDLL->getInterfaceIFace()->addMessage((PlayerTypes)getOwnerINLINE(), true, GC.getDefineINT("EVENT_MESSAGE_TIME"), gDLL->getText("TXT_KEY_MESSAGE_UNIT_ABANDON", getNameKey()), GC.getEraInfo(GC.getGameINLINE().getCurrentEra()).getAudioUnitDefeatScript(), MESSAGE_TYPE_INFO, m_pUnitInfo->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), plot()->getX_INLINE(), plot()->getY_INLINE());
            kill(true);
        }
    }
 
Well for anyone out there that can help... I managed to get a new PrereqCivic attribute for Units added to the game with this code:

Unit Code in CVplayer.cpp:

Code:
if (GC.getUnitInfo(eUnit).getPrereqCivic() != NO_CIVIC)
	{
	    bool bValid = false;
        for (iI = 0; iI < 6; iI++)
        {
            if (getCivics((CivicOptionTypes)iI) == GC.getUnitInfo(eUnit).getPrereqCivic())
            {
                bValid = true;
            }
        }
        if (bValid == false)
        {
            return false;
        }
	}

But this code below still gives me an "infoclass was incorrect" error when I load the game. Makes no sense at all.

Promotion code in CvUnits.cpp:
Code:
int iI;
    if (GC.getPromotionInfo(ePromotion).getCivicPrereq() != NO_CIVIC)
	{
	    bool bValid = false;
        for (iI = 0; iI < 6; iI++)
        {
            if (GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)iI) == GC.getPromotionInfo(ePromotion).getCivicPrereq())
            {
                bValid = true;
            }
        }
        if (bValid == false)
        {
            return false;
        }
	}

What is the problem??
 
I managed to get a new PrereqCivic attribute for Units added to the game with this code:

Code:
    if (GC.[COLOR="Red"][SIZE="3"]getPromotionInfo[/SIZE][/COLOR](ePromotion).getCivicPrereq() != NO_CIVIC)

What is the problem??

If you have a prerequ for units and not for promotion , here should be the problem .

Tcho !
 
If you have a prerequ for units and not for promotion , here should be the problem .

Tcho !

The units code works great.. in the game it does exactly what it is suppose to.. its the Promotion code I can't figure out. It does not work the same as with units code. I have to change something but havent figure it out yet.

Its this line in the Promotion code I need to fix...
Code:
if (GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)iI) == GC.getPromotionInfo(ePromotion).getCivicPrereq())
            {
                bValid = true;
            }
 
Here is another example code I use that also works:

Code:
if (GC.getPromotionInfo(ePromotion).getBonusPrereq() != NO_BONUS)
	{
	   [B] if (!GET_PLAYER(getOwnerINLINE()).hasBonus((BonusTypes)GC.getPromotionInfo(ePromotion).getBonusPrereq()))[/B]
	    {
	        return false;
	    }
	}

So, I tired this code:
Code:
if (GC.getPromotionInfo(ePromotion).getCivicPrereq() != NO_CIVIC)
{
	    bool bValid = false;
        
        {
           
           [B] if (GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)GC.getPromotionInfo(ePromotion).getCivicPrereq()))[/B]
            {
                bValid = true;
            }
        }
        if (bValid == false)
        {
            return false;
        }
}

But I get the same error. The parts in bold are what matter.. I can't see how in the hell none of the code works. And I checked the CvInfos and XMLs time and time again.
 
But , if the civic prereq is an attribute to the unit info class , it would not work unless you have added this attribute in the promotion info class . Have you done that ? ( that requires to add the attribute , change the promotion xml shema , add the functions in the sdk to read and get it .... ) . I think there is a tutorial done by Kael for that . If you don't have added this attribute to the promotion info class , this is obvious it can't get it .

Tcho !
 
But , if the civic prereq is an attribute to the unit info class , it would not work unless you have added this attribute in the promotion info class . Have you done that ? ( that requires to add the attribute , change the promotion xml shema , add the functions in the sdk to read and get it .... ) . I think there is a tutorial done by Kael for that . If you don't have added this attribute to the promotion info class , this is obvious it can't get it .

Tcho !

Yes.. all of that is in order, I know exacly what you are talking about cause I added all the lines for the PrereqCivic attribute in the Units. So, yeah.. all the necessary lines of code are there for the Promotion Civicprereq as well.

Also I named the units tag as PrereqCivics and the Promotion tag as CivicsPrereq so I could tell the difference.
 
I'm not sure about this because I'm unfamiliar with the inner workings of Kael's mod. The first thing I would check is that the code for the promotion is returning a member of the CivicTypes enum and not a string. Look in the XML loading code... are you casting from a String to CivicTypes?
 
I'm not sure about this because I'm unfamiliar with the inner workings of Kael's mod. The first thing I would check is that the code for the promotion is returning a member of the CivicTypes enum and not a string. Look in the XML loading code... are you casting from a String to CivicTypes?

This is whats in the XML schema if thats what you mean..

<ElementType name="CivicPrereq" content="textOnly"/>

Thanks for looking at this guys...driving me nuts. I finally was able to forget it for a while and move on to something else :P

Edit:
ANd this is in the Gameinfoschema

<ElementType name="CivicType" content="textOnly"/>
<ElementType name="CivicOptionType" content="textOnly"/>
 
Are you sure that there's a variable in the SDK that's been set up to pick up the value? It's not enough to just add the tags in XML--that's unfortunately just the first part. What you next have to do is go into the SDK and add scripts to pick up and store the value. If the variables haven't been added to the SDK, sadly, the new XML tags will never work.

The reason the code works when you use a value of NONE is that NONE is pre-defined in the SDK.

Kael wrote an excellent tutorial on how to add tags in XML and pick them up in the SDK.
 
Are you sure that there's a variable in the SDK that's been set up to pick up the value? It's not enough to just add the tags in XML--that's unfortunately just the first part. What you next have to do is go into the SDK and add scripts to pick up and store the value. If the variables haven't been added to the SDK, sadly, the new XML tags will never work.

The reason the code works when you use a value of NONE is that NONE is pre-defined in the SDK.

Kael wrote an excellent tutorial on how to add tags in XML and pick them up in the SDK.

Ahh.. that is what I believe it is.. was just looking over the code that makes the FfH work and there is one extra function call and I bet my bottom thats what I need to add.

Thanks for that tip.. I believe I can solve this now.

Its cool.. I know the very basics of programming and how arrays work but very little about object-oriented programing but as I am looking over the code and seeing examples its all starting to come clear.

Before I was just seeing only #$%Void BLAH, BLAH%&*( = #$@!)#Int($... now I am starting to see Blonds and Red Heads!
 
Well, I see where the problem is but I don't know how to fix it...

In the code that works it starts as...
Code:
void CvUnit::doTurn()
{
	PROFILE("CvUnit::doTurn()")

	FAssertMsg(!isDead(), "isDead did not return false as expected");
	FAssertMsg(getGroup() != NULL, "getGroup() is not expected to be equal with NULL");

	//TK added

	   bool bValid = true;
		if (m_pUnitInfo->getPrereqCivic() != NO_CIVIC)
		{
            bValid = false;
            for (int iI = 0; iI < GC.getDefineINT("MAX_CIVIC_OPTIONS"); iI++)
            {
                if (GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)iI) == m_pUnitInfo->getPrereqCivic())

The code that doesn't work has this at the top:

Code:
bool CvUnit::canAcquirePromotion(PromotionTypes ePromotion) const

Both of these codes are in the CvUnit.cpp

The GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)iI works with void CvUnit::doTurn() but not with the upbove. How can I get around this?
 
Well... I haven't figured out anything but that if you try to add a Civic requirement to Promotions it does some crazy crap.

Just by accident I had TECH_FISHING in the Civicprereq for the promotion. The game loaded fine. If I had the actually Civic listed I get an "infoclass was incorrect". I could also put in "UNITCOMBAT_NAVAL" or the like and it would load fine.. but "UNIT_WARRIOR" would not.

Then here is the craziest part. I had added a new Civic Category called "Military. And the Civics are Primitive, Conscription, Professional, Militia, and Holy War... in that order. I put TECH_FISHING as the requirement for Holy War for testing... and like I said TECH_FISHING was also the requirement for the Promotion "Crusade", by accident.

Now, the game loads fine. But the Promotion Crusade is always available right at the start. So I researched Fishing, and turned on the Holy War Civic...now the flippen Crusade Promotion is no longer acceptable. I can toggle it on and off using the Holy War Civic.. but the on and offs are right opposite of what I was trying to do!! :crazyeye:

I tried to duplicate this bug with other techs.. having both the same for Promotion and Civics but only FISHING has worked that way so far.

How in the hell does that do that????? :wallbash:

Someone please try to duplicate this. Adding a new Civic Category may have messed things I am.. I am going to test this when I get back from town later. But its strange that adding a Civic Requirement for Units has worked fine.
 
Okay, well, I can tell you right now that none of the code you've posted is the source of your problem, but some of the code you posted is wrong and will cause the game to crash.

That said, without seeing your XML files or your CvInfos.cpp code, I would assume that you've made the mistake in one of those two places because those are really the only two places that would cause the failure to load. One thing you should definitely do is use Internet Explorer to try to open the XML file. If it doesn't open in IE, you can be pretty sure it won't load in Civ. If it does open in IE, then the problem is probably in the CvInfos.cpp file and that would be what I would post next.
 
Thanks for your input. The XML loads just fine in IE. All I did was cut and paste working code mostly then changed the names. But it just seems to me when you use a Civic requirement for Promotions its not converting the requirement to integer or something. When I use Civic as a requirement for Units it works fine and they both have the same formate of using "m_i" and "int". Int means "its a number" right?

CvInfos.cpp: bold is what I added. Note the "PrereqOrPromotion3" I added works fine.
Code:
m_pbFeatureDoubleMove(NULL),
m_pbUnitCombat(NULL),
[B]// TK was here
m_iPrereqOrPromotion3(NO_PROMOTION),
m_iCivicPrereq(NO_CIVIC)
[/B]
{
}
----------------------------------------------
[B]int CvPromotionInfo::getCivicPrereq() const
{
	return m_iCivicPrereq;
}[/B]
----------------------------------------------
	stream->ReadString(m_szSound);
[B]//TK was here
	stream->Read(&m_iPrereqOrPromotion3);
	stream->Read(&m_iCivicPrereq);
[/B]
----------------------------------------------
	stream->WriteString(m_szSound);
[B]
//TK was here
	stream->Write(m_iPrereqOrPromotion3);
	stream->Write(m_iCivicPrereq);[/B]

CvInfos.h
Code:
[B]
	//TK was here
	DllExport int getPrereqOrPromotion3() const;
	DllExport void setPrereqOrPromotion3(int i);
	DllExport int getCivicPrereq() const;[/B]
----------------------------------------------
        int m_iKamikazePercent;
    [B]	//TK was here
	int m_iPrereqOrPromotion3;
	int m_iCivicPrereq;
[/B]

PS I removed the added Civic Category I mentioned and still the same error.
 
>>Int means "its a number" right?<<

You can think of it like that, but technically int is an integer (a whole number with no decimal places).

Also, what you posted is the read code for reloading the game from a saved game. What we need to see is the code you're using to read from the XML. That read function is called bool CvCivicInfo::read(CvXMLLoadUtility* pXML). Your code is going to look something like this (no assurances that what's posted below will work because I can't test it):

Code:
        CvString szTextVal;
        pXML->GetChildXmlValByName(szTextVal, "CivicPrereq");
	m_iCivicPrereq = pXML->FindInInfoClass(szTextVal);

However -- I think there may be a worse problem. Looking at the log of XML load orders, CivicInfos loads after Promotions. What this means is that the relationship isn't going to work because at the time the game is reading Promotion data, there is no Civic data to back it up. So what you will need to do, I think is reverse the relationship. The Civic needs to contain an array of structs listing which Promotions it allows. Sorry I didn't catch this earlier--you're actually moving into territory I've didnt start messing with until very recently.
 
Yeah, the code you posted is exactly the way I have it, I missed posting that for some reason. But you have to be right about the "load orders" cause there is something else going on that isn't easily seen.

But, I found a better way to do what I was wanting to do .. but still I was wanting to solve this in case I did want to add a Civic specific promotion.

K, so what you are saying is add the ability to Civics to add promotions, like they add +happiness and such?

Edit: I bet you could add a combat modifier based on Civics maybe.. and just add a note to the Civic display telling of the extra combat modifier

you're actually moving into territory I've didnt start messing with until very recently.

If you have an example of this or know of one post a link so we can check it out.
 
Take a look at how the Traits XML files give free promotions. I'm betting you could copy that format almost directly. I'd post an example but I am out of town all week with no access to my Civ IV stuff.
 
The load orders is definitely the problem.

Couple of things though:

1) You can get around this by having that tag load after the CivicInfos.

2) Having the civic be a prerequisite and having the civic give the promotion for free is two very different things, and you should keep that in mind when designing this.
 
The load orders is definitely the problem.

Couple of things though:

1) You can get around this by having that tag load after the CivicInfos.

2) Having the civic be a prerequisite and having the civic give the promotion for free is two very different things, and you should keep that in mind when designing this.

This problem can also accord in other areas. Like I was trying to add a combat modifier based on Civics but as above the Civic option could not be found correctly. I got around this by having the Civic grant a free promotion when you enter a city with a certain building, and made it so thats the only way to receive this new promotion. And then I just followed the examples of the "amphib" promotion tag, copied and pasted, then added the code for the combat modifiers and it worked out just fine.

1) Not sure I follow you on this.. what "tag" are you referring to exactly, and are you talking about XML loads or C++?

2) Yeah, I finally did figure out that that are two different things. I am not us to C++ but as I am looking over things I am starting to see what is happening.
 
Back
Top Bottom