I'm currently working on improving the UI for my mod using Chili.
I have a synced gadget that maintains a queue of actions that can only be run in sequential order during gameplay. This queue is currently stored as a table (of subtables). I want to display this queue via Chili labels. I have the Chili framework set up and prepared to update.
My roadblock is that I can't seem to get the information past the synced/unsynced barrier. I've managed to do this with within the same gadget before, but this is communication from a synced gadget->widget and the data I'm sending is more complex than a single variable.
Does anybody know how I can pass this information?
function gadget:GetInfo() return { name = "Gundam scoring", desc = "sets high score for players", author = "Smoth", date = "(9/3/2001", license = "PD", layer = 0, enabled = true } end
-------------------------------------------------------------------------------------------------- -- Special thanks to jk, jools and fatcontroller for data that I needed --------------------------------------------------------------------------------------------------
local GetTeamList = Spring.GetTeamList local GetTeamInfo = Spring.GetTeamInfo local AreTeamsAllied = Spring.AreTeamsAllied local Echo = Spring.Echo
-- vanity numbers local playerScores = {} local playerKills = {} local playerUnitKills = {} local playerDeaths = {} local playerDamageTaken = {} local playerDamageDealt = {}
-- for experience system local playerExperience = {} local playerLevelRank = {}
local levels = VFS.Include("gamedata/ranks.lua")
-- store values for player ranks local rankList = {}
local playerLeadKills = 0 local playerLeadID = 0
local showScoresOnce = true local startRank = 1
if (gadgetHandler:IsSyncedCode()) then -- BEGIN SYNCED function gadget:UnitDamaged(unitID, unitDefID, teamID, damage, paralyzer, weaponID, attackerID, attackerDefID, attackerTeamID) if (teamID and attackerTeamID)then isNotAlliedUnit = not AreTeamsAllied(teamID,attackerTeamID) if (unitID and attackerID and unitID ~= attackerID and (isNotAlliedUnit)) then playerDamageTaken[teamID] = playerDamageTaken[teamID] + math.floor(damage) playerDamageDealt[attackerTeamID] = playerDamageDealt[attackerTeamID] + math.floor(damage) end end end
function gadget:UnitDestroyed(unitID, unitDefID, teamID, attackerID, attackerDefID, attackerTeamID) if (teamID and attackerTeamID)then isNotAlliedUnit = not AreTeamsAllied(teamID,attackerTeamID)
if (unitID and attackerID and unitID ~= attackerID and (isNotAlliedUnit)) then table.insert(playerUnitKills, {unitDefID = 1}) playerKills[attackerTeamID] = playerKills[attackerTeamID]+1 playerDeaths[teamID] = playerDeaths[teamID]+1
if (playerKills[attackerTeamID] > playerLeadKills) then playerLeadKills = playerKills[attackerTeamID]
if (attackerTeamID ~= playerLeadID) then playerLeadID = attackerTeamID -- set top player ID end end
-- if we have exceded the experience required for the next rank -- bump our level --Spring.Echo(playerLevelRank[attackerTeamID]+1, -- levels[playerLevelRank[attackerTeamID]+1].xp, -- playerExperience[attackerTeamID])
--avoid null errors if (playerLevelRank[attackerTeamID])then local level = playerLevelRank[attackerTeamID] level = tonumber(level) --Spring.Echo("currentlevel:", level, levels[level].xp, playerExperience[attackerTeamID]) if (levels[level].xp <= playerExperience[attackerTeamID] ) then -- we have reached a level up, have we -- possibly gained enough xp to exceed the current level?
while (levels[level].xp <= playerExperience[attackerTeamID])do level = level +1 --Spring.Echo(level, levels[level].xp, playerExperience[attackerTeamID]) end
--Spring.Echo("new level:", level) playerLevelRank[attackerTeamID] = level - 1 --Spring.Echo("Level up!", levels[playerLevelRank[attackerTeamID]+1].xp) end end end -- Spring.Echo("PassScores",attackerTeamID, -- "playerScores[team]", playerScores[attackerTeamID], -- "playerExperience[team]", playerExperience[attackerTeamID], -- "playerLevelRank[team]", playerLevelRank[attackerTeamID]) SendToUnsynced("PassScores",attackerTeamID, playerScores[attackerTeamID], playerExperience[attackerTeamID], playerLevelRank[attackerTeamID]) end end end
function gadget:Initialize() GG.playerScores = playerScores _G.playerScores = playerScores
playerExperience[team] = 0 playerLevelRank[team] = startRank end end
function gadget:RecvLuaMsg(msg, playerID) if msg:sub(1,12) == 'playerchange' then msg = tonumber(msg:sub(13))
--Spring.Echo("PassScores",msg, -- playerScores[msg], -- playerExperience[msg], -- playerLevelRank[msg]) SendToUnsynced("PassScores",msg, playerScores[msg], playerExperience[msg], playerLevelRank[msg]) end end
function gadget:GameFrame(gameFrame) if gameOver then return end
if gameFrame % 30 < 0.1 then for team, points in pairs (playerScores) do -- Spring.Echo("PassStats",team, -- "playerKills[team]", playerKills[team], -- "playerDeaths[team]", playerDeaths[team], -- "playerDamageTaken[team]", playerDamageTaken[team], -- "playerDamageDealt[team]", playerDamageDealt[team])
-- SendToUnsynced("PassStats",team, -- playerKills[team], -- playerDeaths[team], -- playerDamageTaken[team], -- playerDamageDealt[team]) end end end -- END SYNCED else -- BEGIN UNSYNCED
local function POSToLuaUIScores(_,team, score, experience, rank) if (Script.LuaUI('PassScores')) then Script.LuaUI.PassScores(team, score, experience, rank) end end
local function POSToLuaUIStats(_,team, kills, deaths, damageTaken, damageDealt) if (Script.LuaUI('PassStats')) then Script.LuaUI.PassStats(team, kills, deaths, damageTaken, damageDealt) end end
function gadget:Initialize() gadgetHandler:AddSyncAction('PassStats',POSToLuaUIStats) gadgetHandler:AddSyncAction('PassScores',POSToLuaUIScores) end -- END UNSYNCED end
Code:
function widget:GetInfo() return { name = "Chili score Bars", desc = "", author = "Smoth", date = "2011", license = "PD", layer = 10, experimental = false, enabled = true } end
-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- local Chili -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- local levels = VFS.Include("gamedata/ranks.lua") local white_argb = WG.colors["white_argb"]
local scoreBarTip = "\n" .. white_argb .. " Just your player score, no game value, just for fun :) " local rankBarTip = "\n" .. white_argb .. " Experience to the next level"
local col_metal = {136/255,214/255,251/255,1} local col_energy = {1,1,0,1}
function widget:Update(s) if ( WG.uiElementRegistry["scorebar"] == true) then --Spring.Echo('playerchange' .. WG.myTeamID) Spring.SendLuaRulesMsg('playerchange' .. WG.myTeamID)
Seeing this now I realize how close I was. My issue was that I never tried passing to Unsynced before sending to the Widget. I managed to come up with something funky using Spring.SendLuaUIMsg and a lot of string parsing, but I think this is a much cleaner solution (and requires less procsessing).
To summarize for anybody else checking the thread:
Gadget: [*]Send function from Synced -> Unsynced in the same gadget [*]Script.LuaUI.myFunc(values) to pass to widget
Code:
--Synced
local function SomeOtherFuction () ... SendToUnsynced("PassScores",msg, playerScores[msg], playerExperience[msg], playerLevelRank[msg]) ... end
--Unsynced
local function POSToLuaUIScores(_,team, score, experience, rank) if (Script.LuaUI('PassScores')) then Script.LuaUI.PassScores(team, score, experience, rank) end end
function gadget:Initialize() gadgetHandler:AddSyncAction('PassScores',POSToLuaUIScores) end
Widget: [*]Create a function to handle the inputs [*]RegisterGlobal the incoming function
Code:
function widget:Initalize() widgetHandler:RegisterGlobal("PassScores", PassScores) ... end
function PassScores(team, score, experience, rank) if (team == WG.myTeamID) then --Use values as desired end end
Nerris, your summary post was incredibly helpful to me. That should definitely go on the wiki somewhere. However, I've discovered that sending tables is slightly more complex. Hopefully someone will benefit from what took me days to figure out:
Since SendToUnsynced doesn't accept tables, you have to use _G and SYNCED as mentioned in this wiki article: Lua sync to unsync. Additionally, before sending SYNCED.SomeTable to the widget via Script.LuaUI.SomeFunction, it must be duplicated using spairs, as also shown in that wiki article (reason: viewtopic.php?f=23&t=25510&p=477787#p477787). Then, the duplicated table can be passed to Script.LuaUI.SomeFunction like any other argument.
Yes, I've used this post as well recently myself. The problem with tables can possibly be done with a trick with savetable.lua (you can probably find it in the forums and many mods, but here it is).
So what I do is I pack my stuff in a table before sending it, and unpack it after, like:
Users browsing this forum: No registered users and 1 guest
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum