Does anyone know a way to make an improvement you build grant you a free resource that you haven't built on? As in you build a tile improvement, then that grants you 1 free luxury resource?
Is there a LUA way to do it? I've been trying to get this done for days and it's driving me crazy.
To actually grant the resource, hook into GameEvents.BuildFinished. If the finished improvement is IMPROVEMENT_WHATEVER, then grant one copy of the dummy building in the capital. (There is more stuff to take into account though, such as pillaging or actually having to own the plot).
I've included the code for my Whomp's Fortress civ, as it almost does what you want. Feel free to make changes from there/use it as a template.
Whomp's Fortress gains 1 Stone Luxury for each Stone Bonus Resource
(The code does not take newly spawned stone resources into account though)
Spoiler:
Code:
local iCiv = GameInfoTypes.CIVILIZATION_TRL_WHOMP_FORTRESS
--[..]snip
local iStoneLuxuryDummy = GameInfoTypes.BUILDING_TRL_STONE_LUXURY_DUMMY
local iStoneResource = GameInfoTypes.RESOURCE_STONE
local tStoneResources = {} --table that will contain the plotindexes of all stone resources on the map
--[..]snip
-----===================================================================
--Stone Luxuries: Each Stone Bonus Resource provides one Stone Luxury
--removes all Stone Luxury buildings from all cities
function RemoveAllStoneLuxuries(iPlayer)
local pPlayer = Players[iPlayer]
for pCity in pPlayer:Cities() do
pCity:SetNumRealBuilding(iStoneLuxuryDummy,0)
end
end
--Checks if the number of cities for the Whomp King changes. If yes, then the number of improved stone resources might've changed so we update
function CheckWhompCityCaptured(iOldPlayer,_,_,_,iNewPlayer)
if Players[iOldPlayer]:GetCivilizationType() == iCiv then
print("Whomp city captured, updating stone luxuries!")
UpdateStoneLuxuries(iOldPlayer)
end
if Players[iNewPlayer]:GetCivilizationType() == iCiv then
print("Whomp captured a city, updating stone luxuries")
RemoveAllStoneLuxuries(iNewPlayer)
UpdateStoneLuxuries(iNewPlayer)
end
end
function UpdateStoneLuxuries(iPlayer)
local pPlayer = Players[iPlayer]
if pPlayer:GetCivilizationType() == iCiv then
local iNumStoneLuxuries = 0;
for _,iPlotIndex in ipairs(tStoneResources) do
local pPlot = Map.GetPlotByIndex(iPlotIndex);
if pPlot:GetOwner() == iPlayer and pPlot:GetResourceType() == iStoneResource then
print("Stone resource at ("..pPlot:GetX()..","..pPlot:GetY()..") is in the Player's borders!");
local iImprovement = pPlot:GetImprovementType()
if pPlot:IsCity() or (iImprovement and iImprovement ~= -1 and not pPlot:IsImprovementPillaged() and (pPlot:IsResourceConnectedByImprovement(iImprovement) or GameInfo.Improvements[iImprovement].CreatedByGreatPerson == true)) then
print('This Stone Resource was Connected (by a Quarry, a Great Person-Improvement, or a City!')
iNumStoneLuxuries = iNumStoneLuxuries + 1
end
end
end
local pCapital = pPlayer:GetCapitalCity()
if pCapital then
print(iNumStoneLuxuries.." Stone Luxury Dummies were placed in "..pCapital:GetName())
pCapital:SetNumRealBuilding(iStoneLuxuryDummy,iNumStoneLuxuries)
end
end
end
--Finds all stone resources and stores them in a table; returns this table as well;
--This function is only executed upon game START and game LOAD
function FindAllStoneResources()
print("Finding all Stone Resources...")
local tTable = {};
for i=0, Map.GetNumPlots()-1, 1 do
local pPlot = Map.GetPlotByIndex(i);
if pPlot and pPlot:GetResourceType() == iStoneResource then
print("Stone resource found at ("..pPlot:GetX()..","..pPlot:GetY()..")");
tTable[#tTable+1] = i;
end
end
print(#tTable.." Stone Resources have been found!");
return tTable;
end
if IsCivInPlay(iCiv) then
tStoneResources = FindAllStoneResources();
GameEvents.PlayerDoTurn.Add(UpdateStoneLuxuries)
GameEvents.PlayerCityFounded.Add(UpdateStoneLuxuries) --not required, but instantly grants the stone luxury upon founding a city
GameEvents.BuildFinished.Add(UpdateStoneLuxuries) --not required, but instantly grants the stone luxury upon constructing an improvement
GameEvents.CityCaptureComplete.Add(CheckWhompCityCaptured)
end
Thanks for this. Though, if I'm understanding correctly, all worked stone by your civ will also grant a unique luxury?
Sorry for being so stupid at the moment too, I'm currently so ill I have the cold sweats and I'm shaking. I'll need to look over your LUA again because right now I'm too dizzy to understand it.
I should have described what exactly it is I want to do too. Here it is:
When my civ creates a Unique Improvement: Monolith I want each improvement to grant 1 unique luxury resource: Monolith Tech. I also want the luxury resource to be owned by any civ that has a Monolith in it's border.
I know how crappy civ 5 coding is, so I can be a bit flexible on this, but ideally this is what I'd like. I just can't get my head around it. Sorry again if I'm being simple here, incredibly dizzy.
In that case the code should be adapted, though that would depend on where you are actually able to build a Monolith. Everywhere? On plains? On resources?
If it's constructable on many tiles, then precaching all the possible Plots on the Map in a table (as is done with the Stone Resources) might not be a good idea, as the code would iterate through every possible plot in that table. (Which can be a big number on bigger maps!)
In that case it's a better idea to construct the table dynamically, as follows:
Code:
--when the code loads initially, loop over all plots on the map
--if the plot contains a monolith, then add the plotindex to the table (so that we get all monoliths on the map when reloading the game)
--this is almost the same as precaching all the stone-plots on the map.
--hooking into GameEvents.BuildFinished(), check if the built improvement is IMPORVEMENT_MONOLITH_OR_STH (who can build this improvement, and where, is restricted by the XML/SQL)
--if yes, add the plotindex of the plot where this improvement was constructed to the table
--if no, do nothing
You'll also want to change the following line
Code:
if pPlot:IsCity() or (iImprovement and iImprovement ~= -1 and not pPlot:IsImprovementPillaged() and (pPlot:IsResourceConnectedByImprovement(iImprovement) or GameInfo.Improvements[iImprovement].CreatedByGreatPerson == true)) then
into something like this:
Code:
if iImprovement and iImprovement ~= -1 and not pPlot:IsImprovementPillaged() and iImprovement = GameInfoTypes.IMPROVEMENT_MONOLITH_OR_STH then
If, for some reason, a monolith is removed from the map, then this ensures that it does not count towards the number of luxuries you'll be receiving.
(You could also remove the plotindex form the table in case the "iImprovement = GameInfoTypes.IMPROVEMENT_MONOLITH_OR_STH"-check fails, as there's no longer a Monolith on that plot)
I also want the luxury resource to be owned by any civ that has a Monolith in it's border.
There are several :GetCivilizationType()-checks in the code. If you remove those then any civ (including City States and Barbarians) (with a Capital City) would gain the Whomp Stone Luxury, though I'm not sure how City State Allies would interact.
(This may all sound vague/abstract, but I'm giving you a try first, as the best way to learn stuff is to do it yourself, with all the trial and error that comes with it! )
(This may all sound vague/abstract, but I'm giving you a try first, as the best way to learn stuff is to do it yourself, with all the trial and error that comes with it! )
Thanks, but looking over this I'm clearly far too stupid to understand it. I thought it would be reasonably simple or straightforward but I don't even know where to begin on this.
- :GetCivilizationType()-checks removed so that every civ gains monolith techs
- Variables renamed from StoneSTH to MonolithSTH
- Any imiprovement in tValdiImprovements will provide a Monolith Tech Luxury
- The Monolith-table is now built dynamically: whenever someone constructs a monolith, the plotindex of said monolith is added to the table. On game start/load, we iterate over all the plots on the map once.
- A monolith-entry in the table is removed if (for w/e reason) there no longer is a monolith on that plot
- Only monoliths added via a Worker (or other unit constructing it) are considered! Improvements added via pPlot:SetImprovementType() won't be recognized until you reload the game!!!
Please see the code below
DISCLAIMER: Not actually tested
Spoiler:
Code:
--change these up with your actual names
local iCiv = GameInfoTypes.CIVILIZATION_PLUVIALAD_MONOLITHLAD
local ìMonolithTechLuxury = GameInfoTypes.BUILDING_PLUVIALAD_MONOLITH_TECH_DUMMY
local iMonolith = GameInfoTypes.RESOURCE_PLUVIALAD_MONOLITH
local tMonoliths = {} --table that will contain the plotindexes of all monoliths on the map
local tValidImprovements = {[iMonolith] = true} --table containing all improvements that provide a luxury
-----===================================================================
--Monolith Luxuries: Each Monolith improvement grants +1 Monolith Tech Luxury
--removes all Monolith Tech Luxuries from all Cities of a given player
function RemoveAllMonolithTechLuxuries(iPlayer)
local pPlayer = Players[iPlayer]
for pCity in pPlayer:Cities() do
pCity:SetNumRealBuilding(ìMonolithTechLuxury,0)
end
end
--Checks if the number of cities changes. If yes, then the number of monoliths might've changed so we update
function CheckMonolithCityCaptured(iOldPlayer,_,_,_,iNewPlayer)
--sanity check
if iOldPlayer then
print(iOldPlayer.." City captured, updating monolith tech luxuries!")
UpdateMonolithTechLuxuries(iOldPlayer)
end
--sanity check
if iNewPlayer then
print(iNewPlayer.." Captured a city, updating monolith tech luxuries")
RemoveAllMonolithTechLuxuries(iNewPlayer)
UpdateMonolithTechLuxuries(iNewPlayer)
end
end
function OnMonolithBuilt(iPlayer,iX,iY,iImprovement)
if iImprovement == iMonolith then
print("Monolith constructed at ("..iX..","..iY..")");
local pPlot = Map.GetPlot(iX,iY);
tMonoliths[pPlot:GetPlotIndex()] = true; --add it to the table
end
end
function UpdateMonolithTechLuxuries(iPlayer)
local pPlayer = Players[iPlayer]
local iNumMonolithTechLuxuries = 0;
for iPlotIndex,_ in pairs(tMonoliths) do
local pPlot = Map.GetPlotByIndex(iPlotIndex);
--sanity check
if pPlot then
local iImprovement = pPlot:GetImprovementType()
--plot must be owned by the player
if pPlot:GetOwner() == iPlayer then
--must contain a monolith (or other improvement specified in tValidImprovements)
if iImprovement and iImprovement~=-1 and tValidImprovements[iImprovement] then
--must not be pillaged
if not pPlot:IsImprovementPillaged() then
print("Monolith at ("..pPlot:GetX()..","..pPlot:GetY()..") is in the Player's borders!");
iNumMonolithTechLuxuries = iNumMonolithTechLuxuries + 1
end
else
--no monolith here anymore, so remove it from the table.
tMonoliths[iPlotIndex] = nil;
end
end
end
end
local pCapital = pPlayer:GetCapitalCity()
if pCapital then
print(iNumMonolithTechLuxuries.." Monolith Tech Luxury Dummies were placed in "..pCapital:GetName())
pCapital:SetNumRealBuilding(ìMonolithTechLuxury,iNumMonolithTechLuxuries)
end
end
--Finds all Monoliths on the map and returns a table containing their plotindices
--This function is only executed upon game START and game LOAD
function FindAllMonoliths()
print("Finding all Monolith Improvements...")
local tTable = {};
local iNumMonoliths = 0;
for i=0, Map.GetNumPlots()-1, 1 do
local pPlot = Map.GetPlotByIndex(i);
--We want the improvement in our table even if it's pillaged
if pPlot and pPlot:GetImprovementType() == iMonolith then
print("Monolith found at ("..pPlot:GetX()..","..pPlot:GetY()..")");
tTable[i] = true; --add it to the table (table was restructured)
iNumMonoliths = iNumMonoliths + 1;
end
end
print(iNumMonoliths.." Monolith Resources have been found!");
return tTable;
end
--IsCivInPlay-check here as monoliths can only be constructed if the monolithlad civ is actually in play
--NOTE: Requires Whoward's IsCivInPlay(..) function be be defined somewhere in your code (which it's not in this example)
if IsCivInPlay(iCiv) then
tMonoliths = FindAllMonoliths();
GameEvents.PlayerDoTurn.Add(UpdateMonolithTechLuxuries)
GameEvents.BuildFinished.Add(OnMonolithBuilt)
GameEvents.CityCaptureComplete.Add(CheckMonolithCityCaptured)
end
- :GetCivilizationType()-checks removed so that every civ gains monolith techs
- Variables renamed from StoneSTH to MonolithSTH
- Any imiprovement in tValdiImprovements will provide a Monolith Tech Luxury
- The Monolith-table is now built dynamically: whenever someone constructs a monolith, the plotindex of said monolith is added to the table. On game start/load, we iterate over all the plots on the map once.
- A monolith-entry in the table is removed if (for w/e reason) there no longer is a monolith on that plot
- Only monoliths added via a Worker (or other unit constructing it) are considered! Improvements added via pPlot:SetImprovementType() won't be recognized until you reload the game!!!
Please see the code below
DISCLAIMER: Not actually tested
Spoiler:
Code:
--change these up with your actual names
local iCiv = GameInfoTypes.CIVILIZATION_PLUVIALAD_MONOLITHLAD
local ìMonolithTechLuxury = GameInfoTypes.BUILDING_PLUVIALAD_MONOLITH_TECH_DUMMY
local iMonolith = GameInfoTypes.RESOURCE_PLUVIALAD_MONOLITH
local tMonoliths = {} --table that will contain the plotindexes of all monoliths on the map
local tValidImprovements = {[iMonolith] = true} --table containing all improvements that provide a luxury
-----===================================================================
--Monolith Luxuries: Each Monolith improvement grants +1 Monolith Tech Luxury
--removes all Monolith Tech Luxuries from all Cities of a given player
function RemoveAllMonolithTechLuxuries(iPlayer)
local pPlayer = Players[iPlayer]
for pCity in pPlayer:Cities() do
pCity:SetNumRealBuilding(ìMonolithTechLuxury,0)
end
end
--Checks if the number of cities changes. If yes, then the number of monoliths might've changed so we update
function CheckMonolithCityCaptured(iOldPlayer,_,_,_,iNewPlayer)
--sanity check
if iOldPlayer then
print(iOldPlayer.." City captured, updating monolith tech luxuries!")
UpdateMonolithTechLuxuries(iOldPlayer)
end
--sanity check
if iNewPlayer then
print(iNewPlayer.." Captured a city, updating monolith tech luxuries")
RemoveAllMonolithTechLuxuries(iNewPlayer)
UpdateMonolithTechLuxuries(iNewPlayer)
end
end
function OnMonolithBuilt(iPlayer,iX,iY,iImprovement)
if iImprovement == iMonolith then
print("Monolith constructed at ("..iX..","..iY..")");
local pPlot = Map.GetPlot(iX,iY);
tMonoliths[pPlot:GetPlotIndex()] = true; --add it to the table
end
end
function UpdateMonolithTechLuxuries(iPlayer)
local pPlayer = Players[iPlayer]
local iNumMonolithTechLuxuries = 0;
for iPlotIndex,_ in pairs(tMonoliths) do
local pPlot = Map.GetPlotByIndex(iPlotIndex);
--sanity check
if pPlot then
local iImprovement = pPlot:GetImprovementType()
--plot must be owned by the player
if pPlot:GetOwner() == iPlayer then
--must contain a monolith (or other improvement specified in tValidImprovements)
if iImprovement and iImprovement~=-1 and tValidImprovements[iImprovement] then
--must not be pillaged
if not pPlot:IsImprovementPillaged() then
print("Monolith at ("..pPlot:GetX()..","..pPlot:GetY()..") is in the Player's borders!");
iNumMonolithTechLuxuries = iNumMonolithTechLuxuries + 1
end
else
--no monolith here anymore, so remove it from the table.
tMonoliths[iPlotIndex] = nil;
end
end
end
end
local pCapital = pPlayer:GetCapitalCity()
if pCapital then
print(iNumMonolithTechLuxuries.." Monolith Tech Luxury Dummies were placed in "..pCapital:GetName())
pCapital:SetNumRealBuilding(ìMonolithTechLuxury,iNumMonolithTechLuxuries)
end
end
--Finds all Monoliths on the map and returns a table containing their plotindices
--This function is only executed upon game START and game LOAD
function FindAllMonoliths()
print("Finding all Monolith Improvements...")
local tTable = {};
local iNumMonoliths = 0;
for i=0, Map.GetNumPlots()-1, 1 do
local pPlot = Map.GetPlotByIndex(i);
--We want the improvement in our table even if it's pillaged
if pPlot and pPlot:GetImprovementType() == iMonolith then
print("Monolith found at ("..pPlot:GetX()..","..pPlot:GetY()..")");
tTable[i] = true; --add it to the table (table was restructured)
iNumMonoliths = iNumMonoliths + 1;
end
end
print(iNumMonoliths.." Monolith Resources have been found!");
return tTable;
end
--IsCivInPlay-check here as monoliths can only be constructed if the monolithlad civ is actually in play
--NOTE: Requires Whoward's IsCivInPlay(..) function be be defined somewhere in your code (which it's not in this example)
if IsCivInPlay(iCiv) then
tMonoliths = FindAllMonoliths();
GameEvents.PlayerDoTurn.Add(UpdateMonolithTechLuxuries)
GameEvents.BuildFinished.Add(OnMonolithBuilt)
GameEvents.CityCaptureComplete.Add(CheckMonolithCityCaptured)
end
<!-- BUILDING: Grants a free Resource in your territory and will try to place it on X number of plots. 'ResourceQuantityToPlace' is the quantity you desire that will be placed on each X plot -->
<Table name="Building_ResourcePlotsToPlace">
<Column name="BuildingType" type="text" reference="Buildings(Type)"/>
<Column name="ResourceType" type="text" reference="Resources(Type)"/>
<Column name="NumPlots" type="integer" default="0"/>
<Column name="ResourceQuantityToPlace" type="integer" default="1"/>
</Table>
<!-- BUILDING: Grants a free Resource in your territory and will try to place it on X number of plots. 'ResourceQuantityToPlace' is the quantity you desire that will be placed on each X plot -->
<Table name="Building_ResourcePlotsToPlace">
<Column name="BuildingType" type="text" reference="Buildings(Type)"/>
<Column name="ResourceType" type="text" reference="Resources(Type)"/>
<Column name="NumPlots" type="integer" default="0"/>
<Column name="ResourceQuantityToPlace" type="integer" default="1"/>
</Table>
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.