Jump to content

Example/template of exp bar widget?


Recommended Posts

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!!

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Edited by Kzisor
Fixed code bug.
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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?

Edited by SenL
Link to comment
Share on other sites

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.

Edited by Kzisor
Updated information, some was incorrect after a recent update to the badge.
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Edited by Kzisor
Added updated levelbadge.lua file.
Link to comment
Share on other sites

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...

Edited by SenL
Link to comment
Share on other sites

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.

Edited by Kzisor
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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")?

Edited by SenL
Link to comment
Share on other sites

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.

Edited by Kzisor
Replied to the 3rd question asked.
Link to comment
Share on other sites

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?

Edited by SenL
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...