[SDK]Finding the owner of a plot then checking their civics

Joined
Jun 27, 2007
Messages
2,248
Location
Hamilton, Ontario
Here's the code that counts forests and jungles to get the global warming defence value:
Code:
	int iGlobalWarmingDefense = 0;
	for (int i = 0; i < GC.getMapINLINE().numPlotsINLINE(); ++i)
	{
		CvPlot* pPlot = GC.getMapINLINE().plotByIndexINLINE(i);

		if (pPlot->getFeatureType() != NO_FEATURE)
		{
			if (GC.getFeatureInfo(pPlot->getFeatureType()).getGrowthProbability() > 0)
			{
				++iGlobalWarmingDefense;
			}
		}
	}
Now I want to determine the owner of the plot selected and then check their civics to see if they are running environmentalism. If they are, then add a value saved in GlobalDefinesAlt to iGlobalWarmingDefence, otherwise just add 1 like normal. Using this should get me the plots owner:
Code:
eCulturalOwner = pPlot->calculateCulturalOwner()
but I don't know what to use with eCulturalOwner to extract a true/false for them running environmentalism. I haven't been able to find somewhere in the code that checks for a specific civic so I can copy it. Anyone seen what I'm looking for?
 
but I don't know what to use with eCulturalOwner to extract a true/false for them running environmentalism. I haven't been able to find somewhere in the code that checks for a specific civic so I can copy it. Anyone seen what I'm looking for?
Untested but this is the general approach:
Code:
CivicTypes eEnvironmentalism = GC.getInfoTypeForString("CIVIC_ENVIRONMENTALISM");
bool bIsEnviro = GET_PLAYER(eCulturalOwner).isCivic(eEnvironmentalism);
It isn't optimal to hardcode a civic like that but it will probably work okay in this instance. The most mod-friendly approach would be something like giving the bonus for any civic that increases health. You might have to typecast the result of getInfoTypeForString like this:
Code:
CivicTypes eEnvironmentalism = (CivicTypes)GC.getInfoTypeForString("CIVIC_ENVIRONMENTALISM");
 
I think calculateCulturalOwner() recalculates who should own the plot, whereas you simply want the actual current owner. For that, just use getOwner().
 
Yeah, I thought it would be better to check the civic for a health bonus rather than check it's name too, but I ran into a dead end in what I could figure out. I found this:
Code:
if (kCivic.getExtraHealth() != 0)
which seems perfect so I go and check what kCivic is and got this:
Code:
	CvCivicInfo& kCivic = GC.getCivicInfo(eCivic);
I don't know that the first part does, but I looked up eCivic next:
Code:
CivicTypes eCivic = getCivics((CivicOptionTypes)(GC.getCivicInfo((CivicTypes)iJ).getCivicOptionType()))
Now what the heck is iJ?
Code:
for (iJ = 0; iJ < GC.getNumCivicInfos(); iJ++)
and that doesn't help me understand what iJ does so there's the dead end.
 
You want to loop over the civic option types (5), and for each grab the civic the player is running. For that civic, check its extra health.

Code:
bool bTreeHugger = false;
for (iI = 0; iI < GC.getNumCivicOptionTypes(); iI++)
{
    CivicTypes eCivic = GET_PLAYER(eCulturalOwner).getCivics((CivicOptionTypes)iI)
    if (GC.getCivicInfo(eCivic).getExtraHealth() != 0)
    {
        bTreeHugger = true;
        break;
    }
}

if (bTreeHugger)
{
    // enviromentalism ftw!
}

Note: I'm not testing this, and I haven't done any SDK coding yet, but the C++ at least should be good. :)
 
One further note is that you'll want to make sure you don't try to check the civics of a non-existent player such as when the plot is in neutral territory. So modifying EF's version:

Code:
PlayerTypes eCulturalOwner = pPlot->getOwner();
bool bTreeHugger = false;
if (eCulturalOwner != NO_PLAYER)
{
    for (int iI = 0; iI < GC.getNumCivicOptionTypes(); iI++)
    {
        CivicTypes eCivic = GET_PLAYER(eCulturalOwner).getCivics((CivicOptionTypes)iI);
        if (GC.getCivicInfo(eCivic).getExtraHealth() != 0)
        {
            bTreeHugger = true;
            break;
        }
    }
}

if (bTreeHugger)
{
    // enviromentalism ftw!
}
That would assume neutral territory is treated the same as non-enviro owned territory.
 
Good catch. Also, how about having more than on/off for the effect? For example, different levels for each of these:

  1. Neautral
  2. Owned but not workable
  3. Owned but not worked
  4. Worked
  5. Worked by environmental civ
Perhaps 1 and 2 should be the same. Maybe even 3 as well. But it seems that worked forests shouldn't provide as much of a benefit as those that are left alone. Forest preserves might seem different, but they are probably the same as virgin forests.

Also, if you find this function taking too long (checking the civics of a player for every plot) you could create an boolean array at the start and check all the players' civics before looping over the map.
 
Good catch. Also, how about having more than on/off for the effect? For example, different levels for each of these:

  1. Neautral
  2. Owned but not workable
  3. Owned but not worked
  4. Worked
  5. Worked by environmental civ
Perhaps 1 and 2 should be the same. Maybe even 3 as well. But it seems that worked forests shouldn't provide as much of a benefit as those that are left alone. Forest preserves might seem different, but they are probably the same as virgin forests.

Also, if you find this function taking too long (checking the civics of a player for every plot) you could create an boolean array at the start and check all the players' civics before looping over the map.
I'm going to get this, the last of the four features I first wanted to do done can call that the first version before I do any more. By the way, I don't know how to create a boolean array. Where would one find a boolean array I can look at because thinking about it this is a lot to do for every tile in the game.

Question, about If and Else:
Code:
If this
	If that
		If something
else
In this example I know that if "If this" fails then it goes to else, but what if it fails "If that" or "If something"? Does it go to the "else" on the line with the "if this" or would it only do an else if it was on the same level, requiring one for each. The else in this case is just doing the original add one to Global Warming Defense for when it's just a basic forest with no modifiers.
My original plan was to count the players, count the players with environmentalism and then increase the defence by the percentage of environmentalist states. So is 2/3 are environmentalist multiply the end result GWDefence by 1.66.
 
Code:
[B]abTreeHugger = new bool[MAX_PLAYERS];[/B]

for (int iI = 0; iI < MAX_PLAYERS; iI++)
{
    abTreeHugger[iI] = false;
    if (GET_PLAYER((PlayerTypes)iI).isAlive())
    {
        for (int iJ = 0; iJ < GC.getNumCivicOptionTypes(); iJ++)
        {
            CivicTypes eCivic = GET_PLAYER((PlayerTypes)iI).getCivics((CivicOptionTypes)iJ);
            if (GC.getCivicInfo(eCivic).getExtraHealth() != 0)
            {
                abTreeHugger[iI] = true;
                break;
            }
        }
    }
}

// ... loop over the plots ...

PlayerTypes eCulturalOwner = pPlot->getOwner();
if (eCulturalOwner == NO_PLAYER)
{
    // neutral
}
else
{
    // use abTreeHugger[eCulturalOwner] in calcs
    if (!pPlot->isPotentialCityWork())
    {
        // unworkable (by anyone or owner? I don't know)
    }
    else if (!pPlot->isBeingWorked())
    {
        // not worked
    }
    else
    {
        // worked
    }
}

[B]SAFE_DELETE_ARRAY(abTreeHugger);[/B]

Throughout the DLL I notice that speed was not a priority. Within a single function, the same value will be calculated multiple times by calling a function. While one might avoid early optimization, I actually find this makes the code very hard to read as you have to reread the same code to make sure the same calculation is being done.
 
Question, about If and Else:
Code:
If this
	If that
		If something
else
In this example I know that if "If this" fails then it goes to else, but what if it fails "If that" or "If something"? Does it go to the "else" on the line with the "if this" or would it only do an else if it was on the same level, requiring one for each.

Unlike Python, C++ ignores whitespace. It has no idea about indentation levels. C++ sees the above code like this:

Code:
if this
    if that
        if something
        else

You need to use braces to get your desired effect.

Code:
if this
{
    if that
        if something
}
else
 
Top Bottom