Download
(16 Kb)
Download
Updated: 10/29/22 12:42 AM
Pictures
File Info
Compatibility:
Firesong (8.2.5)
Lost Depths (8.1.5)
High Isle (8.0.0)
Ascending Tide (7.3.5)
Deadlands (7.2.5)
Waking Flame (7.1.5)
Blackwood (7.0.5)
Greymoor (6.0.5)
Updated:10/29/22 12:42 AM
Created:07/31/21 06:50 AM
Monthly downloads:1,526
Total downloads:60,557
Favorites:3
MD5:
LibTutorial  Popular! (More than 5000 hits)
Version: 1.14
by: Alianym [More]
Welcome to LibTutorial!

For developers, this is a re-jig of the base game tutorial functions but usable by AddOn authors with a simple function call once initialized. See the Demo.lua file for some example implementations.

Setting Things Up
The current four Tutorial Types supported are; (see screenshots for visuals):
  • Brief Hud Tutorial
  • Hud Info Tutorial
  • UI Info Box Tutorial
  • Pointer Box Tutorial
    • The 'Pointer' dynamically changes direction based on the control to which it is attached
    • This is the option required for tutorial sequences (outlined further below)

Be careful triggering a tutorial on player login or load-in. I'd recommend putting in an appropriate delay in these scenarios, otherwise the tutorial system may not have appropriately loaded by the time of your function call.

In a simple implementation you'll need an array set up in this format (tutorialIds in the example are "hudbrief" and "hudinfo"):

Code:
local tutorialArray = {
	["hudbrief"] = {					--ID must be at least (string) 5 characters or > (number) 9999
		title = "",					--(string) No title displayed nor needed for this Tutorial Type
		text = "Example Description",			--(string)
		tutorialType = LIB_TUTORIAL_TYPE_HUD_BRIEF,	--LibTutorial Global
		displayPriority = nil,				--Not used for this Tutorial Type
	},
	["hudinfo"] = {						--ID must be at least (string) 5 characters or > (number) 9999
		title = "Example Title",			--(string) 
		text = "Example Description",			--(string)
		tutorialType = LIB_TUTORIAL_TYPE_HUD_INFO,	--LibTutorial Global
		displayPriority = 1,				--(number) Determines priority when inserted into the queue
	},
}

These are the valid tutorialType value:
Code:
LIB_TUTORIAL_TYPE_HUD_BRIEF	--Brief Hud Tutorial
LIB_TUTORIAL_TYPE_HUD_INFO	--Hud Info Tutorial
LIB_TUTORIAL_TYPE_UI_INFO_BOX	--UI Info Box Tutorial
LIB_TUTORIAL_TYPE_POINTER_BOX	--Pointer Box Tutorial

Then you'll need to initialize an instance of LibTutorial:
Code:
LIB_TUTORIAL_EXAMPLE = LibTutorialSetup.New(tutorialArray)

Using LibTutorial to display tutorials:
Just call this function and pass in the tutorialId of the tutorial you want to trigger.
Code:
LIB_TUTORIAL_EXAMPLE:DisplayTutorial(tutorialId) --This is the main function you'd use to display your tutorial. It returns true if the tutorial successfully displays.

If you need to record whether or not you have previously displayed a tutorial you can do so with your AddOn's SavedVars, e.g.:
Code:
local function SetTutorialSeen(tutorialId, seen)
	AddOnSavedVars.tutorialSeen[tutorialId] = seen
end

function ExampleNamespace.GetTutorialSeen(tutorialId)
	return AddOnSavedVars.tutorialSeen[tutorialId]
end

function ExampleNamespace.DoDisplayStuff(tutorialId)
	if not ExampleNamespace.GetTutorialSeen(tutorialId) then
		if LIB_TUTORIAL_EXAMPLE:DisplayTutorial(tutorialId) then
			SetTutorialSeen(tutorialId, true)
		end
	end
end

(NEW!) Tutorial Sequences
You can also set up a sequence of tutorials. See the following things to note:
  • The sequence tutorials must be Pointer Box tutorials that hook to a control you provide
  • LEFT-CLICK on a tutorial to progress, RIGHT-CLICK to exit the sequence.

One example use-case for this is to walk users through panels with many options. The Lib will automatically scroll to center the control when a scrollCtrl is provided or if isLAMPanel is true.

To see this in action, open up the LibTutorial LAM panel and click the button at the top. This demo obviously has a dependency on LibAddonMenu being installed.
*Note: When using LibTutorial sequences with a LAM Panel, the control name is the "reference" attribute given to the control when initially setting up the LAM options table.

There are callbacks you can use to trigger certain functionality, and I use the callbacks to in turn call the LibTutorial-provided function:
Code:
LibTutorialSetSubMenuContainerIsOpen(control, open)
which opens/closes submenus (as well as nested submenus) containing the passed-in control if they exist.

An example layout of a sequence could look like the below (see the comments next to each var/func/etc.):

Code:
local LAM = LibAddonMenu2
tutorialStepsExample = {
	options = {
		showStepNumInTitle = true,					--(boolean) Format title as "Title (#/n)"
		tutorialType = LIB_TUTORIAL_TYPE_POINTER_BOX,			--LibTutorial Global (must be LIB_TUTORIAL_TYPE_UI_INFO_BOX for Steps/Sequence)
		isLAMPanel = true,						--(boolean) If the sequence is for your LAM Panel, (automatically sets fragment and scrollCtr)
	},
	[1] = {
		id = "libtutpb",							--ID must be at least (string) 5 characters or > (number) 9999
		title = "Test Tutorial Sequence",					--(string)
		text = "Test <LibTutorialDescriptionCtrl> Text!",			--(string)
		anchorToControlData = {LEFT, "LibTutorialDescriptionCtrl", RIGHT, 0},	--(myPoint, anchorTargetControl, anchorControlsPoint, offsetX, offsetY)
		--scrollCtrl = GetControl("ScrollControl")				--(optional) The container of the scrollCtrl if required (this requires an attribute of scrollCtrl.scroll). Value is automatically set if isLAMPanel is true
		--fragment = LAM:GetAddonSettingsFragment(),				--(optional) Fragment to which to attach the tutorial. If used, the tutorial will hide with the fragment. Value is automatically set if isLAMPanel is true

		--Callback that triggers just -before- the tutorial is displayed
		--Used here to open the SubMenu as the tutorial is displayed
		iniCustomCallback = function()
			local control = GetControl("LibTutorialDescriptionCtrl")
			LibTutorialSetSubMenuContainerIsOpen(control, true) 		--This control isn't a submenu or in a submenu, this call is just here to show it does what it should (nothing) if there is no submenu to be found
		end,

		--Callback that triggers when a user left-clicks on the tutorial popup
		--Displaying the next tutorial in sequence is handled by LibTutorial, but you can do other stuff here if you want 
		--(It will be called -before- the next tutorialStep is shown)
		nextCustomCallback = function(nextTutStepId) 
			local control = GetControl("LibTutorialDescriptionCtrl")
		end,

		--Callback that triggers when a user right-clicks on the tutorial pointer box
		exitCustomCallback = function(currTutStepId) d(zo_strformat("ID: <<1>>, exitCustomCallback", currTutStepId)) end,
	},
	[2] = {
		id = "libtutpbtwo",
		title = "Test Tutorial Sequence",
		text = "Test <LibTutorialCheckBoxCtrl> Text!",
		anchorToControlData = "LibTutorialCheckBoxCtrl6",

		iniCustomCallback = function()
			--
		end,

		--nextCustomCallback = function(nextTutStepId) end,
		--exitCustomCallback = function(currTutStepId) end,
	},
	[3] = {
		id = "libtutpbthree",
		title = "Test Tutorial Sequence",
		text = "Test <LibTutorialHeaderCtrl> Text!",
		anchorToControlData = "LibTutorialEditBox2",

		iniCustomCallback = function()
			--
		end,

		--nextCustomCallback = function(nextTutStepId) end,
		--exitCustomCallback = function(currTutStepId) end,
	},
	[4] = {
		id = "libtutpbfour",
		title = "Test Tutorial Sequence",
		text = "Test <LibTutorialEditBox> Text!",
		anchorToControlData = "LibTutorialEditBox3",

		iniCustomCallback = function()
			--
		end,

		--nextCustomCallback = function(nextTutStepId) end,
		--exitCustomCallback = function(currTutStepId) end,
	},
	[5] = {
		id = "libtutpbfive",
		title = "Test Tutorial Sequence",
		text = "Test <LibTutorialEditBox> Text!",
		anchorToControlData = "LibTutorialCheckBoxCtrl7",

		iniCustomCallback = function()
			local control = GetControl("LibTutorialCheckBoxCtrl7")
			LibTutorialSetSubMenuContainerIsOpen(control, true)
		end,

		--This callback won't fire because it's the last in the sequence, there is no "next"
		nextCustomCallback = function(nextTutStepId) 
			local control = GetControl("LibTutorialCheckBoxCtrl7")
			LibTutorialSetSubMenuContainerIsOpen(control, false)				
		end,

		exitCustomCallback = function(nextTutStepId) 
			local control = GetControl("LibTutorialCheckBoxCtrl7")
			LibTutorialSetSubMenuContainerIsOpen(control, false)				
		end,
	},
}

Then you can have a button at the top of your panel like the LibTutorial example, which calls the following function:
Code:
--Example Tutorial Sequence Function (Triggered with the button in the LibTutorial LAM Panel)
LIB_TUTORIAL_EXAMPLE:StartTutorialSequence(tutorialStepsExample) --This is the main function you'd use to display a tutorial route
Optional Libraries:
LibAddonMenu
v1.14
  • API Update
  • Updated to prepare for deprecation of a function in U36 Firesong (Pt. II)

v1.13
  • Updated to prepare for deprecation of a function in U36 Firesong

v1.12
  • Removed a reference that would cause a bug on AddOn load

v1.11
  • Updated tutorialIndex to tutorialId (except where referencing ZOS functions or were in fact using an index)
  • Added `return true` value for when a tutorial is displayed so an author can reference if it has been displayed (i.e. seen)

v1.10
  • Added new Tutorial Type (Pointer Box) and Tutorial Sequences (only available with Pointer Box-style tutorials for now)
  • Updated the Demo.lua file to include a demo for Tutorial Sequences (req. LibAddonMenu)
  • TO-DO: Standardize internal references of Index and ID

v1.02
  • Bug Fix: Fixed an issue with HudInfo-type Tutorials that would cause issues if more than one author attempted to use that type at once

v1.01
  • Updated APIVersion to current value (nice catch, Baertram!)

v1.00
  • Bug Fix: Fixed a few : that should've been .
Archived Files (8)
File Name
Version
Size
Uploader
Date
1.13
16kB
Alianym
09/26/22 12:55 AM
1.12
16kB
Alianym
05/30/22 09:21 AM
1.11
16kB
Alianym
05/30/22 08:11 AM
1.10
16kB
Alianym
05/22/22 03:24 AM
1.02
8kB
Alianym
02/08/22 05:45 AM
1.01
8kB
Alianym
02/07/22 08:03 AM
1.0
8kB
Alianym
02/07/22 07:05 AM
0.2
8kB
07/31/21 06:50 AM


Post A Reply Comment Options
Unread 02/08/22, 05:47 AM  
Alianym
AddOn Author - Click to view AddOns

Forum posts: 10
File comments: 110
Uploads: 11
Originally Posted by Alianym
Originally Posted by Baertram
Edit:
As info: Seems the index will be saved internally for each created object of that lib so as long as no addon is reusing the object of another addon, and creates it's own object to use, it should be internally split by addons.
Yep, this is correct.

Also, for anyone following along on this page: there's currently a bug with HudInfo-type tutorials I noticed when messing around with it earlier. I'll aim to fix this shortly, but if anyone is already using this and comes across a bug, this may be it. But feel free to post if you get a bug anyway.
Alright, bug should be fixed. So in lieu of overexplaining I'll just say; it should now all work as described.
And reiterating that multiple AddOns using the same IDs shouldn't cause any issue for the reasons Baertram mentions.
Report comment to moderator  
Reply With Quote
Unread 02/07/22, 08:44 PM  
Alianym
AddOn Author - Click to view AddOns

Forum posts: 10
File comments: 110
Uploads: 11
Originally Posted by Baertram
Edit:
As info: Seems the index will be saved internally for each created object of that lib so as long as no addon is reusing the object of another addon, and creates it's own object to use, it should be internally split by addons.
Yep, this is correct.

Also, for anyone following along on this page: there's currently a bug with HudInfo-type tutorials I noticed when messing around with it earlier. I'll aim to fix this shortly, but if anyone is already using this and comes across a bug, this may be it. But feel free to post if you get a bug anyway.
Report comment to moderator  
Reply With Quote
Unread 02/07/22, 08:06 AM  
Baertram
Super Moderator
 
Baertram's Avatar
ESOUI Super Moderator
AddOn Author - Click to view AddOns

Forum posts: 4963
File comments: 6032
Uploads: 78
Btw 1 question:
Is the ID used for the tutorial global for all addons, so do I need to use something like "MyAddonName_Tut1" as ID?
or is it just registered per addon using the lib?
I saw it can be a number too so using the same ID number, e.g. 1, will overwrite other addons tutorials then?

Edit:
As info: Seems the index will be saved internally for each created object of that lib so as long as no addon is reusing the object of another addon, and creates it's own object to use, it should be internally split by addons.

Originally Posted by Alianym
Originally Posted by Baertram
Thanks for the lib.
Your APIversion is outdated 3 patches
## APIVersion: 100035

Current:
## APIVersion: 101032
I swear I checked that!
Fixing it now.
Last edited by Baertram : 02/07/22 at 11:54 AM.
Report comment to moderator  
Reply With Quote
Unread 02/07/22, 08:01 AM  
Alianym
AddOn Author - Click to view AddOns

Forum posts: 10
File comments: 110
Uploads: 11
Originally Posted by Baertram
Thanks for the lib.
Your APIversion is outdated 3 patches
## APIVersion: 100035

Current:
## APIVersion: 101032
I swear I checked that!
Fixing it now.
Report comment to moderator  
Reply With Quote
Unread 02/07/22, 07:53 AM  
Baertram
Super Moderator
 
Baertram's Avatar
ESOUI Super Moderator
AddOn Author - Click to view AddOns

Forum posts: 4963
File comments: 6032
Uploads: 78
Thanks for the lib.
Your APIversion is outdated 3 patches
## APIVersion: 100035

Current:
## APIVersion: 101032
Report comment to moderator  
Reply With Quote
Post A Reply



Category Jump: