[BTS SDK] Unlimited Colonies

moctezuma

Chieftain
Joined
Nov 16, 2001
Messages
52
Unlimited Colonies v1.0
Compatibility: Beyond the Sword

Download
http://forums.civfanatics.com/uploads/5028/Unlimited_Colonies.zip link is broken

New link to sources for BTS 3.13:
http://forums.civfanatics.com/attachment.php?attachmentid=229861&stc=1&d=1254593360


Installation Instructions

1) Unzip this into the <bts_install_folder>\Mods\ folder.
2) Start the game.
3) Load the mod.

Description of changes

BTS expansion introduces the concept of colonies but their usability is very limited: to create a colony you need at least 2 cities on different continent then your capital.

I like this idea, but I prefer to play on Pangaea maps, so I made some slight changes to the colony concept:

1. You can grant independence to ANY city except your capital and cities with significant amount of foreign culture. Such cities can be only liberated (i.e. gifted to other player) like in vanilla.

2. All accumulated culture in workable plots of new colony city (i.e. fat city cross) is transferred from original owner to new owner. No culture transfer happens if the same plot is also workable by some other city of original owner.

This change was necessary because in vanilla if new colony was created near rival borders; almost all workable plots were lost to rival; city collapsed due to starvation and all almost all resources were lost too.

3. Culture transfer in city plots happens also if you are liberating/gifting the city and receiver is your vassal/colony.

4. Original owner automatically receives espionage points against new colony. Points are calculated in the way that they are sufficient to investigate cities of recently released colony by original owner.

Notes to Modmakers

Package contains also changed SDK sources. Modmakers are free to use my code, as long as my nickname is supplied with it.
In the C++ files modified sections are enclosed by: "BEGIN UNLIMITED COLONIES" and "END UNLIMITED COLONIES".

Because with a new rules is creation of new colonies much easier you may want to increase 18 civilizations limit. Only variable that you need to change is MAX_CIV_PLAYERS (in CvDefines.h).
 

Attachments

This is a good idea. While I'm perfectly okay with the rule from vanilla restricting colonies to new continents, I think the idea that culture should be transferred from the mother civ to the colony is very logical. I was a little disappointed when I learned that this isn't how the case in the vanilla BtS.


May I ask what needs to be done to just have that change (the culture transfer) enacted?

Thanks.
 
May I ask what needs to be done to just have that change (the culture transfer) enacted?

Just replace method CvPlayer::splitEmpire with the following code:

Code:
bool CvPlayer::splitEmpire(int iAreaId)
{
	CvArea* pArea = GC.getMapINLINE().getArea(iAreaId);
	if (!pArea)
	{
		return false;
	}

	TeamTypes eNewTeam = NO_TEAM;
	PlayerTypes eNewPlayer = getSplitEmpirePlayer(iAreaId, eNewTeam);
	if (eNewPlayer == NO_PLAYER)
	{
		return false;
	}

	if (!GET_PLAYER(eNewPlayer).isAlive())
	{
		int iBestValue = -1;
		LeaderHeadTypes eBestLeader = NO_LEADER;
		CivilizationTypes eBestCiv = NO_CIVILIZATION;

		for (int i = 0; i < GC.getNumCivilizationInfos(); ++i)
		{
			bool bValid = true;

			if (!GC.getCivilizationInfo((CivilizationTypes)i).isPlayable() || !GC.getCivilizationInfo((CivilizationTypes)i).isAIPlayable())
			{
				bValid = false;
			}
			else
			{
				for (int j = 0; j < MAX_CIV_PLAYERS; ++j)
				{
					if (getID() != j && GET_PLAYER((PlayerTypes)j).isEverAlive() && GET_PLAYER((PlayerTypes)j).getCivilizationType() == i)
					{
						bValid = false;
						break;
					}
				}
			}

			if (bValid)
			{
				for (int j = 0; j < GC.getNumLeaderHeadInfos(); ++j)
				{
					bool bLeaderValid = true;
					if (!GC.getCivilizationInfo((CivilizationTypes)i).isLeaders(j))
					{
						bLeaderValid = false;
					}

					if (bLeaderValid)
					{
						for (int k = 0; k < MAX_CIV_PLAYERS; ++k)
						{
							if (GET_PLAYER((PlayerTypes)k).isEverAlive() && GET_PLAYER((PlayerTypes)k).getPersonalityType() == j)
							{
								bLeaderValid = false;
								break;
							}
						}
					}

					if (bLeaderValid)
					{
						int iValue = (1 + GC.getGameINLINE().getSorenRandNum(100, "Choosing Split Personality"));

						if (GC.getCivilizationInfo(getCivilizationType()).getDerivativeCiv() == i)
						{
							iValue += 1000;
						}

						if (getCivilizationType() == i)
						{
							iValue += 500;
						}

						if (iValue > iBestValue)
						{
							iBestValue = iValue;
							eBestLeader = (LeaderHeadTypes)j;
							eBestCiv = (CivilizationTypes)i;
						}
					}
				}
			}
		}

		if (eBestLeader == NO_LEADER || eBestCiv == NO_CIVILIZATION)
		{
			return false;
		}

		CvWString szMessage = gDLL->getText("TXT_KEY_MISC_EMPIRE_SPLIT", getNameKey(), GC.getCivilizationInfo(eBestCiv).getShortDescriptionKey(), GC.getLeaderHeadInfo(eBestLeader).getTextKeyWide());
		for (int i = 0; i < MAX_CIV_PLAYERS; ++i)
		{
			if (GET_PLAYER((PlayerTypes)i).isAlive())
			{
				gDLL->getInterfaceIFace()->addMessage((PlayerTypes)i, false, GC.getEVENT_MESSAGE_TIME(), szMessage, "AS2D_REVOLTEND", MESSAGE_TYPE_MAJOR_EVENT, ARTFILEMGR.getInterfaceArtInfo("INTERFACE_CITY_BAR_CAPITAL_TEXTURE")->getPath());
			}
		}
		GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szMessage, -1, -1, (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"));

		GC.getGameINLINE().addPlayer(eNewPlayer, eNewTeam, eBestLeader, eBestCiv);
		GET_PLAYER(eNewPlayer).setParent(getID());

		for (int i = 0; i < GC.getNumTechInfos(); ++i)
		{
			GET_TEAM(eNewTeam).setHasTech((TechTypes)i, GET_TEAM(getTeam()).isHasTech((TechTypes)i), eNewPlayer, false, false);
		}

		for (int iTeam = 0; iTeam < MAX_TEAMS; ++iTeam)
		{
			GET_TEAM(eNewTeam).setEspionagePointsAgainstTeam((TeamTypes)iTeam, GET_TEAM(getTeam()).getEspionagePointsAgainstTeam((TeamTypes)iTeam));
		}
		GET_TEAM(eNewTeam).setEspionagePointsEver(GET_TEAM(getTeam()).getEspionagePointsEver());

		GET_TEAM(getTeam()).assignVassal(GET_PLAYER(eNewPlayer).getTeam(), false);

		AI_updateBonusValue();
	}

	int iLoop;
	for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (pLoopCity->area()->getID() == pArea->getID())
		{
			int iCulture = pLoopCity->getCultureTimes100(getID());
			CvPlot* pPlot = pLoopCity->plot();

			// BEGIN UNLIMITED COLONIES
			GET_PLAYER(eNewPlayer).acquireCity(pLoopCity, false, false);
			// END UNLIMITED COLONIES

			if (NULL != pPlot)
			{
				CvCity* pCity = pPlot->getPlotCity();
				if (NULL != pCity)
				{
					pCity->setCultureTimes100(getID(), 0, false);
					pCity->setCultureTimes100(eNewPlayer, iCulture, true);
				}

				// BEGIN UNLIMITED COLONIES
				//culture in workable plots is transfered to new owner
				for (int iDX = -2; iDX <= 2; iDX++)
				{
					for (int iDY = -2; iDY <= 2; iDY++)
					{
						CvPlot* pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY);

						if (pLoopPlot == NULL || pCity->getCityPlotIndex(pLoopPlot) == -1)
						{
							continue;
						}
					
						if ((pLoopPlot->getWorkingCity() == NULL) ||
							(pLoopPlot->getWorkingCity() == pCity) ||
							(pLoopPlot->getWorkingCity()->getOwner() != getID()))
						{
							int iCulture = pLoopPlot->getCulture(getID());				
							pLoopPlot->setCulture(getID(), 0, false);					
							pLoopPlot->setCulture(eNewPlayer, iCulture, true);
						}
					}
				}

				pCity->AI_assignWorkingPlots();
				// END UNLIMITED COLONIES

				for (int i = 0; i < GC.getDefineINT("COLONY_NUM_FREE_DEFENDERS"); ++i)
				{
					pCity->initConscriptedUnit();
				}
			}
		}
	}

	return true;
}


If the culture transfer should be applied also for cities you give to existing vassal/colony you have to replace CvCity::liberate() method:

Code:
void CvCity::liberate()
{
	CvPlot* pPlot = plot();
	PlayerTypes ePlayer = getLiberationPlayer();
	PlayerTypes eOwner = getOwnerINLINE();

	if (NO_PLAYER != ePlayer)
	{
		int iOldOwnerCulture = getCultureTimes100(eOwner);
		int iOldMasterLand = 0;
		int iOldVassalLand = 0;
		if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(GET_PLAYER(eOwner).getTeam()))
		{
			iOldMasterLand = GET_TEAM(GET_PLAYER(eOwner).getTeam()).getTotalLand();
			iOldVassalLand = GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getTotalLand(false);
		}

		CvWString szBuffer = gDLL->getText("TXT_KEY_MISC_CITY_LIBERATED", getNameKey(), GET_PLAYER(eOwner).getNameKey(), GET_PLAYER(ePlayer).getCivilizationAdjectiveKey());
		for (int iI = 0; iI < MAX_PLAYERS; ++iI)
		{
			if (GET_PLAYER((PlayerTypes)iI).isAlive())
			{
				if (isRevealed(GET_PLAYER((PlayerTypes)iI).getTeam(), false))
				{
					gDLL->getInterfaceIFace()->addMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_REVOLTEND", MESSAGE_TYPE_MAJOR_EVENT, ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_CITY_EDIT")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"), getX_INLINE(), getY_INLINE(), true, true);
				}
			}
		}
		GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, eOwner, szBuffer, getX_INLINE(), getY_INLINE(), (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"));

// BEGIN UNLIMITED COLONIES
		GET_PLAYER(ePlayer).acquireCity(this, false, false);
// END UNLIMITED COLONIES
		GET_PLAYER(ePlayer).AI_changeMemoryCount(eOwner, MEMORY_LIBERATED_CITIES, 1);

		if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(GET_PLAYER(eOwner).getTeam()))
		{
			int iNewMasterLand = GET_TEAM(GET_PLAYER(eOwner).getTeam()).getTotalLand();
			int iNewVassalLand = GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getTotalLand(false);

			GET_TEAM(GET_PLAYER(ePlayer).getTeam()).setMasterPower(GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getMasterPower() + iNewMasterLand - iOldMasterLand);
			GET_TEAM(GET_PLAYER(ePlayer).getTeam()).setVassalPower(GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getVassalPower() + iNewVassalLand - iOldVassalLand);
		}

		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();
			if (NULL != pCity)
			{
				pCity->setCultureTimes100(ePlayer, pCity->getCultureTimes100(ePlayer) + iOldOwnerCulture / 2, true);
			}

			for (int i = 0; i < GC.getDefineINT("COLONY_NUM_FREE_DEFENDERS"); ++i)
			{
				pCity->initConscriptedUnit();
			}

// BEGIN UNLIMITED COLONIES			
			if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(GET_PLAYER(eOwner).getTeam()))
			{
				for (int iDX = -2; iDX <= 2; iDX++)
				{
					for (int iDY = -2; iDY <= 2; iDY++)
					{
						CvPlot* pLoopPlot = plotXY(pCity->getX_INLINE(), pCity->getY_INLINE(), iDX, iDY);

						if (pLoopPlot == NULL || pCity->getCityPlotIndex(pLoopPlot) == -1)
						{
							continue;
						}
					
						if ((pLoopPlot->getWorkingCity() == NULL) ||
							(pLoopPlot->getWorkingCity() == pCity) ||
							(pLoopPlot->getWorkingCity()->getOwner() != eOwner))
						{
							int iCulture = pLoopPlot->getCulture(eOwner);				
							pLoopPlot->setCulture(eOwner, 0, false);					
							pLoopPlot->setCulture(ePlayer, iCulture, true);
						}
					}
				}
				pCity->AI_assignWorkingPlots();
			}
// END UNLIMITED COLONIES			
		}
	}
}
 
Great. So I just need to copy & paste the code directly into the file? Nice.

Which file does this go into? (I'm kind of new to modding, so I don't know which files affect what features yet....)

EDIT: Oh, I see, so this was an addition to CvGameCoreDLL.dll itself, right? Can I make this change ONLY to the file in SOURCES and leave CvGameCoreDLL.dll unchanged? Reason I ask is because I want to use Solver's Patch, which is updated regularly. He provides an updated version of all the SDK files, but I want to use whatever changes he makes along with this mod. So all I want to do is leave Solver's files as-is, with the exception that I want to add just the code you've included above.

Make sense?
 
Oh, I see, so this was an addition to CvGameCoreDLL.dll itself, right? Can I make this change ONLY to the file in SOURCES and leave CvGameCoreDLL.dll unchanged?
Unfortunately it is not so easy for SDK mods. You have to build a new CvGameCoreDLL.dll using Visual Studio NET. I don't recomend to do if you don't have any experience with C++.
Reason I ask is because I want to use Solver's Patch, which is updated regularly. He provides an updated version of all the SDK files, but I want to use whatever changes he makes along with this mod. So all I want to do is leave Solver's files as-is, with the exception that I want to add just the code you've included above.
This is possible only if he provided an updated sources for his DLL. Otherwise you will have to wait for next official patch where most of his changes should be included.
 
This mod is great it was just what I was looking for. I would very much like to use it with an increased number of civs. I found the cvdefines folder and changed the option to 40 in my main game folder but it didnt work. I couldnt find any folder in the files of your MOD. Can you make it so I can play with more than 18. I also noticed that Blue marble doesnt work when you use the MOD. Thanks
 
This mod is great it was just what I was looking for. I would very much like to use it with an increased number of civs. I found the cvdefines folder and changed the option to 40 in my main game folder but it didnt work. I couldnt find any folder in the files of your MOD. Can you make it so I can play with more than 18. I also noticed that Blue marble doesnt work when you use the MOD. Thanks
Here is a version with civ limit increased to 34. Use it on your own risk because BTS has a stabilty problems if number of civs is > 18. The performance of game is affected too. Existing saves are not compatible, you have to start a new game.

Download:
http://forums.civfanatics.com/uploads/5028/Unlimited_Colonies_34.zip
 
Thankyou very much. I am only actually using about 19 civs for a european map I really like. I will test this out and let you know.

Thanks again
 
I just wanted to let you know that the mod is working great with my extra large map. I will post my map tomorrow along along with a second posting of your mod in the pre made maps section. it also appears to be working well with a couple of BTS custom civs added in.

Thanks again
 
I forgot to say blue marble does not work but i can live without it for this mod but it would be good if you could fix this at a later date or give some advice about it.
 
Really useful mod. I suppose lots of what I complain about colonies might be solved here.

I'm gonna try playing it as soon as I get home and will return some feedback.
 
And now for some feedback
I will tell the history of my game. Skip to the bottom if you rather see just what I figured of the mod's working logic.

I'm currently playing a regular sized map, fractal, usual setup for everything else. Some low difficulty i'm unsure which now. Me as the portuguese with 3 AI as The Portuguese (I was checking if that could be done :P) and another AI as the celts.

My game plan was pretty simple. conquer the whole continent (which had all the other portuguese in it, Celts were in a island not so close) and replace them with colonies which would remain friendly and vasals for a while, giving me basicly very little competition.

So I started wars with every other portuguese nation and finally conquered all of them BUT one little bastard that managed to build a city in a close island. Anyway, he was out of the continent landmass, so I made peace with him.

I did my first colony while I was near to wipe the second neighbour (which I never wiped... it was the bastard who ran for the island) and that went well. Just a little note: Every time I make a colony, the first one is America. I guess this is built on the code. Bit weird to have the U.S. born from the portuguese, although.

When I noticed that my second neighbour was not wiped out and found his city in the island, I turned to wage war on my 3rd and last neighbour, and for that, I tried to make my second colony. Didn't work. The cities wanted to be liberated to their former nation, not be made into a new one. Well, I guess that's ok, although it isn't the way I wanted things to be...

I tried then to make the second colony out of the capitol of my 3rd neighbour. They actually could be made independent, but they had pyramids and stonehenge, so, on a second thought, I waited for a more suitable city to make it my second colony. I hadn't destroyed my 3rd neighbour 'cause they really had time to grow while I was out destroying everyone else, so I thought there would be another city for that later. And I was right.

Most cities of my 3rd neighbour I razed, couldn't afford many cities without a second colony. But I got in hold of his second capitol (I already had captured the original one, as I said), and a bit afterwards, his last city was razed. His second capitol could, then, become my second colony, Rome.

In the end I achieved my objective but partially. I wanted to have 3 colonies. Currently, I don't think I want that anymore. I got the secret palace AND Versailles built in very strategic places, which is a first for me, and really took care of the costs, even before I had nationalism. I wouldn't even need State Propriety. However, objective failed. I may still be able to achieve it, if I conqueer the remaining Portuguese in the island (the poor think only have 2 cities, would be a walk in the park) and grant the island independence. Might be done, if, of course, they don't decide that their new motherland is one of my current colonies...

Anyway, I gave the AI no space to create their own colonies. I was at war with each of them for enough time to discourage expansion, and the celts are really slow on tech, and till they get astronomy they won't expand. The first colony, however, expands well. Maybe they will make a colony at some point, if they stop being my vassals. You can't have a vassal if you are a vassal can you? I stoped growing. I have too much land as it is to my original plans. Let's see what they do the next few turns.

========
Now, getting to the point:

So far I noticed the following logic:
1. Cities could only be made independent colonies IF their original culture(a.k.a. Motherland) had been destroyed.

2. I have little clue as to why some cities just believe their motherland is America (my first colony) but some do, and some don't. There must be a distance factor, although neighbouring cities had different opinions on the matter on my map.

3. I had two Capitol cities behaving differently on near conditions. One belonged to the neighbour that survived, and they wanted to be liberated. The other one belonged to the neighbour I wiped, but not by the time I considered making a colony out of it, and it was available for such. No clue as to why, since the new capitol of their motherland was pretty close. However, the cultural pressure of the new capitol of that one was lower than the first case. I guess, then, that it is a matter of cultural influence on the borders.

4. Any city I had built BEFORE the first colony, no matter how close to the first colony's cultural border it is, can be made a new independent colony. Not that I would want them to be, but they didn't mind if I wanted.

5. replacing neighbours with vassals is REALLY worth as an early game strategy. Although i'm playing on an easy set, but I suspect it would still be worthy on harder settings.

I guess the author already exposed a few of these logic (if not all) but the many codes in the posts scared me away from reading it :P Anyway, my first impression is good.

I'd still rather have some cities available to be made colonies instead of liberated, but ok.
 
I reported the problem with colonies not 'inheriting' their parent civ's culture, and Alexman advised that this would be changed in 3.13. So part of this mod has already been implemented in 3.13--although the ability to make colonies on pangaea is still needed.
 
Would there be anyway, with modifications in this mod to nake it so that colonies can be created at anytime, not consuming every city on a continent, regardless to how a city feels about its owner (i.e you could potentially turn any single city into an independant colony; just one city, not a continent.) I suppose it'd be as if ever city in the domestic advisor regardless of its status could be given "independance" and have that arm telling you you're able to do that.
 
Well, doesn't look like there'd been any changes since it was originally uploaded, so you'd need to re-compile it with the 3.13 source files (and Bhruic's unofficial patch, too.) [EDIT: never mind -- OP only provided part of the code in the thread...]

It's probably no longer here because it was lost with the server crash.
 
I've been looking for a mod to do this for ages, can someone upload the files again please, they do indeed appear to have been lost
 
Top Bottom