C++/Lua Request Thread

Spoiler :


Code:
-- RomanBuildingsScript
-- Author: LeeS
-- DateCreated: 8/16/2016
--------------------------------------------------------------

local tRequiredCivs = {}
local tBuildingsForSpecifiedCivs = { [GameInfoTypes.BUILDING_TRAJAN] = "true", [GameInfoTypes.BUILDING_THERMAE] = "true" }

for row in GameInfo.Civilizations("Type='CIVILIZATION_ROME'") do
	tRequiredCivs[row.ID] = "true"
end
for row in GameInfo.Civilizations("Type='CIVILIZATION_SCIPIO_ROME'") do
	tRequiredCivs[row.ID] = "true"
end
for row in GameInfo.Civilizations("Type='CIVILIZATION_GPUZ_ROME_JULIUS'") do
	tRequiredCivs[row.ID] = "true"
end
for row in GameInfo.Civilizations("Type='CIVILIZATION_GPUZ_GAIUS_ROME'") do
	tRequiredCivs[row.ID] = "true"
end
for row in GameInfo.Civilizations("Type='CIVILIZATION_JFD_ROME_CONSTANTINE'") do
	tRequiredCivs[row.ID] = "true"
end
for row in GameInfo.Civilizations("Type='CIVILIZATION_TCM_AURELIAN_ROME'") do
	tRequiredCivs[row.ID] = "true"
end

function PlayerCanBuildRomanBuildings(PlayerID, BuildingType)
	if tBuildingsForSpecifiedCivs[BuildingType] then
		local pPlayer = Players[PlayerID]
		if tRequiredCivs[pPlayer:GetCivilizationType()] then
			return true
		else
			return false
		end
	end
	return true
end
GameEvents.PlayerCanConstruct.Add(PlayerCanBuildRomanBuildings)

print("RomanBuildingsScript loaded to end")


  1. In the table called tBuildingsForSpecifiedCivs you list the buildings only these specified civs can construct. The buildings would normally only be those added within your mod, so you will know whether or not such a building exists within the game's database (ie, you have just added it). If you want to give compatibility to another of your mods when both mods are enabled (such as the thermae mod, where this code would work as-is, and some other 'Roman' building mod), you just add the buildings for that mod as like this:
    Code:
    for row in GameInfo.Buildings("Type='BUILDING_ROMAN_WALLS'") do
    	tBuildingsForSpecifiedCivs[row.ID] = "true"
    end
  2. In the table called tRequiredCivs you list the civilizations that get to construct the specified buildings. As we did for the Baths of Trajan, the list of civs is built depending on whether or not a user has the mod or DLC for any of the specified civilizations.

I saw your chat PM but forgot to get back to after I was done pushing out update to the Scipio mod. Sorry if that seemed kinda rude.
 
Thanks, LeeS! I now have three Lua-fied lists of shared UB's in my mod: one for Scandinavia in general, one pair of wonders for Denmark, and a second pair of wonders for Sweden.
 
@LeeS
Wonderful! The code worked quite nicely!

I only have a few more coding quirks that need be dealt with and I'll be done!

So for this next problem I have, one of my custom Civilizations is supposed to receive Points towards Golden Ages whenever it Liberates a captured city. This works all fine and good, except it only triggers on the first Civ, and I need it to be able to trigger when there are multiple copies of the same Civ.

The code in question below (as provided by qqqbbb):
Code:
local iAmerica = GameInfoTypes.CIVILIZATION_AMERICA
local iSlugterraPlayer
local pSlugterraPlayer

local function OnCityCaptureComplete(iPlayer, bIsCapital, iPlotX, iPlotY, iNewPlayer, iOldPop, bConquest, iGreatWorkCount)
	if iNewPlayer == iSlugterraPlayer then
		local pPlot = Map.GetPlot(iPlotX, iPlotY)
		local pCity = pPlot:GetPlotCity()
		if pCity:GetOriginalOwner() ~= iPlayer then
			pSlugterraPlayer:ChangeGoldenAgeProgressMeter(100)
		end
	end
end

for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
	local pPlayer = Players[iPlayer]
	if pPlayer:IsEverAlive() and pPlayer:GetCivilizationType() == iAmerica then
		GameEvents.CityCaptureComplete.Add(OnCityCaptureComplete)
		pSlugterraPlayer = pPlayer
		iSlugterraPlayer = iPlayer
		break
    end
end
Of course if I could, I'd really prefer that Liberating a captured city immediately trigger a Golden Age, but this method is fine. I just need it to trigger for all instances of said Civ in a game.

I'll include the game files too, just to be safe.
 

Attachments

@Harkodos,

I would use:
Code:
local iAmerica = GameInfoTypes.CIVILIZATION_AMERICA
local bTriggerGoldenAge = true
local bAddGoldenAgeProgressPoints = false
local iGoldenAgeProgressPointsToAdd = 100

local function OnCityCaptureComplete(iOldOwner, bIsCapital, iPlotX, iPlotY, iNewOwner, iOldPop, bConquest, iGreatWorkCount)
	local pNewOwner = Players[iNewOwner]
	if pNewOwner:GetCivilizationType() == iAmerica then
		local pCity = Map.GetPlot(iPlotX, iPlotY):GetPlotCity()
		if pCity ~= nil then
			if pCity:GetOriginalOwner() ~= iOldOwner then
				if bTriggerGoldenAge then
					pNewOwner:ChangeGoldenAgeTurns(pNewOwner:GetGoldenAgeLength())
				end
				if bAddGoldenAgeProgressPoints then
					pNewOwner:ChangeGoldenAgeProgressMeter(iGoldenAgeProgressPointsToAdd)
				end
			end
		end
	end
end

for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
	local pPlayer = Players[iPlayer]
	if pPlayer:IsEverAlive() and pPlayer:GetCivilizationType() == iAmerica then
		GameEvents.CityCaptureComplete.Add(OnCityCaptureComplete)
		break
	end
end
print("Golden Age Points from capturing conquered cities loaded to the end")
These new variables allow you to decide if:
  1. you want a golden age to be started (or extended) via variable bTriggerGoldenAge
    • note that the code does nothing to try to keep the Golden Age Points "Cost" of the next natural golden age from being increased.
  2. you want a to add points to the golden age progress meter via variable bAddGoldenAgeProgressPoints
    • You specify how many golden age progress points to add via variable iGoldenAgeProgressPointsToAdd
You can have both effects occuring at the same time. IE, you can both start a golden age and add points to the meter for the next naturally-occuring golden age.
 
Hello coders, I'm making a little mechanic mod and I wonder if someone can make a LUA code like this:

1, make a new earnable promotion called "sword"(doesn't require LUA, I would make it by myself)

2, The "sword" promotion is only available to Spearman. (I don't know this need LUA or not, but it seem that in SQL/XML, we can only set promotions available with certain UnitCombatType, not UnitType.)

3, When a Spearman pick up the "sword" promotion, it immediately becomes a Swordsman, just like unit upgrade.

:thanx::thanx::thanx:
 
Hey guys,

I've been struggling making a mod which disables Warriors at Ancient era starts, and replacing them with a Scout. Can you guys post some ideas on how to achieve it in lua? :)
 
Hello coders, I'm making a little mechanic mod and I wonder if someone can make a LUA code like this:

1, make a new earnable promotion called "sword"(doesn't require LUA, I would make it by myself)

2, The "sword" promotion is only available to Spearman. (I don't know this need LUA or not, but it seem that in SQL/XML, we can only set promotions available with certain UnitCombatType, not UnitType.)

3, When a Spearman pick up the "sword" promotion, it immediately becomes a Swordsman, just like unit upgrade.

:thanx::thanx::thanx:
#2 & #3:

  1. Set variable bGiveToAllInClass to true in order to make all units from the Spearman class of units able to use this ability. Otherwise, only the actual standard Spearman unit will be able to use the ability.
  2. I have not actually used the UnitPromoted game event before. Hopefully there is not a problem with performing the unit-conversion from a spearman into a swordsman in a listener hooked to this event.
    • I have run into other game events that while they were executing would not allow certain things to happen, which is why this comment. If the conversion to the Swordsman unit does not seem to work, then an alternative 'hook' will have to be used.
  3. You need to alter the name of PROMOTION_SWORD in the lua code to whatever you actually use in your SQL/XML for the promotion-name.
Spoiler :
Code:
local bGiveToAllInClass = false
local iSpearmanSwordPromotion = GameInfoTypes.PROMOTION_SWORD
local tSpearman = { [GameInfoTypes.UNIT_SPEARMAN] = GameInfoTypes.UNIT_SWORDSMAN }
-------------------------------------------------------------------------------------------------------
-- AddAllItemsInSameClassToTable
-- All All Items In Same Classes To Defined Table
-------------------------------------------------------------------------------------------------------
function AddAllItemsInSameClassToTable(tTableName, sDataType)
	if sDataType == "Units" then
		for iUnit,sData in pairs(tTableName) do
			local sUnitClass = GameInfo.Units[iUnit].Class
			for UnitRow in GameInfo.Units("Class='" .. sUnitClass .. "'") do
				if not tTableName[UnitRow.ID] then
					tTableName[UnitRow.ID] = sData
				end
			end
		end
	elseif sDataType == "Buildings" then
		for iBuilding,vData in pairs(tTableName) do
			local sBuildingClass = GameInfo.Buildings[iBuilding].BuildingClass
			for BuildingRow in GameInfo.Buildings("BuildingClass='" .. sBuildingClass .. "'") do
				if not tTableName[BuildingRow.ID] then
					tTableName[BuildingRow.ID] = vData
				end
			end
		end

	end
end
-------------------------------------------------------------------------------------------------------
-- Get correct UnitID for the player from within a UnitClass
-- Can be set to return nil or the original ID unit sent if the player has no such valid unit
-------------------------------------------------------------------------------------------------------
function GetCivSpecificUnitForDefaultUnit(pPlayer, iDefaultUnitLoaded, bReturnNilIfNoValid)
	local bUseNilReturnMethod = (bReturnNilIfNoValid ~= nil)
	local sUnitClass = GameInfo.Units[iDefaultUnitLoaded].Class
	local sCivilizationName = GameInfo.Civilizations[pPlayer:GetCivilizationType()].Type
	for row in GameInfo.Civilization_UnitClassOverrides("CivilizationType='" .. sCivilizationName .. "'") do
		if row.UnitClassType == sUnitClass then
			if row.UnitType ~= "NULL" and row.UnitType ~= "null" and row.UnitType ~= "NONE" and row.UnitType ~= -1 and row.UnitType ~= nil then
				return GameInfoTypes[row.UnitType]
			else
				if bUseNilReturnMethod and (bReturnNilIfNoValid == true) then
					return nil
				end
			end
		end
	end
	for row in GameInfo.UnitClasses("Type='" .. sUnitClass .. "'") do
		if row.DefaultUnit ~= "NULL" and row.DefaultUnit ~= "null" and row.DefaultUnit ~= "NONE" and row.DefaultUnit ~= -1 and row.DefaultUnit ~= nil then
			return GameInfoTypes[row.DefaultUnit]
		else
			if bUseNilReturnMethod and (bReturnNilIfNoValid == true) then
				return nil
			end
		end
	end
	return iDefaultUnitLoaded
end
-------------------------------------------------------------------------------------------------------
-- handles executing the AddAllItemsInSameClassToTable if needed
-------------------------------------------------------------------------------------------------------
if bGiveToAllInClass then
	AddAllItemsInSameClassToTable(tSpearman, "Units")
end
-------------------------------------------------------------------------------------------------------
-- Actual lua function that determines whether a unit can have the Sword promotion
-------------------------------------------------------------------------------------------------------
function SpearmenCanHaveSwordPromotion(iPlayer, iUnit, iPromotion)
	if iPromotion == iSpearmanSwordPromotion then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		if tSpearman[pUnit:GetUnitType()] then
			return true
		else
			return false
		end
	end
	return true
end
GameEvents.CanHavePromotion.Add(SpearmenCanHaveSwordPromotion)
-------------------------------------------------------------------------------------------------------
-- Actual lua function that transforms (upgrades) a Unit when the promotion is selected
-------------------------------------------------------------------------------------------------------
function SpearmenChoosesSwordPromotion(iPlayer, iUnit, iPromotion)
	if iPromotion == iSpearmanSwordPromotion then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		if tSpearman[pUnit:GetUnitType()] then
			local iCorrectUnitForPlayer = GetCivSpecificUnitForDefaultUnit(pPlayer, tSpearman[pUnit:GetUnitType()], true)
			if (iCorrectUnitForPlayer ~= nil) and (iCorrectUnitForPlayer ~= pUnit:GetUnitType()) then
				local pNewUnit = pPlayer:InitUnit(iCorrectUnitForPlayer, pUnit:GetX(), pUnit:GetY())
				pNewUnit:Convert(pUnit) 
			end
		end
	end
end
GameEvents.UnitPromoted.Add(SpearmenChoosesSwordPromotion)[/spoiler]
 
I need some lua help please! I'm looking for the Massagetae (CIVILIZATION_MASSAGETAE) Unique Ability to include getting an extra Steppe Axeman (UNIT_STEPPE_AXEMAN) when one is built, i.e two for the price of one. I've seen it in the Civ 6 video for Tomyris and it seemed like a cool UA for the civ (though it was a horse archer in that case). I might actually give them two UUs and get the unique ability to happen for both units. The other one would be (as per the Civ 6 video) a Saka Horseman (UNIT_SAKA).
 
[*]I have not actually used the UnitPromoted game event before. Hopefully there is not a problem with performing the unit-conversion from a spearman into a swordsman in a listener hooked to this event.

Provided either
a) the promotion is marked as "Lost with upgrade" or
b) you add a check in the UnitPromoted handler to make sure the unit being promoted is a spearman
you'll be OK

Without either of those, you'll send the event handler into a recursive loop

spearman adopts "Sword" promotion, event fires and handler runs, handler converts spearman to swordsman, as part of the conversion swordsman gets the "Sword" promotion (unless a above), event fires and handler runs, handler converts swordsman to swordsman (unless b above), recursive loop ensues!
 
Hey guys,

I've been struggling making a mod which disables Warriors at Ancient era starts, and replacing them with a Scout. Can you guys post some ideas on how to achieve it in lua? :)
Try this mod: http://steamcommunity.com/sharedfiles/filedetails/?id=81981402

It should not really be an lua issue. At higher difficulty levels the AI is still going to get extra units, however, and these extras are not all going to be Scouts, even with BlouBlou's mod running. In order to adjust this behavior you would have to use xml to alter the data in table <HandicapInfos> for difficulty settings:
Difficulty <AIStartingDefenseUnits> <AIStartingExploreUnits>
<Type>HANDICAP_KING</Type> 1 0
<Type>HANDICAP_EMPEROR</Type> 1 1
<Type>HANDICAP_IMMORTAL</Type> 2 1
<Type>HANDICAP_DEITY</Type> 2 1
The numbers specified are in addition to any others they would normally get. AI at higher difficulties also get starting workers.
 
@ zwei833,

I made a couple changes to the code posted in #607 to account for William's feedback and to cover an afterthought paranoia issue on my part.

You will need to make sure the promotion has the "Lost with upgrade" tag applied to it. The lua code as now written should account for not allowing the event to go into an endless loop, but it is better to give insurance in the way the xml of the promotion is written.
 
@LeeS

Thank you for your code!

Here is the code I add to my LUA file:
Spoiler :

Code:
local iSpearmanSwordPromotion = GameInfoTypes.PROMOTION_SWORD
local tSpearman = { [GameInfoTypes.UNIT_SPEARMAN] = GameInfoTypes.UNIT_SWORDSMAN }
-------------------------------------------------------------------------------------------------------
-- Actual lua function that determines whether a unit can have the Sword promotion
-------------------------------------------------------------------------------------------------------
function SpearmenCanHaveSwordPromotion(iPlayer, iUnit, iPromotion)
	if iPromotion == iSpearmanSwordPromotion then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		return tSpearman[pUnit:GetUnitType()]
	end
	return true
end
GameEvents.CanHavePromotion.Add(SpearmenCanHaveSwordPromotion)
-------------------------------------------------------------------------------------------------------
-- Actual lua function that transforms (upgrades) a Unit when the promotion is selected
-------------------------------------------------------------------------------------------------------
function SpearmenChoosesSwordPromotion(iPlayer, iUnit, iPromotion)
	if iPromotion == iSpearmanSwordPromotion then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		local iCorrectUnitForPlayer = GetCivSpecificUnitForDefaultUnit(pPlayer, tSpearman[pUnit:GetUnitType()], true)
		if (iCorrectUnitForPlayer ~= nil) and (iCorrectUnitForPlayer ~= pUnit:GetUnitType()) then
			local pNewUnit = pPlayer:InitUnit(iCorrectUnitForPlayer, pUnit:GetX(), pUnit:GetY())
			pNewUnit:Convert(pUnit) 
		end
	end
end
GameEvents.UnitPromoted.Add(SpearmenChoosesSwordPromotion)

The promotion XML code:
Spoiler :
Code:
<?xml version="1.0" encoding="utf-8"?>
<GameData>
	<UnitPromotions>
		<Row>
			<Type>PROMOTION_SWORD</Type>
			<Description>TXT_KEY_PROMOTION_SWORD</Description>
			<Help>TXT_KEY_PROMOTION_SWORD</Help>
			<Sound>AS2D_IF_LEVELUP</Sound>
			<OrderPriority>1</OrderPriority>
			<OpenAttack>15</OpenAttack>
			<OpenDefense>15</OpenDefense>
			<PortraitIndex>44</PortraitIndex>
			<IconAtlas>PROMOTION_ATLAS</IconAtlas>
			<PediaType>PEDIA_MELEE</PediaType>
			<PediaEntry>TXT_KEY_PROMOTION_SWORD</PediaEntry>
		</Row>
	</UnitPromotions>
	<UnitPromotions_UnitCombats>
		<Row>
			<PromotionType>PROMOTION_SWORD</PromotionType>
			<UnitCombatType>UNITCOMBAT_MELEE</UnitCombatType>
		</Row>
	</UnitPromotions_UnitCombats>
</GameData>

Now the SWORD promotion is only available to Spearman, but when a Spearman get this promotion, just nothing happen. Am I do anything wrong to the code?


EDIT: didn't saw your reply, I will test again.
 
Thank you LeeS!

The code works correctly now.

However, could you please delete the bGiveToAllInClass function? I only need the ability available to specific unit type, and as I need to make a couple of these promotions, I would like to simplify the code.

I try to delete the bGiveToAllInClass function but then the code doesn't work:
Spoiler :
Code:
local iSpearmanSwordPromotion = GameInfoTypes.PROMOTION_SWORD
local tSpearman = { [GameInfoTypes.UNIT_SPEARMAN] = GameInfoTypes.UNIT_SWORDSMAN }
-------------------------------------------------------------------------------------------------------
-- Actual lua function that determines whether a unit can have the Sword promotion
-------------------------------------------------------------------------------------------------------
function SpearmenCanHaveSwordPromotion(iPlayer, iUnit, iPromotion)
	if iPromotion == iSpearmanSwordPromotion then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		if tSpearman[pUnit:GetUnitType()] then
			return true
		else
			return false
		end
	end
	return true
end
GameEvents.CanHavePromotion.Add(SpearmenCanHaveSwordPromotion)
-------------------------------------------------------------------------------------------------------
-- Actual lua function that transforms (upgrades) a Unit when the promotion is selected
-------------------------------------------------------------------------------------------------------
function SpearmenChoosesSwordPromotion(iPlayer, iUnit, iPromotion)
	if iPromotion == iSpearmanSwordPromotion then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		if tSpearman[pUnit:GetUnitType()] then
			local iCorrectUnitForPlayer = GetCivSpecificUnitForDefaultUnit(pPlayer, tSpearman[pUnit:GetUnitType()], true)
			if (iCorrectUnitForPlayer ~= nil) and (iCorrectUnitForPlayer ~= pUnit:GetUnitType()) then
				local pNewUnit = pPlayer:InitUnit(iCorrectUnitForPlayer, pUnit:GetX(), pUnit:GetY())
				pNewUnit:Convert(pUnit) 
			end
		end
	end
end
GameEvents.UnitPromoted.Add(SpearmenChoosesSwordPromotion)
 
I need some lua help please! I'm looking for the Massagetae (CIVILIZATION_MASSAGETAE) Unique Ability to include getting an extra Steppe Axeman (UNIT_STEPPE_AXEMAN) when one is built, i.e two for the price of one. I've seen it in the Civ 6 video for Tomyris and it seemed like a cool UA for the civ (though it was a horse archer in that case). I might actually give them two UUs and get the unique ability to happen for both units. The other one would be (as per the Civ 6 video) a Saka Horseman (UNIT_SAKA).
Rob, does Anno Domini have Machiavelli24's SerialEventUnitCreatedGood system included in it? I'm using Machi's system in Scipio, but if you are not otherwise using it, you would need to add Machi's system as a base component of Anno Domini.

(and then you would not need to add the stuff in folder SerialEventGood within the Scipio Mod since it only ever needs to be added once. Every mod that needs it can then use it).

Drop the following code into an lua file and set the lua file as ImportIntoVFS=false and as an "InGameUIAddin". This can be added in your Massagetae civ's folder even though the Machiavelli SerialEventUnitCreatedGood is added and defined with the base Anno Domini mod.
Code:
local iRequiredCivilization = GameInfoTypes.CIVILIZATION_MASSAGETAE
local tUnitsToDuplicate = { [GameInfoTypes.UNIT_STEPPE_AXEMAN] = GameInfoTypes.UNIT_STEPPE_AXEMAN, [GameInfoTypes.UNIT_SAKA] = GameInfoTypes.UNIT_SAKA }

function DuplicateUnitsToBeSpawned(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
	local pPlayer = Players[playerID]
	local pUnit = pPlayer:GetUnitByID(unitID)
	if(pPlayer == nil or
		not pPlayer:IsAlive() or
		pUnit == nil or
		pUnit:IsDead()) then
		return
	end
	if pPlayer:GetCivilizationType() ~= iRequiredCivilization then return end
	if tUnitsToDuplicate[pUnit:GetUnitType()] then
		local pNewUnit = pPlayer:InitUnit(tUnitsToDuplicate[pUnit:GetUnitType()], pUnit:GetX(), pUnit:GetY())
		pNewUnit:JumpToNearestValidPlot()
	end
end
LuaEvents.SerialEventUnitCreatedGood.Add(DuplicateUnitsToBeSpawned)
Note that I added the UNIT_SAKA in, so you will have to make sure this is a valid unit, or else just change that line to read as
Code:
local tUnitsToDuplicate = { [GameInfoTypes.UNIT_STEPPE_AXEMAN] = GameInfoTypes.UNIT_STEPPE_AXEMAN }

I also wrote the code so that the unit that is given for 'free' is the same as the original unit. But you could specify that the UNIT_STEPPE_AXEMAN, for example, causes some other unit to be created simply by changing the one line to something like this:
Code:
local tUnitsToDuplicate = { [GameInfoTypes.UNIT_STEPPE_AXEMAN] = GameInfoTypes.UNIT_SPEARMAN, [GameInfoTypes.UNIT_SAKA] = GameInfoTypes.UNIT_SAKA }
 
Thank you LeeS!

The code works correctly now.

However, could you please delete the bGiveToAllInClass function? I only need the ability available to specific unit type, and as I need to make a couple of these promotions, I would like to simplify the code.

I try to delete the bGiveToAllInClass function but then the code doesn't work:
This strips the giving the ability to all units in the class, although I don't understand exactly why you would want to do that, nor why you are stripping the code to get the player's correct unit from the Swordsman Class of unit. You did say you were making a 'mechanics' mod and not a AU for a specific player.
Spoiler :
Code:
local iSpearmanSwordPromotion = GameInfoTypes.PROMOTION_SWORD
local tSpearman = { [GameInfoTypes.UNIT_SPEARMAN] = GameInfoTypes.UNIT_SWORDSMAN }
-------------------------------------------------------------------------------------------------------
-- Get correct UnitID for the player from within a UnitClass
-- Can be set to return nil or the original ID unit sent if the player has no such valid unit
-------------------------------------------------------------------------------------------------------
function GetCivSpecificUnitForDefaultUnit(pPlayer, iDefaultUnitLoaded, bReturnNilIfNoValid)
	local bUseNilReturnMethod = (bReturnNilIfNoValid ~= nil)
	local sUnitClass = GameInfo.Units[iDefaultUnitLoaded].Class
	local sCivilizationName = GameInfo.Civilizations[pPlayer:GetCivilizationType()].Type
	for row in GameInfo.Civilization_UnitClassOverrides("CivilizationType='" .. sCivilizationName .. "'") do
		if row.UnitClassType == sUnitClass then
			if row.UnitType ~= "NULL" and row.UnitType ~= "null" and row.UnitType ~= "NONE" and row.UnitType ~= -1 and row.UnitType ~= nil then
				return GameInfoTypes[row.UnitType]
			else
				if bUseNilReturnMethod and (bReturnNilIfNoValid == true) then
					return nil
				end
			end
		end
	end
	for row in GameInfo.UnitClasses("Type='" .. sUnitClass .. "'") do
		if row.DefaultUnit ~= "NULL" and row.DefaultUnit ~= "null" and row.DefaultUnit ~= "NONE" and row.DefaultUnit ~= -1 and row.DefaultUnit ~= nil then
			return GameInfoTypes[row.DefaultUnit]
		else
			if bUseNilReturnMethod and (bReturnNilIfNoValid == true) then
				return nil
			end
		end
	end
	return iDefaultUnitLoaded
end
-------------------------------------------------------------------------------------------------------
-- Actual lua function that determines whether a unit can have the Sword promotion
-------------------------------------------------------------------------------------------------------
function SpearmenCanHaveSwordPromotion(iPlayer, iUnit, iPromotion)
	if iPromotion == iSpearmanSwordPromotion then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		if tSpearman[pUnit:GetUnitType()] then
			return true
		else
			return false
		end
	end
	return true
end
GameEvents.CanHavePromotion.Add(SpearmenCanHaveSwordPromotion)
-------------------------------------------------------------------------------------------------------
-- Actual lua function that transforms (upgrades) a Unit when the promotion is selected
-------------------------------------------------------------------------------------------------------
function SpearmenChoosesSwordPromotion(iPlayer, iUnit, iPromotion)
	if iPromotion == iSpearmanSwordPromotion then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		if tSpearman[pUnit:GetUnitType()] then
			local iCorrectUnitForPlayer = GetCivSpecificUnitForDefaultUnit(pPlayer, tSpearman[pUnit:GetUnitType()], true)
			if (iCorrectUnitForPlayer ~= nil) and (iCorrectUnitForPlayer ~= pUnit:GetUnitType()) then
				local pNewUnit = pPlayer:InitUnit(iCorrectUnitForPlayer, pUnit:GetX(), pUnit:GetY())
				pNewUnit:Convert(pUnit) 
			end
		end
	end
end
GameEvents.UnitPromoted.Add(SpearmenChoosesSwordPromotion)[/spoiler]
This also strips out looking for the correct unit within the "Swordsman" Class that the player ought to get when a unit is upgraded from a Spearman to a Swordsman, but as stated earlier I don't really understand why you want to do that:
Spoiler :
Code:
local iSpearmanSwordPromotion = GameInfoTypes.PROMOTION_SWORD
local tSpearman = { [GameInfoTypes.UNIT_SPEARMAN] = GameInfoTypes.UNIT_SWORDSMAN }
-------------------------------------------------------------------------------------------------------
-- Actual lua function that determines whether a unit can have the Sword promotion
-------------------------------------------------------------------------------------------------------
function SpearmenCanHaveSwordPromotion(iPlayer, iUnit, iPromotion)
	if iPromotion == iSpearmanSwordPromotion then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		if tSpearman[pUnit:GetUnitType()] then
			return true
		else
			return false
		end
	end
	return true
end
GameEvents.CanHavePromotion.Add(SpearmenCanHaveSwordPromotion)
-------------------------------------------------------------------------------------------------------
-- Actual lua function that transforms (upgrades) a Unit when the promotion is selected
-------------------------------------------------------------------------------------------------------
function SpearmenChoosesSwordPromotion(iPlayer, iUnit, iPromotion)
	if iPromotion == iSpearmanSwordPromotion then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		if tSpearman[pUnit:GetUnitType()] then
			local pNewUnit = pPlayer:InitUnit(tSpearman[pUnit:GetUnitType()], pUnit:GetX(), pUnit:GetY())
			pNewUnit:Convert(pUnit) 
		end
	end
end
GameEvents.UnitPromoted.Add(SpearmenChoosesSwordPromotion)[/spoiler]
 
Wow!! That's brilliant LeeS, thank-you! Things have evolved in the Anno Domini world in the last hour, so I might use it for a different civ and unit now, but use it I will!!

Thank-you so much!
 
Thank you Lee, the code works fine.

Let me explain a bit about what I want to do. I want to make a mod in which some units can choose different special weapons or equipments through promotions.

For example, a japanese samurai can choose the "Naginata" promotion to use the naginata weapon, or it can choose the "Musket" promotion to use the musket weapon.

To do this, I need to add new unit Samurai(naginata) and Samurai(musket) with new unit graphic and ability. And the normal samurai could "upgrade" to these special samurais through promotion.

That's why I need the code work with UnitType rather than UnitClassType.

The "spearman to swordsman" is not what I want eventually, but it is an important sample code to my mod, with your code now I know how to make this mod come truth!
 
Thank you Lee, the code works fine.

Let me explain a bit about what I want to do. I want to make a mod in which some units can choose different special weapons or equipments through promotions.

For example, a japanese samurai can choose the "Naginata" promotion to use the naginata weapon, or it can choose the "Musket" promotion to use the musket weapon.

To do this, I need to add new unit Samurai(naginata) and Samurai(musket) with new unit graphic and ability. And the normal samurai could "upgrade" to these special samurais through promotion.

That's why I need the code work with UnitType rather than UnitClassType.

The "spearman to swordsman" is not what I want eventually, but it is an important sample code to my mod, with your code now I know how to make this mod come truth!
Then what you need is a universal handler wherein Promotion_X requires Unit_A and when selected transforms Unit_A into Unit_A_X, and Promotion_Y requires Unit_A and when selected transforms Unit_A into Unit_A_Y. But Promotion_Z requires Unit_B and when selected transforms Unit_B into Unit_B_Z.

Have to give that some thought but should not be that hard to do and ought not to require much more code than that already written. I may have an opportunity to take a look at it later today (it is lunchtime for me now).
 
Thank you Lee, the code works fine.

Let me explain a bit about what I want to do. I want to make a mod in which some units can choose different special weapons or equipments through promotions.

For example, a japanese samurai can choose the "Naginata" promotion to use the naginata weapon, or it can choose the "Musket" promotion to use the musket weapon.

To do this, I need to add new unit Samurai(naginata) and Samurai(musket) with new unit graphic and ability. And the normal samurai could "upgrade" to these special samurais through promotion.

That's why I need the code work with UnitType rather than UnitClassType.

The "spearman to swordsman" is not what I want eventually, but it is an important sample code to my mod, with your code now I know how to make this mod come truth!

Following code uses the Standard Spearmen, Swordsmen, and Musketmen as examples. And it uses two promotions as examples: PROMOTION_SWORD and PROMOTION_MUSKET

To test you just need to create the PROMOTION_SWORD and PROMOTION_MUSKET.

If you select PROMOTION_SWORD, then the Spearman gets upgraded into a Swordsman. If you select PROMOTION_MUSKET, then the Spearman gets upgraded into a Musketman.

Because all this info is in a table no further logic is needed to add more sets of Promotion/Starting-Unit/Upgraded-Unit. You just add the new set to the table called tPromotionUpgradeUnits

Code:
local tPromotionUpgradeUnits = { [GameInfoTypes.PROMOTION_SWORD] = { RequiredUnit = GameInfoTypes.UNIT_SPEARMAN, UpgradeUnit = GameInfoTypes.UNIT_SWORDSMAN },
	[GameInfoTypes.PROMOTION_MUSKET] = { RequiredUnit = GameInfoTypes.UNIT_SPEARMAN, UpgradeUnit = GameInfoTypes.UNIT_MUSKETMAN } }
-------------------------------------------------------------------------------------------------------
-- Actual lua function that determines whether a unit can have the promotion
-------------------------------------------------------------------------------------------------------
function UnitCanHaveUpgradePromotion(iPlayer, iUnit, iPromotion)
	if tPromotionUpgradeUnits[iPromotion] then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		return (tPromotionUpgradeUnits[iPromotion].RequiredUnit == pUnit:GetUnitType())
	end
	return true
end
GameEvents.CanHavePromotion.Add(UnitCanHaveUpgradePromotion)
-------------------------------------------------------------------------------------------------------
-- Actual lua function that transforms (upgrades) a Unit when the promotion is selected
-------------------------------------------------------------------------------------------------------
function UnitChoosesUpgradePromotion(iPlayer, iUnit, iPromotion)
	if tPromotionUpgradeUnits[iPromotion] then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnit)
		if (tPromotionUpgradeUnits[iPromotion].RequiredUnit == pUnit:GetUnitType()) then
			local pNewUnit = pPlayer:InitUnit(tPromotionUpgradeUnits[iPromotion].UpgradeUnit, pUnit:GetX(), pUnit:GetY())
			pNewUnit:Convert(pUnit) 
		end
	end
end
GameEvents.UnitPromoted.Add(UnitChoosesUpgradePromotion)
 
Back
Top Bottom