Mod-Modders Guide to Fall Further

I'm trying to add a few promotions. However they get things like 1494852 gold to purchase and requires level 435822732, rather than the more reasonable 40 and 3.

Does anyone know where to look for the problem?
 
Is there something wrong with this line?
Code:
						if (pLoopPlot->getBonusType(pCity->getTeam()) == GC.getUnitInfo(eUnit).getPrereqVicinityBonus())
Somehow, it seems to make my game CtD. Using a debug dll, it seems to crashes in CvPlot::getBonusType(CvTeam eTeam), on the m_eBonus check:
Code:
BonusTypes CvPlot::getBonusType(TeamTypes eTeam) const
{
	if (eTeam != NO_TEAM)
	{
		if (m_eBonusType != NO_BONUS)
		{
			if (!GET_TEAM(eTeam).isHasTech((TechTypes)(GC.getBonusInfo((BonusTypes)m_eBonusType).getTechReveal())) && !GET_TEAM(eTeam).isForceRevealedBonus((BonusTypes)m_eBonusType))
			{
				return NO_BONUS;
			}
		}
	}

	return (BonusTypes)m_eBonusType;
}
GetPrereqVicinityBonus() is returning an int.

Also, the code I used as a base came from 3.13.
 
It was pLoopPlot that was NULL; the original author didn't do the check. I realized this during the night; Thanks ;)
 
Alright, I'm in need of some assistance. :lol:

I've made an int and an Array, both applied to units.

iAppearanceProb - base probability for an animal unit to spawn, modified by a rand in the function.

AppearanceTechs - array of techs that affect the appearance probability. These techs can be owned by any player.
Code:
<AppearanceTechs>
    <AppearanceTech>
        <AppearanceTechType>TECH_MINING</AppearanceTechType>
        <iAppearanceTech>50</iAppearanceTech>
    </AppearanceTech>
</AppearanceTechs>

Now, my main problem at the moment is getting the proper tech out of the array... How do I go about this? It's based off the ProductionTrait code.

For reference, here's what I've got so far for the animal spawning:

Code:
int iAppearance = (GC.getUnitInfo(eLoopUnit).getAppearanceProb());
for (int iI = 0; iI < GC.getNumTechInfos(); iI++)
{
	if (GC.getUnitInfo(eLoopUnit).getAppearanceTechs(iI))
	{
		int iTech = iI;
		if (iTech != 0)
		{
			for (int iJ = 0; iJ < MAX_TEAMS; iJ++)
			{
				if (GET_TEAM((TeamTypes)iJ).isEverAlive())
				{
					if (GET_TEAM((TeamTypes)iJ).isHasTech((TechTypes)iTech))
					{
						iAppearance += (GC.getUnitInfo(eLoopUnit).getAppearanceTechs(iTech));
					}
				}
			}
		}
	}
}
if (iAppearance > -1)
{
	iValue = (1 + GC.getUnitInfo(eLoopUnit).getAppearanceProb() + getSorenRandNum(100, "Animal Unit Selection"));

	if (iValue > iBestValue)
	{
		eBestUnit = eLoopUnit;
		iBestValue = iValue;
	}
}

It compiles, and animals spawn according to their AppearanceProb, but the AppearanceTechs are not taken into account.
 
There should be plenty of examples in the DLL for this already. Look for a loop where the outter case is something like "If (RANDOMXMLCOMMAND(szName)", and then shortly after that they perform a "getInfoTypeForString(szName)" and then use that variable to set an item in the array after running another XML read command.
 
Here's my revised code: It appears to work. Or at least, after running autoplay for 100 turns, deleting all animals/barbs, granting myself Iron Working (Which is what I set dragons to spawn with), and running it for another 20 turns, there were dragons where before there were none. ;)

Could just be an artifact from the random weighting though, so I'm running it again.

Here's the code... I'd appreciate it if you could go over it real quick, see if there's anything wrong with it. :goodjob:

Code:
int iAppearance = (GC.getUnitInfo(eLoopUnit).getAppearanceProb());
for (int iI = 0; iI < GC.getNumTechInfos(); iI++)
{
    for (int iJ = 0; iJ < MAX_TEAMS; iJ++)
    {
        if (GET_TEAM((TeamTypes)iJ).isEverAlive())
        {
            if (GET_TEAM((TeamTypes)iJ).isHasTech((TechTypes)iI))
            {
                iAppearance += (GC.getUnitInfo(eLoopUnit).getAppearanceTechs(iI));
            }
        }
    }
}
if (iAppearance > -1)
{
    iValue = (1 + iAppearance + getSorenRandNum(100, "Animal Unit Selection"));

    if (iValue > iBestValue)
    {
        eBestUnit = eLoopUnit;
        iBestValue = iValue;
    }
}

Alright, I figured out why it wasn't working correctly. Mostly because I'm an idiot. :p

After figuring out a method to apply the AppearanceTechs to iAppearance, I neglected to increase iValue by iAppearance rather than the unit's AppearanceProb... Essentially, I left this:

Code:
iValue = (1 + GC.getUnitInfo(eLoopUnit).getAppearanceProb() + getSorenRandNum(100, "Animal Unit Selection"));

rather than this:

Code:
iValue = (1 + iAppearance + getSorenRandNum(100, "Animal Unit Selection"));

I've updated the larger code block to show the revised code, because there may be bugs I haven't noticed or a faster way to do it.

That said, it IS working. I assigned a low enough value from Iron Working to all animals but dragons that they couldn't spawn save from dens, and gave Dragons a high chance at the same tech... After giving myself Iron Working, all that spawned naturally were dragons. :goodjob:
 
For the XML loading, I forgot that what I am talking about is set up as a general structure for you in XMLLoadUtility, so just use SetVariableListTagPair and you'll be set. No need for a complicated load method.


The problem with your code is that you are only using the tech values to see if the unit is ALLOWED to spawn, you then return to the value in UnitInfos and ONLY that value to decide which of the legal units should spawn. Use something like this instead:

Code:
int iAppearance = (GC.getUnitInfo(eLoopUnit).getAppearanceProb());
for (int iI = 0; iI < GC.getNumTechInfos(); iI++)
{
    iAppearance += (GC.getUnitInfo(eLoopUnit).getAppearanceTechs(iI)) * countKnownTechNumTeams((TechTypes)iI);
}
if (iAppearance > -1)
{
    iValue = getSorenRandNum(iAppearance, "Animal Unit Selection");

    if (iValue > iBestValue)
    {
        eBestUnit = eLoopUnit;
        iBestValue = iValue;
    }
}


As for your edit, you WANT to use a random number still, as this is the PROBABILITY, and without a random, you will ONLY spawn the highest value unit which is allowed in the tile, ever.

Also notice that I removed a loop in the beginning, but only technically. The loop still is performed in the function now being called, but it makes this segment easier to read.
 
Trying to use the "fGold" tag in the CityBonus to subtract gold from a rival's city via a promotion. The info on the first page says:

Will transfer gold between Unit owner and City Owner each turn, or simply add/remove gold from the treasury if Owners are the same

Here is the tag that I am using:

Code:
				<CityBonus>
					<bApplyRival>1</bApplyRival>
					<fGold>-5</fGold>
					<fDiplo>-.05</fDiplo>
 				</CityBonus>

When I park the unit in the rival city, I can see that their maintenance costs go up by 5 because of "Units in the Vicinity", but I don't get any of that money. I know that there are some tricky outside-the-books calculations that happen for example, with Loki and his "entertain" spell, but I am running 100% science at the very beginning of a game, and I am not seeing any gold coming in at all. I have no maintenance, etc., to pay.

Thanks!
 
For the XML loading, I forgot that what I am talking about is set up as a general structure for you in XMLLoadUtility, so just use SetVariableListTagPair and you'll be set. No need for a complicated load method.


The problem with your code is that you are only using the tech values to see if the unit is ALLOWED to spawn, you then return to the value in UnitInfos and ONLY that value to decide which of the legal units should spawn. Use something like this instead:

Code:
int iAppearance = (GC.getUnitInfo(eLoopUnit).getAppearanceProb());
for (int iI = 0; iI < GC.getNumTechInfos(); iI++)
{
    iAppearance += (GC.getUnitInfo(eLoopUnit).getAppearanceTechs(iI)) * countKnownTechNumTeams((TechTypes)iI);
}
if (iAppearance > -1)
{
    iValue = getSorenRandNum(iAppearance, "Animal Unit Selection");

    if (iValue > iBestValue)
    {
        eBestUnit = eLoopUnit;
        iBestValue = iValue;
    }
}


As for your edit, you WANT to use a random number still, as this is the PROBABILITY, and without a random, you will ONLY spawn the highest value unit which is allowed in the tile, ever.

Also notice that I removed a loop in the beginning, but only technically. The loop still is performed in the function now being called, but it makes this segment easier to read.

Actually, that was a partial edit. Was in the middle of typing that I removed the rand in order to test it (That test failed) when I noticed the issue with iValue myself. :lol: Not sure why I saved the edit, should have just hit back... Already edited my above post describing my error, didn't know you'd posted here already. :p

The loop in the beginning is much better with your version though... Thank you. :goodjob:

Edit: Hmm... I take it this line takes the iAppearance value, and gets a random number within that value? Never seen it quite this way before, but I haven't really dug into the code yet.

Code:
iValue = getSorenRandNum(iAppearance, "Animal Unit Selection");
 
jrandrew: Probably it isn't working completely correct. I'll add it to the bug list so I remember to look and ensure that gold is returned to the unit owner.

Valk: Yes, this version gives you a random number from 0 up to the maximum appearance value. This way, ANY unit with a valid appearance value can show up. Your way, the only way you will have a chance between two units is if their appearance values are within 100 of each other. Now, you might WANT to shut off weaker animals without directly adjusting their appearance values based on the presence of a superior animal, but I think it is nice to continue to have the occasional wolf show up, even when the entire world knows iron working.
 
Valk: Yes, this version gives you a random number from 0 up to the maximum appearance value. This way, ANY unit with a valid appearance value can show up. Your way, the only way you will have a chance between two units is if their appearance values are within 100 of each other. Now, you might WANT to shut off weaker animals without directly adjusting their appearance values based on the presence of a superior animal, but I think it is nice to continue to have the occasional wolf show up, even when the entire world knows iron working.

Actually, wolves would still show up from their dens. :p

But yeah, I think it's a much more elegant way to do it. :goodjob:
 
You can ask the CyGame() for the number of times it has been completed universally, but if the ritual is set to refresh, that refresh is accomplished by lowering this number. I didn't set it up to still track the total number of times any ritual has been completed.

CyGame().getProjectCreatedCount(iProject)
 
Back
Top Bottom