(Help&Ideas)Is there a mod that can move cities?

Ronza149

Chieftain
Joined
Aug 31, 2013
Messages
76
Location
Canada
I have downloaded at least 50 mods so far,but even though I searched a lot,still could not find any decent mods for moving cities around,so I am hoping someone can help me find a mod for this or,if there aren't,make one :)
Basically what I need is to move any cities to an adjacent tile,you know,because AI are terrible at choosing the right tiles to settle and I make these mistakes sometimes as well.
P.S. I watched a video on the upcoming expansion BE rising tide,it explains how moving aquatic cities works,so could any modders make a mod similar to this?
 
This sounds like it may require, more than minor, alterations to the .dll to accomplish.
 
It is definitely possible in the C++ source code. If the necessary functions (or their equivalent work-arounds) are exposed to Lua, then it will be possible to do it in a Lua script as well.

Spoiler :
Disclaimer: I haven't traced through all secondary function calls to see if anything might critically break (i.e. cause a game crash), so you'll have to experiment on your own with it.


Let's break what you want to do down into a bunch of smaller steps:
  1. Get the buildings in the old city (if applicable)
  2. Create a new city
  3. Change the population of the new city to match the old one
  4. Add buildings into the new city (if applicable)
  5. Destroy the old city

Step 1: For step #1 you will need to create a vector (initialized with a size equal to GC.getNumBuildingInfos() for ease of indexing), and loop through the city's building (slots) to see if there are any.

Spoiler :

Example code:
(note: pOldCity is the pointer to your old city)
Code:
std::vector<int> paiNumRealBuilding(GC.getNumBuildingInfos(), 0);

for(iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		// if this building exists, increment.
                paiNumRealBuilding[iI] = pOldCity->GetCityBuildings()->GetNumRealBuilding((BuildingTypes)iI);
        }

Step 2: you would call this function to initialize your new city
Code:
void CvCity::init(int iID, PlayerTypes eOwner, int iX, int iY, bool bBumpUnits, bool bInitialFounding)

Step 3: add the population back in using
Code:
int CvCity::getPopulation() const
and
Code:
void CvCity::setPopulation(int iNewValue, bool bReassignPop /* = true */)

Step 4: add the buildings back in. This is just a copy-paste of existing code from CvCity::acquireCity, so ignore anything related to 'achievements'.

Spoiler :
Code:
BuildingTypes eTraitFreeBuilding = GetPlayerTraits()->GetFreeBuildingOnConquest();
	for(iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		const BuildingTypes eLoopBuilding = static_cast<BuildingTypes>(iI);
		CvBuildingEntry* pkLoopBuildingInfo = GC.getBuildingInfo(eLoopBuilding);
		if(pkLoopBuildingInfo)
		{
			const CvBuildingClassInfo& kLoopBuildingClassInfo = pkLoopBuildingInfo->GetBuildingClassInfo();

			int iNum = 0;

			if(eTraitFreeBuilding == pkLoopBuildingInfo->GetID())
			{
				pNewCity->GetCityBuildings()->SetNumFreeBuilding(eTraitFreeBuilding, 1);
			}

			else if(paiNumRealBuilding[iI] > 0)
			{
				const BuildingClassTypes eBuildingClass = (BuildingClassTypes)pkLoopBuildingInfo->GetBuildingClassType();
				if(::isWorldWonderClass(kLoopBuildingClassInfo))
				{
					eBuilding = eLoopBuilding;
				}
				else
				{
					eBuilding = (BuildingTypes)playerCivilizationInfo.getCivilizationBuildings(eBuildingClass);
				}

				if(eBuilding != NO_BUILDING)
				{
					CvBuildingEntry* pkBuildingInfo = GC.getBuildingInfo(eBuilding);
					if(pkBuildingInfo)
					{
						if(!pkLoopBuildingInfo->IsNeverCapture())
						{
							if(!isProductionMaxedBuildingClass(((BuildingClassTypes)(pkBuildingInfo->GetBuildingClassType())), true))
							{
								// here would be a good place to put additional checks (for example, influence)
								if(!bConquest || bRecapture || (GC.getGame().getJonRandNum(100, "Capture Probability") < pkLoopBuildingInfo->GetConquestProbability()))
								{
									iNum += paiNumRealBuilding[iI];
								}
							}
						}

						// Check for Tomb Raider Achievement
						if(bConquest && !GC.getGame().isGameMultiPlayer() && pkLoopBuildingInfo->GetType() && _stricmp(pkLoopBuildingInfo->GetType(), "BUILDING_BURIAL_TOMB") == 0 && isHuman())
						{
							if(iCaptureGold > 0)  //Need to actually pillage something from the 'tomb'
							{
								gDLL->UnlockAchievement(ACHIEVEMENT_SPECIAL_TOMBRAIDER);
							}
						}

						// Check for Rome conquering Statue of Zeus Achievement
						if(bConquest && !GC.getGame().isGameMultiPlayer() && pkLoopBuildingInfo->GetType() && _stricmp(pkLoopBuildingInfo->GetType(), "BUILDING_STATUE_ZEUS") == 0 && isHuman())
						{
							const char* pkCivKey = getCivilizationTypeKey();
							if(pkCivKey && strcmp(pkCivKey, "CIVILIZATION_ROME") == 0)
							{
								gDLL->UnlockAchievement(ACHIEVEMENT_SPECIAL_ROME_GETS_ZEUS);
							}
						}

						pNewCity->GetCityBuildings()->SetNumRealBuildingTimed(eBuilding, iNum, false, ((PlayerTypes)(paiBuildingOriginalOwner[iI])), paiBuildingOriginalTime[iI]);


Step 5: Finally, you would call the function
Code:
void CvPlayer::disband(CvCity* pCity)
to remove your old city.

I might have missed a couple a lot of things along the way ... so someone more knowledgeable than me with this will likely have corrections.... but this should get you started along the path (if your brain hasn't imploded, that is :crazyeye:).

Hope that fries your brain helps :p!
- ThorHammerz
 
I might have missed a couple things along the way

a) Adjust the internal city count for the civ so as not to suffer tech/culture penalties
b) Adjust any trade routes to/from the city, bearing in mind that the distance may now be too long
c) Save/restore the current production in the city
d) Save/restore the current food overflow in the city
e) Save/restore the current production queue for the city (deal with any issues with terrain changes, eg observatories no longer near mountains)
f) Relocate any units (planes, fortified units, hiding civilians) both in the city and on the destination tile
g) Work out what to do with ships/harbours/water trade routes etc if moving from coastal to non-coastal
h) For Indonesia/City States, relocate any luxuries under the city.
i) Destroy any improvement on the destination tile
j) Work out what to do with resources under the city and on the destination tile
k) Transfer religious followers
l) Deal with any specific issues for destroying a capital/holy city
m) Save/restore the specialist counters (great people generation) for the city
n) Save/restore the worked tiles for the city, and work out what to do with any now out of range
o) Save/restore any we-love-the-king day state
p) Save/restore any unrest/revolt state
q) Relocate any spies
r) Work out what to do with any wonders that required specific terrain that's no longer valid, eg Colossus, Machu Picchu, Sydney Opera House

There are probably others
 

Fairly sure the 'number-of-effective-cities' used in tech cost & social policy calculations is calculated dynamically/on-the-fly, so there should be no problems with that (unless a call is made mid-way through the city transfer process - i.e. before the old city is destroyed & after the new city is initialized)

CvPlayer::disband(CvCity* pCity) will attempt to move the units to the nearest valid tile (otherwise it kills them). Resources the old city is sitting should also disconnected (this is the function used when a city is razed to the ground, so all 'this no longer exists'-esque functionality should be innately covered, i.e. loss of land). It puts the city name into the destroyed city names list, so that would have to be taken out (and give the new city the same name).

CvCity::init() will destroy any improvement on the destination tile (i.e. on city creation) & will connect any resource on the city site.

Graft some of the code from CvCity::kill() to handle the spies + kills units + city connections (well, CC's are updated automatically anyways I think?)

- Great works also need to be moved & set up in their appropriate slots (taking into account if buildings without their pre-reqs conditions might not be moved! do we destroy great works if >1 great work building doesn't get transferred, and we run out of valid slots?)

- Extant World Wonders need to have their graphics manually set up again (including those half-way built mid-production).


I might have missed a couple a lot of things along the way

:crazyeye:
 
How does the Prehistoric mod handle these things? Doesn't it have mobile units that train and stuff?
 
Top Bottom