Alright, so I'm a total noob at programming (Lua or anything else), but I have this idea of how I'd like to improve one aspect of the game (playing on Terra, see http://forums.civfanatics.com/showthread.php?t=470924).
My first step in that direction was creating a new tech (Colonialism) which allows the training of a new unit, the Colonist. All of this was done in xml without much problems.
Now, I need to use Lua to have the Colonist do the following:
1- settle new cities only on new continents (xml <FoundAbroad> doesn't appear to discriminate by continents);
2- upon settling a colony on a new continent: (a) set city pop to 3, (b) add a few free buildings;
3- ensure that regular Settlers settling on a new continent don't get bonuses.
I was hoping to use the "GetContinentArtType()" function (as per whoward69's UI - Overlay Continents) as a proxy to discriminate between the continent of origin and the location of the colony (on Terra maps all CIV start on Europe).
I've tried 2 approaches to deal with the Lua coding:
1- A modular approach
--Is founding unit settler or colonist?
GameEvents.PlayerCityFounded.Add(function isCityFoundedByColonist(iPlayer, iUnit))
local pPlayer = Players[iPlayer]
local pUnit = pPlayer:GetUnitByID(iUnit)
if pUnit = unit:canFound() == true then
if (pUnit == nil or pUnit:IsDelayedDeath()) then
if (pUnit:GetUnitType() == GameInfoTypes["UNIT_COLONIST"]) then
CityFoundedByColonist()
if (pUnit ~= nil and pUnit:IsFound()) then
pUnit:Kill();
print("City is Founded By Colonist:",plotID, "coords",pPlot:GetX(), pPlot:GetY());
end
end
end
Events.SerialEventCityCreated.Add(CityFoundedByColonist)
-- Is new city founded overseas? (modeled on UI-Overlay Continent v.5)
-- From MapGenerator.lua, 0=Ocean, 1=America, 2=Asia, 3=Africa, 4=Europe
GameEvents.PlayerCityFounded.Add(function IsOverseasCity(iHexX, iHexY)
for iPlot = 0, Map.GetNumPlots()-1, 1 do
local pPlot = Map.GetPlotByIndex(iPlot)
local iCity = pCity:GetPlotCity()
if (not pPlot:IsWater()) then
local ColonyLocation = pCity[pPlot:GetContinentArtType()]
local startPlot = pPlayer:GetStartingPlot()
local startPlotContinent = startPlot:GetContinentArtType()
if (ColonyLocation ~= nil and ~= startPlotContinent()) then
OverseasCity(iHexX, iHexY)
print("City is Overseas:",plotID, "coords",pPlot:GetX(), pPlot:GetY(), Map:GetPlotByIndex());
end
end
end
end
Events.SerialEventCityCreated.Add(OverseasCity)
--From Medieval Scenario/TurnsRemaining.lua
GameEvents.PlayerCityFounded.Add(function NewColony(iPlayer, iCityX, iCityY))
local pPlayer = Players[iPlayer];
local iCity = pCity:GetPlotCity()
local NewColony = pCity()
if (pPlayer ~= nil) then
--Is city an overseas colony?
if (pCity:CityFoundedByColonist() and pCity:OverseasCity()) then
if not pPlayer:IsMinorCiv() then
NewColony:SetPopulation(3, true);
local iBuildingID;
iBuildingID = GameInfoTypes["BUILDING_MONUMENT"]
NewColony:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_SHRINE"]
NewColony:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_GRANARY"]
NewColony:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_LIBRARY"]
NewColony:SetNumRealBuilding(iBuildingID, 1)
--Is city coastal or inland?
if pCity:IsCoastal() == true then
iBuildingID = GameInfoTypes["BUILDING_LIGHTHOUSE"]
NewColony:SetNumRealBuilding(iBuildingID, 1)
end
end
end
end
end
Events.SerialEventCityCreated.Add(NewColony)
2- An integrated approach
GameEvents.PlayerCityFounded.Add(function OverseasCityFoundedByColonist(iPlayer, iUnit))
local pPlayer = Players[iPlayer]
for iPlot = 0, Map.GetNumPlots()-1, 1 do
local pPlot = Map.GetPlotByIndex(iPlot)
local pOrigin = pCity:IsCapital()
for pOrigin = 0, Map.GetNumPlots()-1, 1 do
local pOrigin = Map.GetPlotByIndex(iPlot)
if pPlot:GetContinentArtType() ~= pOrigin:GetContinentArtType() then
print("Overseas Plot:",plotID, "coords", pPlot:GetX(), pPlot:GetY(), Map:GetPlotByIndex());
--Is founding unit a colonist?
local pUnit = pPlayer:GetUnitByID(iUnit)
if (pUnit:GetUnitType() == GameInfoTypes["UNIT_COLONIST"]) and (pUnit:canFound(<Plot> pPlot, boolean bTestVisible = false)) then
City:SetPopulation(3, true)
local iBuildingID
iBuildingID = GameInfoTypes["BUILDING_MONUMENT"]
City:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_SHRINE"]
City:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_GRANARY"]
City:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_LIBRARY"]
City:SetNumRealBuilding(iBuildingID, 1)
--Is city coastal or inland?
if pCity:IsCoastal() == true then
iBuildingID = GameInfoTypes["BUILDING_LIGHTHOUSE"]
City:SetNumRealBuilding(iBuildingID, 1)
end
end
end
end
end
end
end
end
Events.SerialEventCityCreated.Add(OverseasCityFoundedByColonist)
Both approaches have failed.
I'd appreciate if you could help with those codes.
Now, I'm fully aware that these codes probably look like feeble pedestrian attempts at coding in Lua... After spending 2 weeks reading Lua tutorials/references, CIVFans Lua threads and countless Lua files, I feel like I have a grasp on the Lua vocab and functions but that I still don't understand the syntax/grammar of connecting Lua to CIV5.
So, in addition to helping me fix the above codes, I'd appreciate if someone could either point me in the direction of some references or enligthen me regarding the following structures:
1) "for iPlot = 0, Map.GetNumPlots()-1, 1 do": Why does iPlot = 0 and why add -1.
2) when do you need to specify the content of "()" and when can you leave it empty? As in NewColony(iPlayer, iCityX, iCityY).
3) What should go within the "()"?
4) When should a new Lua code be ended by a GameEvent or SerialEvent and when can it be ended without mention of such an event.
5) When and what should be defined as local and when is it unnecessary to define elements of the function.
Thanks a lot in advance!
My first step in that direction was creating a new tech (Colonialism) which allows the training of a new unit, the Colonist. All of this was done in xml without much problems.
Now, I need to use Lua to have the Colonist do the following:
1- settle new cities only on new continents (xml <FoundAbroad> doesn't appear to discriminate by continents);
2- upon settling a colony on a new continent: (a) set city pop to 3, (b) add a few free buildings;
3- ensure that regular Settlers settling on a new continent don't get bonuses.
I was hoping to use the "GetContinentArtType()" function (as per whoward69's UI - Overlay Continents) as a proxy to discriminate between the continent of origin and the location of the colony (on Terra maps all CIV start on Europe).
I've tried 2 approaches to deal with the Lua coding:
1- A modular approach
Spoiler :
--Is founding unit settler or colonist?
GameEvents.PlayerCityFounded.Add(function isCityFoundedByColonist(iPlayer, iUnit))
local pPlayer = Players[iPlayer]
local pUnit = pPlayer:GetUnitByID(iUnit)
if pUnit = unit:canFound() == true then
if (pUnit == nil or pUnit:IsDelayedDeath()) then
if (pUnit:GetUnitType() == GameInfoTypes["UNIT_COLONIST"]) then
CityFoundedByColonist()
if (pUnit ~= nil and pUnit:IsFound()) then
pUnit:Kill();
print("City is Founded By Colonist:",plotID, "coords",pPlot:GetX(), pPlot:GetY());
end
end
end
Events.SerialEventCityCreated.Add(CityFoundedByColonist)
-- Is new city founded overseas? (modeled on UI-Overlay Continent v.5)
-- From MapGenerator.lua, 0=Ocean, 1=America, 2=Asia, 3=Africa, 4=Europe
GameEvents.PlayerCityFounded.Add(function IsOverseasCity(iHexX, iHexY)
for iPlot = 0, Map.GetNumPlots()-1, 1 do
local pPlot = Map.GetPlotByIndex(iPlot)
local iCity = pCity:GetPlotCity()
if (not pPlot:IsWater()) then
local ColonyLocation = pCity[pPlot:GetContinentArtType()]
local startPlot = pPlayer:GetStartingPlot()
local startPlotContinent = startPlot:GetContinentArtType()
if (ColonyLocation ~= nil and ~= startPlotContinent()) then
OverseasCity(iHexX, iHexY)
print("City is Overseas:",plotID, "coords",pPlot:GetX(), pPlot:GetY(), Map:GetPlotByIndex());
end
end
end
end
Events.SerialEventCityCreated.Add(OverseasCity)
--From Medieval Scenario/TurnsRemaining.lua
GameEvents.PlayerCityFounded.Add(function NewColony(iPlayer, iCityX, iCityY))
local pPlayer = Players[iPlayer];
local iCity = pCity:GetPlotCity()
local NewColony = pCity()
if (pPlayer ~= nil) then
--Is city an overseas colony?
if (pCity:CityFoundedByColonist() and pCity:OverseasCity()) then
if not pPlayer:IsMinorCiv() then
NewColony:SetPopulation(3, true);
local iBuildingID;
iBuildingID = GameInfoTypes["BUILDING_MONUMENT"]
NewColony:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_SHRINE"]
NewColony:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_GRANARY"]
NewColony:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_LIBRARY"]
NewColony:SetNumRealBuilding(iBuildingID, 1)
--Is city coastal or inland?
if pCity:IsCoastal() == true then
iBuildingID = GameInfoTypes["BUILDING_LIGHTHOUSE"]
NewColony:SetNumRealBuilding(iBuildingID, 1)
end
end
end
end
end
Events.SerialEventCityCreated.Add(NewColony)
2- An integrated approach
Spoiler :
GameEvents.PlayerCityFounded.Add(function OverseasCityFoundedByColonist(iPlayer, iUnit))
local pPlayer = Players[iPlayer]
for iPlot = 0, Map.GetNumPlots()-1, 1 do
local pPlot = Map.GetPlotByIndex(iPlot)
local pOrigin = pCity:IsCapital()
for pOrigin = 0, Map.GetNumPlots()-1, 1 do
local pOrigin = Map.GetPlotByIndex(iPlot)
if pPlot:GetContinentArtType() ~= pOrigin:GetContinentArtType() then
print("Overseas Plot:",plotID, "coords", pPlot:GetX(), pPlot:GetY(), Map:GetPlotByIndex());
--Is founding unit a colonist?
local pUnit = pPlayer:GetUnitByID(iUnit)
if (pUnit:GetUnitType() == GameInfoTypes["UNIT_COLONIST"]) and (pUnit:canFound(<Plot> pPlot, boolean bTestVisible = false)) then
City:SetPopulation(3, true)
local iBuildingID
iBuildingID = GameInfoTypes["BUILDING_MONUMENT"]
City:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_SHRINE"]
City:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_GRANARY"]
City:SetNumRealBuilding(iBuildingID, 1)
iBuildingID = GameInfoTypes["BUILDING_LIBRARY"]
City:SetNumRealBuilding(iBuildingID, 1)
--Is city coastal or inland?
if pCity:IsCoastal() == true then
iBuildingID = GameInfoTypes["BUILDING_LIGHTHOUSE"]
City:SetNumRealBuilding(iBuildingID, 1)
end
end
end
end
end
end
end
end
Events.SerialEventCityCreated.Add(OverseasCityFoundedByColonist)
Both approaches have failed.
I'd appreciate if you could help with those codes.
Now, I'm fully aware that these codes probably look like feeble pedestrian attempts at coding in Lua... After spending 2 weeks reading Lua tutorials/references, CIVFans Lua threads and countless Lua files, I feel like I have a grasp on the Lua vocab and functions but that I still don't understand the syntax/grammar of connecting Lua to CIV5.
So, in addition to helping me fix the above codes, I'd appreciate if someone could either point me in the direction of some references or enligthen me regarding the following structures:
1) "for iPlot = 0, Map.GetNumPlots()-1, 1 do": Why does iPlot = 0 and why add -1.
2) when do you need to specify the content of "()" and when can you leave it empty? As in NewColony(iPlayer, iCityX, iCityY).
3) What should go within the "()"?
4) When should a new Lua code be ended by a GameEvent or SerialEvent and when can it be ended without mention of such an event.
5) When and what should be defined as local and when is it unnecessary to define elements of the function.
Thanks a lot in advance!
