Lua - How to make an improvement unbuildable based on it's location

Genghis.Khan

Person
Joined
Jun 9, 2012
Messages
934
Location
Somewhere
As the title says, I would like to make an improvement unbuildable if it is in a five-plot-radius of any city. Checking if it is is not the problem, the problem is that there is no event like Unit.CanBuild, so I'm am not sure if there is a Lua solution to this problem (maybe some UI trick to hide the build button if the unit is in an unbuildable spot, or is there another simpler way to do this?)

The code to check if the unit is in a buildable spot would be something like this:

Code:
function ColonyValidSpots ()
	local OnlyColonySpots = GameInfo.Improvements.Colonies
	local unitID = GameInfo.Units.UNIT_COLONIST
	for pUnit in Player:Units() do
		if pUnit.GetUnitType == unitID then
			local currentplot = pUnit:GetPlot()
				for i = 0, GameDefines.MAX_MAJOR_CIVS - 1 do
					if Players[i]:IsEverAlive() then
						for pCity in Players[i]:Cities() do
							local plotX = pCity:GetX()
							local plotY = pCity:GetY()
							local plotCity = City:AtPlot(plotX, plotY)
							for i = 0, plotCity:GetNumCityPlots() -1 do
								if plotCity:GetCityIndexPlot(i) ~= nil then
									if Map.PlotDistance(currentPlot:GetX(), currentPlot:GetY(), plotCity:GetX(), plotCity:GetY()) < 5) then
										--return false somehow
									else
										return true
									end
								end
							end
						end
					end
		end
	end
end

Can somebody help me to find a way to do this?
 
I'd be interested in the outcome; I tried to do the opposite, restricting an improvement to a city's workable tile, with mixed results. Think all I ended doing, was turning workers ability to build an improvement fullstop on/off :-S
 
Sorry for not getting back on this sooner. I'd been trying to do something with plot:CanHaveImprovement(impreovement, team, potential), but with no joy, and assuming it's only for putting map stuff together maybe(?).

That said, I'm not sure how to interpret potential as a boolean, outside of a "yes, the improvement in question can/can't be built on this plot".
 
The potential bool in CanHaveImprovement is not used. CanHaveImprovement just test if the plot can have the improvement according to the rules in the DLL. You can't use CanHaveImprovement in lua to force it to accept or not accept an improvement.
 
so this is the function:

Code:
bool CvPlot::canHaveImprovement(ImprovementTypes eImprovement, TeamTypes eTeam, bool) const
{
	CvPlot* pLoopPlot;
	bool bValid;
	int iI;

	CvAssertMsg(eImprovement != NO_IMPROVEMENT, "Improvement is not assigned a valid value");
	CvAssertMsg(getTerrainType() != NO_TERRAIN, "TerrainType is not assigned a valid value");

	CvImprovementEntry& improvementInfo = *GC.getImprovementInfo(eImprovement);

	bValid = false;

	if (isCity())
	{
		return false;
	}

	if (isImpassable())
	{
		return false;
	}

	if (improvementInfo.IsWater() != isWater())
	{
		return false;
	}

	if (getFeatureType() != NO_FEATURE)
	{
		if (GC.getFeatureInfo(getFeatureType())->isNoImprovement())
		{
			return false;
		}
	}

	ResourceTypes thisResource = getResourceType(eTeam);
	// Resource REQUIRES a certain Improvement
	if (		thisResource != NO_RESOURCE &&
			!improvementInfo.IsBuildableOnResources() &&	// Some improvements can be built anywhere
			!improvementInfo.IsImprovementResourceMakesValid(thisResource))
	{
		return false;
	}
	// If there IS a valid resource here then set validity to true (because something has to)
	else if (thisResource != NO_RESOURCE)
	{
		bValid = true;
	}

	const bool bIsFreshWater = isFreshWater();

	if (improvementInfo.IsNoFreshWater() && bIsFreshWater)
	{
		return false;
	}

	if (improvementInfo.IsRequiresFlatlands() && !isFlatlands())
	{
		return false;
	}

	if (improvementInfo.IsRequiresFlatlandsOrFreshWater() && !isFlatlands() && !bIsFreshWater)
	{
		return false;
	}

	if (improvementInfo.IsRequiresFeature() && (getFeatureType() == NO_FEATURE))
	{
		return false;
	}

	if (improvementInfo.IsCoastal() && !isCoastalLand())
	{
		return false;
	}

	if (improvementInfo.IsHillsMakesValid() && isHills())
	{
		bValid = true;
	}

	if (improvementInfo.IsFreshWaterMakesValid() && bIsFreshWater)
	{
		bValid = true;
	}

	if (improvementInfo.IsRiverSideMakesValid() && isRiverSide())
	{
		bValid = true;
	}

	if (improvementInfo.GetTerrainMakesValid(getTerrainType()))
	{
		bValid = true;
	}

	if ((getFeatureType() != NO_FEATURE) && improvementInfo.GetFeatureMakesValid(getFeatureType()))
	{
		bValid = true;
	}

	if (!bValid)
	{
		return false;
	}

	if (improvementInfo.IsRiverSideMakesValid())
	{
		bValid = false;

		for (iI = 0; iI < NUM_DIRECTION_TYPES; ++iI)
		{
			pLoopPlot = plotDirection(getX(), getY(), ((DirectionTypes)iI));

			if (pLoopPlot != NULL)
			{
				if (isRiverCrossing(directionXY(this, pLoopPlot)))
				{
					if (pLoopPlot->getImprovementType() != eImprovement)
					{
						bValid = true;
						break;
					}
				}
			}
		}

		if (!bValid)
		{
			return false;
		}
	}

	for (iI = 0; iI < NUM_YIELD_TYPES; ++iI)
	{
		if (calculateNatureYield(((YieldTypes)iI), eTeam) < improvementInfo.GetPrereqNatureYield(iI))
		{
			return false;
		}
	}

	return true;

}


so, I just have to do the same I did in Lua and transform it in C++

can somebody provide me the "translation"
 
Top Bottom