1.) If you're using GameEvents.CityCaptureComplete for an UA, could you use it to grant a promotion to the unit that captures the capital, once per capital?
(If that's not possible, I guess could I have a Lua code where the units that where the nearby units gain experience points when the capital is captured. I remember there being a Civ with something like that I could base on, only with healing the units instead. What was it?)
2.) Is there some way to have a building that gets extra production when built in a captured city?
3.) A have an idea for UA where units get an attack boost when a Policy Tree in finished for 10 turns. How could you scale it for the Game Speed?
4.) A have an idea for a Unique Unit when it is born, it generate Golden Age points. It also would have a special promotion where if that unit dies or a unit with that promotion dies, it transfers that promotion to another unit and it there would be only 1 unit with that promotion. Is that possible?
1) Since the hook returns the city which was captured, you could check which COMBAT(thanks to Whoward for the correction) unit is currently in the city space. That will always be the unit which captured the city (since only melee units can capture cities)! Next, you would add a dummy marker to the captured city. If this marker was not yet in a city upon capture, the unit gains a promotion. If the marker was already in a city, the unit will not gain a promotion.
2) I guess two different buildings or the use of dummy buildings would work.
3) I haven't worked with game speeds yet, so I won't be of use here EDIT: See Whoward's post below
4)
Code:
pPlayer:ChangeGoldenAgeProgressMeter() (I think this would work? Then again, it's Firaxis we're talking about :lol:)
(hook) UnitKilledInCombat(ePlayer,eKilledPlayer,eKilledUnit) (There were some issues with using this hook, though I can't recall what they specifically were...)
Thanks for the help! I still need some help with the code, though.
1.) I got this code from borrowing others. And there's definitely some errors. (I'll never understand Lua.) I'm not sure how it can detect the unit when capturing the capital.
Code:
GameEvents.CityCaptureComplete.Add(
function PromotionFromOriginalCapitalCapture(iOldOwner, bIsCapital, iX, iY, iNewOwner, iPop, bConquest)
gPromotionDummy = GameInfoTypes.BUILDING_DECEPTICONS_PROMOTION_DUMMY
local iPlayerCiv = pPlayer:GetCivilizationType()
local iCapital = pPlayer:GetCapitalCity()
local iUnit = pPlayer:GetUnitType()
local plot = Map.GetPlot(iX, iY)
local iNewOwner = cCity:GetOwner();
local iOldOwner = cCity:GetOriginalOwner();
local iPreviousOwner = cCity:GetPreviousOwner();
if iPlayerCiv == GameInfoTypes.CIVILIZATION_DECEPTICONS then
if iNewOwner ~= iOldOwner then
if iCapital:IsOriginalCapital() then
if iUnit in iCapital then
if iUnit = GameInfoTypes.UNITCOMBAT_MOUNTED or GameInfoTypes.UNITCOMBAT_RECON or GameInfoTypes.UNITCOMBAT_MELEE or GameInfoTypes.UNITCOMBAT_GUN or GameInfoTypes.UNITCOMBAT_ARMOR or GameInfoTypes.UNITCOMBAT_HELICOPTER then
iCapital:SetNumRealBuilding(gPromotionDummy) then
if gPromotionDummy in iCapital then
end
if gPromotionDummy ~= in iCapital then
iUnit:CanHavePromotion()
print ("Promotion granted!")
end
if else
end
end
end
end
end
end)
GameEvents.CityCaptureComplete.Add(PromotionFromOriginalCapitalCapture)
3.) I haven't wrote the code for number 3, but what Lua hook detects when a Policy tree is finished? And how could I combine it with the code whoward posted?
4.) I forgot to mention this, but the UU I mentioned was a Great General replacement. I haven't wrote this code either. And would I need to use PlotIterators.lua for this code? (As in the transferring of the Special Promotion).
DISCLAIMER FOR FUTURE READERS: I've made quite a few formatting mistakes, resulting in fatal errors in the code! For working versions, check LeeS's code in the post(s) below!
1) Here are some mistakes you made in your lua code:
You added multiple GameEvents of the same thing:
You either use:
Code:
function myFunction(arg1, arg2, arg3)
--insert code here
end
GameEvents.AnyRandomLuaHookHere.Add(myFunction)
or
Code:
GameEvents.AnyRandomLuaHookHere.Add( function( arg1,arg2,arg3)
--insert code here
end)
pPlayer was never defined anywhere, while you are trying to use it in line 4 and 5
Code:
[..snipped code..]
local iPlayerCiv = [COLOR="Red"]pPlayer[/COLOR]:GetCivilizationType()
local iCapital = [COLOR="red"]pPlayer[/COLOR]:GetCapitalCity()
[..snipped code..]
There is no such thing as eNewPlayer in the CityCaptureComplete lua hook. This is the correct format (Source: Whoward's GameEvents cheat sheet; I highly recommend it )
EDIT: I had an outdated version of the Cheat Sheet; The arguments/parameters OTiger used were in fact correct
I don't know what you are trying to do with the "in". (line 18 and 20) (I have no clue myself how you should use "in", which I why I usually avoid them )
EDIT: If it was meant to use it as "check if the building is inside the city" then that's not how you use it, we have pCity:IsHasBuilding(iBuilding) for that
To give a city a building we use pCity:SetNumRealBuilding(iBuilding,1)
To remove a building from a city we use pCity:SetNumRealBuilding(iBuilding,0)
Regarding, "iUnit:CanHavePromotion()" (line 21):
iUnit needs to be pUnit, you can't use a unit ID here; you need the pointer!
You also need an argument (a.k.a. parameter) in between the brackets. This argument is the promotion ID (E.g. iPromotion)
:CanHavePromotion(iPromotion) is used to check if a unit is allowed to gain a certain promotion. E.g. Used to check if the Warrior can gain the 'Sentry' Promotion.
To check if a unit has a promotion we use pUnit:IsHasPromotion(iPromotion)
To grant a promotion to a unit we use pUnit:SetHasPromotion(iPromotion,true)
To remove a promotion from a unit we use pUnit:SetHasPromotion(iPromotion,false)
Source: Whoward's Lua cheat sheet; I also highly recommend this one! (The ModWiki is incomplete and is occasionally incorrect as well)
Line 24-25 states:
Code:
if else
end
which would cause a syntax error (I think); Also, it doesn't really add anything to the code, so we can safely remove it
SpoilerUNTESTED Code that might work :
Code:
local iMarkerPromotionBuilding = GameInfoTypes.BUILDING_DECEPTICONS_PROMOTION_DUMMY
local iCiv = GameInfoTypes.CIVILIZATION_DECEPTICONS
local iPromotion = GameInfoTypes.PROMOTION_WHATEVER
function PromotionFromOriginalCapitalCapture(iOldOwner, bCapital, iX, iY, iNewOwner, iOldPop, bConquest, iGreatWorkCount, iGreatWorkCount)
if not bCapital then return end --if the captured city was not the captial then end the code here
print("A Capital City was conquered!")
local pCityPlot = Map.GetPlot(iX,iY); --get the plot on which the city is located
local pCity = pCityPlot:GetPlotCity(); --get the city which was captured
local pPlayer = pCity:GetOwner(); --get the civ which captured the city
if pPlayer:GetCivilizationType() == iCiv then --check if the decepticons took the city
print("The DECEPTICONS were the ones that took it! CALL OPTIMUS PRIME!") --print statements for our lua console; they're here for clarity and debugging :)
if not pCity:IsHasBuilding(iMarkerPromotionBuilding) then --check if the city has the marker building (a.k.a. if the city has not been captured before)
print("This city was taken for the first time!")
pCity:SetNumRealBuilding(iMarkerPromotionBuilding,1)--give the city the marker building
local pUnit = pCity:GetGarrisonedUnit(); --get the unit that has captured the city (this unit will be the only garrisoned unit and can thus not be a civilian IIRC!)
pUnit:SetHasPromotion(iPromotion,true) --give that unit the special promotion
print("The Decepticon that had captured the city gained a special promotion! We should inform Optimus Prime about this!")
else
print("This city has been taken by the Decepticons before!")
end
else
print("The Decepticons were not the ones that took it! Move along Optimus Prime!")
end
end
--Whoward's IsCivInPlay
function IsCivInPlay(iCivType) --This isn't specificall neccesary to allow the code to function, though it's here to prevent lag
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
if (IsCivInPlay(iCiv)) then --only allow our Lua code to check if the decepticons are actually in the game (to prevent lag)
GameEvents.CityCaptureComplete.Add(PromotionFromOriginalCapitalCapture)
end
EDIT: This code contained (quite a few) fatal errors, check LeeS's code below!
3) There is none that fires when a policy tree is finished. There is one though when one is opened (PlayerAdoptPolicyBranch(ePlayer,ePolicyBranch)) and when a policy is adopted (PlayerAdoptedPolicy(ePlayer,ePolicy); this will be the one we're going to use)! (NOTE: This also works for ideologies and ideological tenets! EDIT: PlayerAdoptPolicy does work for Ideological tenets, PlayerAdoptPolicyBranch does not!))
We do however also have access to the function pPlayer:IsPolicyBranchFinished(iPolicyBranchID) This page contains all the policy branch IDs.
Therefore, what we could do is simply add a loop which loops through all of the policy branches. If it finds one that is finished, it checks the value from an array/table (which specifies if that branch has been finished before):
Code:
local bBranchFinished = {false, false, false, false, false, false, false[COLOR="DarkRed"], false, false, false[/COLOR]} --remove parts in red if you want to exclude ideological trees
local iOurCiv = GameInfoTypes.CIVILIZATION_AUTOBOTS --I assumed this civilization would be the autobots, since the other one were the decepticons;
function PolicyTreeFinishedAttackBoost (iPlayer,ePolicy)
pPlayer = Players[iPlayer]
if pPlayer:GetCivilizationType==iOurCiv then
print("The autobots have arrived; they've adopted another policy!")
for i=0,9,1 do --"i" in this for-loop corresponds to the PolicyBranch IDs; replace 9 by 6 if you want to exclude ideological trees
if pPlayer:IsPolicyBranchFinished(i) and not bBranchFinished[i+1] then -- i+1 because Lua Arrays start at 1 -.-
print("The Autobots have Finished a Policy Branch for the first time! Surely Social Policies will be useful when fighting the Decepticons!!")
bBranchFinished[i+1]=true
--this is where we will apply the buff
else
print("This policy branch has already been finished before")
end
end
end
end
GameEvents.PlayerAdoptedPolicy.Add(PolicyTreeFinishedAttackBoost)
To Apply the buff, we will need a promotion that we grant to every unit. We will also add a counter so that our promotion will only last a certain amount of turns (paste this code in the comment in the code above):
Code:
local iPolicyTurns = 0
local iOurUnit = GameInfoTypes.UNIT_BUMBLE_BEE
local iPolicyPromotion = GameInfoTypes.PROMOTION_POLICY_FINISHED
local fTrainFactor = GameInfo.GameSpeeds[PreGame.GetGameSpeed()].TrainPercent / 100.0
local iStandardTurns = 10
local iBoostTurns = math.floor(iStandardTurns * fTrainFactor + 0.5) --not sure why there is a +0.5 here; it simply ALWAYS adds half a turn extra on every game speed :confused:
--since the above five lines are static (a.k.a. they don't change during the game) we will move them in the final code
for pUnit in pPlayer:Units do --loop through every unit of our player
if pUnit:GetUnitType() == iOurUnit then
pUnit:SetHasPromotion(iPolicyPromotion,true)
print("Promotion granted to our unit!")
end
end
iPolicyTurns = iPolicyTurns + iBoostTurns
You could also use this code instead of the one above if you want the combat boost to apply to every unit (except civilian units (Yes I do learn from my mistakes ) and nukes):
Code:
local iPolicyTurns = 0
local iPolicyPromotion = GameInfoTypes.PROMOTION_POLICY_FINISHED
local fTrainFactor = GameInfo.GameSpeeds[PreGame.GetGameSpeed()].TrainPercent / 100.0
local iStandardTurns = 10
local iBoostTurns = math.floor(iStandardTurns * fTrainFactor + 0.5) --not sure why there is a +0.5 here; it simply ALWAYS adds half a turn extra on every game speed :confused:
--since the above four lines are static (a.k.a. they don't change during the game) we will move them in the final code
for pUnit in pPlayer:Units do --loop through every unit of our player
if pUnit:GetBaseRangedCombatStrength > 0 or pUnit:GetBaseCombatStrength > 0 then
pUnit:SetHasPromotion(iPolicyPromotion,true)
print("Promotion granted to our unit!")
end
end
iPolicyTurns = iPolicyTurns + iBoostTurns
Now we only need our counter to actually count (and move down!)
Code:
local iOurCiv = CIVILIZATION_AUTOBOTS
function PolicyBranchCombatBoostCounter(iPlayer)
if iPolicyTurns == 0 then
local pPlayer = Players[iPlayer]
if pPlayer:GetCivilizationType() == iOurCiv then
for pUnit in pPlayer:Units do
pUnit:SetHasPromotion(iPolicyPromotion,false)
print("It has been too long since we have last finished a social policy tree. Rip Extra Combat damage")
end
end
end
end
SpoilerFull Code :
Code:
local bBranchFinished = {false, false, false, false, false, false, false[COLOR="DarkRed"], false, false, false[/COLOR]} --remove parts in red if you want to exclude ideological trees
local iOurCiv = GameInfoTypes.CIVILIZATION_AUTOBOTS --I assumed this civilization would be the autobots, since the other one were the decepticons;
local iPolicyTurns = 0
local iPolicyPromotion = GameInfoTypes.PROMOTION_POLICY_FINISHED
--Whoward's GameSpeed Scaling Factor
local fTrainFactor = GameInfo.GameSpeeds[PreGame.GetGameSpeed()].TrainPercent / 100.0
local iStandardTurns = 10
local iBoostTurns = math.floor(iStandardTurns * fTrainFactor + 0.5) --NOTE: not sure why there is a +0.5 here; it simply ALWAYS adds half a turn extra on every game speed :confused:
function PolicyTreeFinishedAttackBoost (ePlayer,ePolicy)
pPlayer = Player[iPlayer]
if pPlayer:GetCivilizationType==iOurCiv then
print("The autobots have arrived; they've adopted another policy!")
for i=0,9,1 do --"i" in this for-loop corresponds to the PolicyBranch IDs; replace 9 by 6 if you want to exclude ideological trees
if pPlayer:IsPolicyBranchFinished(i) and not bBranchFinished[i+1] then -- i+1 because Lua Arrays start at 1 -.-
print("The Autobots have Finished a Policy Branch for the first time! Surely Social Policies will be useful when fighting the Decepticons!!")
bBranchFinished[i+1]=true
for pUnit in pPlayer:Units do --loop through every unit of our player
if pUnit:GetBaseRangedCombatStrength > 0 or pUnit:GetBaseCombatStrength > 0 then
pUnit:SetHasPromotion(iPolicyPromotion,true)
print("Promotion granted to our unit!")
end
end
iPolicyTurns = iPolicyTurns + iBoostTurns
else
print("This policy branch has already been finished before")
end
end
end
end
function PolicyBranchCombatBoostCounter(iPlayer) --EDIT: I screwed this "Counter" up big time; don't look please
if iPolicyTurns == 0 then
local pPlayer = Players[iPlayer]
if pPlayer:GetCivilizationType() == iOurCiv then
for pUnit in pPlayer:Units do
pUnit:SetHasPromotion(iPolicyPromotion,false)
print("It has been too long since we have last finished a social policy tree. Rip Extra Combat damage")
end
end
end
end
--Whoward'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
if (IsCivInPlay(iOurCiv)) then
GameEvents.PlayerAdoptedPolicy.Add(PolicyTreeFinishedAttackBoost)
GameEvents.PlayerDoTurn.Add(PolicyBranchCombatBoostCounter)
end
EDIT: This code contained quite a few fatal errors (as well as some other mistakes) as well! Again, check LeeS's code below!
NOTE: There will probably be better solutions (perhaps even for all the things I'm mentioning in this post); I usually work quite inefficient. Then again "If it's stupid but it works, it's not stupid"
OTiger said:
4.) I forgot to mention this, but the UU I mentioned was a Great General replacement. I haven't wrote this code either. And would I need to use PlotIterators.lua for this code? (As in the transferring of the Special Promotion).
You could use PlotIterators, though that would be overkill if you only want the promotion to move a maximum distance of one tile (= tiles adjacent) to the Great General. However, if you want no limit (or a limit that is >1 tile distance) PlotIterators is indeed the best solution
EDIT: Oh man this might be the longest post I've every typed
local iMarkerPromotionBuilding = GameInfoTypes.BUILDING_DECEPTICONS_PROMOTION_DUMMY
local iCiv = GameInfoTypes.CIVILIZATION_DECEPTICONS
local iPromotion = GameInfoTypes.PROMOTION_WHATEVER
function PromotionFromOriginalCapitalCapture(iOldOwner, bCapital, iX, iY, iCity, iOldPop, bConquest, iGreatWorkCount, iGreatWorkCount)
if not bCapital then return end --if the captured city was not the captial then end the code here
print("A Capital City was conquered!")
local pCityPlot = Map.GetPlot(iX,iY); --get the plot on which the city is located
local pCity = pPlot.GetPlotCity(); --get the city which was captured
local pPlayer = pCity:GetOwner(); --get the civ which captured the city
if pPlayer:GetCivilizationType() == iCiv then --check if the decepticons took the city
print("The DECEPTICONS were the ones that took it! CALL OPTIMUS PRIME!") --print statements for our lua console; they're here for clarity and debugging :)
if not pCity:IsHasBuilding(iMarkerPromotionBuilding) then --check if the city has the marker building (a.k.a. if the city has not been captured before)
print("This city was taken for the first time!")
pCity:SetNumRealBuilding(iMarkerPromotionBuilding,1)--give the city the marker building
local pUnit = pCity:GetGarrisonedUnit(); --get the unit that has captured the city (this unit will be the only garrisoned unit and can thus not be a civilian IIRC!)
pUnit:SetHasPromotion(iPromotion,true) --give that unit the special promotion
print("The Decepticon that had captured the city gained a special promotion! We should inform Optimus Prime about this!")
else
print("This city has been taken by the Decepticons before!")
end
else
print("The Decepticons were not the ones that took it! Move along Optimus Prime!")
end
end
--Whoward's IsCivInPlay
function IsCivInPlay(iCivType) --This isn't specificall neccesary to allow the code to function, though it's here to prevent lag
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
if (IsCivInPlay(iCiv)) then --only allow our Lua code to check if the decepticons are actually in the game (to prevent lag)
GameEvents.CityCaptureComplete.Add(PromotionFromOriginalCapitalCapture)
end
Cool! I got the Lua cheatsheets, but I got confused on how it works. Thanks for that.
Anyways, I haven't tested this one or the other one yet, but I'll let you know if it work when I have the time.
But could this code work by having a random special promotion everytime you conquer the city? Like, if you make the PROMOTION_WHATEVER work similar to Indonesia's Kris Swordsman? Or would it get the "Pre-Promotion" before if fights?
If we would give the Indonesia-Promotion in place of PROMOTION_WHATAVER we would still have to enter combat another time, since the unit has never entered combat with the promotion! (That being said, I think you could make a custom promotion that basically does the same as the Indonesia-promotion but rather upon promotion-adoption. That would also require Lua however EDIT: Or just give it a random promotion directly)
function FasilGhebbiCityCaptured(iOldOwner, bIsCapital, iX, iY, [COLOR="Blue"]iNewOwner[/COLOR], iPop, bConquest)
local pCity = Map.GetPlot(iX, iY):GetPlotCity()
if pCity:IsHasBuilding(iFasilGhebbiWonder) then
--City with the Fasil Ghebbi Wonder was just captured
--run through units of the old owner and subtract away the promotion
local pOldOwner = Players[iOldOwner]
for pUnit in pOldOwner:Units() do
if tValidFasilGhebbiUnitDomains[pUnit:GetDomainType()] and pUnit:IsCombatUnit() then
pUnit:SetHasPromotion(iFasilGhebbiPromotion, false)
end
end
--run through the units of the capturing civ and add the promotion to those who qualify
iFasilGhebbiOwner = iNewOwner
local pNewOwner = Players[iNewOwner]
for pUnit in pNewOwner:Units() do
if tValidFasilGhebbiUnitDomains[pUnit:GetDomainType()] then
if pUnit:IsCombatUnit() and (Map.PlotDistance(pUnit:GetX(), pUnit:GetY(), pFasilGhebbiPlot:GetX(), pFasilGhebbiPlot:GetY()) <= iFasilGhebbiRange) then
pUnit:SetHasPromotion(iFasilGhebbiPromotion, true)
else
pUnit:SetHasPromotion(iFasilGhebbiPromotion, false)
end
end
end
end
end
GameEvents.CityCaptureComplete.Add(FasilGhebbiCityCaptured)
This is a portion of a modmod I made for myself to implement a few outstanding issues with Enlightenment Era. I don't have anything specified in my function for the final two (2?) parameters passed by CityCaptureComplete but the highlighted one is in fact the ID of the player who captured the city.
whoward69's original posting had incorrect designation-names here for CityCaptureComplete's parameters which he fixed in the most recent update(s).
PlayerAdoptPolicyBranch does not work for ideologies. PlayerAdoptPolicy does however work for the indivudual 'tenants' within ideologies because they are actually just policies.
Ok, I finally tested the code you gave me, Troller. And there some errors from it.
This one is about the Decepticons UA:
(Anyways, how could you make it to create a pool of random promotions to get from city conquest?)
Code:
[28057.984] \Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Trait: A Capital City was conquered!
[28058.484] Runtime Error: C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Trait.lua:10: attempt to index global 'pPlot' (a nil value)
stack traceback:
C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\DK Trait.lua:10: in function <C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Trait.lua:5>
And for the Autobot UA code, there's errors too:
Code:
[29404.500] Syntax Error: C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Trait 2.lua:19: function arguments expected near '=='
[29404.500] Runtime Error: Error loading C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Trait 2.lua.
This may shed some light on the various problems. Not promising I caught all the fatal syntax or other small errors:
Spoiler:
Code:
local bBranchFinished = {} --data setting into this table moved to bottom and is based on correct conditions at game reload or game start
local iOurCiv = GameInfoTypes.CIVILIZATION_AUTOBOTS --I assumed this civilization would be the autobots, since the other one were the decepticons;
local iPolicyTurns = 0
local iPolicyPromotion = GameInfoTypes.PROMOTION_POLICY_FINISHED
--Whoward's GameSpeed Scaling Factor
local fTrainFactor = GameInfo.GameSpeeds[PreGame.GetGameSpeed()].TrainPercent / 100.0
local iStandardTurns = 10
local iBoostTurns = math.floor(iStandardTurns * fTrainFactor + 0.5) --NOTE: not sure why there is a +0.5 here; it simply ALWAYS adds half a turn extra on every game speed :confused:
local bExcludeIdeologyBranches = true
function PolicyTreeFinishedAttackBoost(iPlayer, ePolicy)
local pPlayer = Players[iPlayer]
if pPlayer:GetCivilizationType() == iOurCiv then
local bAddPromotion = false
print("The autobots have arrived; they've adopted another policy!")
for PolicyBranch in GameInfo.PolicyBranchTypes() do
local bBranchIsAnIdeology = false
local iPolicyBranch = PolicyBranch.ID
if (PolicyBranch.FreePolicy == nil) or (PolicyBranch.FreePolicy == "NULL") then
bBranchIsAnIdeology = true
end
if bBranchIsAnIdeology then
if not bExcludeIdeologyBranches then
if pPlayer:GetLateGamePolicyTree() == iPolicyBranch then
if bBranchFinished[iPolicyBranch] == false then
bBranchFinished[iPolicyBranch] = true
bAddPromotion = true
iPolicyTurns = iPolicyTurns + iBoostTurns
end
end
end
else
if pPlayer:IsPolicyBranchFinished(iPolicyBranch) and (bBranchFinished[iPolicyBranch] == false) then
print("The Autobots have Finished a Policy Branch for the first time! Surely Social Policies will be useful when fighting the Decepticons!!")
bBranchFinished[iPolicyBranch] = true
bAddPromotion = true
iPolicyTurns = iPolicyTurns + iBoostTurns
else
print("This policy branch has already been finished before")
end
end
end
if bAddPromotion then
for pUnit in pPlayer:Units() do --loop through every unit of our player
if pUnit:IsCombatUnit() then
pUnit:SetHasPromotion(iPolicyPromotion,true)
print("Promotion granted to our unit!")
end
end
end
end
end
function PolicyBranchCombatBoostCounter(iPlayer)
local pPlayer = Players[iPlayer]
if pPlayer:GetCivilizationType() == iOurCiv then
if iPolicyTurns == 0 then
print("It has been too long since we have last finished a social policy tree. Rip Extra Combat damage")
for pUnit in pPlayer:Units() do
pUnit:SetHasPromotion(iPolicyPromotion,false)
end
elseif iPolicyTurns > 0 then
iPolicyTurns = iPolicyTurns - 1
end
end
end
--Whoward'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
if (IsCivInPlay(iOurCiv)) then
for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1 do
local pPlayer = Players[iPlayer]
if pPlayer ~= nil then
if pPlayer:GetCivilizationType() == iOurCiv then
for PolicyBranch in GameInfo.PolicyBranchTypes() do
local bBranchIsAnIdeology = false
local iPolicyBranch = PolicyBranch.ID
if (PolicyBranch.FreePolicy == nil) or (PolicyBranch.FreePolicy == "NULL") then
bBranchIsAnIdeology = true
end
if bBranchIsAnIdeology then
bBranchFinished[iPolicyBranch] = (pPlayer:GetLateGamePolicyTree() == iPolicyBranch)
else
bBranchFinished[iPolicyBranch] = pPlayer:IsPolicyBranchFinished(iPolicyBranch)
end
end
end
end
end
iPolicyTurns = iBoostTurns
GameEvents.PlayerAdoptPolicy.Add(PolicyTreeFinishedAttackBoost)
GameEvents.PlayerDoTurn.Add(PolicyBranchCombatBoostCounter)
end
This is for the finishing of policy branches. Since you really never 'finish' an ideology branch, the effect for those (when you allow ideology branches to give the effect) is for adopting the ideology.
Aaand I am not sure I caught all the typos in the original code. You need for example "Players[iSomething]" instead of "Player[iSomething]" but I am not sure I caught all these types of typo oopses.
This is for the finishing of policy branches. Since you really never 'finish' an ideology branch, the effect for those (when you allow ideology branches to give the effect) is for adopting the ideology.
Aaand I am not sure I caught all the typos in the original code. You need for example "Players[iSomething]" instead of "Player[iSomething]" but I am not sure I caught all these types of typo oopses.
Well, there's still the "Syntax Error: C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Trait 2.lua:19: function arguments expected near '=='" error still there, so not all errors are gone yet.
Well, there's still the "Syntax Error: C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Trait 2.lua:19: function arguments expected near '=='" error still there, so not all errors are gone yet.
I just tested that code again. It kinda works, but the promotion isn't being awarded when the policy tree is finished.
I have the Lua file for analysis. It seems to repeat "It has been too long since we have last finished a social policy tree. Rip Extra Combat damage" more than usual, but I don't think that's an error.
The code will spit that message every turn for every unit so long as the 'counter' is '0'.
And apparently there are still a few errors in the code. There is no game event called PlayerAdoptedPolicy. The correct name is PlayerAdoptPolicy. I made update to code in Post #11, fixing this incorrect naming, as well as I fixed a possible logic-error that might come into play at some point.
If the code still doesn't seem to be working correctly I'll take a more stringent look at it tomorrow.
The code will spit that message every turn for every unit so long as the 'counter' is '0'.
And apparently there are still a few errors in the code. There is no game event called PlayerAdoptedPolicy. The correct name is PlayerAdoptPolicy. I made update to code in Post #11, fixing this incorrect naming, as well as I fixed a possible logic-error that might come into play at some point.
If the code still doesn't seem to be working correctly I'll take a more stringent look at it tomorrow.
I tested it out, and it seems to work! That's one code, two more to go.
(There's a fourth code, technically, that's the building if it's in a conquered city production bonus. It sounds simple compared to the other ones, so I'll try to make it myself.)
The code will spit that message every turn for every unit so long as the 'counter' is '0'.
And apparently there are still a few errors in the code. There is no game event called PlayerAdoptedPolicy. The correct name is PlayerAdoptPolicy. I made update to code in Post #11, fixing this incorrect naming, as well as I fixed a possible logic-error that might come into play at some point.
If the code still doesn't seem to be working correctly I'll take a more stringent look at it tomorrow.
Ok, I finally tested the code you gave me, Troller. And there some errors from it.
This one is about the Decepticons UA:
Code:
[28057.984] \Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Trait: A Capital City was conquered!
[28058.484] Runtime Error: C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Trait.lua:10: attempt to index global 'pPlot' (a nil value)
stack traceback:
C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\DK Trait.lua:10: in function <C:\Users\Admin\Documents\My Games\Sid Meier's Civilization 5\MODS\Test Mod (v 1)\Test Trait.lua:5>
I didn't define pPlot anywhere there (which is why it returns nil); I did define pCityPlot however (but didn't use it anywhere); How to fix that bug: pPlot should be pCityPlot
NOTE: There will probably be some more issues within that code
EDIT2: This line: local pCity = pCityPlot.GetPlotCity(); --get the city which was captured
should be this: local pCity = pCityPlot:GetPlotCity(); --get the city which was captured
(the dot (.) should be replaced by a colon (:). Dots are used for static things that never change during the game (E.g. Gamespeeds or the Map)
EDIT3: For Random Promotion, check out this thread
OK, so I order to get the code I want for the Deception's UA, do I have to edit and combine the code that LeeS has from #9 and the Random Promotion code, correct?
What changes would I need to do for the code in post #9, other than changing the names for the locals?
From what I understand, LeeS's code in post #9 is for a wonder that adds a promotion to the owner's units that are in range of the city (with a specific domain type). While it does show perfectly how to add a promotion to a units once a city is captured, it lacks a few things which we need (E.g. the city must be a capital, check for the marker building, etc.).
This promotion is also applied to every player's unit, rather than only the unit which captured the city! We could however easily change that by reducing the range to 0 (as in, a 0 tile distance from the city plot, meaning on the city plot)
So what we ultimately want is a combination of LeeS's and my code, since LeeS's code does contain some very useful specifications and bugfixes (E.g. specific unit domains and allowing ships to also gain the promotion (since they never garrison it caused a bug!)
I've tried some things to define the unit domains for LeeS's table, but everything I've tried seemed to cause a bug/have wrong syntax (which is definitely a fault on my end!). So LeeS, how did you define the table for the specific unit domains? Fixed, thank you LeeS
SpoilerFull code that I will actually test this time :
Code:
local iMarkerPromotionBuilding = GameInfoTypes.BUILDING_DECEPTICONS_PROMOTION_DUMMY
local iCiv = GameInfoTypes.CIVILIZATION_DECEPTICON
local tValidCapturePromotion = {GameInfoTypes.PROMOTION_SHOCK_1, GameInfoTypes.PROMOTION_SHOCK_2, GameInfoTypes.PROMOTION_SHOCK_3} --a table/array of the promotions; that are applicable for the random city-capture promotion; as many promotions can be added here, as long as there is a minimum of one!
local tValidCityCaptureUnitDomains = {[GameInfoTypes.DOMAIN_LAND]=GameInfoTypes.DOMAIN_LAND, [GameInfoTypes.DOMAIN_SEA]=GameInfoTypes.DOMAIN_SEA} --EDIT: Thank you LeeS :)
function PromotionFromOriginalCapitalCapture(iOldOwner, bCapital, iX, iY, iNewOwner, iOldPop, bConquest, iGreatWorkCount, iGreatWorkCount)
if not bCapital then return false end --if the captured city was not the captial then end the code here
print("A Capital City was conquered!")
local pCityPlot = Map.GetPlot(iX,iY); --get the plot on which the city is located
local pCity = pCityPlot:GetPlotCity(); --get the city which was captured
local iPlayer = pCity:GetOwner(); --get the civ which captured the city; this returned the player ID; that being said, we could've also used iNewOwner
local pPlayer = Players[iPlayer];
if pPlayer:GetCivilizationType() == iCiv then --check if the decepticons took the city
print("The DECEPTICONS were the ones that took it! CALL OPTIMUS PRIME!") --print statements for our lua console; they're here for clarity and debugging :)
if not pCity:IsHasBuilding(iMarkerPromotionBuilding) then --check if the city has the marker building (a.k.a. if the city has not been captured before)
print("This city was taken for the first time!")
pCity:SetNumRealBuilding(iMarkerPromotionBuilding,1)--give the city the marker building
for pUnit in pPlayer:Units() do
if tValidCityCaptureUnitDomains[pUnit:GetDomainType()] then
if pUnit:IsCombatUnit() and (Map.PlotDistance(pUnit:GetX(), pUnit:GetY(), pCityPlot:GetX(), pCityPlot:GetY()) <= 0) then
iPromotion= tValidCapturePromotion[Game.Rand(#tValidCapturePromotion,"Rolling a random promotion")+1]
pUnit:SetHasPromotion(iPromotion,true) --give that unit the special promotion
print("The Decepticon that had captured the city gained a special promotion! We should inform Optimus Prime about this!")
return true;
end
else
print("invalid unit domain")
end
end
else
print("This city has been taken by the Decepticons before!")
end
else
print("The Decepticons were not the ones that took it! Move along Optimus Prime!")
end
return false;
end
--Whoward's IsCivInPlay
function IsCivInPlay(iCivType) --This isn't specificall neccesary to allow the code to function, though it's here to prevent lag
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
if (IsCivInPlay(iCiv)) then --only allow our Lua code to check if the decepticons are actually in the game (to prevent lag)
GameEvents.CityCaptureComplete.Add(PromotionFromOriginalCapitalCapture)
end
The function now also returns whether it was successful in giving a unit the promotion
I've tested it now and I'm pretty sure it works (apart from the domain issue)
Interesting things I found out too: If you re-capture your own capital your unit also gains the promotion; if you capture a city state your unit also gains the promotion
From what I understand, LeeS's code in post #9 is for a wonder that adds a promotion to the owner's units that are in range of the city (with a specific domain type). While it does show perfectly how to add a promotion to a units once a city is captured, it lacks a few things which we need (E.g. the city must be a capital, check for the marker building, etc.).
This promotion is also applied to every player's unit, rather than only the unit which captured the city! We could however easily change that by reducing the range to 0 (as in, a 0 tile distance from the city plot, meaning on the city plot)
So what we ultimately want is a combination of LeeS's and my code, since LeeS's code does contain some very useful specifications and bugfixes (E.g. specific unit domains and allowing ships to also gain the promotion (since they never garrison it caused a bug!)
I've tried some things to define the unit domains for LeeS's table, but everything I've tried seemed to cause a bug/have wrong syntax (which is definitely a fault on my end!). So LeeS, how did you define the table for the specific unit domains?
SpoilerFull code that I will actually test this time :
Code:
local iMarkerPromotionBuilding = GameInfoTypes.BUILDING_DECEPTICONS_PROMOTION_DUMMY
local iCiv = GameInfoTypes.CIVILIZATION_DECEPTICON
local tValidCapturePromotion = {GameInfoTypes.PROMOTION_SHOCK_1, GameInfoTypes.PROMOTION_SHOCK_2, GameInfoTypes.PROMOTION_SHOCK_3} --a table/array of the promotions; that are applicable for the random city-capture promotion; as many promotions can be added here, as long as there is a minimum of one!
local tValidCityCaptureUnitDomains = {true,true} --this allows only DOMAIN_AIR and DOMAIN_LAND to work; I'll need some editing over here LeeS because I'm sure this is NOT how it should be defined xD
function PromotionFromOriginalCapitalCapture(iOldOwner, bCapital, iX, iY, iNewOwner, iOldPop, bConquest, iGreatWorkCount, iGreatWorkCount)
if not bCapital then return false end --if the captured city was not the captial then end the code here
print("A Capital City was conquered!")
local pCityPlot = Map.GetPlot(iX,iY); --get the plot on which the city is located
local pCity = pCityPlot:GetPlotCity(); --get the city which was captured
local iPlayer = pCity:GetOwner(); --get the civ which captured the city; this returned the player ID; that being said, we could've also used iNewOwner
local pPlayer = Players[iPlayer];
if pPlayer:GetCivilizationType() == iCiv then --check if the decepticons took the city
print("The DECEPTICONS were the ones that took it! CALL OPTIMUS PRIME!") --print statements for our lua console; they're here for clarity and debugging :)
if not pCity:IsHasBuilding(iMarkerPromotionBuilding) then --check if the city has the marker building (a.k.a. if the city has not been captured before)
print("This city was taken for the first time!")
pCity:SetNumRealBuilding(iMarkerPromotionBuilding,1)--give the city the marker building
for pUnit in pPlayer:Units() do
if tValidCityCaptureUnitDomains[pUnit:GetDomainType()] then
if pUnit:IsCombatUnit() and (Map.PlotDistance(pUnit:GetX(), pUnit:GetY(), pCityPlot:GetX(), pCityPlot:GetY()) <= 0) then
iPromotion= tValidCapturePromotion[Game.Rand(#tValidCapturePromotion,"Rolling a random promotion")+1]
pUnit:SetHasPromotion(iPromotion,true) --give that unit the special promotion
print("The Decepticon that had captured the city gained a special promotion! We should inform Optimus Prime about this!")
return true;
end
else
print("invalid unit domain")
end
end
else
print("This city has been taken by the Decepticons before!")
end
else
print("The Decepticons were not the ones that took it! Move along Optimus Prime!")
end
return false;
end
--Whoward's IsCivInPlay
function IsCivInPlay(iCivType) --This isn't specificall neccesary to allow the code to function, though it's here to prevent lag
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
if (IsCivInPlay(iCiv)) then --only allow our Lua code to check if the decepticons are actually in the game (to prevent lag)
GameEvents.CityCaptureComplete.Add(PromotionFromOriginalCapitalCapture)
end
The function now also returns whether it was successful in giving a unit the promotion
I've tested it now and I'm pretty sure it works (apart from the domain issue)
Interesting things I found out too: If you re-capture your own capital your unit also gains the promotion; if you capture a city state your unit also gains the promotion
I didn't post the entirety of the code because I was only meaning to address the issue of the incorrect understanding of which parameters are passed in which positions for the CityCaptureComplete event. Plus, I didn't want to offend Pouakai by posting the whole code labelled as a 'fixer for bits missing from a mod' since I've never discussed this code with him. That having said, here's the entirety of the code for the Fasil Ghebbi (I've highlighted in blue how my definition of Unit-Domain within table tValidFasilGhebbiUnitDomains matches to an actual in-game Unit's domain). You need to study William Howard's thread on data-driven code techniques to understand this usage a little more, but long-story short is you do not structure lua-tables for this sort of thing in the way you have been, ie, as in like this:
local tValidFasilGhebbiUnitDomains = { [color="blue"][GameInfoTypes.DOMAIN_LAND][/color] = GameInfoTypes.DOMAIN_LAND }
local iFasilGhebbiWonder = GameInfoTypes.BUILDING_EE_FASIL_GHEBBI
local iFasilGhebbiRange = 2
local iFasilGhebbiPromotion = GameInfoTypes.PROMOTION_EE_FASIL_GHEBBI
local iFasilGhebbiOwner = "NONE"
local pFasilGhebbiPlot = "NONE"
function FasilGhebbiCityCaptured(iOldOwner, bIsCapital, iX, iY, iNewOwner, iPop, bConquest)
local pCity = Map.GetPlot(iX, iY):GetPlotCity()
if pCity:IsHasBuilding(iFasilGhebbiWonder) then
--City with the Fasil Ghebbi Wonder was just captured
--run through units of the old owner and subtract away the promotion
local pOldOwner = Players[iOldOwner]
for pUnit in pOldOwner:Units() do
if tValidFasilGhebbiUnitDomains[pUnit:GetDomainType()] and pUnit:IsCombatUnit() then
pUnit:SetHasPromotion(iFasilGhebbiPromotion, false)
end
end
--run through the units of the capturing civ and add the promotion to those who qualify
iFasilGhebbiOwner = iNewOwner
local pNewOwner = Players[iNewOwner]
for pUnit in pNewOwner:Units() do
if tValidFasilGhebbiUnitDomains[color="blue"][pUnit:GetDomainType()][/color] then
if pUnit:IsCombatUnit() and (Map.PlotDistance(pUnit:GetX(), pUnit:GetY(), pFasilGhebbiPlot:GetX(), pFasilGhebbiPlot:GetY()) <= iFasilGhebbiRange) then
pUnit:SetHasPromotion(iFasilGhebbiPromotion, true)
else
pUnit:SetHasPromotion(iFasilGhebbiPromotion, false)
end
end
end
end
end
function UnitsNearFasilGhebbi(playerID, unitID, unitX, unitY)
if playerID == iFasilGhebbiOwner then
local pUnit = Players[playerID]:GetUnitByID(unitID)
if (Map.PlotDistance(unitX, unitY, pFasilGhebbiPlot:GetX(), pFasilGhebbiPlot:GetY()) <= iFasilGhebbiRange) then
if tValidFasilGhebbiUnitDomains[color="blue"][pUnit:GetDomainType()][/color] and pUnit:IsCombatUnit() then
pUnit:SetHasPromotion(iFasilGhebbiPromotion, true)
end
else
pUnit:SetHasPromotion(iFasilGhebbiPromotion, false)
end
end
end
function FasilGhebbiCompleted(ownerId, cityId, buildingType, bGold, bFaithOrCulture)
if buildingType == iFasilGhebbiWonder then
iFasilGhebbiOwner = ownerId
local pPlayer = Players[ownerId]
pFasilGhebbiPlot = pPlayer:GetCityByID(cityId):Plot()
for pUnit in pPlayer:Units() do
if tValidFasilGhebbiUnitDomains[color="blue"][pUnit:GetDomainType()][/color] then
if pUnit:IsCombatUnit() and (Map.PlotDistance(pUnit:GetX(), pUnit:GetY(), pFasilGhebbiPlot:GetX(), pFasilGhebbiPlot:GetY()) <= iFasilGhebbiRange) then
pUnit:SetHasPromotion(iFasilGhebbiPromotion, true)
else
pUnit:SetHasPromotion(iFasilGhebbiPromotion, false)
end
end
end
--add additional event subscriptions here
GameEvents.UnitSetXY.Add(UnitsNearFasilGhebbi)
GameEvents.CityCaptureComplete.Add(FasilGhebbiCityCaptured)
GameEvents.CityConstructed.Remove(FasilGhebbiCompleted)
end
end
GameEvents.CityConstructed.Add(FasilGhebbiCompleted)
--this loop is executed upon saved game reload and upon new-game startup
--it makes sure the correct game events are activated based upon whether the wonder has already been constructed
for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1 do
local pPlayer = Players[iPlayer]
if pPlayer:IsAlive() then
if pPlayer:CountNumBuildings(iFasilGhebbiWonder) > 0 then
iFasilGhebbiOwner = iPlayer
for pCity in pPlayer:Cities() do
if pCity:IsHasBuilding(iFasilGhebbiWonder) then
pFasilGhebbiPlot = pCity:Plot()
break
end
end
GameEvents.UnitSetXY.Add(UnitsNearFasilGhebbi)
GameEvents.CityCaptureComplete.Add(FasilGhebbiCityCaptured)
GameEvents.CityConstructed.Remove(FasilGhebbiCompleted)
break
end
end
end
If you want both Land and Sea units to be covered, then you do as like this:
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.