Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

SenL

Example/template of exp bar widget?

Recommended Posts

SenL    29

Thanks to Kzisor I have learned a bit about leveler component and replica/dirty/netvariable etc.

Now I want to learn how to create a simple widget to display exp bar.

I see so many (example: Starve Wars) but the code gives me headache. I need a simple one to start.

Does anyone have a sample, template or tutorial?

Thanks!!

Share this post


Link to post
Share on other sites
Kzisor    1,058
12 hours ago, SenL said:

I see so many (example: Starve Wars) but the code gives me headache. I need a simple one to start.

Does anyone have a sample, template or tutorial?

Give me an hour and I will have a generic badge which you can use, that acts like the Wortox, Demon King badge. It will allow you to override the bank/build based on the character so it will be able to be used by multiple characters on the same server.

Share this post


Link to post
Share on other sites
Kzisor    1,058

The attached file is the generic level badge which will be used to display the experience to the user. You will need to use the following code to make it become attached to your character.

Example:

Modmain code to add badge to specific character.

local function MakeLevelBadge( self, badge_name, owner_tag, level_system, bank, build, background_build, show_progress, show_remaining, position_normal, position_modded )

	if self.owner:HasTag(owner_tag) then
		local LevelBadge = require "widgets/levelbadge"
		self[badge_name] = self:AddChild(LevelBadge(self.owner, level_system, bank, build, background_build, show_progress, show_remaining))

		-- Compatibility with Always On Status mod.
		-- Change the position so badges to not overlap if you create multiple leveling systems.
		if GLOBAL.KnownModIndex:IsModEnabled("workshop-376333686") then			
			self[badge_name]:SetPosition(position_modded)
		else	
	    	self[badge_name]:SetPosition(position_normal)
		    self.brain:SetPosition(-40,-55,0)
		   	self.moisturemeter:SetPosition(0,-120,0)
		end

		local function leveldelta( data )
			
			self[badge_name]:SetPercent( data.newpercent, data.maxexperience, data.currentlevel, data.maxlevel )

		end

		local function OnSetPlayerMode( self )
			if self["on" .. level_system .. "delta"] == nil then
				self["on" .. level_system .. "delta"] = function( owner, data ) leveldelta( data ) end
				self.inst:ListenForEvent( "leveldelta", self["on" .. level_system .. "delta"], self.owner )
				if self.owner.replica.leveler then
					leveldelta( { newpercent = self.owner.replica.leveler:GetPercent( level_system ),
						maxexperience = self.owner.replica.leveler:GetMaxExperience( level_system ),
						currentlevel = self.owner.replica.leveler:GetLevel( level_system ),
						maxlevel = self.owner.replica.leveler:GetMaxLevel( level_system ) })
				end
			end
		end

		local function OnSetGhostMode( self )

			if self["on" .. level_system .. "delta"] ~= nil then

				self.inst:RemoveEventCallback( "leveldelta", self["on" .. level_system .. "delta"], self.owner )

				self["on" .. level_system .. "delta"] = nil

			end

		end

		local _SetGhostMode = self.SetGhostMode

		function self:SetGhostMode( ghostmode )
			_SetGhostMode( self, ghostmode )
			if ghostmode then
				self[badge_name]:Hide()
				OnSetGhostMode( self )
			else
				self[badge_name]:Show()
				OnSetPlayerMode( self )
			end
		end

		OnSetPlayerMode( self )

	end


	return self

end

local function StatusDisplaysPostInit( self )
	MakeLevelBadge( self, "[INSERT BADGE NAME HERE]", "[INSERT OWNER TAG HERE]", "[INSERT LEVEL SYSTEM NAME HERE]", "[INSERT BADGE ICON ANIMATION BANK HERE]", "[INSERT BADGE ICON ANIMATION BUILD HERE]", "[INSERT BACKGROUND ANIMATION BUILD HERE]", [INSERT TRUE OR FALSE: SHOW PROGRESS], [INSERT TRUE OR FALSE: SHOW REMAINING (DEFAULT IS FALSE)], {x=40, y=-55, z=0}, { x=-62, y=-52, z=0 })
end

AddClassPostConstruct( "widgets/statusdisplays", StatusDisplaysPostInit)

Simple change the following line in the above code to the appropriate settings and you're done.

	MakeLevelBadge( self, "[INSERT BADGE NAME HERE]", "[INSERT OWNER TAG HERE]", "[INSERT LEVEL SYSTEM NAME HERE]", "[INSERT BADGE ICON ANIMATION BANK HERE]", "[INSERT BADGE ICON ANIMATION BUILD HERE]", "[INSERT BACKGROUND ANIMATION BUILD HERE]", [INSERT TRUE OR FALSE: SHOW PROGRESS], [INSERT TRUE OR FALSE: SHOW REMAINING (DEFAULT IS FALSE)], {x=40, y=-55, z=0}, { x=-62, y=-52, z=0 })

Note: The badge icon template is a simple template I created it might not work correctly as I changed the images on it. If the images are not placed where you want them change the default pivot position in Spriter until they are located where you want them to be.

Note2: The background_template is the actual badge that is shown. You should name it what you want your badge to be named. You should also change the color of the background images, but leave the actual name of the files.

badge_icon_template.zip

background_template.zip

PS: Remember to give credit where credit it due!

levelbadge.lua

Share this post


Link to post
Share on other sites
Kzisor    1,058
1 minute ago, SenL said:

Oh man, can't wait to try this out.

Thank you so much!

I tried to make it as simple as possible to use so it could be used by as many people that wanted to use it. Remember that you will need to modify the position if you want multiple badges to show up.

Share this post


Link to post
Share on other sites
SenL    29

How does owner tag work, do I have to do

inst:AddTag("mycharnamehere")

in mychar.lua?

And use "mycharnamehere" in the "[INSERT OWNER TAG HERE]"?

Share this post


Link to post
Share on other sites
Kzisor    1,058
28 minutes ago, SenL said:

How does owner tag work, do I have to do

 

Hidden Content

 

in mychar.lua?

And use "mycharnamehere" in the "[INSERT OWNER TAG HERE]"?

This is correct. Remember the tag is put in the common_postinit function, not the master_postinit function.

Share this post


Link to post
Share on other sites
SenL    29

I don't understand the levelbadge.lua -> self:SetPercent() function.

It takes 4 parameters: val, max, level and maxlevel

1) How does it change the bar?

It does self.anim:GetAnimState():SetPercent("anim", 1-val) and similar thing on self.overlay -- these set the bank and build ... but how does it work with the scml (spriter) you provided? I guess I need a lesson how to make animation/build with spriter...

2) max is not being used?

 

Other questions

3) where and how do you tell the system about these 2 zip files? Is it in modmain or mychar.lua?

 

Spoiler

 

Assets = {

...

Asset("ANIM", "anim/mycharlevelbar.zip")

Asset("ANIM", "anim/badge_icon_template.zip")

...

}

 

 

4) Using your two zip files, do I do:

 

Spoiler

 

MakeLevelBadge(self,"mychar_exp", "mychar", "mycharLevelSystem", "icon", "anim", "level")

 

 

?

Thanks

 

Edit:

Crashes on modmain.lua

attempt to index global 'KnownModIndex' (a nil value)

Edit:

Fixed when I prepend it with GLOBAL. Wonder why?

Share this post


Link to post
Share on other sites
Kzisor    1,058
19 hours ago, SenL said:

I don't understand the levelbadge.lua -> self:SetPercent() function.

It takes 4 parameters: val, max, level and maxlevel

1) How does it change the bar?

It does self.anim:GetAnimState():SetPercent("anim", 1-val) and similar thing on self.overlay -- these set the bank and build ... but how does it work with the scml (spriter) you provided? I guess I need a lesson how to make animation/build with spriter...

2) max is not being used?

1 and 2) levelbadge.lua -> self:SetPercent isn't used by the badge itself it's used by the OnUpdate function of the badge, it's also used in the code in the modmain.lua file for the StatusDisplays.

Understanding how Spirter animations work inside the Don't Starve engine could be an entirely separate topic in and of itself.

19 hours ago, SenL said:

3) where and how do you tell the system about these 2 zip files? Is it in modmain or mychar.lua?

4) Using your two zip files, do I do:

3) Inside the modmain.lua file is where I placed the assets to be loaded, along with all the other ui related images such as bigportraits, avatars, etc.

4) No that is not fully correct.

The Icon Files:

You would rename the .scml file to the icon name you want it to be, such as SenL_Badge; for the Icon BANK it would be 'icon' and for the BUILD it would be 'SenL_Badge'.

The Background Files:

You would rename the .scml file to the badge name; inside the .scml you would rename the bank where it says 'level' to the badge name as well. Inside the MakeLevelBadge for the background build you would use the badge name.

MakeLevelBadge(self,"mychar_exp", "mychar", "mycharLevelSystem", "icon", "SenL_Badge", "mychar_badge") 

 

19 hours ago, SenL said:

Edit:

Crashes on modmain.lua

attempt to index global 'KnownModIndex' (a nil value)

Edit:

Fixed when I prepend it with GLOBAL. Wonder why?

This is simply an error on my part; I've edited the original post to include that specific GLOBAL reference to KnownModIndex. The reason it crashes without GLOBAL. is simply due to a scope issue of calling the KnownModIndex function.

Share this post


Link to post
Share on other sites
SenL    29

I got a crash on "self[badge_name]:SetPercent(data.newpercent, data.maxexperience, data.currentlevel, data.maxlevel)" inside leveldelta(data)

 

widgets/levelbadge.lua:38: bad argument #1 to 'ceil' (number expected, got nil)

 

I started a new game with only 1 mod active.

Share this post


Link to post
Share on other sites
Kzisor    1,058
5 hours ago, SenL said:

I got a crash on "self[badge_name]:SetPercent(data.newpercent, data.maxexperience, data.currentlevel, data.maxlevel)" inside leveldelta(data)

 

widgets/levelbadge.lua:38: bad argument #1 to 'ceil' (number expected, got nil)

 

I started a new game with only 1 mod active.

This seems to be an error when Always On Status is active, give me 5 minutes to fix it.

Note: The attached levelbadge.lua file is an update file which will work without crashing. I've also updated the one in the third post so you can simply download it from there if you're new to this thread.

Share this post


Link to post
Share on other sites
SenL    29

Fixed!

New bug :).

Get exp was 1 now 4 but badge still shows number 1.

The circle fills up though. Let me see if I can find out the problem...

Share this post


Link to post
Share on other sites
SenL    29

Actually... there are two numbers: 1 inside the circle frame and 2 is underneath it.

The bottom number displays the character level. This is correct.

The top number always displays 100 (max level) on mouseover. This is correct but I would like this to display how many percent to next level.

Let me see how I can do that...

Share this post


Link to post
Share on other sites
Kzisor    1,058
1 hour ago, SenL said:

The top number always displays 100 (max level) on mouseover. This is correct but I would like this to display how many percent to next level.

If you do that then please name the file to something other than levelbadge.lua. This badge is not designed to be changed and therefore you should name it something completely different as to not interfere with mods that are already in the game using the badge.

I've updated the badge to contain this functionality.

Share this post


Link to post
Share on other sites
Kzisor    1,058
Just now, SenL said:

Oh so that number 100 is intentional?

Yes, it's intentional. Give me 5 minutes and I will modify the levelbadge to allow you to show either the percentage or the max level.

Share this post


Link to post
Share on other sites
SenL    29

When I print(data.maxlevel), it crashes because maxlevel is nil.

How come?

local function leveldelta(data)
  print("leveldelta: " .. data.newpercent .. " " .. data.maxexperience .. " " .. data.currentlevel .. " " .. data.maxlevel) --crashes on data.maxlevel being nil
  self[badge_name]:SetPercent(data.newpercent, data.maxexperience, data.currentlevel, data.maxlevel)
end

Share this post


Link to post
Share on other sites
Kzisor    1,058
Just now, SenL said:

When I print(data.maxlevel), it crashes because maxlevel is nil.

How come?

 

Hidden Content

 

maxlevel isn't set until the game fully loads, but you start printing before the game is fully loaded.

Share this post


Link to post
Share on other sites
Kzisor    1,058
11 minutes ago, SenL said:

Oh so that number 100 (maxlevel) is intentional?

I've uploaded the new files in the third post along with the new MakeLevelBadge function. Copy/Paste those in the appropriate place to now be able to show percentage of either into the level or remaining. There are 2 new arguments, the first will make the progress show, the second forces it to remaining exp to level.

Share this post


Link to post
Share on other sites
SenL    29

Works flawlessly!

Now to learn about this since it's soooo much stuff.

Questions.

1) You are setting self.maxnum:SetString()  ... this is used to display the string in the circle frame but only when mouseover.

Is this correct?

If so, how does self.maxnum being used (and how)? Is it in the badge widget (Don't Starve Together\data\scripts\widgets)?

2) On MakeLevelBadge() function, you do

 

Spoiler

 

if GLOBAL.KnownModIndex:IsModEnabled("workshop-376333686") then            
            self[badge_name]:SetPosition(-62, -52, 0)
        else    
            self[badge_name]:SetPosition(40, -55, 0)
            self.brain:SetPosition(-40,-55,0)
               self.moisturemeter:SetPosition(0,-120,0)
        end

 

 

So when the "Always On Status" mod is enabled, you only display this badge on position -62,-52,0.

2a) What position coordinates are these?

2b) If that mod is not enabled, then display this badge on position 40,-55,0 but also display sanity (self.brain) on position -40,-55,0 and also display moisturemeter on position 0,-120,0 -- why did you decide to display two extra?

Edit: Oh I see, without the "Always On Status" mod, the brain is in the middle and it's in the way. You moved it to the left aligning with the health badge. Makes sense. But what about this moisturemeter...

 

Edit:

3) The function OnSetPlayerMode() does "ListenForEvent" for "leveldelta".

What pushes this event ("leveldelta")?

Share this post


Link to post
Share on other sites
Kzisor    1,058
16 minutes ago, SenL said:

Works flawlessly!

Now to learn about this since it's soooo much stuff.

Questions.

1) You are setting self.maxnum:SetString()  ... this is used to display the string in the circle frame but only when mouseover.

Is this correct?

If so, how does self.maxnum being used (and how)? Is it in the badge widget (Don't Starve Together\data\scripts\widgets)?

self.maxnum is only used in the Always On Status mod, it's how they tell the different between the current value and the maximum value of the stats being displayed. You might be able to make it show always, but that would be a configuration within the Always On Status mod.

16 minutes ago, SenL said:

2) On MakeLevelBadge() function, you do

 

Hidden Content

 

So when the "Always On Status" mod is enabled, you only display this badge on position -62,-52,0.

2a) What position coordinates are these?

2b) If that mod is not enabled, then display this badge on position 40,-55,0 but also display sanity (self.brain) on position -40,-55,0 and also display moisturemeter on position 0,-120,0 -- why did you decide to display two extra?

2) Not really a question, more of a statement.

2a) The parameters are X, Y, Z. I believe Z refers to if something will be visually before or after another widget in the same location. X is the left most of the container. Y is the top most of the container. This is why we use negative numbers because the level badge is a child of the Stats Display.

2b) The brain(sanity) and moisture meter are simply being moved, we aren't displaying two extra meters. You could also change the health and hunger badges to move them where you want them much like Always On Status does.

16 minutes ago, SenL said:

Edit:

3) The function OnSetPlayerMode() does "ListenForEvent" for "leveldelta".

What pushes this event ("leveldelta")?

Currently there is nothing pushing that event, however, it's a client side event that could be used to update the badge if needed.

Share this post


Link to post
Share on other sites
SenL    29

Nothing pushes this event... so how does this level badge updates when mychar gets exp ... is that built in the core statusdisplays widget? something must be calling this leveldelta() function, no?

Share this post


Link to post
Share on other sites
Kzisor    1,058
25 minutes ago, SenL said:

Nothing pushes this event... so how does this level badge updates when mychar gets exp ... is that built in the core statusdisplays widget? something must be calling this leveldelta() function, no?

The levelbadge has an OnUpdate function which updates the display of the badge.

Share this post


Link to post
Share on other sites
SenL    29

Oh I see. So what calls this OnUpdate :)? I searched modmain, badge widget and statusdisplays widget and found no "OnUpdate"

Share this post


Link to post
Share on other sites