As some of you may know, there are no functions to pull a character id from a portrait index. With a bit of hacking, you can work around this. A caveat is that it won't work if multiple characters have the same name
, but nobody would be that unoriginal, right?
First, as always, you have to click a portrait before you can retrieve a character id - data won't be stored in the characters table until you do this. So far, this is the fastest way I've figured out to pull all the character data, which takes about 120ms for me - I suggest pairing with "if (e:GetActiveEngine() == worldScreen)".
local numchars = Infinity_GetNumCharacters() - 1
for i=0,numchars do
This "quickly" switches the screen to the options screen, clicks all portraits, then switches back to the world screen. By switching away from the world screen (or the map screen), clicking a portrait will not change the selection nor cause character reaction quotes. It takes about 20ms to switch to the world screen, then about 10-20ms per portrait click. Switching to the options screen takes 0ms.
This is obviously unreasonable to do constantly (causes framerate hitches), and only the "currently selected character" will have their data updated with Infinity_UpdateLuaStats() (but you can use this to constantly (like, once a second, not every frame) update the current character without much lag). I like to have all the characters' info update when I pause, personally.
Once you have figured out however you want to populate the characters table, you can then match portraits to ids. It's pretty simple: you can get a portrait's character name, by portrait index, by retrieving the portrait tooltip, then match it to the characters table. The tooltip displays "characterName\nhp/maxHp", so by getting the part before the \n, you can grab their name, then retrieve the name field for each entry in the characters table and match it.
if (not index) then return end
local tt = Infinity_GetPortraitTooltip(index)
local charaName = tt:match("(.*)\n")
if (type(name) == "number") then name = getCharacterName(name) end
for id,data in pairs(characters) do
if data.name == name then
data = characters[getCharacterKey(0)]
-- You can also use Infinity_GetSelectedCharacterName() to get the currently selected character's name
data = characters[getCharacterKey(Infinity_GetSelectedCharacterName())]
-- You can view all fields with table printing code (look some up), but for a simple 'get all categories' you can use:
-- for _,d in pairs(characters) do for key,val in pairs(d) do Infinity_Log(key) end break end
As a little personal project, I made little XP bars on the portrait interface (although they only update if I click to the character or pause the game), but you can probably come up with more creative solutions. Some examples are custom GUI elements or buttons based on the current character's class (characters[x].class), alternate health bars (characters[x].HP.(current/max)), displaying number of inventory slots free (characters[x].equipment.<slots>.empty), priest/mage spell data (characters[x].(priest/mage)Spells)...