adapt a script

If pUnit = gc.getUnitInfo(eUnit) – then, yes, that would be my best bet. And I agree that going via the unit class is a good way to deal with unique settler units.
the intention is no more settler after 5 cities, and only colonist from 6 to 7 cities, and neither of both after 7 cities
That looks correct to me then.
 
I think I didn't understand how to write the string, maybe I'm doing something wrong
 

Attachments

  • 1.png
    1.png
    25 KB · Views: 13
Either
Code:
pUnit = gc.getUnitInfo(eUnit)
if pUnit.getUnitClassType() ==
(etc.)
or in one line if gc.getUnitInfo(eUnit).getUnitClassType() == (etc.)
 
Sorry again, now this script is giving me an error
 

Attachments

  • 2.png
    2.png
    77.2 KB · Views: 7
  • 1.png
    1.png
    1.2 MB · Views: 10
Oh, I had assumed that you've defined that function (_addBuilding) somewhere and just didn't include that in the screenshots. Should be somewhere in the code that you've copied, probably based on setNumRealBuilding.
 
i added this part
but i have this error
 

Attachments

  • 1.png
    1.png
    638.5 KB · Views: 8
  • 2.png
    2.png
    76.9 KB · Views: 5
Last edited:
in this mod, it seems to work-I correct myself, I don't know why it only works for me, while the a.i. uses it but doesn't give buildings
 

Attachments

  • 2.png
    2.png
    80.2 KB · Views: 7
Last edited:
Ah, the head-selected unit exists only for human players. Not going to work correctly in networked multiplayer games either btw.

The relevant DLL code is (possibly a bit different in Realism Invictus):
Spoiler :
Code:
bool CvUnit::found()
{
	if (!canFound(plot()))
	{
		return false;
	}

	if (GC.getGameINLINE().getActivePlayer() == getOwnerINLINE())
	{
		gDLL->getInterfaceIFace()->lookAt(plot()->getPoint(), CAMERALOOKAT_NORMAL);
	}

	GET_PLAYER(getOwnerINLINE()).found(getX_INLINE(), getY_INLINE());

	if (plot()->isActiveVisible(false))
	{
		NotifyEntity(MISSION_FOUND);
	}

	kill(true);

	return true;
}
Code:
void CvPlayer::found(int iX, int iY)
{
	// ...
	pCity = initCity(iX, iY, true, true);
	// ...
	// (Init free buildings from start era)
	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		eLoopBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI)));

		if (eLoopBuilding != NO_BUILDING)
		{
			if (GC.getBuildingInfo(eLoopBuilding).getFreeStartEra() != NO_ERA)
			{
				if (GC.getGameINLINE().getStartEra() >= GC.getBuildingInfo(eLoopBuilding).getFreeStartEra())
				{
					if (pCity->canConstruct(eLoopBuilding))
					{
						pCity->setNumRealBuilding(eLoopBuilding, 1);
					}
				}
			}
		}
	}
	// ...
	CvEventReporter::getInstance().cityBuilt(pCity);
}
So the unit is actually still alive when the Python call occurs – CvUnit::found first calls CvPlayer::found and kills the unit only afterwards. CvPlayer::found creates the city, initializes free buildings in case that the game has started in an era later than Ancient (and also initializes free defenders for Barbarian cities; I've deleted that for the sake of brevity), then calls CvEventReporter::cityBuilt, which calls onCityBuilt in Python. The info which unit has founded the city is not passed along. If it's a human unit, then the head-selected unit should be a reliable way to identify that unit. In the case of an AI unit ... Python knows the city's coordinates. There could, in theory, be both a settler and a colonist at those coordinates. Probably it would be safe to look at the missions of the selection groups in the plot. While the AI doesn't select (multiple) units like a human player does, it still forms groups. And the group with the settler should be assigned the mission MISSION_FOUND at that point. And the first unit in that group able to found a city should be the correct one. I infer this from code in CvSelectionGroup::startMission:
Spoiler :
Code:
		while (pUnitNode != NULL)
		{
			pLoopUnit = ::getUnit(pUnitNode->m_data);
			pUnitNode = nextUnitNode(pUnitNode);

			if (pLoopUnit->canMove())
			{
				switch (headMissionQueueNode()->m_data.eMissionType)
				{
				case MISSION_MOVE_TO:
				// ...

				case MISSION_FOUND:
					if (pLoopUnit->found())
					{
						bAction = true;
					}
					break;
				// ...
				}
				if (getNumUnits() == 0)
				{
					break;
				}

				if (headMissionQueueNode() == NULL)
				{
					break;
				}
			}
		}
		// ...
I could try to write some Python code along those lines, but I don't think I'll want to set up the necessary context for testing it, so this could require some back and forth between us, and I'm not sure it'll ultimately work.
 
Here's a first attempt:
Spoiler :
Code:
def _getFoundUnit(city):
	cityPlot = city.plot()
	print "Looking for founding unit at " + str(cityPlot.getX()) + ", " + str(cityPlot.getY())
	print str(cityPlot.getNumUnits()) + " units in that plot"
	for iUnit in range(cityPlot.getNumUnits()):
		unit = cityPlot.getUnit(iUnit)
		# (Let's avoid encoding problems here if we can)
		print "Checking unit " + str(iUnit) #str(unit.getName())
		if not unit.isFound():
			print "Unable to found cities; dismissed."
			continue
		if unit.getOwner() != city.getOwner():
			print "Not owned by city owner; dismissed."
			continue
		group = unit.getGroup()
		print "Group ID is " + str(group.getID())
		if group.getLengthMissionQueue() <= 0:
			print "Group has no missions queued; dismissed."
			continue
		mission = group.getMissionFromQueue(0)
		if mission.eMissionType != MissionTypes.MISSION_FOUND:
			print "Head mission is not MISSION_FOUND; dismissed."
			continue
		print "This seems to be the founding unit"
		return unit
	print "Failed to identify a founding unit"
	return None
This would go somewhere at the bottom, maybe just before the definition of _addBuilding. (Doesn't really matter.) The print statements are just a temporary measure to help with debugging if necessary. And the pUnit = CyInterface().getHeadSelectedUnit() would be replaced with: pUnit = _getFoundUnit(city)
If it works at all, then it could also work for the human player, so I'd try to use _getFoundCity either way. Should also be easier to test for a human player first, and might also work in network games this way.

Edit: Just ran a quick test by just modifying BtS' original CvGameTextMgr.py, and, shockingly, it worked just like this, i.e. my own settler was correctly identified when I founded my first city, and, according to the printed statements, the AI settlers were also correctly identified when I ended my turn. Sample log output:
Spoiler :
Code:
PY:City Built Event: Beijing
Looking for founding unit at 53, 31

3 units in that plot

Checking unit 0

Unable to found cities; dismissed.

Checking unit 1

Unable to found cities; dismissed.

Checking unit 2

Group ID is 8192

This seems to be the founding unit
You might want to test a case where multiple settlers or a settler and a colonist are in the same plot, or maybe also a settler of another player. Or perhaps it's fine to just wait until that comes up naturally (maybe it'll never happen anyway).
 
Last edited:
I saw this one from platysettler, which does a similar thing, which works for both A.I. which in multi, I have attached an excerpt. hoping it can be of help
 

Attachments

  • 1.png
    1.png
    36 KB · Views: 5
i try :)These are the parts added so it should work?
 

Attachments

  • 1.png
    1.png
    103.5 KB · Views: 5
Last edited:
Looks good.

Yep, Platy has indeed written a similar function:
Spoiler :
Code:
	def GetSettler(self, pCity):
		iPlayer = pCity.getOwner()
		pPlayer = gc.getPlayer(iPlayer)
		(pUnit, iter) = pPlayer.firstUnit(False)
		while(pUnit):
			if pUnit.isFound():
				if pUnit.getX() == pCity.getX() and pUnit.getY() == pCity.getY():
					self.SettlerEffects(pUnit, pCity)
					break
			(pUnit, iter) = pPlayer.nextUnit(iter, False)
This one checks only whether the unit is in the correct tile, owned by the correct player and able to found cities. Does not check the group mission, so it might get the wrong unit in the unlikely event that multiple settlers are present.
 
last question. Do you think this script could work? meaning the creator says that when the era stops, the search bar goes back to 0%, can this be plausible?

obviously I delete self
 

Attachments

  • 1.png
    1.png
    47.8 KB · Views: 5
The way I read the code, it prevents Classical tech from being researched prior to the year 2000 BC, Medieval tech prior to AD 250 etc. And it looks like most of the iMaxEra= lines need to be indented one tab further for correct syntax.
 
I would like to add another variable in cannotrain for the settler, so that it can never happen that the colonist and the settler are on the same map at the same time, I tried to add the script indicated in red but it gives me an error..
 

Attachments

  • 1.png
    1.png
    54.6 KB · Views: 11
Last edited:
So Administration unlocks the colonist, and at that point the settler should become unavailable. Could perhaps also be achieved through XML, just by letting settlers upgrade to colonists. Well, maybe they're not supposed to upgrade or there is some other problem with this approach. But the general rule is that a unit becomes unavailable in a city once that city can train all the upgrade targets (if there are any).

Techs are tracked per team, and the function is named "isHasTech" (a bit of an odd choice; just "hasTech" would be canonical).
So it should be:
Code:
if gc.getTeam(pPlayer.getTeam()).isHasTech(gc.getInfoTypeForString("TECH_ADMINISTRATION")):
(The frequent use of numerical IDs alongside complex structures is unfortunate and leads to unwieldy code like this; CyPlayer.getTeam only provides the ID, CyGlobalContext.getTeam gets the team object from the ID ...)
 
you're right, except that I should modify the original realism invictus files, consider that there are I think about thirty types of settler units in the game. Then consider that in this way I could make the settlers obsolete before the tech administration, leaving a phase in which no city can be founded. now i try the script. thx.
work :) thx
my basic objective, in huge maps of the wprld,( I also created other very large ones) is create collected civilizations with 5 cities 2 spaces apart, so as to then create desolate spaces between civilizations, and then re-unlock the colonists and encourage the birth of very distant colonies. And by doing so, lightening the game in the final stages, considering that are huge maps whit 50 civilizations.
taking an idea from civilization 3, I modified the world scenario map of realism invicuts, enlarging it both in width and height, making Europe larger by a third, so as to balance the European nations with the African and Asian ones.I took a screenshot of the map for you. for gameplay it is much better to have a europe larger than 1/3 even if it is unreal
 

Attachments

  • 1.png
    1.png
    2 MB · Views: 14
Last edited:
Back
Top Bottom