Improvement doubles luxury resource

Danmacsch

Geheimekabinetsminister
Joined
Jan 14, 2014
Messages
1,316
Location
Copenhagen, Denmark
Is there an easy way to double the amount of a luxury resource when a specific improvement is built on it.

I've made the improvement so that it can only be build on luxury resources in SQL ("improvements_validresources" or something like that). Instead of creating a dummy building for each of these resources that provides a fixed amount of 4 of the respective resource, is there some way to simply double the amount when the improvement is built?
Also, the amount of the resource should of course be lowered to the standard amount if the tile is no longer owned by a specific civilisation.

Hopefully my request makes sense ;)
 
Great, will give that a try.

Since this thread is actually in the lua subsection, maybe I should continue with an actual lua question :)

I'm having some trouble with the following code (syntax error) and can't really see where I've gone wrong.
There's four functions: two utility functions by JFD (add/remove promotion) and two main functions; one that counts the number of a specific improvement, and one that gives a specific unit type promotions corresponding to the number of improvements.
Code:
function JFD_AddPromotion(unit, promotionID)
	if not unit:IsHasPromotion(promotionID) then
		unit:SetHasPromotion(promotionID, true)
	end
end
Code:
function JFD_RemovePromotion(unit, promotionID)
	if unit:IsHasPromotion(promotionID) then
		unit:SetHasPromotion(promotionID, false)
	end
end
Code:
local DMS_TradeColonyInternal = GameInfoTypes["IMPROVEMENT_DMS_TRADE_COLONY_INTERNAL"]
local DMS_TradeColonyCityState = GameInfoTypes["IMPROVEMENT_DMS_TRADE_COLONY_CITYSTATE"]
local DMS_SotR1 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_1"]
local DMS_SotR2 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_2"]
local DMS_SotR3 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_3"]
local DMS_SotR4 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_4"]
local DMS_SotR5 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_5"]
local DMS_SotR6 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_6"]
local DMS_SotR7 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_7"]
local DMS_SotR8 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_8"]
local DMS_Argosy = GameInfoTypes["UNIT_DMS_ARGOSY"]
local DMS_ArgosyUpg = GameInfoTypes["UNIT_DMS_ARGOSY_UPG"]
local DMS_Trgovac = GameInfoTypes["UNIT_DMS_TRGOVAC"]
local DMS_TrgovacCS = GameInfoTypes["UNIT_DMS_TRGOVAC_CS"]
Code:
DMS_CountTradeColonyCS_PlayerID = 0
DMS_CountTradeColonyCS_iX = 0
DMS_CountTradeColonyCS_iY = 0
DMS_CountTradeColonyCS_ID = 0

function DMS_CountTradeColonyCS(playerID, plotX, plotY, improvementID)
	if DMS_CountTradeColonyCS_PlayerID == playerID and DMS_CountTradeColonyCS_iX == iX and DMS_CountTradeColonyCS_iY == iY and DMS_CountTradeColonyCS_ID == improvementID then return end

	DMS_CountTradeColonyCS_PlayerID = 0
	DMS_CountTradeColonyCS_iX = 0
	DMS_CountTradeColonyCS_iY = 0
	DMS_CountTradeColonyCS_ID = 0

	local player = Players[playerID]
	local DMS_NumTradeColonyCS = 0
	if player:IsAlive() and player:GetCivilizationType() == civilisationID then 
		if improvementID == DMS_TradeColonyCityState then
			DMS_NumTradeColonyCS = DMS_NumTradeColonyCS + 1
		end
	return DMS_NumTradeColonyCS
	end
end
GameEvents.BuildFinished.Add(DMS_CountTradeColonyCS)
Code:
function DMS_ArgosyPromotions(playerID)
	local player = Players[playerID]
	if player:IsAlive() and player:GetCivilizationType() == civilisationID then
		for unit in player:Units() do
			if unit and unit:GetUnitType() == DMS_Argosy then
				if (DMS_NumTradeColonyCS == 1) then JFD_AddPromotion(unit, DMS_SotR1)
				elseif (DMS_NumTradeColonyCS == 2) then JFD_AddPromotion(unit, DMS_SotR2) and JFD_RemovePromotion(unit, DMS_SotR1)
				elseif (DMS_NumTradeColonyCS == 3) then JFD_RemovePromotion(unit, DMS_SotR2) and JFD_AddPromotion(unit, DMS_SotR3)
				elseif (DMS_NumTradeColonyCS == 4) then JFD_RemovePromotion(unit, DMS_SotR3) and JFD_AddPromotion(unit, DMS_SotR4)
				elseif (DMS_NumTradeColonyCS == 5) then JFD_RemovePromotion(unit, DMS_SotR4) and JFD_AddPromotion(unit, DMS_SotR5)
				elseif (DMS_NumTradeColonyCS == 6) then JFD_RemovePromotion(unit, DMS_SotR5) and JFD_AddPromotion(unit, DMS_SotR6)
				elseif (DMS_NumTradeColonyCS == 7) then JFD_RemovePromotion(unit, DMS_SotR6) and JFD_AddPromotion(unit, DMS_SotR7)
				elseif (DMS_NumTradeColonyCS >= 8) then JFD_RemovePromotion(unit, DMS_SotR7) and JFD_AddPromotion(unit, DMS_SotR8)
				end
			end
		end
	end
end
GameEvents.PlayerDoTurn.Add(DMS_ArgosyPromotions)
The syntax error I get is referenced to the "if (DMS_NumTradeColonyCS == 1) then JFD_AddPromotion(unit, DMS_SotR1)" line in the DMS_ArgosyPromotions function.
 
I can't see anything wrong in the line you mentioned, but in the next lines you can't use 'and' like this - it's used only in logical expressions (like if conditions), not to join two instructions together. I think you can just remove these ands and keep everything else as it is - two instructions separated by a space will get executed normally.
 
I don't see a civilisationID = ? anywhere unless I missed it.

'?' being in this case an integer value or a variable.

If not set beforehand, civilisationID will just be 'nil' all the time, which wouldn't allow the function(s) to run once the syntax issues are cleared up, since the PlayerID data isn't ever going to "match" 'nil'.
 
I can't see anything wrong in the line you mentioned, but in the next lines you can't use 'and' like this - it's used only in logical expressions (like if conditions), not to join two instructions together. I think you can just remove these ands and keep everything else as it is - two instructions separated by a space will get executed normally.

That seems to have done the trick - thanks. I hadn't even considered that. :)


Okay, there's another thing, I'm having some trouble with, and I can't figure out how to do it code-wise. Maybe one of you guys can give me some guidance. (Didn't toss this at you in your Hyperion's Moon Base thread, Bane_, since it's quite a big request :D, but if you want to have a crack at it, please do :please:)

Some time ago I had another thread with some lua questions, one of which was if it would be possible to detect when a certain feature (for example forest) was removed from a plot.
I learned that this was not possible without dll changes (could be done with Whoward's DLL) unfortunately.
Then I stumbled upon this thread, in which Pazyryk in post #5 describes a way which makes it possible (I think).

In shortness what I want to do is to add a specific unit (say trieme) when a certain feature (say forest) is removed.
I think the method Pazyryk was talking about is to have a function that checks every plot for feature types (in my case, just plots owned by the player) and stores the information. Then another function will check for all the stored tiles if they still - after every turn - have the same feature. If the feature before was a forest and isn't now (i.e. was removed), then a Trieme would be added.

I hope what I'm trying to describe makes sense :crazyeye:
 
That seems to have done the trick - thanks. I hadn't even considered that. :)

Ok, now I'm confused. Why was that making the next line not work?
If you simply put "if var then" shouldn't the code work normally if the variable isn't nil? That was my impression, but it seems to be equivocated from the results of this problem solution.
 
Maybe I should have phrased it differently; "seems to have done the trick" as in "not getting syntax error anymore".
I haven't re-checked if the function actually does what it's suppose to do.
Regarding the line, maybe I messed the line number up, and the line that was actually referenced was the one PawelS corrected in post #4. Or maybe that wasn't what you were referring to?

Now the code is as follows:
Spoiler :
Code:
function DMS_ArgosyPromotions(playerID)
	local player = Players[playerID]
	if player:IsAlive() and player:GetCivilizationType() == civilisationID then
		for unit in player:Units() do
			if unit and unit:GetUnitType() == DMS_Argosy or unit:GetUnitType() == DMS_ArgosyUpg then
				if (DMS_NumTradeColonyCS == 1) then			JFD_AddPromotion(unit, DMS_SotR1)
				elseif (DMS_NumTradeColonyCS == 2) then		JFD_AddPromotion(unit, DMS_SotR2)		JFD_RemovePromotion(unit, DMS_SotR1)
				elseif (DMS_NumTradeColonyCS == 3) then		JFD_AddPromotion(unit, DMS_SotR3)		JFD_RemovePromotion(unit, DMS_SotR2)
				elseif (DMS_NumTradeColonyCS == 4) then		JFD_AddPromotion(unit, DMS_SotR4)		JFD_RemovePromotion(unit, DMS_SotR3)
				elseif (DMS_NumTradeColonyCS == 5) then		JFD_AddPromotion(unit, DMS_SotR5)		JFD_RemovePromotion(unit, DMS_SotR4)
				elseif (DMS_NumTradeColonyCS == 6) then		JFD_AddPromotion(unit, DMS_SotR6)		JFD_RemovePromotion(unit, DMS_SotR5)
				elseif (DMS_NumTradeColonyCS == 7) then		JFD_AddPromotion(unit, DMS_SotR7)		JFD_RemovePromotion(unit, DMS_SotR6)
				elseif (DMS_NumTradeColonyCS >= 8) then		JFD_AddPromotion(unit, DMS_SotR8)		JFD_RemovePromotion(unit, DMS_SotR7)
				end
			end
		end
	end
end
GameEvents.PlayerDoTurn.Add(DMS_ArgosyPromotions)
 
Hmm, in the DMS_ArgosyPromotions function you're using a variable called DMS_NumTradeColonyCS, but you don't seem to assign a value to it... there is a variable with the same name in the DMS_CountTradeColonyCS function, but it's a local variable, so its value is not visible outside of that function. Also DMS_CountTradeColonyCS returns this value, which doesn't make sense as the "hook" events (like BuildFinished) aren't supposed to return anything.
 
Danmacsch,

perhaps it would be good to post the whole file in a spoiler to clear up any confusions as to where and how you are asigning variables and their values, and how your functions should interact between the PlayerDo Turn and the BuildFinished.
 
That would probably be a good idea, LeeS :blush:. I'm still very new at this lua stuff.

In the spoiler I've included my whole lua script. There's a couple of functions besides the ones posted earlier and some variables not yet in use.
Spoiler :
Code:
--=======================================================================================================================
-- UTILITY FUNCTIONS	
--=======================================================================================================================
-- IsRagusaActive
--------------------------------------------------------------------------------------------------------------------------
local civilisationID = GameInfoTypes["CIVILIZATION_DMS_RAGUSA"]

function IsRagusaActive(civilisationID)
	for iSlot = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
		local slotStatus = PreGame.GetSlotStatus(iSlot)
		if (slotStatus == SlotStatus["SS_TAKEN"] or slotStatus == SlotStatus["SS_COMPUTER"]) then
			if PreGame.GetCivilization(iSlot) == civilisationID then
				return true
			end
		end
	end

	return false
end

if IsRagusaActive(civilisationID) then
	print("The Republic of Ragusa joins the game!")
end
--------------------------------------------------------------------------------------------------------------------------
-- JFD_AddPromotion
--------------------------------------------------------------------------------------------------------------------------
function JFD_AddPromotion(unit, promotionID)
	if not unit:IsHasPromotion(promotionID) then
		unit:SetHasPromotion(promotionID, true)
	end
end
--------------------------------------------------------------------------------------------------------------------------
-- JFD_RemovePromotion
--------------------------------------------------------------------------------------------------------------------------
function JFD_RemovePromotion(unit, promotionID)
	if unit:IsHasPromotion(promotionID) then
		unit:SetHasPromotion(promotionID, false)
	end
end
--------------------------------------------------------------------------------------------------------------------------
-- DMS_IsInCSTerritory
--------------------------------------------------------------------------------------------------------------------------
function DMS_IsInCSTerritory(unit)
	local player = Players[playerID]
	local plot = Map.GetPlot(unit:GetX(), unit:GetY())
	if plot:GetOwner() == player:IsMinorCiv() then 
	
	return true

	end	
end
--------------------------------------------------------------------------------------------------------------------------
-- DMS_convertUnit
--------------------------------------------------------------------------------------------------------------------------
function DMS_convertUnit(pUnit, sNewUnitType)
	local pPlayer = Players[pUnit:GetOwner()]
	local pNewUnit = pPlayer:InitUnit(GameInfoTypes[sNewUnitType], pUnit:GetX(), pUnit:GetY())
	pNewUnit:SetDamage(pUnit:GetDamage())
	pNewUnit:SetExperience(pUnit:GetExperience())
	pNewUnit:SetLevel(pUnit:GetLevel())
	for unitPromotion in GameInfo.UnitPromotions() do
		local iPromotionID = unitPromotion.ID;
		if (pUnit:IsHasPromotion(iPromotionID)) then
			if (pNewUnit:IsPromotionValid(iPromotionID)) then
				pNewUnit:SetHasPromotion(iPromotionID, true)
			end
		end
	end
end
--==========================================================================================================================
-- CORE FUNCTIONS
--==========================================================================================================================
local DMS_TradeColonyInternal = GameInfoTypes["IMPROVEMENT_DMS_TRADE_COLONY_INTERNAL"]
local DMS_TradeColonyCityState = GameInfoTypes["IMPROVEMENT_DMS_TRADE_COLONY_CITYSTATE"]
local DMS_SotR1 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_1"]
local DMS_SotR2 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_2"]
local DMS_SotR3 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_3"]
local DMS_SotR4 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_4"]
local DMS_SotR5 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_5"]
local DMS_SotR6 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_6"]
local DMS_SotR7 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_7"]
local DMS_SotR8 = GameInfoTypes["PROMOTION_SWORD_OF_THE_RECTOR_8"]
local DMS_Argosy = GameInfoTypes["UNIT_DMS_ARGOSY"]
local DMS_ArgosyUpg = GameInfoTypes["UNIT_DMS_ARGOSY_UPG"]
local DMS_Trgovac = GameInfoTypes["UNIT_DMS_TRGOVAC"]
local DMS_TrgovacCS = GameInfoTypes["UNIT_DMS_ARGOSY_UPG"]
--------------------------------------------------------------------------------------------------------------------------
-- DMS_CountTradeColonyCS
--------------------------------------------------------------------------------------------------------------------------
DMS_CountTradeColonyCS_PlayerID = 0
DMS_CountTradeColonyCS_iX = 0
DMS_CountTradeColonyCS_iY = 0
DMS_CountTradeColonyCS_ID = 0

function DMS_CountTradeColonyCS(playerID, plotX, plotY, improvementID)
	if DMS_CountTradeColonyCS_PlayerID == playerID and DMS_CountTradeColonyCS_iX == iX and DMS_CountTradeColonyCS_iY == iY and DMS_CountTradeColonyCS_ID == improvementID then return end

	DMS_CountTradeColonyCS_PlayerID = 0
	DMS_CountTradeColonyCS_iX = 0
	DMS_CountTradeColonyCS_iY = 0
	DMS_CountTradeColonyCS_ID = 0

	local player = Players[playerID]
	local DMS_NumTradeColonyCS = 0
	if player:IsAlive() and player:GetCivilizationType() == civilisationID then 
		if improvementID == DMS_TradeColonyCityState then
			DMS_NumTradeColonyCS = DMS_NumTradeColonyCS + 1
		end
	return DMS_NumTradeColonyCS
	end
end
GameEvents.BuildFinished.Add(DMS_CountTradeColonyCS)
--------------------------------------------------------------------------------------------------------------------------
-- DMS_ArgosyPromotions
--------------------------------------------------------------------------------------------------------------------------
function DMS_ArgosyPromotions(playerID)
	local player = Players[playerID]
	if player:IsAlive() and player:GetCivilizationType() == civilisationID then
		for unit in player:Units() do
			if unit and unit:GetUnitType() == DMS_Argosy or unit:GetUnitType() == DMS_ArgosyUpg then
				if (DMS_NumTradeColonyCS == 1) then			JFD_AddPromotion(unit, DMS_SotR1)
				elseif (DMS_NumTradeColonyCS == 2) then		JFD_AddPromotion(unit, DMS_SotR2)		JFD_RemovePromotion(unit, DMS_SotR1)
				elseif (DMS_NumTradeColonyCS == 3) then		JFD_AddPromotion(unit, DMS_SotR3)		JFD_RemovePromotion(unit, DMS_SotR2)
				elseif (DMS_NumTradeColonyCS == 4) then		JFD_AddPromotion(unit, DMS_SotR4)		JFD_RemovePromotion(unit, DMS_SotR3)
				elseif (DMS_NumTradeColonyCS == 5) then		JFD_AddPromotion(unit, DMS_SotR5)		JFD_RemovePromotion(unit, DMS_SotR4)
				elseif (DMS_NumTradeColonyCS == 6) then		JFD_AddPromotion(unit, DMS_SotR6)		JFD_RemovePromotion(unit, DMS_SotR5)
				elseif (DMS_NumTradeColonyCS == 7) then		JFD_AddPromotion(unit, DMS_SotR7)		JFD_RemovePromotion(unit, DMS_SotR6)
				elseif (DMS_NumTradeColonyCS >= 8) then		JFD_AddPromotion(unit, DMS_SotR8)		JFD_RemovePromotion(unit, DMS_SotR7)
				end
			end
		end
	end
end
GameEvents.PlayerDoTurn.Add(DMS_ArgosyPromotions)
------------------------------------------------------------------------------------------------------------------------
-- ConvertUnitInCSBorders
------------------------------------------------------------------------------------------------------------------------
function ConvertUnitInCSBorders(playerID)
	local player = Players[playerID]
	for unit in player:Units() do
		if unit and DMS_IsInCSTerritory(unit) == true then
			if unit:GetUnitType() == DMS_Argosy then
				DMS_convertUnit(unit, DMS_ArgosyUpg)
			elseif unit:GetUnitType() == DMS_Trgovac then
				DMS_convertUnit(unit, DMS_TrgovacCS)
			end
		end
	end
end
GameEvents.PlayerDoTurn.Add(ConvertUnitInCSBorders)
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
The DMS_IsInCSTerritory, convertUnit and DMS_ConvertUnitInCSBorders are not really the issue (right now, but if you spot some issues, please let me know).

Basically what I hoped to achieve was that the DMS_CountTradeColonyCS function would fire with the BuildFinished game event and return DMS_NumTradeColonyCS (the number of improvements called DMS_TradeColonyCityState)

Then the function DMS_ArgosyPromotions would give promotions (the DMS_SotR promotions) matching the number DMS_NumTradeColonyCS to unit of types DMS_Argosy and DMS_ArgosyUpg.
 
Ok, I am thoroughly confused now. :lol:
Please someone explain me like I was a child please.

What is the issue? I thought you solved the problem before by removing the 'and' as PawelS suggested. Is the code working? If not, what seems to be causing the problem? Have you tried using print() statements to check how far your code goes?

This. Is. Madness! :aargh:
 
Haven't analysed the whole thing as yet, but as PawelS mentioned, this won't work:
Code:
return DMS_NumTradeColonyCS
because the variable is local to the function, and the function is running on the BuildFinished hook, so there's nowhere for the function to "return" the info to. You could put the variable in your top set of variable definitions (where you have the others right below the "--CORE FUNCTIONS" comment), eliminate the lines
Code:
local DMS_NumTradeColonyCS = 0
&
return DMS_NumTradeColonyCS
within the DMS_CountTradeColonyCS function, and that should add "1" to DMS_NumTradeColonyCS every time one of those improvements is completed, but then you'd have to persist the data across saved games or scan through all map plots on saved-game loading in order to reset the data in DMS_NumTradeColonyCS to the appropriate number.
 
What is the issue? I thought you solved the problem before by removing the 'and' as PawelS suggested. Is the code working?
Unfortunately it doesn't no.:cry:

Haven't analysed the whole thing as yet, but as PawelS mentioned, this won't work:
Code:
return DMS_NumTradeColonyCS
because the variable is local to the function, and the function is running on the BuildFinished hook, so there's nowhere for the function to "return" the info to. You could put the variable in your top set of variable definitions (where you have the others right below the "--CORE FUNCTIONS" comment), eliminate the lines
Code:
local DMS_NumTradeColonyCS = 0
&
return DMS_NumTradeColonyCS
within the DMS_CountTradeColonyCS function, and that should add "1" to DMS_NumTradeColonyCS every time one of those improvements is completed, but then you'd have to persist the data across saved games or scan through all map plots on saved-game loading in order to reset the data in DMS_NumTradeColonyCS to the appropriate number.
I hadn't thought of what loading a saved game would do to DMS_NumTradeColonyCS, but of course it resets the data. Is there some easier way to store the data across saved games instead of having to scan through all map plots to set the DMS_NumTradeColonyCS to the correct number?


Another thing I've realized with the code is that the following function doesn't work.
Code:
function DMS_IsInCSTerritory(unit)
	local player = Players[playerID]
	local plot = Map.GetPlot(unit:GetX(), unit:GetY())
	[COLOR="Red"]if plot:GetOwner() == player:IsMinorCiv() then [/COLOR]
	
	return true

	end	
end
I've marked the line in which a runtime error occurs red. What would I do to get this function to work.
It's suppose to be a utility function used in another function (see spoiler in post #14). It should for a unit get it's current plot, check plot ownership and return true if owner is a minor civ.
 
plot:GetOwner() is a player's ID, whilst player:IsMinorCiv is a boolean, and the two can't be compared. To do what you're wanting:

Code:
if Players[plot:GetOwner()]:IsMinorCiv() then

To save persisted data, you can include the NewSaveUtils.lua file in your mod, include that into your lua file, include("NewSaveUtils.lua") and use the SetPersistentProperty(propertyName, value) and GetPersistentProperty(propertyName) functions, where propertyName is a unique name that acts as a variable into which the value goes.
 
plot:GetOwner() is a player's ID, whilst player:IsMinorCiv is a boolean, and the two can't be compared. To do what you're wanting:

Code:
if Players[plot:GetOwner()]:IsMinorCiv() then
Naively I tried just changing the code to the following :blush: - of course that didn't work as I'm still getting a runtime error on the marked line:
Spoiler :
Code:
function DMS_IsInCSTerritory(unit)
	local player = Players[playerID]
	local plot = Map.GetPlot(unit:GetX(), unit:GetY())
	[COLOR="Red"]if Players[plot:GetOwner()]:IsMinorCiv() then[/COLOR]
		
	return true
	
	end	
end
Could you please spell out for how to do it correctly :please:
 
are these referenced units:
Code:
local DMS_Argosy = GameInfoTypes["UNIT_DMS_ARGOSY"]
local DMS_ArgosyUpg = GameInfoTypes["UNIT_DMS_ARGOSY_UPG"]
local DMS_Trgovac = GameInfoTypes["UNIT_DMS_TRGOVAC"]
local DMS_TrgovacCS = GameInfoTypes["UNIT_DMS_ARGOSY_UPG"]
specific to this civ:
local civilisationID = GameInfoTypes["CIVILIZATION_DMS_RAGUSA"]

??

If so, it would make a fair difference in how I would approach the function ConvertUnitInCSBorders(playerID).
 
Top Bottom