pPlayer:GetUnits() table not updating on certain events (lua)

TC_

Chieftain
Joined
Jul 8, 2017
Messages
77
Hey guys,

My mod needs to iterate through the current player units table each time a unit is added or removed from the game. However, it seems that table is not updating on certain events. The problems I can currently identify are:
-When a unit is removed from the game due to using it's last charge
-When a unit is removed from the game when combining that unit into a corps or armada

I have tested this a few different ways, but those units simply aren't being removed from the player unit table until the following turn. I have ran iterations through the unit table by hooking into UnitRemovedFromMap, UnitOperationCleared, UnitFormCorps and UnitFormArmy. The unit in question still exists in the table after each of these.

As a note, the unit table IS immediately updated in gameplay context upon losing a unit to combat, deleting a unit, and creating a unit. Also, the UnitRemovedFromMap event IS being called when using up the charges on a unit, so it seems the player unit table isn't updated directly from there.

Another observation - the updates work immediately in the UI context - just not in gameplay. When I use up a unit with charges, or combine a unit into a formation, my UI elements update immediately. The function used for counting units in the UI context is identical to the one I am using in the gameplay version.

So, my questions:
Has anyone else experienced this issue?
Is there a way to force an update of a player's unit table in gameplay context?
If not, and no other solution is apparent, can I pull data from UI context into Gameplay lua?

Thanks in advance
 
Dead Units often still show in the list of units seen in Player:GetUnits()

This has been true from the initial release of the game.

In order to sort out units that are no longer valid simply do as
Code:
local pUnits = pPlayer:GetUnits()
for i,pUnit in pUnits:Members() do
    if (pUnit:IsDead() == false) and (pUnit:IsDelayedDeath() == false) then
         -- do stuff for the unit
    end
end
The reason that Delayed Death units and dead units still show as being part of the GetUnits() list is that on the Gameplay Scripts side of the lua engine, certain hook events fire before a "killed off" unit is actually removed within the game's core operating system so the querry to the InGame side of the gamecore returns these units that have not completely been handled for the removal from the game. The various hook events that trigger based on a unit removal from the game fire in a specific order each time a unit is removed (or added) for any reason, and some of these hook events fire before the unit is completely removed from the game on purpose.

The GetUnits() table is never updated by anything done from an lua hook event. It is updated in the Gameplay Processing Core and then this data is sent out to any lua script that requests the list of units via the Player:GetUnits() method . You cannot therefore "force" GetUnits() to update by anything you do in an lua script. The User Interface panel where you can click on "delete unit" does not actually remove the unit from the game -- it sends a request to the gamecore to delete the unit. The same is true of a Gameplay script which makes use of
Code:
pPlayer:GetUnits():Destroy(pUnit)
The lua script does not remove the unit nor directly cause the update of the GetUnits() table -- it sends a request to the gameplay processing thread of the gamecore to delete the unit. In both cases however the deleted unit would likely still be showing in a previously-cached table of units retrieved from the GetUnits() function.

User Interface contexts do not usually appear to reflect these issues because it is a different game processing-thread and is updated from the current gameplay state when the User Interface script executes based on a hook trigger. User Interface scripts however sometimes lag behind the actual gameplay state of the game and are not always instantly updated -- this is one of the reasons why a city panel will sometimes show wrong information until the human user switches from the current city to some other city and then back again. The User Interface lua context has to request or be sent an update from the actual gameplay state. This update of data sent from the gameplay state to the User Interface context is not anything you can access or control -- it is done automatically at the C++ level of the game's operating code.
 
Last edited:
  • Like
Reactions: TC_
The IsDead and IsDelayedDeath checks worked perfectly, thank you as always LeeS. And extra thanks for the in depth explanation.
 
Top Bottom