ccpalyer Posted January 14, 2022 Share Posted January 14, 2022 Hi, guys, I want to add a text widgets to show the exp of a character made by another author. Here is the define of the character's exp and expmax local common_postinit = function(inst) ...... inst:AddTag("sora") inst.soraexp = net_int(inst.GUID, "sora_exp", "soraexpdirty") inst.soraexpmax = net_int(inst.GUID, "sora_expmax", "soraexpdirty") ....... end Here is my code scripts/widgets/sora_exp_title.lua local Widget = require "widgets/widget" local Text = require "widgets/text" local SoraExpTitle = Class(Widget, function(self, owner) Widget._ctor(self, "SoraExpTitle") self.soraexptitle = self:AddChild(Text(BODYTEXTFONT, 30)) owner:ListenForEvent("soraexpdirty", function(owner, data) self.exp = owner.soraexp:value() self.maxexp = owner.soraexpmax:value() end) self:StartUpdating() end) function SoraExpTitle:OnUpdate(dt) local str = self.exp.." / "..self.maxexp self.soraexptitle:SetString(str) end return SoraExpTitle modmain.lua local soraexptitle = GLOBAL.require("widgets/sora_exp_title") AddClassPostConstruct("widgets/controls", function(self) if not self.owner:HasTag("sora") then return end self.title = self:AddChild(soraexptitle(self.owner)) self.title:SetHAnchor(0) self.title:SetVAnchor(1) self.title:SetPosition(70,-50,0) end) The question is when i first enter the game, everything is ok, but when game reload(whether quit or not quit the game), the widgets show wrong value of the exp. It seems that there is a problem with the data synchronization of the network variables. Here are some of my findings 1. I make a healer prefab, when i use it, it always works well local function showExp(inst, target) if target ~= nil then if target:HasTag("sora") then TheNet:Say(target.soraexp:value() .. ' / ' .. target.soraexpmax:value()) end end end --------------------------------------- ······ inst:AddComponent("healer") inst.components.healer.health = 0 inst.components.healer.Heal = showExp ······· return Prefab("sora_exp_show", fn, assets, prefabs) (It seems that true value is normal on the server, but the client is only valid when you first enter the game) 2. Another place store experience TheWorld.components.soraexpsave.exps[userid] It's not a netvar type, i don't know how to listen to the change of this table and get its value in widgets. Some code about the character's exp -- store/restore the exp when game save/reload local soraexpsave = Class(function(self, inst) self.inst = inst self.exps={} end) function soraexpsave:SetExp(userid,setexp) self.exps[userid] = setexp end function soraexpsave:GetExp(userid) return userid and self.exps[userid] and math.max(0,self.exps[userid]-1000) or -1 end function soraexpsave:OnSave() return {exps=self.exps} or { a =1} end function soraexpsave:OnLoad(data) if data then self.exps = data.exps or {} end end return soraexpsave local function OnSoraSpawn(inst) local first = true if TheWorld.components.soraexpsave then local saveexp = TheWorld.components.soraexpsave:GetExp(inst.userid) first = saveexp == -1 if saveexp > 0 then inst:GetExp(saveexp) end end end set exp local function GetExp(inst, num, code, dmaxexp, once) inst.soraexp:set(math.max(0, inst.soraexp:value() + num)) if inst.soralevel:value() < 30 and inst.soraexp:value() >= expfornextlev(inst.soralevel:value()) or num <= 0 then applyupgrades(inst, true) end inst.soraexpget = inst.soraexpget + num if inst.soraexpget > 1000 then inst.soraexpget = 0 applyupgrades(inst, true) end TheWorld.components.soraexpsave:SetExp(inst.userid, inst.soraexp:value()) end Is there any way to solving the above problem? Please help, thanks~ Link to comment https://forums.kleientertainment.com/forums/topic/136899-why-i-cant-get-the-true-value-of-netvar/ Share on other sites More sharing options...
Monti18 Posted January 14, 2022 Share Posted January 14, 2022 If I remember correctly, this happens because you have the ListenForEvent in the construction of the widget with owner as the instance. I think somehow this instance of the owner can change so that it isn't able to listen to events. I think you can fix this by adding the ListenForEvent in the AddClassPostConstruct: Spoiler local soraexptitle = GLOBAL.require("widgets/sora_exp_title") AddClassPostConstruct("widgets/controls", function(self) if not self.owner:HasTag("sora") then return end self.title = self:AddChild(soraexptitle(self.owner)) self.title:SetHAnchor(0) self.title:SetVAnchor(1) self.title:SetPosition(70,-50,0) self.owner:ListenForEvent("soraexpdirty", function(owner, data) self.exp = owner.soraexp:value() self.maxexp = owner.soraexpmax:value() end) end) Link to comment https://forums.kleientertainment.com/forums/topic/136899-why-i-cant-get-the-true-value-of-netvar/#findComment-1532586 Share on other sites More sharing options...
ccpalyer Posted January 14, 2022 Author Share Posted January 14, 2022 (edited) 1 hour ago, Monti18 said: If I remember correctly, this happens because you have the ListenForEvent in the construction of the widget with owner as the instance. I think somehow this instance of the owner can change so that it isn't able to listen to events. I think you can fix this by adding the ListenForEvent in the AddClassPostConstruct: Hide contents local soraexptitle = GLOBAL.require("widgets/sora_exp_title") AddClassPostConstruct("widgets/controls", function(self) if not self.owner:HasTag("sora") then return end self.title = self:AddChild(soraexptitle(self.owner)) self.title:SetHAnchor(0) self.title:SetVAnchor(1) self.title:SetPosition(70,-50,0) self.owner:ListenForEvent("soraexpdirty", function(owner, data) self.exp = owner.soraexp:value() self.maxexp = owner.soraexpmax:value() end) end) thanks for your answer , I tried, It shows up correctly when I enter the game and do nothing, but when my exp changes(like do work pick, character will increase 2 exp), the exp shows up incorrectly again. It's really weird. my code local soraexptitle = GLOBAL.require("widgets/sora_exp_title") AddClassPostConstruct("widgets/controls", function(self) if not self.owner:HasTag("sora") then return end self.title = self:AddChild(soraexptitle(self.owner)) self.title:SetHAnchor(0) self.title:SetVAnchor(1) self.title:SetPosition(70,-50,0) self.owner:ListenForEvent("soraexpdirty", function(owner,data) owner.exp = owner.soraexp:value() owner.maxexp = owner.soraexpmax:value() end) end) local Widget = require "widgets/widget" local Text = require "widgets/text" local SoraExpTitle = Class(Widget, function(self, owner) Widget._ctor(self, "SoraExpTitle") self.soraexptitle = self:AddChild(Text(BODYTEXTFONT, 30)) self.owner = owner self:StartUpdating() end) function SoraExpTitle:OnUpdate(dt) self.owner.exp = self.owner.exp and self.owner.exp or '-' self.owner.maxexp = self.owner.maxexp and self.owner.maxexp or '-' local str = self.owner.exp.." / "..self.owner.maxexp self.soraexptitle:SetString(str) return end return SoraExpTitle Is it possible for the author to add some monitoring? I checked all the code related to exp, but I found no sign of doing so. Edited January 14, 2022 by ccpalyer Link to comment https://forums.kleientertainment.com/forums/topic/136899-why-i-cant-get-the-true-value-of-netvar/#findComment-1532600 Share on other sites More sharing options...
Monti18 Posted January 14, 2022 Share Posted January 14, 2022 Try replacing your widget with this: Spoiler local Widget = require "widgets/widget" local Text = require "widgets/text" local SoraExpTitle = Class(Widget, function(self, owner) Widget._ctor(self, "SoraExpTitle") self.soraexptitle = self:AddChild(Text(BODYTEXTFONT, 30)) self.inst:ListenForEvent("soraexpdirty", function(owner, data) self.exp = owner.soraexp:value() self.maxexp = owner.soraexpmax:value() end,owner) self:StartUpdating() end) function SoraExpTitle:OnUpdate(dt) local str = self.exp.." / "..self.maxexp self.soraexptitle:SetString(str) end The ListenForEvent is written with the owner added at the end, which makes a difference as to how it is called. Link to comment https://forums.kleientertainment.com/forums/topic/136899-why-i-cant-get-the-true-value-of-netvar/#findComment-1532617 Share on other sites More sharing options...
ccpalyer Posted January 17, 2022 Author Share Posted January 17, 2022 On 1/14/2022 at 9:09 PM, Monti18 said: Try replacing your widget with this: Reveal hidden contents local Widget = require "widgets/widget" local Text = require "widgets/text" local SoraExpTitle = Class(Widget, function(self, owner) Widget._ctor(self, "SoraExpTitle") self.soraexptitle = self:AddChild(Text(BODYTEXTFONT, 30)) self.inst:ListenForEvent("soraexpdirty", function(owner, data) self.exp = owner.soraexp:value() self.maxexp = owner.soraexpmax:value() end,owner) self:StartUpdating() end) function SoraExpTitle:OnUpdate(dt) local str = self.exp.." / "..self.maxexp self.soraexptitle:SetString(str) end The ListenForEvent is written with the owner added at the end, which makes a difference as to how it is called. It doesn't work either. T_T, when the game doesn't include the cave, everything works fine. Link to comment https://forums.kleientertainment.com/forums/topic/136899-why-i-cant-get-the-true-value-of-netvar/#findComment-1533220 Share on other sites More sharing options...
Wonderlarr Posted January 18, 2022 Share Posted January 18, 2022 15 hours ago, ccpalyer said: It doesn't work either. T_T, when the game doesn't include the cave, everything works fine. That's because the game doesn't run as a client connected to a server when you host a game without caves, you ARE the server, meaning any server data is directly shown to you,since you, well, are the server. Link to comment https://forums.kleientertainment.com/forums/topic/136899-why-i-cant-get-the-true-value-of-netvar/#findComment-1533409 Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now