LUA Trait Help

I'm curious to know how the effect would work actually. As far as I understand it: every turn, a random number between 0 - 100 will be generated. If it's in the lower third 'percentile', then the effect of adding a dummy building will happen if there is at least one great work of music in the appropriate building.

My question is will the happiness, culture and tourism boosts from the dummy building actually stockpile from turn to turn? Because if the dummy building is disappearing and reappearing every 1 in 3 turns (on average) will there be enough time for the effects to actually stack each turn. Another way to put this: is the stockpiling effect instantaneous when the building appears, or does it need to wait for the turn end to add on the above 'resources'. I'm only asking this because I've seen the effects of some things happen only on the next turn, rather than the actual turn the 'trigger' takes place.

Plus I'm still not confident I'm giving the AI a strategically balanced equivalent trait to the human player... because essentially they would have a great work AND the dummy building at the same time. Whereas the human player would have to have the Griot alive (or 'unexpended') on a plot somewhere, so it would have never created the great work. Although, the human can create a great work of music AND THEN have a roaming Griot later in the game, so I guess it may balance out after a bit... reckon I should increase the random number chance from 33% to 50%?
 
33% seems fine.

The effects of the dummy building will be added during "NEXT TURN" processing, then the PlayerDoTurn will fire for the player and the lua code will execute. If the dummy is removed and then re-added to the same city as part of the PlayerDoTurn processing the net effect will be the same as for a building that was never removed from the city.

The only time the effects of adding any building to a city (whether by lua or other means) are "instantaneous" are for permanent effects such as giving a free unit, adjusting the player's influence with city-states, adding a spy, tech, or policy for free, and other similar effects.

Direct building "Yield-y" (Building_YieldChanges, Building_YieldModifiers, Building_TerrainYieldChanges, TechEnhancedTourism, etc) effects are not implemented until turn processing, though they will be calculated into the top-panel display for gold, culture, etc. Changes to plot yields coming from buildings will be reflected in tooltips and the like but will also not actually be implemented until turn processing.

Happiness effects are also instantaneous, both in the addition and the removal of a building that adds either local or global happiness.
 
I've decided to go with 40% now (to reflect the fact that a human player will always try to favour it).

I've also decided to scrap the
Code:
if (pCity:GetNumGreatWorksInBuilding(operaHouseID) > 0) or (pCity:GetNumGreatWorksInBuilding(broadcastTowerID) > 0) or (pCity:GetNumGreatWorksInBuilding(broadwayID) > 0) or (pCity:GetNumGreatWorksInBuilding(sydneyOperaHouseID) > 0) then

and replaced it with
Code:
                if (pCity:IsHasBuilding(musiciansGuildID) == true) or if (pCity:IsHasBuilding(broadwayID) == true) or if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) then

so that the random number effect starts from when the player has something that can produce a Griot instead of from when the game start (because even Warriors and Scouts at the beginning of the game could generate Griot points, and hence Griots early.)

As such, I have also tried to include the same check for the generation of Griot points in general (as in my UA effect). Thus, I have made my "GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)" rely on the following check:

Code:
if (IsCivInPlay(senegalID) == true) then
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == senegalID) then
        for pCity in pPlayer:Cities() do
            if (pCity:IsHasBuilding(musiciansGuildID) == true) or if (pCity:IsHasBuilding(broadwayID) == true) or if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) then
                GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
            end
        end
    end
end

I was thinking about making the condition a certain era (Renaissance seems best since that's when a Musicians Guild can be built and its likely that the player will have finished a (liberty) policy tree by then)... would you agree with this?

Please see below my fully updated code for the entire Civ of Senegal:

Code:
--------------------------------------------------------------
-- UA: Négritude - +2 Griot points are earned for your capital when your units kill, or are killed. Get 25 culture for each enemy killed. Embarked units pay just one movement to disembark to land.
-- UU: Gendarmerie - Replaces Infantry. When garrisoned in a city, the city's spy stealing rate reduced 10%, has +5 defence and generates +2 culture.
-- UU: Griot - Replaces Great Musician. Slower. When in a 3-tile radius of your city's territory, the city produces +1 happiness, +3 culture and +10% tourism. Only 1 set of effects per city. (For the AI, this simply happens 40% of the time regardless)

----------------------------------------------------------------------------------------------------------------------------
-- GLOBAL VARIABLES
----------------------------------------------------------------------------------------------------------------------------
local senegalID = GameInfoTypes["CIVILIZATION_SENEGAL"]
local specialistGriotID = GameInfoTypes["SPECIALIST_MUSICIAN"]
local gendarmerieID = GameInfoTypes["UNIT_GENDARMERIE"]
local griotID = GameInfoTypes["UNIT_GRIOT"]
local gendarmerieDummyBuildingID = GameInfoTypes["BUILDING_GENDARMERIE_DUMMY"]
local griotDummyBuildingID = GameInfoTypes["BUILDING_GRIOT_DUMMY"]
local musiciansGuildID = GameInfoTypes["BUILDING_MUSICIANS_GUILD"]
local broadwayID = GameInfoTypes["BUIDLING_BROADWAY"]
local libertyBranchID = PolicyBranchTypes["POLICY_BRANCH_LIBERTY"]

----------------------------------------------------------------------------------------------------------------------------
---- WilliamHoward's IsCivInPlay
----------------------------------------------------------------------------------------------------------------------------
function IsCivInPlay(iCivType)
    for iSlot = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
        local iSlotStatus = PreGame.GetSlotStatus(iSlot)
        if (iSlotStatus == SlotStatus.SS_TAKEN or iSlotStatus == SlotStatus.SS_COMPUTER) then
            if (PreGame.GetCivilization(iSlot) == iCivType) then
                return true
            end
        end
    end
    return false
end

----------------------------------------------------------------------------------------------------------------------------
-- UA: NÉGRITUDE
----------------------------------------------------------------------------------------------------------------------------
function GriotPointsWhenUnitDie(iPlayer, iKilledPlayer, iKilledUnit)
    local pKillingPlayer = Players[iPlayer]
    local pKilledPlayer = Players[iKilledPlayer]
    if (pKillingPlayer:GetCivilizationType() == senegalID) or (pKilledPlayer:GetCivilizationType() == senegalID) then
        local griotPoints = 2
        local griotCity = pKillingPlayer:GetCapitalCity()
        if (pKillingPlayer:GetCivilizationType() ~= senegalID) then
            griotCity = pKilledPlayer:GetCapitalCity()
        end
        griotCity:ChangeSpecialistGreatPersonProgressTimes100(specialistGriotID, griotPoints*100)
        if pKillingPlayer:IsHuman() then
            Events.GameplayAlertMessage("Your unit has killed an enemy! Your capital gains 2 [ICON_GREAT_PEOPLE] Great Griot Points!")
        elseif pKilledPlayer:IsHuman() then
            Events.GameplayAlertMessage("Your unit was killed by an enemy. Your capital gains 2 [ICON_GREAT_PEOPLE] Great Griot Points!")
        end
    end
end

if (IsCivInPlay(senegalID) == true) then
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == senegalID) then
        for pCity in pPlayer:Cities() do
            if (pCity:IsHasBuilding(musiciansGuildID) == true) or if (pCity:IsHasBuilding(broadwayID) == true) or if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) then
                GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
            end
        end
    end
end

----------------------------------------------------------------------------------------------------------------------------
-- UU Boosts (Gendarmerie boosted by city garrison and Griot boosted by city limits)
----------------------------------------------------------------------------------------------------------------------------
function UUBoosts(iPlayer)
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == senegalID) then 
        local tUnitsAlreadyProcessed = {}
        for pCity in pPlayer:Cities() do
            pCity:SetNumRealBuilding(griotDummyBuildingID, 0)
            pCity:SetNumRealBuilding(gendarmerieDummyBuildingID, 0)
            local pCityPlot = pCity:Plot()
            if pCityPlot:IsUnit() then -- Gendarmerie Boost
                for i = 0, (pCityPlot:GetNumUnits() - 1) do
                    local pUnit = pCityPlot:GetUnit(i)
                    if pUnit then
                        if (pUnit:GetUnitType() == gendarmerieID) and (pUnit:GetOwner() == iPlayer) then
                            pCity:SetNumRealBuilding(gendarmerieDummyBuildingID, 1)
                        end
                    end
                end
            end
            if (pPlayer:IsHuman() == true) then --------------------------------- Griot Boost if Player is Human
                for iPlot = 0, pCity:GetNumCityPlots() - 1, 1 do
                    local pCityTerritoryPlot = pCity:GetCityIndexPlot(iPlot)
                    if (pCityTerritoryPlot:GetOwner() == iPlayer) then
                        if pCityTerritoryPlot:IsUnit() then
                            for iUnit = 0, (pCityTerritoryPlot:GetNumUnits() - 1) do
                                local pUnit = pCityTerritoryPlot:GetUnit(iUnit)
                                if pUnit then
                                    if (pUnit:GetUnitType() == griotID) and (pUnit:GetOwner() == iPlayer) then
                                        local iUnitID = pUnit:GetID()
                                        if not tUnitsAlreadyProcessed[iUnitID] then
                                            --if the unit's ID# has not already been added as a "key" in the table, add the dummy building
                                            --then add the unit's ID# as a "Key" in the table with a value of text "processed"
                                            pCity:SetNumRealBuilding(griotDummyBuildingID, 1)
                                            tUnitsAlreadyProcessed[iUnitID] = "processed"
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
            if (pPlayer:IsHuman() == false) then --------------------------------- Griot Boost if Player is not Human
                if (pCity:IsHasBuilding(musiciansGuildID) == true) or if (pCity:IsHasBuilding(broadwayID) == true) or if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) then
                    if math.random( 0 , 100) <= 40 then
                        pCity:SetNumRealBuilding(griotDummyBuildingID, 1)
                end
                for iPlot = 0, pCity:GetNumCityPlots() - 1, 1 do
                    local pCityTerritoryPlot = pCity:GetCityIndexPlot(iPlot)
                    if (pCityTerritoryPlot:GetOwner() == iPlayer) then
                        if pCityTerritoryPlot:IsUnit() then
                            for iUnit = 0, (pCityTerritoryPlot:GetNumUnits() - 1) do
                                local pUnit = pCityTerritoryPlot:GetUnit(iUnit)
                                if pUnit then
                                    if (pUnit:GetUnitType() == griotID) and (pUnit:GetOwner() == iPlayer) then
                                        local iUnitID = pUnit:GetID()
                                        if not tUnitsAlreadyProcessed[iUnitID] then
                                            --if the unit's ID# has not already been added as a "key" in the table, add the dummy building
                                            --then add the unit's ID# as a "Key" in the table with a value of text "processed"
                                            pCity:SetNumRealBuilding(griotDummyBuildingID, 1)
                                            tUnitsAlreadyProcessed[iUnitID] = "processed"
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end
GameEvents.PlayerDoTurn.Add(UUBoosts)
 
Your syntax here is incorrect:
Code:
if (IsCivInPlay(senegalID) == true) then
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == senegalID) then
        for pCity in pPlayer:Cities() do
            if (pCity:IsHasBuilding(musiciansGuildID) == true) or if (pCity:IsHasBuilding(broadwayID) == true) or if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) then
                GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
            end
        end
    end
end
You have multiple "if" commands plopped into the same "if ... then" line, which is not allowed. The line needs to be:
Code:
if (IsCivInPlay(senegalID) == true) then
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == senegalID) then
        for pCity in pPlayer:Cities() do
            if (pCity:IsHasBuilding(musiciansGuildID) == true) or (pCity:IsHasBuilding(broadwayID) == true) or (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) then
                GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
            end
        end
    end
end
Also you need a "break" command in there so that only the first city that matches the needed conditions will initiate the GameEvent subscription, otherwise you will be telling the game to attempt to subscribe the same function to the same game event hook multiple times, potentially:
Code:
if (IsCivInPlay(senegalID) == true) then
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == senegalID) then
        for pCity in pPlayer:Cities() do
            if (pCity:IsHasBuilding(musiciansGuildID) == true) or (pCity:IsHasBuilding(broadwayID) == true) or (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) then
                GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
		break
            end
        end
    end
end
A similar issue applies to adding (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) into a loop through a player's cities, since if it is true for one city it is true for all. And if it is true at all there would be no neeed to loop through the player's cities, so:
Code:
if (IsCivInPlay(senegalID) == true) then
	local pPlayer = Players[iPlayer]
	if (pPlayer:GetCivilizationType() == senegalID) then
		if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) then
			GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
		else
			for pCity in pPlayer:Cities() do
				if (pCity:IsHasBuilding(musiciansGuildID) == true) or (pCity:IsHasBuilding(broadwayID) == true) then
					GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
					break
				end
			end
		end
	end
end
In this way if the player has the policy-branch completed the event will be subscribed and the loop through the player's cities will not even be conducted.

However, it is possible to simplify this even further by simply asking the game for the player's "building-count" instead of looking through all the player's cities looking for the same two buildings:
Code:
if (IsCivInPlay(senegalID) == true) then
	local pPlayer = Players[iPlayer]
	if (pPlayer:GetCivilizationType() == senegalID) then
		if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) or (pPlayer:CountNumBuildings(musiciansGuildID) > 0) or (pPlayer:CountNumBuildings(broadwayID) > 0) then
			GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
		end
	end
end
You have a more fundamental issue, though in that the code will simply create an error for attempting to "index" a nil value. "iPlayer" is nil within that chunk of code because it has never been defined. You would need to add a loop through all player's that are actively part of the game:
Code:
if (IsCivInPlay(senegalID) == true) then
	for iSlot = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
		local iSlotStatus = PreGame.GetSlotStatus(iSlot)
		if (iSlotStatus == SlotStatus.SS_TAKEN or iSlotStatus == SlotStatus.SS_COMPUTER) then
			if (PreGame.GetCivilization(iSlot) == senegalID) then
				local pPlayer = Players[iSlot]
				if pPlayer:IsAlive() and (pPlayer:GetCivilizationType() == senegalID) then
					if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) or (pPlayer:CountNumBuildings(musiciansGuildID) > 0) or (pPlayer:CountNumBuildings(broadwayID) > 0) then
						GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
					end
				end
			end
		end
	end
end
------------------------------------------------

The issue with potential multiple subscriptions of the same function to the same game event hook does not apply within your UUBoosts function because you are not adding a game event subscription there.

------------------------------------------------

erm, spelling error:
Code:
local broadwayID = GameInfoTypes["BUIDLING_BROADWAY"]
------------------------------------------------

You're missing an "end" here:
Code:
                if (pCity:IsHasBuilding(musiciansGuildID) == true) or if (pCity:IsHasBuilding(broadwayID) == true) or if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) then
                    if math.random( 0 , 100) <= 40 then
                        pCity:SetNumRealBuilding(griotDummyBuildingID, 1)
                end
---------------------------

AI seem to be tremendously silly about never finishing policy trees.
 
Fair enough. Need to keep a watch out of those spelling errors... not sure if I would have caught it...

Do I need to keep WilliamHoward's IsCivInPlay function then? It seems you have included a lot of that code in the

Code:
if (IsCivInPlay(senegalID) == true) then
    for iSlot = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
        local iSlotStatus = PreGame.GetSlotStatus(iSlot)
        if (iSlotStatus == SlotStatus.SS_TAKEN or iSlotStatus == SlotStatus.SS_COMPUTER) then
            if (PreGame.GetCivilization(iSlot) == senegalID) then
                local pPlayer = Players[iSlot]
                if pPlayer:IsAlive() and (pPlayer:GetCivilizationType() == senegalID) then
                    if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) or (pPlayer:CountNumBuildings(musiciansGuildID) > 0) or (pPlayer:CountNumBuildings(broadwayID) > 0) then
                        GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
                    end
                end
            end
        end
    end
end

bit.

Could I not simply combine the two to have:

Code:
function IsCivInPlay(senegalID)
    for iSlot = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
        local iSlotStatus = PreGame.GetSlotStatus(iSlot)
        if (iSlotStatus == SlotStatus.SS_TAKEN or iSlotStatus == SlotStatus.SS_COMPUTER) then
            if (PreGame.GetCivilization(iSlot) == senegalID) then
                local pPlayer = Players[iSlot]
                if pPlayer:IsAlive() and (pPlayer:GetCivilizationType() == senegalID) then
                    if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) or (pPlayer:CountNumBuildings(musiciansGuildID) > 0) or (pPlayer:CountNumBuildings(broadwayID) > 0) then
                        GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
                    end
                end
            end
        end
    end
    return false
end
 
Theoretically you could, but I tend not to like to re-write other people's "toolkit" routines. And you forgot to return true in the re-write.

And a second look at the code tells me I had a redundancy here since two lines previous the same question is being answered for whether the player is Senegal:
Code:
if pPlayer:IsAlive() and (pPlayer:GetCivilizationType() == senegalID) then
------------------------------------

And taking a third look at your code, you have the issue wherein if the player completes the policy-branch or one of the buildings mid-game-session, the UnitKilledInCombat function will never be subscribed to the hook since you are only looking at this upon start-up of the game-session.
 
Are you suggesting that I don't need WilliamHowards' IsCivInPlay because I can simply use:

if pPlayer:IsAlive() and (pPlayer:GetCivilizationType() == senegalID) then
?

To address your third point, I've included the code WITHIN the UnitKilledInCombat event:

Code:
function GriotPointsWhenUnitDie(iPlayer, iKilledPlayer, iKilledUnit)
    for iSlot = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
        local iSlotStatus = PreGame.GetSlotStatus(iSlot)
        if (iSlotStatus == SlotStatus.SS_TAKEN or iSlotStatus == SlotStatus.SS_COMPUTER) then
            if (PreGame.GetCivilization(iSlot) == senegalID) then
                local pPlayer = Players[iSlot]
                if pPlayer:IsAlive() and (pPlayer:GetCivilizationType() == senegalID) then
                    if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) or (pPlayer:CountNumBuildings(musiciansGuildID) > 0) or (pPlayer:CountNumBuildings(broadwayID) > 0) then
                            local pKillingPlayer = Players[iPlayer]
                            local pKilledPlayer = Players[iKilledPlayer]
                            if (pKillingPlayer:GetCivilizationType() == senegalID) or (pKilledPlayer:GetCivilizationType() == senegalID) then
                                local griotPoints = 2
                                local griotCity = pKillingPlayer:GetCapitalCity()
                                if (pKillingPlayer:GetCivilizationType() ~= senegalID) then
                                    griotCity = pKilledPlayer:GetCapitalCity()
                                end
                                griotCity:ChangeSpecialistGreatPersonProgressTimes100(specialistGriotID, griotPoints*100)
                                if pKillingPlayer:IsHuman() then
                                    Events.GameplayAlertMessage("Your unit has killed an enemy! Your capital gains 2 [ICON_GREAT_PEOPLE] Great Griot Points!")
                                elseif pKilledPlayer:IsHuman() then
                                    Events.GameplayAlertMessage("Your unit was killed by an enemy. Your capital gains 2 [ICON_GREAT_PEOPLE] Great Griot Points!")
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end
GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)

New full code:

Code:
--------------------------------------------------------------
-- UA: Négritude - +2 Griot points are earned for your capital when your units kill, or are killed. Get 25 culture for each enemy killed. Embarked units pay just one movement to disembark to land.
-- UU: Gendarmerie - Replaces Infantry. When garrisoned in a city, the city's spy stealing rate reduced 10%, has +5 defence and generates +2 culture.
-- UU: Griot - Replaces Great Musician. Slower. When in a 3-tile radius of your city's territory, the city produces +1 happiness, +3 culture and +10% tourism. Only 1 set of effects per city. (For the AI, this simply happens 40% of the time regardless)

----------------------------------------------------------------------------------------------------------------------------
-- GLOBAL VARIABLES
----------------------------------------------------------------------------------------------------------------------------
local senegalID = GameInfoTypes["CIVILIZATION_SENEGAL"]
local specialistGriotID = GameInfoTypes["SPECIALIST_MUSICIAN"]
local gendarmerieID = GameInfoTypes["UNIT_GENDARMERIE"]
local griotID = GameInfoTypes["UNIT_GRIOT"]
local gendarmerieDummyBuildingID = GameInfoTypes["BUILDING_GENDARMERIE_DUMMY"]
local griotDummyBuildingID = GameInfoTypes["BUILDING_GRIOT_DUMMY"]
local musiciansGuildID = GameInfoTypes["BUILDING_MUSICIANS_GUILD"]
local broadwayID = GameInfoTypes["BUILDING_BROADWAY"]
local libertyBranchID = PolicyBranchTypes["POLICY_BRANCH_LIBERTY"]

----------------------------------------------------------------------------------------------------------------------------
-- UA: NÉGRITUDE
----------------------------------------------------------------------------------------------------------------------------
function GriotPointsWhenUnitDie(iPlayer, iKilledPlayer, iKilledUnit)
    for iSlot = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
        local iSlotStatus = PreGame.GetSlotStatus(iSlot)
        if (iSlotStatus == SlotStatus.SS_TAKEN or iSlotStatus == SlotStatus.SS_COMPUTER) then
            if (PreGame.GetCivilization(iSlot) == senegalID) then
                local pPlayer = Players[iSlot]
                if pPlayer:IsAlive() and (pPlayer:GetCivilizationType() == senegalID) then
                    if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) or (pPlayer:CountNumBuildings(musiciansGuildID) > 0) or (pPlayer:CountNumBuildings(broadwayID) > 0) then
                            local pKillingPlayer = Players[iPlayer]
                            local pKilledPlayer = Players[iKilledPlayer]
                            if (pKillingPlayer:GetCivilizationType() == senegalID) or (pKilledPlayer:GetCivilizationType() == senegalID) then
                                local griotPoints = 2
                                local griotCity = pKillingPlayer:GetCapitalCity()
                                if (pKillingPlayer:GetCivilizationType() ~= senegalID) then
                                    griotCity = pKilledPlayer:GetCapitalCity()
                                end
                                griotCity:ChangeSpecialistGreatPersonProgressTimes100(specialistGriotID, griotPoints*100)
                                if pKillingPlayer:IsHuman() then
                                    Events.GameplayAlertMessage("Your unit has killed an enemy! Your capital gains 2 [ICON_GREAT_PEOPLE] Great Griot Points!")
                                elseif pKilledPlayer:IsHuman() then
                                    Events.GameplayAlertMessage("Your unit was killed by an enemy. Your capital gains 2 [ICON_GREAT_PEOPLE] Great Griot Points!")
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end
GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
----------------------------------------------------------------------------------------------------------------------------
-- UU Boosts (Gendarmerie boosted by city garrison and Griot boosted by city limits)
----------------------------------------------------------------------------------------------------------------------------
function UUBoosts(iPlayer)
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == senegalID) then 
        local tUnitsAlreadyProcessed = {}
        for pCity in pPlayer:Cities() do
            pCity:SetNumRealBuilding(griotDummyBuildingID, 0)
            pCity:SetNumRealBuilding(gendarmerieDummyBuildingID, 0)
            local pCityPlot = pCity:Plot()
            if pCityPlot:IsUnit() then -- Gendarmerie Boost
                for i = 0, (pCityPlot:GetNumUnits() - 1) do
                    local pUnit = pCityPlot:GetUnit(i)
                    if pUnit then
                        if (pUnit:GetUnitType() == gendarmerieID) and (pUnit:GetOwner() == iPlayer) then
                            pCity:SetNumRealBuilding(gendarmerieDummyBuildingID, 1)
                        end
                    end
                end
            end
            if (pPlayer:IsHuman() == true) then --------------------------------- Griot Boost if Player is Human
                for iPlot = 0, pCity:GetNumCityPlots() - 1, 1 do
                    local pCityTerritoryPlot = pCity:GetCityIndexPlot(iPlot)
                    if (pCityTerritoryPlot:GetOwner() == iPlayer) then
                        if pCityTerritoryPlot:IsUnit() then
                            for iUnit = 0, (pCityTerritoryPlot:GetNumUnits() - 1) do
                                local pUnit = pCityTerritoryPlot:GetUnit(iUnit)
                                if pUnit then
                                    if (pUnit:GetUnitType() == griotID) and (pUnit:GetOwner() == iPlayer) then
                                        local iUnitID = pUnit:GetID()
                                        if not tUnitsAlreadyProcessed[iUnitID] then
                                            --if the unit's ID# has not already been added as a "key" in the table, add the dummy building
                                            --then add the unit's ID# as a "Key" in the table with a value of text "processed"
                                            pCity:SetNumRealBuilding(griotDummyBuildingID, 1)
                                            tUnitsAlreadyProcessed[iUnitID] = "processed"
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
            if (pPlayer:IsHuman() == false) then --------------------------------- Griot Boost if Player is not Human
                if (pCity:IsHasBuilding(musiciansGuildID) == true) or (pCity:IsHasBuilding(broadwayID) == true) or (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) then
                    if math.random( 0 , 100) <= 40 then
                        pCity:SetNumRealBuilding(griotDummyBuildingID, 1)
                    end
                end
                for iPlot = 0, pCity:GetNumCityPlots() - 1, 1 do
                    local pCityTerritoryPlot = pCity:GetCityIndexPlot(iPlot)
                    if (pCityTerritoryPlot:GetOwner() == iPlayer) then
                        if pCityTerritoryPlot:IsUnit() then
                            for iUnit = 0, (pCityTerritoryPlot:GetNumUnits() - 1) do
                                local pUnit = pCityTerritoryPlot:GetUnit(iUnit)
                                if pUnit then
                                    if (pUnit:GetUnitType() == griotID) and (pUnit:GetOwner() == iPlayer) then
                                        local iUnitID = pUnit:GetID()
                                        if not tUnitsAlreadyProcessed[iUnitID] then
                                            --if the unit's ID# has not already been added as a "key" in the table, add the dummy building
                                            --then add the unit's ID# as a "Key" in the table with a value of text "processed"
                                            pCity:SetNumRealBuilding(griotDummyBuildingID, 1)
                                            tUnitsAlreadyProcessed[iUnitID] = "processed"
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end
GameEvents.PlayerDoTurn.Add(UUBoosts)
 
no. if you look at my last bit of sample code I was asking the same thing twice.
Code:
(PreGame.GetCivilization(iSlot) == senegalID)
and
Code:
(pPlayer:GetCivilizationType() == senegalID)
are essentially equivalent questions which will have the same answer in that chunk of code.

-----------------------------------------------------

and really really no. you should never do what you are doing here
Code:
function GriotPointsWhenUnitDie(iPlayer, iKilledPlayer, iKilledUnit)
    for iSlot = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
        local iSlotStatus = PreGame.GetSlotStatus(iSlot)
        if (iSlotStatus == SlotStatus.SS_TAKEN or iSlotStatus == SlotStatus.SS_COMPUTER) then
            if (PreGame.GetCivilization(iSlot) == senegalID) then
                local pPlayer = Players[iSlot]
                if pPlayer:IsAlive() and (pPlayer:GetCivilizationType() == senegalID) then
                    if (pPlayer:IsPolicyBranchFinished(libertyBranchID) == true) or (pPlayer:CountNumBuildings(musiciansGuildID) > 0) or (pPlayer:CountNumBuildings(broadwayID) > 0) then
                            local pKillingPlayer = Players[iPlayer]
                            local pKilledPlayer = Players[iKilledPlayer]
                            if (pKillingPlayer:GetCivilizationType() == senegalID) or (pKilledPlayer:GetCivilizationType() == senegalID) then
                                local griotPoints = 2
                                local griotCity = pKillingPlayer:GetCapitalCity()
                                if (pKillingPlayer:GetCivilizationType() ~= senegalID) then
                                    griotCity = pKilledPlayer:GetCapitalCity()
                                end
                                griotCity:ChangeSpecialistGreatPersonProgressTimes100(specialistGriotID, griotPoints*100)
                                if pKillingPlayer:IsHuman() then
                                    Events.GameplayAlertMessage("Your unit has killed an enemy! Your capital gains 2 [ICON_GREAT_PEOPLE] Great Griot Points!")
                                elseif pKilledPlayer:IsHuman() then
                                    Events.GameplayAlertMessage("Your unit was killed by an enemy. Your capital gains 2 [ICON_GREAT_PEOPLE] Great Griot Points!")
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end
This would make the game run through every player in the game every time a unit is killed in combat, which would be just swatting a fly with a nukebomb.

You'd be far better off just subscribing GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie) from the start of the game and just using this for GriotPointsWhenUnitDie
Code:
function GriotPointsWhenUnitDie(iPlayer, iKilledPlayer, iKilledUnit)
	local pKillingPlayer = Players[iPlayer]
	local pKilledPlayer = Players[iKilledPlayer]
	if (pKillingPlayer:GetCivilizationType() == senegalID) or (pKilledPlayer:GetCivilizationType() == senegalID) then
		local bEnactEffect = false
		local griotPoints = 2
		local griotCity = pKillingPlayer:GetCapitalCity()
		if (pKillingPlayer:GetCivilizationType() == senegalID) then
			if (pKillingPlayer:IsPolicyBranchFinished(libertyBranchID) == true) or (pKillingPlayer:CountNumBuildings(musiciansGuildID) > 0) or (pKillingPlayer:CountNumBuildings(broadwayID) > 0) then
				bEnactEffect = true
			end
		else
			griotCity = pKilledPlayer:GetCapitalCity()
			if (pKilledPlayer:IsPolicyBranchFinished(libertyBranchID) == true) or (pKilledPlayer:CountNumBuildings(musiciansGuildID) > 0) or (pKilledPlayer:CountNumBuildings(broadwayID) > 0) then
				bEnactEffect = true
			end
		end
		if bEnactEffect then
			griotCity:ChangeSpecialistGreatPersonProgressTimes100(specialistGriotID, griotPoints*100)
			if pKillingPlayer:IsHuman() then
				Events.GameplayAlertMessage("Your unit has killed an enemy! Your capital gains 2 [ICON_GREAT_PEOPLE] Great Griot Points!")
			elseif pKilledPlayer:IsHuman() then
				Events.GameplayAlertMessage("Your unit was killed by an enemy. Your capital gains 2 [ICON_GREAT_PEOPLE] Great Griot Points!")
			end
		end
	end
end
if (IsCivInPlay(senegalID) == true) then
     GameEvents.UnitKilledInCombat.Add(GriotPointsWhenUnitDie)
end
Put William's IsCivInPlay function as he wrote it back into your code and just let GriotPointsWhenUnitDie run from the start of the game rather than trying to over-complicate.

I think you're banging your head on the top end of where your understanding has reached for the moment and you're just spinning your wheels making extra complications. Get the mod to run, let it sit as it is for a short time while you study-up a bit more on lua and civ5's API for lua. The best way to study up on lua as used in civ5 is to look at other people's code (including at some point Firaxis' own code for the Scenarios) and analyse what these different codes are doing.

This is essentially the process I used. My first "largish" lua file was a horrid mess, to be honest, even though it worked. When I came back to the same code some time later I was able without much effort to cut it down to about 1/3 of it's previous size, and to make it run a whole lot more efficiently.
 
That's good advice... I certainly feel I need some time to process it.

I really appreciate the help you have given me. I am planning many more Civs and I feel I can at least start to get some lua code down.

I've actually cobbled together a list of the mods I have and the unique abilities and units/buildings/improvements that they use so I can pinpoint similar codes in the future, so you saying that makes it seem like that was worthwhile.

Have you kept any notes from your learnings that I could use at all?

For example, you have mentioned that some methods, though relevant, are just not up to scratch for some types of effects.
 
unfortunately the notes are all in my head.

double-checking the City:GetGarrisonedUnit() method via a test did show that it will give you the object for a land combat unit if there is one on the city tile regardless of how many other units are also on the city tile, even though units are not "garrisoned" anymore in BNW. I did not test to see if there is only a civilian (worker or great person) whether that unit would be returned, but I don't think it will. So it's a bit more reliable than I had remembered, but you'd still have to look through all units on the tile if looking for a great person.
 
Top Bottom