Civic Attitude Modifier

That won't compile:

CvPlayerAI.cpp(18882) : error C2440: 'initializing' : cannot convert from 'CvCivicInfo' to 'CivicOptionTypes'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
CvPlayerAI.cpp(18886) : error C2228: left of '.getCivicAttitudeChange' must have class/struct/union type

Oh, and I triple checked CvInfos.cpp, there aren't any hidden -100's laying around anymore.
 
It sounds like we didn't need copyNonDefaultsReadPass2(). :lol: You should remove it entirely at some point to avoid confusion.

xienwolf's code needs a slight change:

Code:
[B]CvCivicInfo& kCivicOption[/B] = GC.getCivicInfo(getCivics((CivicOptionTypes)iI));
int iJunk = 0;
for (int iJ = 0; iJ < GC.getNumCivicOptionInfos(); iJ++)
{
    iAttitude += [B]kCivicOption[/B].getCivicAttitudeChange(GET_PLAYER(ePlayer).getCivics((CivicOptionTypes)iJ));
}

The strange thing is that a single change in civics results in a +200 or more shift. A +100 shift wouldn't be sufficient unless you were at -50 which can't happen assuming all values are +/- 100.
 
Rewrite your code slightly like this,
Check.
just so that you have a variable to do a mouseover on, and set a breakpoint on the line in red.
I'm not sure what a breakpoint is, but I think I set one.
Then run a debug DLL and you can place the mouse over eCivicOption and it will expand all data loaded on the civic option.
Now I'm completely lost...
 
Are you attaching Visual Studio to the running Civ4BeyondSword.exe process? If so, that means that the game is running "through" VS by having VS allow execution of each line of code while watching. You set a breakpoint probably by double-clicking in the left margin of the line where you'd like execution to stop.

Once that line is reached during the game, VS will take control and stop running there. You can inspect variable values and single-step line-by-line through the code, watching what happens.
 
Are you attaching Visual Studio to the running Civ4BeyondSword.exe process? If so, that means that the game is running "through" VS by having VS allow execution of each line of code while watching. You set a breakpoint probably by double-clicking in the left margin of the line where you'd like execution to stop.

Once that line is reached during the game, VS will take control and stop running there. You can inspect variable values and single-step line-by-line through the code, watching what happens.

I see. I did set the breakpoint correctly, I'll just have to look at the VS more closely.
 
The game should halt (freeze) when the breakpoint is hit, and you go to VS to inspect the variables and continue executing.
 
The game should halt (freeze) when the breakpoint is hit, and you go to VS to inspect the variables and continue executing.

Ugh. This means I have to set up the SDK in VS? I've never had any luck with VS. I've always used codeblocks...
 
Yes, Codeblocks cannot do the debugging, and debugging is VERY nice for things like this.

Thanks for the fix on the Mouseover variable, I haven't set those up often so I never remember how to do it right. If I had stopped to think for a moment I would have remembered that an enum carries no data, but I was nose-deep in python (ugh!) at the time, so wasn't thinking too straight :blush:
 
Those are memory addresses (locations)--not garbage. Arrays created using the "new" operator are stored in a different memory location, and the value m_paiFoo holds is a pointer to that location. You need to follow the pointers to see the data the arrays hold. There should be some way to pull kCivicOption into a separate pane so you can drill down into the arrays.
 
In the lower left pane ("Autos") you should be able to click on the "+" next to kCivicOption, then find your particular info. You may need to click another "+" next to it to get the list expanded. Give or take a click.
 
In the lower left pane ("Autos") you should be able to click on the "+" next to kCivicOption, then find your particular info. You may need to click another "+" next to it to get the list expanded. Give or take a click.

That isn't giving me any more useful information. I still think it's holding garbage.

See For yourself

Edit:
Oh, hehe, I was watching SW: IV.
 
In your first screenshot, within the mouseover you see a little + in a box on the left of the array name. Hover your mouse over that and it will expand to show you the actual contents of the array.

EDIT: Looking closer it would seem that you DID do that on the last array m_piCivicAttitudeChanges, and it contains a single INT of questionable value, potentially that is a MAX_INT or close to it, meaning an overflow issue. But also the size of the array is wrong. So something is going afoul in the loading/creating of your arrays.


EDIT 2: I highly recommend that you scroll to the VERY bottom of this screen, and in the dropdown on the far left select "Black CFC" it looks so much better ;)


EDIT 3: Ok, so I am slow at looking at screenshots.... Anyway, in your second screenshot I can see the variable types, m_piCivicAttitudeChanges is an int* like we want it to be, which is good, but holding only 1 value is bad, so set up some breakpoints in your copyNonDefaultsReadPass2 and compare the m_piCivicAttitudeChanges in pSource and this, that will show you what is TRYING to load, and what is being kept. If both of those are garbage, then place breakpoints in ::readPass2 so you can see what the values are while they load.
 
The value it is showing looks a lot like an address. In hex it's 0x1F9D029E which is not all that far from the addess of that value (about 7.5MB).

Isn't the value of m_piCivicAttitudeChanges itself an array? (Perhaps it ought to be named "m_paiCivicAttitudeChanges".)

I think you are seeing the address of the start of the array of values for the modifiers for this civic vs. the other civics. You still have not reached the actual data values.

Perhaps the way the value is declared is off by a "*" in one or more places, or perhaps Visual Studio is just not very clever. It's been a while since I've needed to do it, so I don't remember how - but there is a way to make it show you what you want to see by casting the contents of the location as a pointer to int then walking the list. Or something like that.
 
EDIT: Looking closer it would seem that you DID do that on the last array m_piCivicAttitudeChanges, and it contains a single INT of questionable value, potentially that is a MAX_INT or close to it, meaning an overflow issue. But also the size of the array is wrong. So something is going afoul in the loading/creating of your arrays.

I figured that that number was garbage... Great, back to CvInfos then.
EDIT 2: I highly recommend that you scroll to the VERY bottom of this screen, and in the dropdown on the far left select "Black CFC" it looks so much better ;)

I like Modern CFC, TYVM.

EDIT 3: Ok, so I am slow at looking at screenshots.... Anyway, in your second screenshot I can see the variable types, m_piCivicAttitudeChanges is an int* like we want it to be, which is good, but holding only 1 value is bad, so set up some breakpoints in your copyNonDefaultsReadPass2 and compare the m_piCivicAttitudeChanges in pSource and this, that will show you what is TRYING to load, and what is being kept. If both of those are garbage, then place breakpoints in ::readPass2 so you can see what the values are while they load.
Hmm. Okay, I'll try this.

Isn't the value of m_piCivicAttitudeChanges itself an array? (Perhaps it ought to be named "m_paiCivicAttitudeChanges".)

I think it's more of an array of an array. CivicAttitudeChange is the array, and CivicAttitudeChanges is the other int with the actual value. At least that's how I understand it...
 
Update:
I put breakpoints in both the noncopydefualts and noncopydefualtsreadpass2 functions, and onyl noncopydefualts breakpoints were set off, leading me to think we can just get rid of noncopydefualtsreadpass2, as it isn't being used. Otherwise though, all the date looked fine from that function.
 
It should definitely be called m_paiCivicAttitudeChanges. It is a pointer (p) to an array (a) of ints (i), each one being a CivicAttitudeChange. Of course, the name won't affect anything, but it will make maintaining the code easier if you match it to other variable names. Here's that standard naming convention thing again. ;)

It looks to me like the array is not being initialized after allocation. That's usually the cause of garbage values in an array. Doesn't InitList() initialize the array to all 0?

Yes, definitely get rid of copyNonDefaultsReadPass2(). I guess copyNonDefaults() belongs to readpass2() and copyNonDefaultsReadPass2() belongs to readpass3(). Brilliant! :rolleyes:
 
It looks to me like the array is not being initialized after allocation. That's usually the cause of garbage values in an array. Doesn't InitList() initialize the array to all 0?

What is showing looks like another address as much as it looks like garbage. Like, perhaps, the address of the array where the data is actually stored.

Why there would be the extra level of pointers, I don't know. The code should be examined to see what m_piCivicAttitudeChanges is really set to. I'm thinking it should hold the address of the first array element, but it looks like it is holding a pointer - possibly a pointer to the array with the data.

Unless the junk just happens to be an address, perhaps inherited from unreinitialized memory.
 
Do you have any modules which alter civics at all? It could be that it just doesn't run the copyNonDef unless needed. CND2 is indeed used for pass2, and CND is for pass 1. pass3 doesn't need a CND, it is handled during pass 1 and then again during the normal pass3.


So as long as we know that CND2 isn't running at all, we can ignore that and focus on your actual function for reading the values into the XML in the normal readPass2. You said those DID fire, so at least we know that the function runs. You also said that the results look normal, what results precisely, and how "normal" is normal? Did you do a breakpoint in the middle of reading to see what was being taken out of the XML, or one at the end of all the loops and just look at the finished product?
 
Do you have any modules which alter civics at all? It could be that it just doesn't run the copyNonDef unless needed. CND2 is indeed used for pass2, and CND is for pass 1. pass3 doesn't need a CND, it is handled during pass 1 and then again during the normal pass3.

No. My changes were to the main CivicInfos.xml file.

Okay, so I set a few more breakpoints. Here are screenshots of what happened. I'm pretty much stumped at this point.


Spoiler :

screenshot5.jpg


screenshot3.jpg


screenshot4.jpg


Yes. I do go to other forums too. Try not to comment too much.



Oh, and I just noticed, but I have a bunch of commented out code in CvPlayer, I've forgotten if It's needed.
 
Back
Top Bottom