Some help and question for Lua

It seems the forums added a space between unitPromotionMun and iID of my correction :mad: Get rid of that space and it should work
EDIT: For some reason I had to put the correction in between code tags or else I couldn't get rid of the space :crazyeye:
 
The code works, but it doesn't seem to give the promotion to the Units with that other Unit with the promotion. Do you know what's going on?

Code:
local unitPromotionMuniID = GameInfoTypes["PROMOTION_SHOCK_1"]
local unitPromotionMuniGaverID = GameInfoTypes["PROMOTION_WHATEVER"]
local unitCombatLandID = {[GameInfoTypes.UNITCOMBAT_MELEE]=GameInfoTypes.UNITCOMBAT_MELEE, [GameInfoTypes.UNITCOMBAT_GUN]=GameInfoTypes.UNITCOMBAT_GUN}

function MunitionsGunBoost(playerID)
	local player = Players[playerID]
	local MunitionsNearby = false
	for unit in player:Units() do
		if (unit:GetUnitCombatType() == unitCombatLandID and not (unit:IsEmbarked())) then
			for munitionsPromotion in player:Units() do
				if munitionsPromotion:IsHasPromotion(unitPromotionMuniID) then
					if Map.PlotDistance(unit:GetX(), unit:GetY(), munitionsPromotion:GetX(), munitionsPromotion:GetY()) < 3 then
						MunitionsNearby = true
					end
				end
			end
			
			if MunitionsNearby then
				if not unit:IsHasPromotion(unitPromotionMuniGaverID) then
					unit:SetHasPromotion(unitPromotionMuniGaverID, true)
				end
			else
				if unit:IsHasPromotion(unitPromotionMuniGaverID) then
					unit:SetHasPromotion(unitPromotionMuniGaverID, false)
				end
			end
			
		else
			if unit:IsHasPromotion(unitPromotionMuniGaverID) then
				unit:SetHasPromotion(unitPromotionMuniGaverID, false)
			end
		end
	end
end
GameEvents.UnitSetXY.Add(MunitionsGunBoost) 
GameEvents.PlayerDoTurn.Add(MunitionsGunBoost)
 
Here's an error:
Code:
unit:GetUnitCombatType() == unitCombatLandID
You are checking if UNITCOMBAT_MELEE == a table, which will never be the case thus the code will not fire.
Change that part to this:
Code:
unitCombatLandID[unit:GetUnitCombatType()]

I recommend you change up some variable names because right now some of them are a bit misleading :)
E.g. Change unitCombatLandID to tValidCombatTypes (where the 't' stands for 'table')
 
Good news, the code works! Interestingly, the owner of the unitPromotionMuniID Promotion gets the unitPromotionMuniGaverID promotion if it's a gun or melee unit. Is it possible to have the owner of the unitPromotionMuniID promotion to not get the effects of the promotion it gives?
 
This is going to be really hard to explain, but let's give it a shot:
Code:
local unitPromotionMuniID = GameInfoTypes["PROMOTION_SHOCK_1"]
local unitPromotionMuniGaverID = GameInfoTypes["PROMOTION_WHATEVER"]
local unitCombatLandID = {[GameInfoTypes.UNITCOMBAT_MELEE]=GameInfoTypes.UNITCOMBAT_MELEE, [GameInfoTypes.UNITCOMBAT_GUN]=GameInfoTypes.UNITCOMBAT_GUN}

function MunitionsGunBoost(playerID)
	local player = Players[playerID]
	local MunitionsNearby = false
	[COLOR="DarkRed"]for unit in player:Units() do[/COLOR]
		[COLOR="Blue"]if( [/COLOR]unitCombatLandID[unit:GetUnitCombatType()] and not (unit:IsEmbarked())[COLOR="blue"]) then[/COLOR]
			[COLOR="Green"]for munitionsPromotion in player:Units() do[/COLOR]
				if munitionsPromotion:IsHasPromotion(unitPromotionMuniID) then
					[COLOR="Orange"]if [/COLOR]Map.PlotDistance(unit:GetX(), unit:GetY(), munitionsPromotion:GetX(), munitionsPromotion:GetY()) < 3 [COLOR="orange"]then[/COLOR]
						MunitionsNearby = true
					end
				end
			[COLOR="green"]end[/COLOR]
			
			if MunitionsNearby then
				if not unit:IsHasPromotion(unitPromotionMuniGaverID) then
					unit:SetHasPromotion(unitPromotionMuniGaverID, true)
				end
			else
				if unit:IsHasPromotion(unitPromotionMuniGaverID) then
					unit:SetHasPromotion(unitPromotionMuniGaverID, false)
				end
			end
			
		else
			if unit:IsHasPromotion(unitPromotionMuniGaverID) then
				unit:SetHasPromotion(unitPromotionMuniGaverID, false)
			end
		end
	[COLOR="darkred"]end[/COLOR]
end
GameEvents.UnitSetXY.Add(MunitionsGunBoost) 
GameEvents.PlayerDoTurn.Add(MunitionsGunBoost)

So in the red loop, you loop through every unit, and only start the green loop if the unit is a gun/melee unit. In the green loop, you loop through every unit again, and check if that unit has the IbuffMyAllies-promotion and is in range of the unit of the red loop. If that is the case, the ImBuffed-promotion is given.

So why is the promotion also given to the IbuffMyAllies-unit as well when it's a gun/melee unit?
It's because you loop through every unit in the green loop, which includes the exact same unit. And since the distance in hexes/in range is 0 (because the units are on the same tile (because they are the same unit) and because the code doesn't care that it's the same unit), the ImBuffed-promotion is also given to that unit!

There are two possible fixes for this depending on what you want:
1. Check if "unit ~= munitionsPromotion" and only apply the promotion if that's the case (because if this is true, it means that the IbuffMyAllies is not checking itself). This does however mean that IbuffMyAllies_A can give the promotion to IbuffMyAllies_B, and the other way around. (Add it to the orange if-statement)
OR
2. Check if "not unit:IsHasPromotion(IbuffMyAllies)", which would prevent the unit from getting buffed if it is a IbuffMyAllies-unit. (Add it to the blue if-statement)
 
I tried the 2nd fix you said, but it's not working, it's in red in the code below. I didn't try the 1st fix yet, I'm kinda confused about that one.

Code:
local unitPromotionMuniID = GameInfoTypes["PROMOTION_SHOCK_1"]
local unitPromotionMuniGaverID = GameInfoTypes["PROMOTION_WHATEVER"]
local unitCombatLandID = {[GameInfoTypes.UNITCOMBAT_MELEE]=GameInfoTypes.UNITCOMBAT_MELEE, [GameInfoTypes.UNITCOMBAT_GUN]=GameInfoTypes.UNITCOMBAT_GUN}, not [COLOR="Red"]unit:IsHasPromotion(unitPromotionMuniID)[/COLOR]

function MunitionsGunBoost(playerID)
	local player = Players[playerID]
	local MunitionsNearby = false
	for unit in player:Units() do
		if(unitCombatLandID[unit:GetUnitCombatType()] and not (unit:IsEmbarked())) then
			for munitionsPromotion in player:Units() do
				if munitionsPromotion:IsHasPromotion(unitPromotionMuniID) then
					if Map.PlotDistance(unit:GetX(), unit:GetY(), munitionsPromotion:GetX(), munitionsPromotion:GetY()) < 3 then
						MunitionsNearby = true
					end
				end
			end
			
			if MunitionsNearby then
				if not unit:IsHasPromotion(unitPromotionMuniGaverID) then
					unit:SetHasPromotion(unitPromotionMuniGaverID, true)
				end
			else
				if unit:IsHasPromotion(unitPromotionMuniGaverID) then
					unit:SetHasPromotion(unitPromotionMuniGaverID, false)
				end
			end
			
		else
			if unit:IsHasPromotion(unitPromotionMuniGaverID) then
				unit:SetHasPromotion(unitPromotionMuniGaverID, false)
			end
		end
	end
end
GameEvents.UnitSetXY.Add(MunitionsGunBoost) 
GameEvents.PlayerDoTurn.Add(MunitionsGunBoost)

And here's something from FireTuner:

Code:
[10182.218] Runtime Error: C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Promotion.lua:8: attempt to index global 'unit' (a nil value)
stack traceback:
	C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Promotion.lua:8: in main chunk
	=[C]: ?
[10182.218] Runtime Error: Error loading C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Promotion.lua.
 
Code:
local unitPromotionMuniID = GameInfoTypes["PROMOTION_SHOCK_1"]
local unitPromotionMuniGaverID = GameInfoTypes["PROMOTION_WHATEVER"]
local unitCombatLandID = {[GameInfoTypes.UNITCOMBAT_MELEE]=GameInfoTypes.UNITCOMBAT_MELEE, [GameInfoTypes.UNITCOMBAT_GUN]=GameInfoTypes.UNITCOMBAT_GUN}[S], not unit:IsHasPromotion(unitPromotionMuniID)[/S]

function MunitionsGunBoost(playerID)
	local player = Players[playerID]
	local MunitionsNearby = false
	for unit in player:Units() do
		if(unitCombatLandID[unit:GetUnitCombatType()] and not (unit:IsEmbarked()) and [COLOR="DarkRed"]not (unit:IsHasPromotion(unitPromotionMuniID))[/COLOR]) then
			for munitionsPromotion in player:Units() do
				if munitionsPromotion:IsHasPromotion(unitPromotionMuniID) then
					if Map.PlotDistance(unit:GetX(), unit:GetY(), munitionsPromotion:GetX(), munitionsPromotion:GetY()) < 3 then
						MunitionsNearby = true
					end
				end
			end
			
			if MunitionsNearby then
				if not unit:IsHasPromotion(unitPromotionMuniGaverID) then
					unit:SetHasPromotion(unitPromotionMuniGaverID, true)
				end
			else
				if unit:IsHasPromotion(unitPromotionMuniGaverID) then
					unit:SetHasPromotion(unitPromotionMuniGaverID, false)
				end
			end
			
		else
			if unit:IsHasPromotion(unitPromotionMuniGaverID) then
				unit:SetHasPromotion(unitPromotionMuniGaverID, false)
			end
		end
	end
end
GameEvents.UnitSetXY.Add(MunitionsGunBoost) 
GameEvents.PlayerDoTurn.Add(MunitionsGunBoost)

This is what I meant :)
 
I've been trying this code borrowed from JFD's Meiji's Japan Civ, and I can't get it to work, when I check it with IGE. I'm trying to use this code to have a dummy building generated in the capital when a unit with a certain promotion in garrisoned.

Code:
local buildingPrimePC	= GameInfoTypes["BUILDING_PRIME_P_AND_C"]
local unitPromotionPrimeID = GameInfoTypes["PROMOTION_MATRIX_BEARER"] 

function PrimeGarrison(playerID)
	local player = Players[playerID]
	if player:IsAlive() then
		for city in player:Cities() do
			local cityPlot = city:Plot()
			local primeInCity = false
			for unitID = 0, cityPlot:GetNumUnits() - 1, 1 do
				if (cityPlot and cityPlot:GetUnit(unitID):IsHasPromotion(unitPromotionPrimeID)) then
					primeGarrison = true
					break
				end
			end

			if primeInCity then
				if (not city:IsHasBuilding(buildingPrimePC)) then
					city:SetNumRealBuilding(buildingPrimePC, 1)
				end
			else
				if city:IsHasBuilding(buildingPrimePC) then
					city:SetNumRealBuilding(buildingPrimePC, 0)
				end
			end
		end
	end
end
GameEvents.PlayerDoTurn.Add(PrimeGarrison)


Here's the Dummy Building files, if you're curious. I'll be also using this code for another dummy building that actives with the same promotion (The BUILDING_COMMUNICATIONS):
Spoiler :
Code:
	<BuildingClasses>
		<Row>
			<Type>BUILDINGCLASS_COMMUNICATIONS</Type>
			<DefaultBuilding>BUILDING_COMMUNICATIONS</DefaultBuilding>
			<Description>TXT_KEY_BUILDING_COMMUNICATIONS</Description>

		</Row>
	</BuildingClasses>
	<Buildings>
		<Row>
			<Type>BUILDING_COMMUNICATIONS</Type>
			<BuildingClass>BUILDINGCLASS_COMMUNICATIONS</BuildingClass>
			<Description>TXT_KEY_BUILDING_COMMUNICATIONS</Description>
			<PrereqTech>NULL</PrereqTech>
			<Cost>-1</Cost>
			<GreatWorkCount>-1</GreatWorkCount>
			<FaithCost>-1</FaithCost>
			<MinAreaSize>-1</MinAreaSize>
			<NeverCapture>true</NeverCapture>
			<NukeImmune>true</NukeImmune>
			<PortraitIndex>19</PortraitIndex>
			<IconAtlas>BW_ATLAS_1</IconAtlas>
			<EspionageModifier>-15</EspionageModifier>
		</Row>
	</Buildings>
	<Language_en_US>
		<Row Tag="TXT_KEY_BUILDING_COMMUNICATIONS">
			<Text>Decepticons Communications Dummy Building</Text>
		</Row>
	</Language_en_US>

	<BuildingClasses>
		<Row>
			<Type>BUILDINGCLASS_PRIME_P_AND_C</Type>
			<DefaultBuilding>BUILDING_PRIME_P_AND_C</DefaultBuilding>
			<Description>TXT_KEY_BUILDING_PRIME_P_AND_C</Description>

		</Row>
	</BuildingClasses>
	<Buildings>
		<Row>
			<Type>BUILDING_PRIME_P_AND_C</Type>
			<BuildingClass>BUILDINGCLASS_PRIME_P_AND_C</BuildingClass>
			<Description>TXT_KEY_BUILDING_PRIME_P_AND_C</Description>
			<PrereqTech>NULL</PrereqTech>
			<Cost>-1</Cost>
			<GreatWorkCount>-1</GreatWorkCount>
			<FaithCost>-1</FaithCost>
			<MinAreaSize>-1</MinAreaSize>
			<NeverCapture>true</NeverCapture>
			<NukeImmune>true</NukeImmune>
			<PortraitIndex>19</PortraitIndex>
			<IconAtlas>BW_ATLAS_1</IconAtlas>
			<CultureRateModifier>10</CultureRateModifier>
		</Row>
	</Buildings>
	<Building_YieldModifiers>
		<Row>
			<BuildingType>BUILDING_PRIME_P_AND_C</BuildingType>
			<YieldType>YIELD_PRODUCTION</YieldType>
			<Yield>10</Yield>
		</Row>
	</Building_YieldModifiers>
	<Language_en_US>
		<Row Tag="TXT_KEY_BUILDING_PRIME_P_AND_C">
			<Text>Autobot Prime Dummy Building</Text>
		</Row>
	</Language_en_US>
</GameData>
 
I've been trying this code borrowed from JFD's Meiji's Japan Civ, and I can't get it to work, when I check it with IGE. I'm trying to use this code to have a dummy building generated in the capital when a unit with a certain promotion in garrisoned.

Code:
local buildingPrimePC	= GameInfoTypes["BUILDING_PRIME_P_AND_C"]
local unitPromotionPrimeID = GameInfoTypes["PROMOTION_MATRIX_BEARER"] 

function PrimeGarrison(playerID)
	local player = Players[playerID]
	if player:IsAlive() then
		for city in player:Cities() do
			local cityPlot = city:Plot()
			[COLOR="DarkRed"]local primeInCity = false[/COLOR]
			for unitID = 0, cityPlot:GetNumUnits() - 1, 1 do
				if (cityPlot and cityPlot:GetUnit(unitID):IsHasPromotion(unitPromotionPrimeID)) then
					[COLOR="darkred"]primeGarrison = true[/COLOR]
					break
				end
			end

			if [COLOR="DarkRed"]primeInCity[/COLOR] then
				if (not city:IsHasBuilding(buildingPrimePC)) then
					city:SetNumRealBuilding(buildingPrimePC, 1)
				end
			else
				if city:IsHasBuilding(buildingPrimePC) then
					city:SetNumRealBuilding(buildingPrimePC, 0)
				end
			end
		end
	end
end
GameEvents.PlayerDoTurn.Add(PrimeGarrison)

Look closely at the variable names highlighted in red
Spoiler :
If you still don't see it, they are not the same, meaning that primeInCity will always stay false
 
Alright, I found a new problem with my most recent mod, for some reason the Decepticons' UA doesn't seem to work, thanks to a tip from a Steam user.

Using Firetuner doesn't work, it doesn't seem to find the error from Lua, so I'm not sure what's going wrong.

Click here to download the mod.

Code:
--local tValidCityCaptureUnitDomains = {[GameInfoTypes.DOMAIN_LAND]=GameInfoTypes.DOMAIN_LAND, [GameInfoTypes.DOMAIN_SEA]=GameInfoTypes.DOMAIN_SEA} --EDIT: Thank you LeeS :)
local tValidCityCaptureUnitDomains = GameInfoTypes.DOMAIN_LAND
[...]
if tValidCityCaptureUnitDomains[pUnit:GetDomainType()]

tValidCityCaptureUnitDomains needs to be a table for this to work. Try
Code:
local tValidCityCaptureUnitDomains = {[GameInfoTypes.DOMAIN_LAND]=true}
instead.
 
(In addition to what Klisz said: )

In the Lua:
Code:
local iMarkerPromotionBuilding = GameInfoTypes.BUILDING_DECEPTICONS_PROMOTION_DUMMY
local iCiv = GameInfoTypes.[COLOR="Red"]CIVILIZATION_DECEPTICON[/COLOR]

local tValidCapturePromotion = {GameInfoTypes.PROMOTION_COMMUNICATIONS, 
								GameInfoTypes.PROMOTION_MILITARY_OPS, 
								GameInfoTypes.PROMOTION_GROUND_AND_AIR,
								GameInfoTypes.PROMOTION_FUEL_SCOUT,
								GameInfoTypes.PROMOTION_PSYCHO_WARFARE,
								GameInfoTypes.PROMOTION_AEROSPACE_COMMANDER,
								GameInfoTypes.PROMOTION_DEMOLITIONS,
								GameInfoTypes.PROMOTION_MUNITIONS,
								GameInfoTypes.PROMOTION_SABOTEUR,
								GameInfoTypes.PROMOTION_TERRORIST,
								GameInfoTypes.PROMOTION_ELEC_WARRIOR,
								GameInfoTypes.PROMOTION_STUNTSCOUT} 
[...]

In the XML:
Code:
<Civilizations>
		<Row>
			<Type>[COLOR="red"]CIVILIZATION_DECEPTICON[B]S[/B][/COLOR]</Type>
			<Description>TXT_KEY_CIVILIZATION_DECEPTICONS_DESC</Description>
			<Civilopedia></Civilopedia>
[...]

Spoiler :
CIVILIZATION_DECEPTICON in the Lua, and CIVILIZATION_DECEPTICONS in the XML

Credits to Agent Ransack ;)


The code itself was working perfectly fine, it just wasn't doing what we expected :p
 
Back
Top Bottom