Forums » General StepMania » SM5 Unlock system

Does it actually work?

Check me out on SMO!
Reply
To the best of my knowledge it works fine, although I'm not sure who actually knows how to use it.
Reply
Someone has to know how to do it. Can someone make a tutorial?

Last edited: 6 August 2014 3:25pm


Check me out on SMO!
Reply
It works. I used it a bit this past spring to assist my university's rhythm game club in carrying out a semester long event in which songs were unlocked by accomplishing objectives. If you give me a day or two, I can write a description of what I did. (It won't be much.)

Last edited: 7 August 2014 9:12pm

Reply
OMG Thank you! I actually have hope now!

Check me out on SMO!
Reply
I thought that by just putting the unlock names on the metrics.ini file (inside theme folder) would work, but it apparently doesn't unlock the song even when the requirement is met (it remains locked forever).

But maybe I'm doing it wrong... not sure if it needs some sort of tweaking, though.

Getting the Unlock System to work in SM5

Last edited: 8 August 2014 2:15pm

Reply
What are the unlock names? I dont know how to do it.

Last edited: 8 August 2014 6:20pm


Check me out on SMO!
Reply
DISCLAIMER:
This is NOT the only way to use UNLOCKMAN nor is it necessarily the "best" way. This is one method I found that worked for me and my university's rhythm game club this past Spring 2014 semester.

We ran a semester-long event in which goals were posted (like, play 15 songs by artist Kors K or play songs 15 songs on reverse scroll, or etc.) and then gradually completed by club members each meeting. For the purposes of this event, we kept track of progress outside of StepMania. With proper and knowledgable theming, such goals could be automatically tracked by a theme and content could be automatically unlocked. Such topics are outside the scope of this particular tutorial.

PREAMBLE
This tutorial assumes that you are slightly comfortable with theming, or (at least) some minor file editing and experimenting until things work. It will cover one way in which I used SM5's built-in unlock system. There are (apparently) many ways it can be used. If you are clever enough with your theming, the built-in system is unnecessary (but you might need a completely custom MusicWheel or ScreenPlayerOptions or etc.).

Styling your unlock screen to aesthetically "fit in" with the rest of your theme is outside the scope of this tutorial.

I STRONGLY encourage you to use an up-to-date version of StepMania for testing this.

BACKGROUND
UNLOCKMAN in StepMania 5 allows you to lock and unlock certain elements of gameplay using a combination of Metrics and Lua. As described in UnlockManager.cpp, you can lock/unlock:
static const char *UnlockRewardTypeNames[] =

{
"Song",
"Steps",
"StepsType",
"Course",
"Modifier",
};


Locking a Song does what you probably think it does; the song and all associated charts will not show up in the musicwheel. In this tutorial, we will lock Songs. I haven't tried locking anything else, and can't discuss those knowledgeably, but, to summarize:

Steps are a specific stepcharts associated with a Song. "Hard single dance" or "expert double pump" are examples of Steps (I think).
StepsType are types of Steps (like 'StepsType_Dance_Single' or 'StepsType_Pump_Double' or 'StepsType_Techno_Single8'). For a full list of StepsType, see the StepsType Enum in Lua.xml
Courses are Course objects. I don't have much experience with these.
Modifiers are (presumably) gameplay modifiers (like Dark, Drunk, Flip, Hidden, etc.).




PART 1. Setting up UnlockManager
In your theme's operator menu, ensure that you have "Unlock System" set to "On." If your theme does not have an OptionRow for "Unlock System" you may have to temporarily switch to the Default theme. Alternatively, you can edit your Preferences.ini file so that UseUnlockSystem=1

Next, create a section in your theme's metrics for UnlockManger:
# Changes applied to [UnlockManager] while SM is running

# don't get picked up when metrics are refreshed via Shift+F2 (it seems?)
# so, make sure things are the way you want them to be (or restart StepMania).

[UnlockManager]
# determine if songs loaded via the AdditionalSongs= line in Preferences.ini should be locked.
# I haven't experimented with this and don't know if it works.
SongsNotAdditional=false

# add an additional UnlockName for each song you want to lock
UnlockNames="1,2,3"

# replace the paths I provide here with your own
# replace the "code" with an unlock string you want your user to type in to perform the unlock
# codes NEED to all be unique; duplicate codes will cause SM to crash
Unlock1Command=song,"dbk5/Applause";code,"blah";
Unlock2Command=song,"dbk5/I Need Your Love";code,"blahblah";
Unlock3Command=song,"dbk5/Killin It - Mutrix Remix";code,"blahblahblah";






PART 2. Setting up an Unlock Screen
In this tutorial, there are three parts to an "Unlock Screen." You'll need:
1. a way to get there
2. a screen where users will type in passphrases to unlock content
3. a results/reward screen

In my system, I chose to get to my ScreenUnlock from ScreenTitleJoin. ScreenTitleJoin normally displays only in "Pay" and "Free" mode; use ScreenTitleMenu if you want to get there from "Home" mode. You can switch between modes by holding F3 and tapping 1.

Here are the metrics I used for each of those three screens:

# this is for when we are in Free/Pay mode
[ScreenTitleJoin]
Fallback="ScreenTitleMenu"
ChoiceNames="1,2"
Choice1="applydefaultoptions;screen,ScreenSelectColor;text,Dance Mode"
Choice2="screen,ScreenUnlock;text,Enter Unlock Code"


# This screen prompts the user to type in an unlock code.
[ScreenUnlock]
Fallback="ScreenTextEntry"
PrevScreen="ScreenTitleJoin"
NextScreen="ScreenUnlock2"

QuestionY=_screen.cy-50


# This screen handles how to inform the user whether anything
# was successfully unlocked or not.
[ScreenUnlock2]
Fallback="ScreenPrompt"
PrevScreen="ScreenTitleJoin"
NextScreen="ScreenTitleJoin"


Your theme probably already has a Metrics section for ScreenTitleJoin, so it will likely be a matter of adding an additional Choice for getting to the unlock screen.





PART 3: Your Unlock Screen
In your theme's ./BGAnimations directory, create a new file titled ScreenUnlock background.lua

This is the code I used in that file. Each line is commented to the best of my ability:

local TextEntrySettings = {
-- ScreenMessage to send on pop (optional, "SM_None" if omitted)
--SendOnPop = "",

-- The question to display
Question = "Enter your unlock code:",

-- Initial answer text
InitialAnswer = "",

-- Maximum amount of characters
MaxInputLength = 30,

-- Validation function; function(answer, errorOut), must return boolean, string.
Validate = nil,

-- On OK; function(answer)
OnOK = function(answer)
UnlockSomeStuffMaybe(answer)
end,

-- On Cancel; function()
OnCancel = nil,

-- Validate appending a character; function(answer,append), must return boolean
ValidateAppend = nil,

-- Format answer for display; function(answer), must return string
FormatAnswerForDisplay = nil,
}


local t = Def.ActorFrame{
OnCommand=function(self)
SCREENMAN:GetTopScreen():Load(TextEntrySettings)
end
}

return t


The thing to note is the OnOK function that is executed when the user is done typing her passphrase. In the code above, it calls another function, UnlockSomeStuffMaybe(), and passes the text that the user typed in to that function. Let's create that function next.






PART 4: Your Unlock Script
In your theme's ./Scripts/ directory, create a new file titled "Unlock.lua" and put this code in it:


-- by not prefixing "local" before this variable,
-- it will have global scope throughout your theme
-- and can be accessed from any other theme file
ItemThatWasJustUnlocked = nil

function UnlockSomeStuffMaybe(text)

-- How many unlocks are there? Get the number.
local HowMany = UNLOCKMAN:GetNumUnlocks()

if HowMany > 0 then

-- Use the text that was typed to see if it matches any "Codes" set under
-- [UnlockManager] in your Metrics.ini
local UnlockSongs = UNLOCKMAN:GetSongsUnlockedByEntryID(text)

-- The line above returns a table whether it finds anything or not
-- so check the size of that table.
if #UnlockSongs > 0 then

local group = UnlockSongs[1]:GetGroupName()
local title = UnlockSongs[1]:GetDisplayFullTitle()

-- create a path out of the song's group and title
local path = group.."/"..title

-- set the variable with global scope equal to the path
-- we'll use this variable later on ScreenUnlock2
ItemThatWasJustUnlocked = path

--unlock that song using the text the user typed in
UNLOCKMAN:UnlockEntryID(text)
else

-- the lookup didn't find any locked content that matched the typed text
-- so set this variable to nil
ItemThatWasJustUnlocked = nil
end

end
end







PART 5: Your Reward Screen
Finally, in your ./BGAnimations directory, create a file titled ScreenUnlock2 overlay.lua

Here is the code I put in that file:

local t = Def.ActorFrame{}

-- if something was unlocked, the ItemThatWasJustUnlocked variable will have been set
-- to be a path in the UnlockSomeStuffMaybe() function in your ./Scripts/Unlock.lua file
if ItemThatWasJustUnlocked then

local song = SONGMAN:FindSong(ItemThatWasJustUnlocked)

if song then

-- attempt to find the banner for the song
bannerpath = song:GetBannerPath()

-- if a banner was found...
if bannerpath then

-- ... then display it!
t[#t+1] = Def.Banner{
Name="RewardBanner",
InitCommand=cmd(xy, _screen.cx, _screen.cy-55; ),
OnCommand=function(self)
self:LoadFromSong(song)
-- apply these after loading the banner
self:setsize(418, 164)
self:zoom(0.6)
end
}
end

-- regardless of banner or not-banner, display some reward text
t[#t+1] = LoadFont("Common normal")..{
Name="RewardText",
InitCommand=cmd(xy, _screen.cx, 110; zoom,1.25),
OnCommand=function(self)
self:settext("You have unlocked: " .. ItemThatWasJustUnlocked)
end
}

-- this is a sound to be played upon a successful unlock
-- this looks in your theme's ./Sounds/ directory for a file called "_unlock.ogg"
t[#t+1] = LoadActor( THEME:GetPathS("", "_unlock.ogg") )..{ Name="songUnlocked"; }

-- play that sound
t.OnCommand=function(self)
if song then
self:GetChild("songUnlocked"):play()
end
end
end


-- otherwise, nothing was unlocked, and the path variable is nil
else

t[#t+1] = LoadFont("Common normal")..{
Name="FailureText",
Text="Not quite...",
InitCommand=cmd(xy, _screen.cx,_screen.cy-50; zoom,1.4)
}

-- this is a sound to be played upon a failure to unlock
-- this looks in your theme's ./Sounds/ directory for a file called "_unlockFail.ogg"
t[#t+1] = LoadActor( THEME:GetPathS("", "_unlockFail.ogg") )..{ Name="songNotUnlocked" }

-- play that sound
t.OnCommand=function(self)
self:GetChild("songNotUnlocked"):play()
end
end
-- either way, set this to nil again now
ItemThatWasJustUnlocked = nil

return t


Here are some screenshots of what this looks like in my theme:

Last edited: 8 April 2015 11:08am

Reply