Lua Objects

Also related, damage from combat are applied before the combat event is called.
 
@cromcrom You mean standard game healing? If so, that's ok because it must happen within player's turn, after you move, etc. So, it will be before PlayerTurnDectivate and TurnEnd, since they are called after the player's done its things. If you want to apply attrition before healing, then:
A) hook into unit movement
B) hook into PlayerTurnAcfivate which could be really a logical choice since you will be able to apply attrition to,initial warrior and settler as well if they spawn in bad terrain. Otherwise, they will have a chance to escape.
 
I apologize if this has been answered already. I'd like to be able to pinpoint the Hex a player clicked on. I assume there is some way to do this since Firetuner lets you select a hex to drop units/features/etc on. Is this replicable with Lua? I don't see any obvious Firaxis code that pinpoints how, but I assume it has to exist given its such a core game requirement.
 
I apologize if this has been answered already. I'd like to be able to pinpoint the Hex a player clicked on. I assume there is some way to do this since Firetuner lets you select a hex to drop units/features/etc on. Is this replicable with Lua? I don't see any obvious Firaxis code that pinpoints how, but I assume it has to exist given its such a core game requirement.
try this
Code:
        local plotX:number, plotY:number = UI.GetCursorPlotCoord();

There are also a lot of other function related to plot/world/screen coordinate in the UI table
 
try this
Code:
        local plotX:number, plotY:number = UI.GetCursorPlotCoord();

There are also a lot of other function related to plot/world/screen coordinate in the UI table


This is perfect, thanks. I'm still struggling a bit with the Civ 6 object model and Lua. Hoping I can use this to good ends. :)
 
Does anyone have info related to manipulating districts specifically through Lua? The documentation you guys have uncovered so far is great, but I'm stuck at WorldBuilder.CityManager(), which I assume would be my portal for changing all things about cities, but I can't find any functions to set anything related to districts anywhere (eg. change an adjacency bonus).

I've detailed what I'm trying to do in this topic.

I feel genuinely stuck at the moment. I have plenty of experience with other languages, but not Lua, particularly with switching contexts and using the FireTuner console to cajole data out of the game at runtime. I don't really know how to "select" a district in-game, seems like it would be under the city manager.
 
Does anyone have info related to manipulating districts specifically through Lua? The documentation you guys have uncovered so far is great, but I'm stuck at WorldBuilder.CityManager(), which I assume would be my portal for changing all things about cities, but I can't find any functions to set anything related to districts anywhere (eg. change an adjacency bonus).

I've detailed what I'm trying to do in this topic.

I feel genuinely stuck at the moment. I have plenty of experience with other languages, but not Lua, particularly with switching contexts and using the FireTuner console to cajole data out of the game at runtime. I don't really know how to "select" a district in-game, seems like it would be under the city manager.

I'd have thought that WorldBuilder would operate solely with, well, WorldBuilder...

As for Set functions, then yea they're pretty thin on the ground :/
 
I'd have thought that WorldBuilder would operate solely with, well, WorldBuilder...

As for Set functions, then yea they're pretty thin on the ground :/

The reason I brought up WorldBuilder is that it appears able to assign plot ownership to specific cities at runtime through WorldBuilder.CityManager(), which gives me the impression that it does more than simply construct the game world before the game starts. I imagine the function I'm looking for is somewhere inside the City Manager, possibly after multiple layers of indirection. I'm attempting to use the debug dump functions created by @Gedemon / @LeeS to expose more functions, but I'm having trouble getting them to work. I have no experience with Lua and it doesn't appear to be similar enough to other scripting languages I'm comfortable with, like Python, to just jump in without a primer. I don't mind sitting down some evening and doing a "Lua for Dummies"-style tutorial, but I don't know if that'll end up getting me very much closer to finding the setter functions we would need to make truly interesting mods.

A few have been found, like the aforementioned "SetPlotOwner", which is why I have hope that many more exist.
 
The reason I brought up WorldBuilder is that it appears able to assign plot ownership to specific cities at runtime through WorldBuilder.CityManager(), which gives me the impression that it does more than simply construct the game world before the game starts. I imagine the function I'm looking for is somewhere inside the City Manager, possibly after multiple layers of indirection. I'm attempting to use the debug dump functions created by @Gedemon / @LeeS to expose more functions, but I'm having trouble getting them to work. I have no experience with Lua and it doesn't appear to be similar enough to other scripting languages I'm comfortable with, like Python, to just jump in without a primer. I don't mind sitting down some evening and doing a "Lua for Dummies"-style tutorial, but I don't know if that'll end up getting me very much closer to finding the setter functions we would need to make truly interesting mods.

A few have been found, like the aforementioned "SetPlotOwner", which is why I have hope that many more exist.

If you just wanna practice Lua, then I'd highly recommend playing around in Civ 5; Civ 6's Lua capabilities are abysmal, so if you wanna play around and actually be able to do stuff then I'd just sit down with Bane_'s tutorial and be able to actually do stuff.
 
I'm going to need examples that work in actual .lua code, because the very first one I tried in Lua Console in FireTuner didn't work: print(_G.Players[0]:GetName()) produces just an error message. It seems that _G.Players is nil, which leaves me pretty much up a creek without a paddle to the point where further testing, not that I haven't done any, is pointless, because if I can't even tell which player is which my civilization specific lua is stillborn.

Has any of the output been tested or is it just some arbitrary readout from a DLL with no provenance, no reliability, no practical use. Yes, I'm angry, but not at the OP. I'm disappointed that the best that we can do is lists of three values that don't seem to work and don't come with descriptions to indicate what they should do if they did work. I'm angry at Firaxis for treating us like mushrooms — They told us Civ VI was designed to be modded not designed to be reverse engineered. I appreciate attempts to do the latter and at the same time I deplore the need.
 
_G is not available for modding. Player object doesn't have GetName() function. You can use PlayerConfigurations[0]:GetPlayerName() or PlayerConfigurations[0]:GetCivilizationShortDescription().
If you are referring to the list of Lua functions in Excel - I can assure you that all of them are working (at least I have not encountered a situation where they would not). The problem is only with parameters - you need to look in the code provided by Firaxis. If a function is not used anywhere (many cases, unfortunately).. well, that's a real pickle.
And the other thing. I did a little of Civ5 modding, but I can say that Civ6 is much better designed, both DB and Lua interface. There's a lot of logic that can help you actually discover how how some of functions are working.
 
Code:
local sPlayerCivName = PlayerConfigurations[0]:GetCivilizationTypeName()
local sPlayerLeaderName = PlayerConfigurations[0]:GetLeaderTypeName()
print(Locale.Lookup(GameInfo.Civilizations[sPlayerCivName].Name)
print(Locale.Lookup(GameInfo.Leaders[sPlayerLeaderName].Name)
That will print into the lua log file the name of the human-player's civilization and leader (assuming a single-player game) as seen in-game.

Civ6 lua is workable and has much room for improvement but I cannot say I agree it is better designed or implemented at the moment. But Vanilla civ5 was also kind of kludgey in some degree: for example there was no hook event for a city completing a building or wonder, or a city training a unit, or purchasing a tile: these were added in the Fall'14 patch, along with a whole series of other lua event hooks.
 
Adding GameEvents to the google doc:

CityBuilt
CityConquered
OnCityPopulationChanged
OnFaithEarned
OnGameTurnStarted
OnGreatPersonActivated
OnNewMajorityReligion
OnPillage
OnUnitRetreated
PlayerTurnStartComplete
PlayerTurnStarted

thanks @Gleb Bazov
 
I am posting here a few of the function arguments and event parameters that I have sleuthed out. They may have already been posted, but, if not, here they are. I have more, and I'll keep on posting them here for everyone's convenience. Cheers,

UnitManager.RestoreMovement(pUnit)

UnitManager.MoveUnit( pUnit, iPlotX, iPlotY )

UnitManager.PlaceUnit( pUnit, iPlotX, iPlotY )

NOTE: In order to move or place a unit after a move that exhausts its movement points. the unit's movement points must first be restored. If this is not done, and PlaceUnit is used, error artifacts appear on the game screen, where the game treats the unit as being at the new location, but the graphics do not update. I.e. visually it remains at the old location, but, in actuality, it is at the new location.

If MoveUnit is used to move a unit that has exhausted its movement points, no move takes place. The function fires successfully, but has no effect.

-- where:

local pPlayer = Players[ iPlayerID ]

local pUnit = pPlayer:GetUnits():FindID( iUnitID )

On a separate note, I have determined the following parameters for the following event:

function OnUnitGreatPersonCreated( iPlayerID, iUnitID, igpType, igpID )
-- main chunk --
end
Events.UnitGreatPersonCreated.Add(OnUnitGreatPersonCreated);

-- where:

igpType is an integer, from 0 to 8, corresponding to the index of the GreatPersonClasses table

-- and:

igpID is an integer, corresponding to the index of the GreatPersonIndividuals table
 
UnitManager.MoveUnit( pUnit, iPlotX, iPlotY )

UnitManager.PlaceUnit( pUnit, iPlotX, iPlotY )
thanks you for finding those, they are new, I was waiting since release for something allowing control over movement of AI units :)

(and now I'll have to test if it allows to initialize combat)
 
My pleasure :) ! @Infixo suggested that I try them, and they worked well for me. If they work for initializing combat, please let me know!

I spent a couple of hours tonight sleuthing out a few more events and parameters that might be missing from the excel table. Here they are:

Code:
function OnNationalParkAdded( iPlayerID, iParkRootX, iParkRootY )
-- main chunk --
Events.NationalParkAdded.Add( OnNationalParkAdded );

-- iParkRootX: coordinate X of the National Park's tower (the lower end of the vertical diamond)
-- iParkRootX: coordinate Y of the National Park's tower (the lower end of the vertical diamond)

--====================================================================================================================

function OnPlotYieldChanged( iPlotX, iPlotY )
-- main chunk --
Events.PlotYieldChanged.Add( OnPlotYieldChanged );

--====================================================================================================================

function OnTreasuryChanged( iPlayerID, iGoldPerTurn, iCurrentTreasury)
-- main chunk --
Events.TreasuryChanged.Add( OnTreasuryChanged );

-- iGoldPerTurn refers to the player's gold income per turn, and not to the change in the player's treasury
-- event fires every time there is a change in the player's treasury, but does not yield the quantum of the change itself

--====================================================================================================================

function OnUnitFormCorps( iPlayerID, iUnitID )
-- main chunk --
Events.UnitFormCorps.Add( OnUnitFormCorps );

--====================================================================================================================

function OnUnitFormArmy( iPlayerID, iUnitID )
-- main chunk --
Events.UnitFormArmy.Add( OnUnitFormArmy );

--====================================================================================================================

function UnitGreatPersonActivated( iUnitOwnerID, iUnitID, iGreatPersonClass, iGreatPersonType)
-- main chunk --
Events.UnitGreatPersonActivated.Add( UnitGreatPersonActivated );

-- iGreatPersonType refers to the index of the GreatPersonIndividuals table
-- iGreatPersonClass refers to the index of the GreatPersonClasses table

--====================================================================================================================

function UnitGreatPersonChanged( iPlayerID, iUnitID)
-- main chunk --
Events.UnitGreatPersonChanged.Add( UnitGreatPersonChanged );

--====================================================================================================================

function UnitMoveComplete( iPlayerID, iUnitID, iTerminusX, iTerminusY)
-- main chunk --
Events.UnitMoveComplete.Add( UnitMoveComplete );

-- fires every time a unit stops moving
-- for a multi-plot movement path, will fire only for the final destination plot on which the unit stops for that turn

--====================================================================================================================

function CityCommandStarted( iPlayerID, iCityID, iIntegerA, iIntegerB, Hash, iIntegerC )
-- main chunk --
Events.CityCommandStarted.Add( CityCommandStarted );

-- in the case of the human player's capital city, iIntegerB = iCityID
-- for other human player cities, iIntegerB differs from iCityID
-- in all fired events, iIntegerA and iIntegerC consistently print as 0
-- Hash appears to refer to the hash of the city command that triggers the event
-- The events does not seem to fire for non-human player cities where the human player has no visibility (or,
-- alternatively, the event does not fire for non-human player cities at all).

--====================================================================================================================

function CityTileOwnershipChanged( iPlayerID, iCityID )
-- main chunk --
Events.CityTileOwnershipChanged.Add( CityTileOwnershipChanged );

function DiplomacyDealEnacted( iFirstPlayerID, iSecondPlayerID )
-- main chunk --
Events.DiplomacyDealEnacted.Add( DiplomacyDealEnacted );

-- it is assumed that iFirstPlayerID refers to the player initiating the deal, while iSecondPlayerID is the player
-- accepting the deal, but insufficient testing done to rule out the possibility of it being the reverse in certain cases

function DiplomacyDeclareWar( iFirstPlayerID, iSecondPlayerID )
--    iFirstPlayerID = player declaring war
--    iSecondPlayerID = player subject to the declaration of war
Events.DiplomacyDeclareWar.Add( DiplomacyDeclareWar );

function DiplomacySessionClosed( iPlayerID )
-- iPlayerID = player that responds to the diplomatic interaction
-- event fires on conclusion of a diplomatic exchange (refusal/acceptance of a deal, acknowledgement of war declaration)
Events.DiplomacySessionClosed.Add( DiplomacySessionClosed );

--DISTRICTS

function DistrictUnitsChanged( iPlayerID, iDistrictID )
-- iDistrictID refers to the district's object ID in the game
Events.DistrictUnitsChanged.Add( DistrictUnitsChanged );

function DistrictAddedToMap( iPlayerID, iDistrictID, iCityID, iDistrictX, iDistrictY, iDistrictType, HashA, HashB, iPercentComplete, iAppealRating, iIntegerB )
-- iCityID = 65536 is the same for the capital city ID of every player (major and minor)
-- iCityID = iDistrictID for any City Center District
-- iDistrictType refers to the index of the Districts table
-- iPercentComplete is always 100 for City Centers and DISTRICT_WONDERs, and 0 for all other newly-placed districts
-- HashA is always the same: 440626330 for the human player and -1851407529 for non-human players
-- HashB remain the same and constant for any district of a given player
-- iAppealRating is the appeal of the district's tile
-- iIntegerB always prints as 0 in all (limited) tests
Events.DistrictAddedToMap.Add( DistrictAddedToMap );

function DistrictBuildProgressChanged( iPlayerID, iDistrictID, iCityID, iDistrictX, iDistrictY, iDistrictType, HashA, HashB, iPercentComplete, iAppealRating, iIntegerB )
-- iCityID = 65536 is the same for the capital city ID of every player (major and minor)
-- iCityID = iDistrictID for any City Center District
-- iDistrictType refers to the index of the Districts table
-- iPercentComplete changes as district build progress advances
-- HashA is always the same: 440626330 for the human player and -1851407529 for non-human players
-- HashB remain the same and constant for any district of a given player
-- iAppealRating is the appeal of the district's tile
-- iIntegerB always prints as 0 in all (limited) tests
Events.DistrictBuildProgressChanged.Add( DistrictBuildProgressChanged );

--POLICIES

function GovernmentPolicyChanged( iPlayerID, iPolicyID )
-- iPolicyID refers to the index of the Policies table
-- fires when changes are made to a player's policies and accepted
-- fires on acceptance of policy changes for the old (removed) and the new (adopted) policies
Events.GovernmentPolicyChanged.Add( GovernmentPolicyChanged );

function GovernmentChanged( iPlayerID, iGovernmentID )
-- iGovernmentID refers to the index of the Governments table
Events.GovernmentChanged.Add( GovernmentChanged );

-- GPs

function GreatPeopleTimelineChanged()
-- no parameters --
Events.GreatPeopleTimelineChanged.Add( GreatPeopleTimelineChanged );

function GreatWorkCreated( iPlayerID, iGreatWorkID, iLocationX, iLocationY, iMuseumID, iIndexOfGreatWorkInGame )
-- iLocationX and iLocationY refer to the location cooredinates of the Great Work
-- iIndexOfGreatWorkInGame refers to great work's order of appearance in the game
-- iMuseumID identifies the museum where the great work is placed
Events.GreatWorkCreated.Add( GreatWorkCreated );

function GreatWorkMoved( iOldPlayerID, iOldCityID, iNewPlayerID, iNewCityID, iMuseumID, iIndexOfGreatWorkInGame )
-- iMuseumID identifies the museum where the great work is placed
-- iIndexOfGreatWorkInGame refers to great work's order of appearance in the game
Events.GreatWorkMoved.Add( GreatWorkMoved );

--====================================================================================================================
--====================================================================================================================

-- GAME EVENTS --

function OnGreatPersonActivated( iUnitOwnerID, iUnitID, iGreatPersonType, iGreatPersonClass )
-- main chunk --
GameEvents.OnGreatPersonActivated.Add( OnGreatPersonActivated );

-- iGreatPersonType refers to the index of the GreatPersonIndividuals table
-- iGreatPersonClass refers to the index of the GreatPersonClasses table
 
Last edited:
Code:
function GetArgumentDatas(sOrigin, tTable)
	print("============================================================================================")
	print("[" .. sOrigin .. "]: Dumping Event Hook Argument Data")
	print("............................................................................................")
	for k,v in pairs(tTable) do
		local sKeyType = type(k)
		local sValueType = type(v)
		print("[" .. sOrigin .. "]: Key is of type " .. sKeyType .. " = " .. tostring(k) .. ", Value is of type " .. sValueType .. " = " .. tostring(v))
	end
	print("............................................................................................")
	print("[" .. sOrigin .. "]: dump completed for this firing of the event")
	print("============================================================================================")
end
function OnDistrictAddedToMap(...)
	--OnDistrictAddedToMap(iPlayer, iDistrict, iCity, iX, iY, iDistrictIndex, iUnknownEventSubType1, iUnknownEventSubType2, iPercentComplete, iPlotAppeal, iUnknown3)
		--above was for city center district
		--for human player (Cleopatra, Egypt)
			--iUnknownEventSubType1 == -1851407529
			--iUnknownEventSubType2 == -1155553852
		--for Montezuma, Aztecs:
			--iUnknownEventSubType1 == -1851407529
			--iUnknownEventSubType2 ==  1347583174
		--iDistrict == iCity for founding a city and plopping the City Center District
	--OnDistrictAddedToMap(iPlayer, iDistrict, iCity, iX, iY, iDistrictIndex, iUnknownEventSubType1, iUnknownEventSubType2, iPercentComplete, iPlotAppeal, iUnknown3)
		--for adding Holy Site to the build qeue in human player's capital city: 0, 131073, 65536, 66, 30, 1, -1851407529, -1155553852, 0, 2, 0
	--the event only appears to fire when the district is placed for construciton, not when it is completed.
	--OnDistrictAddedToMap(iPlayer, iDistrict, iCity, iX, iY, iDistrictIndex, iUnknownEventSubType1, iUnknownEventSubType2, iPercentComplete, iPlotAppeal, iUnknown3)
		--for adding Hanging Gardens to the map on save reload next to human player's capital city: 0, 196610, 65536, 21, 59, 13, -1851407529, -1806906687, 100, -4, 0
		--"13" matches to the index # within table <Districts> for "DISTRICT_WONDER"
	--Event fires as part of saved-game reloading for all districts and wonders placed on the map
	print("Events.DistrictAddedToMap fired for function OnDistrictAddedToMap")
	GetArgumentDatas("OnDistrictAddedToMap", {...})
end
Events.DistrictAddedToMap.Add(OnDistrictAddedToMap)
 
I've attached new dumps from script and UI context in the second post.
 
Back
Top Bottom