Lua Objects

Not sure if this is the right place to ask this, but here it goes...

I'm trying to create a simple script to allow me to change the LeaderNameType while in game. For now I'm just testing stuff around, but my aim will be to use it to make leaders that will change their look as the Eras go by. I know this will probably break Leader specific achievements, but I cant see any other way I could change this, unlesss I can tap directly into the XMLs that specify the Leader art/BLP this is what I have so far. Using a turn event for now, aswell as normal Leader Types, just to test things out:

Code:
function OnPlayerTurnActivated(ePlayer:number, bFirstTimeThisTurn:boolean)
    local pPlayer = Players[ ePlayer ];
    local pPlayerConfig :table = PlayerConfigurations[ePlayer];

    if (pPlayer:IsAlive() == true and pPlayer:IsMajor() == true) then
        print("PlayerTurnActivated ", ePlayer, pPlayer, pPlayerConfig:GetLeaderTypeName());
        if (pPlayerConfig:GetLeaderTypeName() == "LEADER_GILGAMESH") then
            -- pPlayer:SetLeaderTypeName("LEADER_CLEOPATRA");
            -- pPlayerConfig:SetLeaderTypeName("LEADER_CLEOPATRA");
            -- PlayerConfigurations[pPlayer]:SetLeaderTypeName("LEADER_CLEOPATRA");
            -- PlayerConfigurations[ePlayer]:SetLeaderTypeName("LEADER_CLEOPATRA");
        end
    end
end

Events.PlayerTurnActivated.Add(OnPlayerTurnActivated)

The commented lines are things I tried, but I always get this error:
function expected instead of nil
stack traceback:
EraTracker.lua:22: in function 'OnPlayerTurnActivated'
[C]: in function 'func'
[C]: in function '(anonymous)'

Not even sure if what I'm trying to achieve is possible, I wanted to go with the feature that there was on CIV: BE, which made leaders change the looks while their affinities progressed.
 
How's your Lua file loaded in your mod ?

SetLeaderTypeName is available in UI contexts, not script.
 
Ah maybe thats it then, I dont know what I'm doing... I usually compare myself to scripting, as a monkey on the Monkey Theorem... eventually I get to do something close to Shakespear! xD

Should I load it as AddUserInterface then?

(Thanks for your awesome quick reply btw!)

EDIT: Well, that didnt worked, after hitting Start Game, it "boots" me back again to the main menu =S
 
Last edited:
AddUserInterface, yes, what's in your modinfo ?
 
it was as Gameplay Script. But when I do with AddUserInterface, cant even start a game

EDIT: I fixed the issue of not being able to load it by adding the property <Context>InGame</Context>

But, the script is not running at all either, I have a simple print, and not even that is being output. I figured that part because I was looking for a mod called Current Time of Day, which also has a XML, which I dont quite get what is it for, but I'm sure I'm missing a XML to somehow "append" the script?

EDIT 2:
Got it working, although not sure if the XML file is properly done...

Code:
<GameData>
    <AlphaAnim ID="EraTracker" Cycle="Once" Speed="10" />
</GameData>

If you could explain me better whats happening here (I like to understand what I'm doing) I'd be appreciated ofc! But its working now. When I go to the diplomacy screen, I now get Cleopatra instead of Gilgamesh. Now all I have to do is create "fake" leaders/BLPs to have them change through the eras =D
 
Last edited:
For floating text in script:
Code:
Game.AddWorldViewText(0, "your text", x, y, 0)
or in UI:
Code:
UI.AddWorldViewText(0, "your text", x, y, 0)

the first 0 can be replaced by an EventSubTypes (like EventSubTypes.DAMAGE), no idea for the second.
This final argument appears to be a delay value
  • If I change the iDelay variable I am using to the player ID # I sometimes miss the message for the human player, and the AI player messages get more and more delayed the higher the player ID# as these successive players found their capital city.
  • However, it seems to need the previous message to have "scrolled up" for that plot before the timer starts. So for settings of '0' the second message will be instantaneous more or less but only as soon as message #1 has cleared.
Code:
function CityFoundedCreateMessage(iPlayer, iCityID)
    local pCities = Players[iPlayer]:GetCities();
    local pCity = pCities:FindID(iCityID)
    local iCityX, iCityY, iDelay = pCity:GetX(), pCity:GetY(), 0
    local sMessage = "Player City Founded for Player " ..  PlayerConfigurations[iPlayer]:GetCivilizationTypeName() .. " at X" .. iCityX .. ", Y" .. iCityY
    if (iPlayer ~= 0) then
        iCityX, iCityY = Players[0]:GetStartingPlot():GetX(), Players[0]:GetStartingPlot():GetY()
    else
        iDelay = 2
    end
    Game.AddWorldViewText(0, sMessage, iCityX, iCityY, iDelay)
end
Events.CityInitialized.Add(CityFoundedCreateMessage)
 
if there is no example of use in the game's lua files, yes, educated guesses.
 
In Civ5 lua mod, a notification can be sent like this:

iPlayer:AddNotification(NotificationTypes.NOTIFICATION_WONDER_BEATEN, msg, tip, iCity:GetX(), iCity:GetY(), iPlayer );

So, in CIV6 lua mod, how to implement this functionality?
 
Last edited:
if there is no example of use in the game's lua files, yes, educated guesses.
So where are these lua files? So far I've been making do by cannibalizing other mod creators' lua code. Also, do you know where I can find tutorials on how to use FireTuner? No Idea how to use the lua console - GameCore give me errors whenever I try to access stuff (while a game is loaded and stationary in the background)
 
I'll do it for vanilla, but someone else will have to do it for R&F, code is in second post (may require to add some new string function to the ignore table)
 
I uploaded the log for Scripts. The UI one was getting errors so I might mess around and see what I find later not sure if you know Gedemon? I looked through and picked out all the differences, it is possible I missed some.

Spoiler :

Code:
City:
    ChangeLoyalty
    GetOriginalOwner
 
CombatManager:
    CanAttackTarget
    SimulatePriorityAttackInto

DealManager:
    RequestUpdate

Game:
    GetGameDiplomacy
    ChangePlayerEraScore

Notification Manger:
    FindType

Players:
    GetStats:
        GetNumMyCitiesFollowingSpecificReligion
        GetNumDistrictsFollowingReligion
        GetNumForeignCitiesFollowingReligion
        GetNumForeignFollowers
        TypeName
        GetNumFollowers
        GetNumCitiesFollowingReligion
        GetNumBeliefsInReligion
    GetCulture:
        GetPolicyToUnlock
    GetReligion:
        GetReligionTypeCreated
        ChangeNumBeliefsEarned
    GetAi_Military:
        SetRival
        StartScriptedOperationWithTargetAndRally
        ScriptForceUpdateTargets
        StartScriptedOperation
        SetScriptedTargetAndRally
        SetScriptedOperationReady
        AddUnitToScriptedOperation
    GetAi_Religion:
        SetFavoredReligion
        TypeName
    GetGovernors:
        GetGovernorPoints
        TypeName
        GetGovernorPointsSpent
        ChangeGovernorPoints
     
Plot:
    IsInternalOnlyDistrict
    IsImprovementPillaged
    GetImprovementOwner
    GetAdjacencyYield
    GetNationalParkName
    CanHaveDistrict
    GetAdjacencyBonusType
    IsNationalPark
    IsValidFoundLocation
    CanHaveWonder
    GetAppeal
    GetFeature: (was GetFeatureType)
        GetDirection
        GetType
    GetDefenseModifier
    GetMovementCost
    GetAdjacencyBonusTooltip
    IsChokepoint
    GetAirUnits
    GetNearestLandPlot:
        GetDistrictID
        IsInternalOnlyDistrict
        IsImprovementPillaged
        GetImprovementOwner
        GetAdjacencyYield
        GetNationalParkName
        CanHaveDistrict
        GetAdjacencyBonusType
        IsNationalPark
        IsValidFoundLocation
        CanHaveWonder
        GetAppeal
        GetFeature: (was GetFeatureType)
            GetDirection
            GetType
            TypeName
        GetDefenseModifier
        GetMovementCost
        GetAdjacencyBonusTooltip
        IsChokepoint
        GetWorkerCount
        GetAirUnits
        IsWonderComplete
        HasFeatureBeenAdded
    IsWonderComplete
    HasFeatureBeenAdded
 
Unit:
    GetReligion:
        ChangeReligiousHealCharges
        GetReligiousHealCharges
     
UnitManager:
    GetOperationTypeName



Here is a list of events that I found that were different; I'm sure there are more.

Spoiler :

Code:
CityLoyaltyChanged
    CityTransfered
    EmergencyStarted
    EmergencyCompleted
    EmergencyRejected
    EmergencyAvailable
    EmergenciesUpdated
    PlayerEraTransitionBegins
    PlayerDarkAgeChanged
    PlayerAgeChanged
    AllianceAvailable
    AllianceEnded
    GovDistrictPolicyUnlocked
    CulturalIdentityCityConverted
    CulturalIdentityConversionOutcomeChanged
    GovernorAssigned
    GovernorAppointed
    GovernorPromoted
    GovernorChanged
    GovernorPointsChanged
    SpyMissionCompleted
 

Attachments

  • ScriptDump.txt
    26.9 KB · Views: 254
Last edited:
For the UI dump, look at the last function listed, and add it in the exclusion table (
listExceptionStr), that will prevent the function to be tested (for subset of function) which lead to a failure for some of them.
 
Ok here is the UI differences that I could find, with the dump attached. Again, I could of missed stuff.

I added "GetNetworkIdentifer" and "GetGovernors" to the ignore for it too work. Though I manually added all the GetGovernor attributes I could find.

Spoiler :
Code:
City:
    GetReligion
        GetReligiousPressureSources
        GetTurnsToNextReligion
    GetAllAssignedGovernors
    GetDistricts
        GetDistrict
            GetAdjacencyYield
            CanAttack
    GetOriginalOwner
    GetLoyaltyAdvice
    GetTrade
        HasTradeRouteFrom
    GetGrowth
        GetAmenitiesFromGovernors
        GetLoyaltyGrowthModifier
        GetAmenitiesFromImprovements
    GetAssignedGovernor
    GetLastTransferType
    GetCulturalIdentity
        IsAlwaysFullyLoyal
        GetLoyaltyPerTurn
        GetTurnsToConversion
        GetLoyaltyPerTurnFromIdentityPressureRatio
        GetLoyalty
        GetIdentitySourcesDetailedBreakdown
            1
                Pressure from nearby [ICON_Citizen] Citizens
            2
                [ICON_Citizen] Citizens living here
            3
                [ICON_Governor] Governor placed here
            4
                Ownership of this city
            5
                Occupation
            6
                Garrisoned unit during Occupation
            7
                Happiness level
            8
                Starvation
            9
                [ICON_TradeRoute] Trade Routes
            10
                Other effects
            11
                Being the original owner of the city
            12
                Being the owner of the city before occupation
            13
                Nearby [ICON_Citizen] Citizens
            14
                Nearby rival [ICON_Citizen] Citizens
            15
                Nearby Diplomat [ICON_Governor] Governor
            16
                Nearby rival Diplomat [ICON_Governor] Governors
        TypeName
        GetMaxLoyalty
        GetIdentitySourcesBreakdown
            1
                PopulationPressure
            2
                Governors
            3
                Happiness
            4
                Other
        GetLoyaltyLevel
        GetCityIdentityPressures
            1
                IdentityPressureTotal
                IdentityPressureFromPopulation
                IdentityPressureFromAges
                CityID
                IdentityPressureFromModifiers
                CityOwner
                IdentityPressureFromOwnership
        GetLoyaltyPerTurnStatus
        GetPlayerIdentitiesInCity
        GetPotentialTransferPlayer
        GetConversionOutcome
        GetGovernorIdentityPressures
             
CombatManager:
    CanAttackTarget
    SimulatePriorityAttackInto
 
Game:
    GetEmergencyManager
    GetGameDiplomacy
    GetEras
    GetHistoryManager
    GetGreatWorkDataFromIndex

GameConfiguration:
    IsPlayByCloud
    SetCloudTurnPlayer
    GetCloudTurnPlayer
    SetRuleSet
    GetRuleSet
    SetToDefaultGameName
    SetToPreGame
    SetGameState
 
GameGetTradeManager:
    CalculateOriginReligiousPressureFromPotentialRoute
    IsRouteAllowed
    CalculateDestinationReligiousPressureFromPotentialRoute
 
InstanceManager:
    ReleaseInstance
    __index
    m_iCount
    ReleaseInstanceByParent
    GetInstance
    m_iAvailableInstances
    m_iAllocatedInstances
    BuildInstance
    ResetInstances
    FindInstanceByControl
    GetAllocatedInstance
    new
    DestroyInstances
 
Map:
    GetContinentPlotsLoyalty

NotificationManager:
    FindType
 
PlayerConfigurations:
    IsHumanRequired
 
Players:
    GetDiplomacy
        GetAllianceTurnsUntilExpiration
        GetAllianceLevel
        GetAlliancePointsTooltip
        GetAlliancePointsPerTurn
        CanLiberateCityTo
        GetSourceTurnsRemaining
        GetAllianceType
        GetAllianceTurnsToNextLevel
        GetDeclaredFriendshipTurn
        GetAllianceTurnsThisLevel
    GetCulture
        GetPolicyToUnlock
        GetAnarchyEndTurn
    GetStats
        GetNumBuildingsOfType
    IsFreeCities
    GetUnits
        GetFirstReadyUnit
            GetAntiAirCombat
            IsCannotAttack
            GetFormationMaxMoves
            GetRangedCombat
            IsDelayedDeath
            GetBarbarianTribeIndex
            GetBarbarianTargetPlayer
            GetOwner
            GetFormationUnitCount
            GetReligiousStrength
            GetMovementMovesRemaining
            IsEmbarked
            TypeName
            GetAirUnits
            GetName
            GetOriginalOwner
            HasMovedIntoZOC
            __instances
                userdata: 0000000129F75B30
                    __instance
                userdata: 0000000129F75C58
                    f
                    __instance
            GetExperience
                HasPromotion
                __instances
                    userdata: 0000000129F75C58
                        f
                        __instance
                GetExperienceForNextLevel
                GetExperiencePoints
                GetVeteranName
                GetUnit
                GetLevel
                TypeName
                GetPromotions
            GetRange
            GetUpgradeCost
            GetPursuingSpyName
            IsDead
            GetLootName
            GetGreatWorkIndex
            GetDamage
            GetX
            GetUnitType
            GetSpyOperation
            GetTrade
                GetLastOriginTradeCityComponentID
                    type
                    player
                    id
                GetLastDestinationTradeCityComponentID
                    type
                    player
                    id
                TypeName
                __instances
                    userdata: 0000000129F75CB8
                        f
                        __instance
            GetArchaeologyHomeCity
            GetSpyOperationEndTurn
            GetFortifyTurns
            GetReligionType
            GetMilitaryFormation
            HasHiddenVisibility
            GetFormationID
            IsReadyToMove
            GetFormationClass
            GetReligiousHealCharges
            GetFormationMovesRemaining
            GetID
            GetMaxDamage
            IgnoresZOC
            GetMovesRemaining
            GetSpreadCharges
            GetPlotId
            GetMaxMoves
            GetAttacksRemaining
            IsReadyToAutomate
            GetGreatPerson
                GetActivationHighlightPlots
                    f
                    __instance
                GetPassiveNameText
                __instances
                    userdata: 0000000129F75C90
                IsGreatPerson
                GetUnit
                GetActionCharges
                GetClass
                GetPassiveEffectText
                HasPassiveEffect
                GetIndividual
                TypeName
                GetAreaHighlightPlots
            IsAutomated
            GetLocation
                x
                y
            GetY
            GetBombardCombat
            GetComponentID
                type
                player
                id
            GetBuildCharges
            GetCombat
            GetAirSlots
            IsReadyToSelect
            IsHuman
            HasPendingOperations
    GetGovernors
        CanEarnPromotion
        CanAssignGovernor
        HasGovernor
        GetGovernorPointsSpent
        GetGovernorPoints
        CanPromote
        GetBaseTurnsUntilEstablished
        GetGovernorList
        GetAssignedCity
        GetAssignedGovernor

Plot:
    GetArea
        HasNoFlatCoast
        GetTotalResources
        __instances
        GetTotalNaturalWonders
        IsWater
        GetImprovementCount
        IsNone
        GetPlotCount
        GetID
        GetRiverEdgeCount
        IsMountains
        GetResourceCount
        GetTotalImprovements
        TypeName
        IsCanyons
    GetNearestLandPlot
        GetImprovementOwner
        IsWOfCliff
        GetAreaID
        IsHills
        IsAt
        GetAdjacencyBonusType
        IsFreshWater
        IsWonderComplete
        GetContinentType
        IsWater
        IsNWOfCliff
        IsMountain
        GetX
        GetRouteType
        IsUnit
        GetAirUnits
        GetIndex
        GetWorkerCount
        IsRiverSide
        IsCoastalLand
        IsOwned
        GetDistrictID
        HasFeatureBeenAdded
        IsRiverCrossingFlowClockwise
        IsImpassable
        IsLake
        GetOwner
        GetRiverEFlowDirection
        SetProperty
        IsRoughGround
        GetResourceType
        GetRiverSEFlowDirection
        GetFeature
            GetDirection
            GetType
            TypeName
        GetProperty
        IsValidFoundLocation
        CanHaveWonder
        IsNationalPark
        GetYield
        IsStartingPlot
        IsCanyon
        IsNWOfRiver
        GetAdjacencyBonusTooltip
        GetNationalParkName
        IsRiverCrossing
        IsRoute
        CanHaveDistrict
        GetTerrainType
        GetAdjacencyYield
        IsRoutePillaged
        IsAdjacentPlayer
        IsNaturalWonder
        IsNEOfRiver
        GetResourceCount
        GetDefenseModifier
        GetMovementCost
        GetRiverSWFlowDirection
        GetResourceTypeHash
        TypeName
        IsAdjacentOwned
        IsWOfRiver
        GetNearestLandPlot
        GetRiverCrossingCount
        GetNearestLandArea
            HasNoFlatCoast
            GetTotalResources
            GetTotalNaturalWonders
            IsWater
            GetImprovementCount
            IsNone
            GetPlotCount
            GetID
            GetRiverEdgeCount
            IsMountains
            GetResourceCount
            GetTotalImprovements
            TypeName
            IsCanyons
        GetArea
        IsRiverConnection
        IsRiverCrossingToPlot
        SharesAdjacentArea
        IsAdjacentToArea
        IsRiverAdjacent
        IsNEOfCliff
        IsCity
        GetDistrictType
        IsAdjacentToShallowWater
        IsAdjacentToLand
        GetWonderType
        IsInternalOnlyDistrict
        IsImprovementPillaged
        GetUnitCount
        GetImprovementType
        GetY
        IsFlatlands
        IsChokepoint
        GetFeatureType
        IsNone
        IsRiver
        GetAppeal
        IsOpenGround
        SetOwner
 
UnitManager:
    GetUnitArmyMaintenance
    GetUnitMaintenance
    GetUnitCorpsMaintenance
     
UserConfiguration
    IsCityRangeAttackTurnBlocking
 

Attachments

  • UIDump.txt
    40.3 KB · Views: 291
In case anyone else was wondering. It's possible to be able to communicate between the Gameplay scripts and the UI scripts, so it's possible to execute UI commands from Gameplay and vice versa.

The method I'm using may not be the only one, and won't suffice for all use cases, but at least it works. If anyone knows of any better way let me know

Both scripts in Gameplay and UI can access the ExposedMembers table. You can add new items to it and read out of it from both contexts
So you can write to it from Gameplay and then later on read out of it from UI and use that to execute UI methods etc.

Not sure yet if it's possible to force the other context to immediately execute stuff, maybe there's a way through events?
 
Yes, I also use ExposedMembers to share tables and function between context, and you can use (custom or not) lua events to execute stuff in all contexts.

Can't post example from my phone, but I'm using it a lot in the mods in my sig, and there are one or two threads discussing it (maybe it's in the current thread too) , I'll try to link them when back on my PC if you've not found them before.
 
Been experimenting more with allowing units to move through lua. It turns out it's actually possible to directly control units without the double move issues.
There's two key points necessary which I missed last time:
- The code needs to be executed on the GameEvents.PlayerTurnStartComplete event. PlayerTurnStarted didn't work for me
- You need to manually reduce the moves remaining. These lines work for me:
UnitManager.MoveUnit(unit,x,y);
UnitManager.FinishMoves(unit);
UnitManager.ChangeMovesRemaining(unit,-(unit:GetMovesRemaining()));

Unfortunately I can't seem to find a way to do other actions using this system. Being able to attack is pretty important..



I've tried a second route too: moving all of my code over to the UI context to try to use the same methods as the game UI uses to allow humans to move units around. However I can't seem to get this to work, it seems to either not work at all or very inconsistently.
This is the code I'm using now, based on Civ6Common.luas RequestMoveOperation, if anyone has any ideas how to get this to work that would be a lifesaver.

Spoiler :

local params = {};
params[UnitOperationTypes.PARAM_MODIFIERS] = UnitOperationMoveModifiers.ATTACK;
params[UnitOperationTypes.PARAM_X] = newx;
params[UnitOperationTypes.PARAM_Y] = newy;

if (UnitManager.CanStartOperation( unit, UnitOperationTypes.MOVE_TO, nil, params) ) then
print("This says we can move, but it still doesn't do anything");
end

UnitManager.RequestOperation( unit, UnitOperationTypes.MOVE_TO, params);



Now besides these direct controls, there's actually a third way of ordering units around, but it's rather convoluted. It abuses StartScriptedOperationWithTargetAndRally and AddUnitToScriptedOperation to make a unique operation for a single unit with a target, then executes it and discards it next turn.
To actually use this, you need to make your own operation and accompanying behaviortree. I've got the basics working, but it probably needs some refinement, will share later if I end up using this method.
Unfortunately this method still means the inbuild AI is making some of the decisions, it's also the most complex, hardest to debug and performance wise the worst.
But, unless the other two methods can be made to fully work, it's the only way to actually both control movement and attacks right now.



Out of the three, the UI method would be the most promising, if it would actually work..
 
I uploaded the log for Scripts. The UI one was getting errors so I might mess around and see what I find later not sure if you know Gedemon? I looked through and picked out all the differences, it is possible I missed some.

Spoiler :

Code:
City:
    ChangeLoyalty
    GetOriginalOwner
 
CombatManager:
    CanAttackTarget
    SimulatePriorityAttackInto

DealManager:
    RequestUpdate

Game:
    GetGameDiplomacy
    ChangePlayerEraScore

Notification Manger:
    FindType

Players:
    GetStats:
        GetNumMyCitiesFollowingSpecificReligion
        GetNumDistrictsFollowingReligion
        GetNumForeignCitiesFollowingReligion
        GetNumForeignFollowers
        TypeName
        GetNumFollowers
        GetNumCitiesFollowingReligion
        GetNumBeliefsInReligion
    GetCulture:
        GetPolicyToUnlock
    GetReligion:
        GetReligionTypeCreated
        ChangeNumBeliefsEarned
    GetAi_Military:
        SetRival
        StartScriptedOperationWithTargetAndRally
        ScriptForceUpdateTargets
        StartScriptedOperation
        SetScriptedTargetAndRally
        SetScriptedOperationReady
        AddUnitToScriptedOperation
    GetAi_Religion:
        SetFavoredReligion
        TypeName
    GetGovernors:
        GetGovernorPoints
        TypeName
        GetGovernorPointsSpent
        ChangeGovernorPoints
     
Plot:
    IsInternalOnlyDistrict
    IsImprovementPillaged
    GetImprovementOwner
    GetAdjacencyYield
    GetNationalParkName
    CanHaveDistrict
    GetAdjacencyBonusType
    IsNationalPark
    IsValidFoundLocation
    CanHaveWonder
    GetAppeal
    GetFeature: (was GetFeatureType)
        GetDirection
        GetType
    GetDefenseModifier
    GetMovementCost
    GetAdjacencyBonusTooltip
    IsChokepoint
    GetAirUnits
    GetNearestLandPlot:
        GetDistrictID
        IsInternalOnlyDistrict
        IsImprovementPillaged
        GetImprovementOwner
        GetAdjacencyYield
        GetNationalParkName
        CanHaveDistrict
        GetAdjacencyBonusType
        IsNationalPark
        IsValidFoundLocation
        CanHaveWonder
        GetAppeal
        GetFeature: (was GetFeatureType)
            GetDirection
            GetType
            TypeName
        GetDefenseModifier
        GetMovementCost
        GetAdjacencyBonusTooltip
        IsChokepoint
        GetWorkerCount
        GetAirUnits
        IsWonderComplete
        HasFeatureBeenAdded
    IsWonderComplete
    HasFeatureBeenAdded
 
Unit:
    GetReligion:
        ChangeReligiousHealCharges
        GetReligiousHealCharges
     
UnitManager:
    GetOperationTypeName



Here is a list of events that I found that were different; I'm sure there are more.

Spoiler :

Code:
CityLoyaltyChanged
    CityTransfered
    EmergencyStarted
    EmergencyCompleted
    EmergencyRejected
    EmergencyAvailable
    EmergenciesUpdated
    PlayerEraTransitionBegins
    PlayerDarkAgeChanged
    PlayerAgeChanged
    AllianceAvailable
    AllianceEnded
    GovDistrictPolicyUnlocked
    CulturalIdentityCityConverted
    CulturalIdentityConversionOutcomeChanged
    GovernorAssigned
    GovernorAppointed
    GovernorPromoted
    GovernorChanged
    GovernorPointsChanged
    SpyMissionCompleted
Plot:GetFeature() is also valid in vanilla but only appears to be used in the WorldBuilder Editor file. It appears to return an object table of info relating to the feature.

Plot:GetFeatureType() is also valid in vanilla and merely returns the "ID" number for the type of feature (or -1 when the plot has no feature).
 
Been experimenting more with allowing units to move through lua. It turns out it's actually possible to directly control units without the double move issues.
There's two key points necessary which I missed last time:
- The code needs to be executed on the GameEvents.PlayerTurnStartComplete event. PlayerTurnStarted didn't work for me
- You need to manually reduce the moves remaining. These lines work for me:


Unfortunately I can't seem to find a way to do other actions using this system. Being able to attack is pretty important..



I've tried a second route too: moving all of my code over to the UI context to try to use the same methods as the game UI uses to allow humans to move units around. However I can't seem to get this to work, it seems to either not work at all or very inconsistently.
This is the code I'm using now, based on Civ6Common.luas RequestMoveOperation, if anyone has any ideas how to get this to work that would be a lifesaver.

Spoiler :

local params = {};
params[UnitOperationTypes.PARAM_MODIFIERS] = UnitOperationMoveModifiers.ATTACK;
params[UnitOperationTypes.PARAM_X] = newx;
params[UnitOperationTypes.PARAM_Y] = newy;

if (UnitManager.CanStartOperation( unit, UnitOperationTypes.MOVE_TO, nil, params) ) then
print("This says we can move, but it still doesn't do anything");
end

UnitManager.RequestOperation( unit, UnitOperationTypes.MOVE_TO, params);



Now besides these direct controls, there's actually a third way of ordering units around, but it's rather convoluted. It abuses StartScriptedOperationWithTargetAndRally and AddUnitToScriptedOperation to make a unique operation for a single unit with a target, then executes it and discards it next turn.
To actually use this, you need to make your own operation and accompanying behaviortree. I've got the basics working, but it probably needs some refinement, will share later if I end up using this method.
Unfortunately this method still means the inbuild AI is making some of the decisions, it's also the most complex, hardest to debug and performance wise the worst.
But, unless the other two methods can be made to fully work, it's the only way to actually both control movement and attacks right now.



Out of the three, the UI method would be the most promising, if it would actually work..
Thanks, I had done similer tests with GameEvents.PlayerTurnStarted and PlayerTurnActivated (and failed to get consistent results) but did not try with GameEvents.PlayerTurnStartComplete !

what if you remove the unit's moves left on PlayerTurnStartComplete (to prevent the AI from using it), then try to restore the move and use the UI code later during the AI turn ? (maybe tricky to get an event firing at the correct time)
 
Top Bottom