Gifting a CS to a player?

Leugi

Supreme Libertador
Joined
Jan 25, 2013
Messages
1,675
Location
Bolivia
So... I've been meaning to make a code that gifts a City-State to a player after certain conditions are met. (similar to Austria or Venice in gameplay terms). So, when Austria or Venice do that, they manage to erase the City-State status... And that's what I want.

So I think this is the lua thing I could use:

Player:AcquireCity(City city, bool conquest, bool trade)

Supposedly setting Conquest to False and Trade to True, means that the city was not conquered, right?... Well, that didn't seem to work, as the City still acts as occuppied (only difference is the number of surviving habitants); and when another player checks the city it can be Liberated, so it still has CS status.

So, any idea on how to do this?

...OR, any way of gathering all info from a city (Habitants, Buildings, Territory), remove the city and init a new city with all that info?
 
Create Great Merchant of Venice (not on city plot, because he can conquer it, but in CS territory, move CS units if needed).
Push mission (i would be surprised if there is no mission for it).
 
Ok.. this is odd...

See, I tried doing the Merchant of Venice thing, and it worked! It granted me the CS; though it still showed the (Annex, Puppet, View City) popup thing... I simply annexed and done...

Then I used Firetuner to skip my turn and see the adquired CS from another player, and it kept the CS status! What could cause this?
 
The MoV unit only has the ability to buy CSes, it's the "No Annexing" trait that affects how the city is acquired
 
Hmn... seems I will have to use the No Annex thing...

I also tried with this:

Game.DoMinorBuyout(pPlayer, minorCiv)

But it didn't work either... Ok. Thanks anyway!
 
IIRC DoMinorBuyout() calls into the same code, so needs the trait as well
 
Code:
function FakeMinorMarriage(iPlayerID, minorID)
	FakeUnit(minorID)
	for iCity in Players[minorID]:Cities() do
		if iCity:GetOriginalOwner() == minorID then
			FakeBuildings(iCity)
			FakePlots(iCity, iCity:GetX(), iCity:GetY(), minorID, iPlayerID)
			FakeName = iCity:GetName();
			FakeCitizens = iCity:GetPopulation();
			FakeCityPlot = iCity:Plot();
			FakeDMG = iCity:GetDamage();
			iCity:Kill()
--If Kill() will not work, there is player:Disband()
			FakeNewCity(iPlayerID)
		else
			Players[iPlayerID]:AcquireCity(iCity, false, true);
		end
	end
	FakeNewUnits(iPlayerID)
end

function FakeUnit(minorID)
	FMunits = {}
	for iUnit in Players[minorID]:Units() do
		FMunits[iUnit] = {}
		FMunits[iUnit][1] = iUnit:GetUnitType();
		FMunits[iUnit][2] = iUnit:GetPlot();
		FMunits[iUnit][3] = iUnit:GetDamage();
		iUnit:Kill();
	end
end

function FakePlots(iCity, x, y, minorID, iPlayerID)
	FMplots = {}
	for i = 0, iCity:GetNumCityPlots() -1, 1 do
		local iPlot = iCity:GetCityIndexPlot( i );
		if not iPlot ~= iCity:Plot() then
			if Map.PlotDistance(iPlot:GetX(), iPlot:GetY(), x, y) > 1 then
				if iPlot:GetOwner() == minorID then
					FMplots[iPlot] = iPlayerID;
				end
			elseif iPlot:GetOwner() == -1 then
				FMplots[iPlot] = -1;
			end
		end
	end
end

function FakeBuildings(iCity)
	FMbuildings = {}
	for iBuilding in GameInfo.Buildings() do
		if iCity:IsHasBuilding(iBuilding.ID) then
--I don't know if CStates build national wonders; this might be an issue; just report if there are multiple.
			FMbuildings[iBuilding.ID] = 2;
		end
	end
end

function FakeNewUnits(iPlayerID)
	for i, v in pairs(FMunits) do
		fmUnit = Players[iPlayerID]:InitUnit(v[1], v[2]:GetX(), v[2]:GetY());
		fmUnit:SetDamage(v[3]);
	end
	FMunits = nil;
end

function FakeNewCity(iPlayerID)
	Players[iPlayerID]:InitCity(FakeCityPlot:GetX(), FakeCityPlot:GetY());
	NewCity = FakeCityPlot:GetPlotCity();
	NewCity:SetName(FakeName, true);
	NewCity:SetDamage(FakeDMG);
	NewCity:SetPopulation(FakeCitizens);
	NewCityID = NewCity:GetID()
	for iPlot, owner in pairs(FMplots) do
		iPlot:SetOwner(owner, NewCityID, true, true);
	end
	FMplots = nil;
	for iBuilding, meh in pairs(FMbuildings) do
		NewCity:SetNumRealBuilding(iBuilding, 1);
	end
	FMbuildings = nil;
end
AI will probably treat it as settling (may be angry if nearby).
 
Amazing! It worked with Player: Disband

The only thing that didn't work though is the plots, it just gets the city with all adjacent plots just like when founding.
 
This:
Code:
function FakePlots(iCity, x, y, minorID, iPlayerID)
	FMplots = {}
	for i = 0, iCity:GetNumCityPlots() -1[COLOR="Red"], 1[/COLOR] do
into:
Code:
function FakePlots(iCity, x, y, minorID, iPlayerID)
	FMplots = {}
	for i = 0, iCity:GetNumCityPlots() -1 do

Also, you may update first function (to avoid rare scenario messing up with plots):
Code:
function FakeMinorMarriage(iPlayerID, minorID)
	FakeUnit(minorID)
	FMocity = nil;
	for iCity in Players[minorID]:Cities() do
		if iCity:GetOriginalOwner() == minorID then
			FMocity = iCity;
		else
			Players[iPlayerID]:AcquireCity(iCity, false, true);
		end
	end
--it simply gives you conquered cities first, so their tiles will be not considered later
	if FMocity ~= nil then
			FakeBuildings(FMocity)
			FakePlots(FMocity, FMocity:GetX(), FMocity:GetY(), minorID, iPlayerID)
			FakeName = FMocity:GetName();
			FakeCitizens = FMocity:GetPopulation();
			FakeCityPlot = FMocity:Plot();
			FakeDMG = FMocity:GetDamage();
--here is player:Disband(), but FMocity instead iCity
			FakeNewCity(iPlayerID)
	end
	FakeNewUnits(iPlayerID)
end
 
Amazing!... Just one last minor issue I can't seem to get around though...

Although the number of citizens and tiles are correctly transfered. Citizens can't seem to work the new tiles (even though they appear as part of the city at the city-screen, clicking the Citizen icon does nothing), and also one can't assign specialists... Any ideas as to why this might be happening?
 
Although the number of citizens and tiles are correctly transfered. Citizens can't seem to work the new tiles (even though they appear as part of the city at the city-screen, clicking the Citizen icon does nothing), and also one can't assign specialists... Any ideas as to why this might be happening?

It needs to be
Code:
NewCity:SetPopulation(FakeCitizens, [B][COLOR="Red"]true[/COLOR][/B]);

If that fails to work, try
Code:
NewCity:ChangePopulation(FakeCitizens-1, true);
 
Spoiler :
Code:
function FakeMinorMarriage(iPlayerID, minorID)
	FakeUnit(minorID)
	FMocity = nil;
	for iCity in Players[minorID]:Cities() do
		if iCity:GetOriginalOwner() == minorID then
			FMocity = iCity;
		else
			Players[iPlayerID]:AcquireCity(iCity, false, true);
		end
	end
	if FMocity ~= nil then
			FakeBuildings(FMocity)
			FakePlots(FMocity, FMocity:GetX(), FMocity:GetY(), minorID, iPlayerID)
			FakeName = FMocity:GetName();
			FakeCitizens = FMocity:GetPopulation();
			FakeCityPlot = FMocity:Plot();
			FakeDMG = FMocity:GetDamage();
			FakeJCL = FMocity:GetJONSCultureLevel();
			Players[minorID]:Disband(FMocity);
			FakeNewCity(iPlayerID)
	end
	FakeNewUnits(iPlayerID)
end

function FakeUnit(minorID)
	FMunits = {}
	for iUnit in Players[minorID]:Units() do
		FMunits[iUnit] = {}
		FMunits[iUnit][1] = iUnit:GetUnitType();
		FMunits[iUnit][2] = iUnit:GetPlot();
		FMunits[iUnit][3] = iUnit:GetDamage();
		iUnit:Kill();
	end
end

function FakePlots(iCity, x, y, minorID, iPlayerID)
	FMplots = {}
	for i = 0, Map:GetNumPlots() - 1, 1 do
		local fPlot = Map.GetPlotByIndex( i );
		if fPlot:GetOwner() == minorID then
			FMplots[fPlot] = iPlayerID;
		elseif Map.PlotDistance(fPlot:GetX(), fPlot:GetY(), x, y) == 1 then
			if fPlot:GetOwner() == -1 then
				FMplots[fPlot] = -1;
			end
		end
	end
end

function FakeBuildings(iCity)
	FMbuildings = {}
	for iBuilding in GameInfo.Buildings() do
		if iCity:IsHasBuilding(iBuilding.ID) then
			if GameInfo.BuildingClasses[iBuilding.BuildingClass].MaxPlayerInstances ~= 1 then
				FMbuildings[iBuilding.ID] = 2;
			end
		end
	end
end

function FakeNewUnits(iPlayerID)
	for i, v in pairs(FMunits) do
		fmUnit = Players[iPlayerID]:InitUnit(v[1], v[2]:GetX(), v[2]:GetY());
		fmUnit:SetDamage(v[3]);
	end
	FMunits = nil;
end

function FakeNewCity(iPlayerID)
	Players[iPlayerID]:InitCity(FakeCityPlot:GetX(), FakeCityPlot:GetY());
	NewCity = FakeCityPlot:GetPlotCity();
	NewCity:SetName(FakeName, true);
	NewCity:SetDamage(FakeDMG);
	NewCity:SetPopulation(FakeCitizens, true);
	NewCityID = NewCity:GetID()
	for iPlot, owner in pairs(FMplots) do
		iPlot:SetOwner(owner, NewCityID, true, true);
	end
	FMplots = nil;
	NewCity:SetJONSCultureLevel(FakeJCL);
	for iBuilding, meh in pairs(FMbuildings) do
		NewCity:SetNumRealBuilding(iBuilding, 1);
	end
	FMbuildings = nil;
end
I have tested it today and made several fixes:
1) Mentioned citizens
2) Palace
3) Plots were limited to 3 (working) range
4) Culture cost level
What's more, AI seemed to not be angry about InitCity.

What is still not done:
1) Religion, though I can set major, it will be weak (very convertable). I think it can't be copied properly with LUA. You can create Prophet and spread there religion, but It would still be meh solution.
2) Some irrelevant (for me) staff, culture stored for next plot, food stored, current production...
 
Top Bottom