Single Player bugs and crashes v38 plus (SVN) - After the 20th of February 2018

VERY new to C2C, and even newer to the SVN. I apologize if this has been covered elsewhere.

I just installed the SVN, and I'm missing the entire screen wrap. What I mean by this is, I can ONLY see the map and its contents. All buttons, information fields, etc are missing. I seem to recall having this problem once before with another mod, but I cannot seem to remember what the fix was. Can anyone tell me what option I've enabled or disabled that has left me with this problem?

For clarification purposes, the top is my C2C game. The bottom is a standard Civ game.View attachment 491358 View attachment 491359
Turn on playing as an administrator, make sure the mod folder is named Caveman2Cosmos, and start first by setting up a Play Now game, saving and getting out then setting up the game you actually want to play.
 
Hmm, so he want threshold reductions to act differently from threshold increases, I initially though Raledon's suggestion was only about reducing rounding errors. With that in mind I would have written it like this:
Code:
int CvCity::growthThreshold() const
{
    int iThreshold = GET_PLAYER(getOwnerINLINE()).getGrowthThreshold(getPopulation());
    int iDenominator = 1;
    int iNumerator = 1;
    int iThresholdModifier = GET_PLAYER(getOwnerINLINE()).getPopulationgrowthratepercentage();

    if ( iThresholdModifier < 0 )
    {
        iDenominator *= iThresholdModifier * -1 + 100;
        iNumerator *= 100
    }
    else if ( iThresholdModifier > 0 )
    {
        iNumerator *= iThresholdModifier + 100;
        iDenominator *= 100;
    }
    iThresholdModifier = getPopulationgrowthratepercentage();

    if ( iThresholdModifier < 0 )
    {
        iDenominator *= iThresholdModifier * -1 + 100;
        iNumerator *= 100
    }
    else if ( iThresholdModifier > 0 )
    {
        iNumerator *= iThresholdModifier + 100;
        iDenominator *= 100;
    }
    if (getNumCityPlots() == NUM_CITY_PLOTS)
    {
        iThresholdModifier = GC.getDefineINT("CITY_THIRD_RING_EXTRA_GROWTH_THRESHOLD_PERCENT");

        if ( iThresholdModifier < 0 )
        {
            iDenominator *= iThresholdModifier * -1 + 100;
            iNumerator *= 100
        }
        else if ( iThresholdModifier > 0 )
        {
            iNumerator *= iThresholdModifier + 100;
            iDenominator *= 100;
        }
    }
    if ( isHominid() )
    {
        iDenominator *= 2;    //    Those barbarians are just so damned fecund!
    }
    iThreshold *= iNumerator / iDenominator

    return std::max(1,iThreshold);
}
I know it looks a bit scarier, but it isn't all that difficult to grasp what is done mathematically.
I check if the modifiers are below 0 right away while Raledon multiply all the modifiers together and then check if the result is below 0.
I found the possible flip flopping between negative and positive value for the iThresholdModifier as somewhat confusing. ^^

This line is the only place where a rounding error would occur: iThreshold *= iNumerator / iDenominator

In Raledon's initial example there was two rounding error spots:
iThresholdModifier /= iDivide;
iThreshold /= iThresholdModifier;
I'll let Raledon comment to say if he can follow the code. At first glance it looks straight but I'd have to run numbers to be sure myself.
 
2. How do Aristocrates work? I thought they just increase GP rate without changing the odds. My typical strategy is to get as many Cultures as possible, build all possible Heroes and (after using them to build appriopriate Small Wonders) settle them in my Capital as Aristocrates (to increase GP rate) or, if not available, as Great Generals in my main military city. It seems they just increase the Great Artist probability - in my present game I avoided building most of GA spawning wonders in my Capital (Unlimited Wonders on), settled a lot of Aristocrates and the odds are: 42% Great Artist, 22% Great Prophet etc.
I'll have to check into the code. Hopefully it's not doing something silly like giving unassigned GP pt types by default to a GA or something.
 
@Cyrus317

1.Are you running as Administrator ?
2. Where did you place the Caveman2Cosmos mod, must be in the /BtS/Mods folder, not in My Documents.
3. Is the Mod's name you are using actually Caveman2Cosmos?
4. If yes to all the above you may need to clear/delete the cache folder contents found here: C:\Users\"Username"\AppData\Local\My Games\Beyond the Sword\cache . Other mods cached data for quicker loading can cause missing UI when you try a new mod.
 
@Thunderbrd ,

Just entered Classical Era and now all Mil units have lost their base Combat 1 promo or for Rangers their base Woodsman1 promo and/or both.
View attachment 491280

Here you see one of my rangers, it already has Woodsman II but now I can select I or III. This unit also Had Combat 1 but it was removed and is now offered as a "New" selection too. I only got to pick 1 promo so I took the Wood III. But clearly this is not working as intended, I hope. Lost my wood ! and Combat 1 to get a Wood III.

I have saved this game in the middle of this turn. If you want it I will upload it.
Pretty sure I figured this out. Was kinda complicated but your screenshot and report helped a LOT to show what might have gone wrong. I cannot help with errors in progress with the fix, but I can correct the underlying flaw at least, which was that Combat I is potentially assigned by a trait and was thus being removed from every unit that had it, whether given free or not, if you didn't have the trait that gives it. When doing another procedural fix I forgot that it was possible for traits to assign generic promotions from the skill based promo tree. Oops.
 
I have some stacks with trained dogs and hunters. After attacking, the trained dogs can have movement points left. Sometimes all commands except separate group disappear, so I have to reselect the stack to give the wait command.
 
I have some stacks with trained dogs and hunters. After attacking, the trained dogs can have movement points left. Sometimes all commands except separate group disappear, so I have to reselect the stack to give the wait command.
Yeah, that's how that would process. It gives you the opportunity to use the units that haven't used up their moves. I don't know how to resolve the limited commands issue when that happens though.
 
I have some stacks with trained dogs and hunters. After attacking, the trained dogs can have movement points left. Sometimes all commands except separate group disappear, so I have to reselect the stack to give the wait command.
Yeah, that's how that would process. It gives you the opportunity to use the units that haven't used up their moves. I don't know how to resolve the limited commands issue when that happens though.
I am now getting a similar problem sometimes when attacking a single unit with a single unit. In the case here a hunter just won against an elephant. It still has focus but has no actions.

BtW stack attack does appear to be working.
 

Attachments

  • hunter.jpg
    hunter.jpg
    371.3 KB · Views: 50
I am now getting a similar problem sometimes when attacking a single unit with a single unit. In the case here a hunter just won against an elephant. It still has focus but has no actions.

BtW stack attack does appear to be working.
OK... I might be able to fix it... get me a save from before that happens with instructions on replicating and I'll look into it further. Otherwise, the last bug of critical importance to address on my plate is the withdawal during an ambush by multiple units issue. But I'm still setup to study movement issues so I can maybe figure this out too... I don't know.
 
This is how I would've expressed the code you stated earlier, Raledon. I know it's just picky but if kept to this kind of indentation structure I can read the code much easier, even if it IS legal either way in the compile process.

No problem. I wrote it on the forums instead of the IDE so my indentation was fudged up. Didn't notice it- sorry for posting it without correcting it myself!

As for the math... I'm not really sure. With both of your examples I'm getting a bit lost in what we're trying to achieve exactly. My understanding is that the goal is to adjust the formula so that we can be more granular when we get into negative amounts of thresholdmodifier (aka getPopulationgrowthratepercentage from all sources). That it becomes divisional at that point as opposed to just reducing things down to a minimum of 1. Is that right? I suspect the code above is a touch more complex than necessary for that but I will probably need to think it through a lot more than I have.

The difference is the meaning of the %.
A) Currently (haven't changed yet) the meaning "how much food is needed".
B) After the change, it'll be "how slow will it the city grow".
So with +100% and base of 100, the city needs twice as much and grow at half speed, requiring an end result of 200 food. In this case, A and B give the same result.
With -50% and base of 100:
Option A will reduce the amount of food needed to 50. This means that the city will grow twice as fast. (with 600 food, the city will grow 12 times instead of 6)
Option B will reduce the amount of food needed to 67. This means that the city will grow 50% faster. (with 600 food, the city will grow 9 times instead of 6)

The problem with A is that stacking more of it is extremely efficient. in the above scenario, if the city got an additional -25%:
Option A requires 25 food, so the city will grow 4 times as fast (24 instead of 6)
Option B requires 57 food, the city will grow 75% faster.

We also open up the zone of -100% and below.

Hmm, so he want threshold reductions to act differently from threshold increases, I initially though Raledon's suggestion was only about reducing rounding errors. With that in mind I would have written it like this:
Code:
int CvCity::growthThreshold() const
{
    int iThreshold = GET_PLAYER(getOwnerINLINE()).getGrowthThreshold(getPopulation());
    int iDenominator = 1;
    int iNumerator = 1;
    int iThresholdModifier = GET_PLAYER(getOwnerINLINE()).getPopulationgrowthratepercentage();

    if ( iThresholdModifier < 0 )
    {
        iDenominator *= iThresholdModifier * -1 + 100;
        iNumerator *= 100
    }
    else if ( iThresholdModifier > 0 )
    {
        iNumerator *= iThresholdModifier + 100;
        iDenominator *= 100;
    }
    iThresholdModifier = getPopulationgrowthratepercentage();

    if ( iThresholdModifier < 0 )
    {
        iDenominator *= iThresholdModifier * -1 + 100;
        iNumerator *= 100
    }
    else if ( iThresholdModifier > 0 )
    {
        iNumerator *= iThresholdModifier + 100;
        iDenominator *= 100;
    }
    if (getNumCityPlots() == NUM_CITY_PLOTS)
    {
        iThresholdModifier = GC.getDefineINT("CITY_THIRD_RING_EXTRA_GROWTH_THRESHOLD_PERCENT");

        if ( iThresholdModifier < 0 )
        {
            iDenominator *= iThresholdModifier * -1 + 100;
            iNumerator *= 100
        }
        else if ( iThresholdModifier > 0 )
        {
            iNumerator *= iThresholdModifier + 100;
            iDenominator *= 100;
        }
    }
    if ( isHominid() )
    {
        iDenominator *= 2;    //    Those barbarians are just so damned fecund!
    }
    iThreshold *= iNumerator / iDenominator

    return std::max(1,iThreshold);
}
I know it looks a bit scarier, but it isn't all that difficult to grasp what is done mathematically.
I check if the modifiers are below 0 right away while Raledon multiply all the modifiers together and then check if the result is below 0.
I found the possible flip flopping between negative and positive value for the iThresholdModifier as somewhat confusing. ^^

This line is the only place where a rounding error would occur: iThreshold *= iNumerator / iDenominator

In Raledon's initial example there was two rounding error spots:
iThresholdModifier /= iDivide;
iThreshold /= iThresholdModifier;
I'd probably change it to work with a macro (to avoid the super long function), as your solution seems better.
 
I am now getting a similar problem sometimes when attacking a single unit with a single unit. In the case here a hunter just won against an elephant. It still has focus but has no actions.
This has been going on along with the other attack problems for a bit. I found I have to right click the unit to get the "commands" to re appear.
 
I'd probably change it to work with a macro (to avoid the super long function), as your solution seems better.
By macro (not familiar with that term in this context), do you mean a function like this:

int aFunction(int &iDenominator, int &iNumerator, int iThresholdModifier)
{
if ( iThresholdModifier < 0 )
{
iDenominator *= iThresholdModifier * -1 + 100;
iNumerator *= 100​
}
else if ( iThresholdModifier > 0 )
{
iNumerator *= iThresholdModifier + 100;
iDenominator *= 100;​
}​
}
That can be called over and over again in the function we are discussing like so?
Code:
int CvCity::growthThreshold() const
{
    int iThreshold = GET_PLAYER(getOwnerINLINE()).getGrowthThreshold(getPopulation());
    int iDenominator = 1;
    int iNumerator = 1;
    int iThresholdModifier = GET_PLAYER(getOwnerINLINE()).getPopulationgrowthratepercentage();
    aFunction(iDenominator, iNumerator, iThresholdModifier)

    iThresholdModifier = getPopulationgrowthratepercentage();
    aFunction(iDenominator, iNumerator, iThresholdModifier)

    if (getNumCityPlots() == NUM_CITY_PLOTS)
    {
        iThresholdModifier = GC.getDefineINT("CITY_THIRD_RING_EXTRA_GROWTH_THRESHOLD_PERCENT");
        aFunction(iDenominator, iNumerator, iThresholdModifier)
    }
    if ( isHominid() )
    {
        iDenominator *= 2;    //    Those barbarians are just so damned fecund!
    }
    iThreshold *= iNumerator / iDenominator

    return std::max(1,iThreshold);
}
 
By macro (not familiar with that term in this context), do you mean a function like this:

int aFunction(int &iDenominator, int &iNumerator, int iThresholdModifier)
{
if ( iThresholdModifier < 0 )
{
iDenominator *= iThresholdModifier * -1 + 100;
iNumerator *= 100​
}
else if ( iThresholdModifier > 0 )
{
iNumerator *= iThresholdModifier + 100;
iDenominator *= 100;​
}​
}
That can be called over and over again in the function we are discussing like so?
Code:
int CvCity::growthThreshold() const
{
    int iThreshold = GET_PLAYER(getOwnerINLINE()).getGrowthThreshold(getPopulation());
    int iDenominator = 1;
    int iNumerator = 1;
    int iThresholdModifier = GET_PLAYER(getOwnerINLINE()).getPopulationgrowthratepercentage();
    aFunction(iDenominator, iNumerator, iThresholdModifier)

    iThresholdModifier = getPopulationgrowthratepercentage();
    aFunction(iDenominator, iNumerator, iThresholdModifier)

    if (getNumCityPlots() == NUM_CITY_PLOTS)
    {
        iThresholdModifier = GC.getDefineINT("CITY_THIRD_RING_EXTRA_GROWTH_THRESHOLD_PERCENT");
        aFunction(iDenominator, iNumerator, iThresholdModifier)
    }
    if ( isHominid() )
    {
        iDenominator *= 2;    //    Those barbarians are just so damned fecund!
    }
    iThreshold *= iNumerator / iDenominator

    return std::max(1,iThreshold);
}

In a sense, yes.
The difference between macro and a function is in how the compiler handles them.
When you call a function, you change the state of the Stack memory, do stuff, and throw them away. This is why you needed to pass iDenominator and iNumerator as references.
A macro is a code's copy paste. The compiler will copy paste the macro, and then compile as normal.
In this case, the only differences between using macro or function is possibly DLL size and possibly runtime (but mostly that I don't like passing integer by reference). The reason for "possibly" is that using macro should save a bit of time at the cost of a bit of hard disk space, but the compiler/cpu might optimize better than such a change.
While I doubt there is any actual reason to, you can read more about macros here: https://gcc.gnu.org/onlinedocs/cpp/Macros.html
 
No problem. I wrote it on the forums instead of the IDE so my indentation was ****ed up. Didn't notice it- sorry for posting it without correcting it myself!



The difference is the meaning of the %.
A) Currently (haven't changed yet) the meaning "how much food is needed".
B) After the change, it'll be "how slow will it the city grow".
So with +100% and base of 100, the city needs twice as much and grow at half speed, requiring an end result of 200 food. In this case, A and B give the same result.
With -50% and base of 100:
Option A will reduce the amount of food needed to 50. This means that the city will grow twice as fast. (with 600 food, the city will grow 12 times instead of 6)
Option B will reduce the amount of food needed to 67. This means that the city will grow 50% faster. (with 600 food, the city will grow 9 times instead of 6)

The problem with A is that stacking more of it is extremely efficient. in the above scenario, if the city got an additional -25%:
Option A requires 25 food, so the city will grow 4 times as fast (24 instead of 6)
Option B requires 57 food, the city will grow 75% faster.

We also open up the zone of -100% and below.


I'd probably change it to work with a macro (to avoid the super long function), as your solution seems better.
I'm gonna trust you guys to sort this out. It sounds like you intend to change the meaning of the values established in the XML. Is that the case or does this just change how things process and the final conclusion of how it works? From what you're trying to explain, it's kinda soaring over my head how it's supposed to calculate but if I had more patience to try to figure it out I would. Suffice it to say, though I'm not trying to follow it enough to audit it, the end results sound very positive.
 
I'm gonna trust you guys to sort this out. It sounds like you intend to change the meaning of the values established in the XML. Is that the case or does this just change how things process and the final conclusion of how it works? From what you're trying to explain, it's kinda soaring over my head how it's supposed to calculate but if I had more patience to try to figure it out I would. Suffice it to say, though I'm not trying to follow it enough to audit it, the end results sound very positive.
Values for the relevant tag in xml above 0 will behave as we are used to, but values below 0 will behave differently in the sense that a tag value of -100 will not nullify the amount of food needed for growth. There will be a damping effect on food-threshold reductions defined in xml.

A value of -1 used to mean multiply by 0.99, now it means divide by 1.01
A value of -99 used to mean multiply by 0.01, now it means divide by 1.99
Values below -100 made no sense before as it would always result in a food threshold of 1, but now a value like -999 means that the threshold is divided by 10.99 and unless the base threshold is lower than 22 the result will be bigger than 1.
 
Last edited:
I am now getting a similar problem sometimes when attacking a single unit with a single unit. In the case here a hunter just won against an elephant. It still has focus but has no actions.

BtW stack attack does appear to be working.
Sorry but I cannot find a way to replicate. Not saying it isn't happening. I need to catch HOW it happens is the thing. I MIGHT have incidentally fixed it due to a code bug I found along the way here but I kinda doubt that was it. So yeah, if anyone can catch me a save right before this happens with instructions on replicating the effect, I'd be mighty appreciative.
 
Values for the relevant tag in xml above 0 will behave as we are used to, but values below 0 will behave differently in the sense that a tag value of -100 will not nullify the amount of food needed for growth. There will be a damping effect on food-threshold reductions defined in xml.
Perfect. Make it so guys!

@Raledon: just remember to update then recompile the final release and debug DLLs if your update pulls in a new dll/code files. I'm probably being a broken record by now but there's been a lot of code updates lately, including one I just committed.
 
SVN9991 forestry upgrade does not work for the warrior.
Should be corrected now with the fix to promos earlier today. Existing units in an existing game may not behave quite as they should but as games progress now, I suspect this is corrected.
 
I was wrong , this is getting very aggravating, sorry // / whereas my unit not only Master Hunter as before, do not move as they used to. i personally dont care about stack attack, that much, so pls have it the way it used to be on movement of individual units . .and not have this "blank" movement and then having to go back to that unit and click on it and then move it before it proceeds to next unit . . thx . .
 

Attachments

  • movement.JPG
    movement.JPG
    377.1 KB · Views: 59
Back
Top Bottom