Line endings...be normalized!
This commit is contained in:
@@ -1,51 +1,51 @@
|
||||
-- This file is always executed first.
|
||||
|
||||
-- Override Lua's upper and lower functions with our own, which is always UTF-8.
|
||||
if Uppercase then
|
||||
string.upper = Uppercase
|
||||
string.lower = Lowercase
|
||||
Uppercase = nil -- don't use directly
|
||||
Lowercase = nil -- don't use directly
|
||||
end
|
||||
|
||||
Trace = lua.Trace
|
||||
Warn = lua.Warn
|
||||
print = Trace
|
||||
|
||||
PLAYER_1 = "PlayerNumber_P1"
|
||||
PLAYER_2 = "PlayerNumber_P2"
|
||||
NUM_PLAYERS = #PlayerNumber
|
||||
|
||||
function string:find_last( text )
|
||||
local LastPos = 0
|
||||
while true do
|
||||
local p = string.find( self, text, LastPos+1, true )
|
||||
if not p then
|
||||
return LastPos
|
||||
end
|
||||
LastPos = p
|
||||
end
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
-- This file is always executed first.
|
||||
|
||||
-- Override Lua's upper and lower functions with our own, which is always UTF-8.
|
||||
if Uppercase then
|
||||
string.upper = Uppercase
|
||||
string.lower = Lowercase
|
||||
Uppercase = nil -- don't use directly
|
||||
Lowercase = nil -- don't use directly
|
||||
end
|
||||
|
||||
Trace = lua.Trace
|
||||
Warn = lua.Warn
|
||||
print = Trace
|
||||
|
||||
PLAYER_1 = "PlayerNumber_P1"
|
||||
PLAYER_2 = "PlayerNumber_P2"
|
||||
NUM_PLAYERS = #PlayerNumber
|
||||
|
||||
function string:find_last( text )
|
||||
local LastPos = 0
|
||||
while true do
|
||||
local p = string.find( self, text, LastPos+1, true )
|
||||
if not p then
|
||||
return LastPos
|
||||
end
|
||||
LastPos = p
|
||||
end
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
--[[ sm-ssc aliases (non-compatibility)
|
||||
This is mainly here for making commands case-insensitive without needing to
|
||||
clutter up the C++ code. It can also be used to add custom functions that
|
||||
wouldn't otherwise belong somewhere else.
|
||||
--]]
|
||||
|
||||
-- in fact, this probably belongs in Sprite.lua...
|
||||
function Sprite:cropto(w,h)
|
||||
self:CropTo(w,h)
|
||||
end
|
||||
|
||||
function Actor:SetSize(w,h)
|
||||
self:setsize(w,h)
|
||||
end
|
||||
|
||||
-- shorthand! this is tedious to type and makes things ugly so let's make it shorter.
|
||||
-- screen.w, screen.h, etc.
|
||||
local _screen = {
|
||||
w = SCREEN_WIDTH,
|
||||
h = SCREEN_HEIGHT,
|
||||
cx = SCREEN_CENTER_X,
|
||||
cy = SCREEN_CENTER_Y
|
||||
--[[ sm-ssc aliases (non-compatibility)
|
||||
This is mainly here for making commands case-insensitive without needing to
|
||||
clutter up the C++ code. It can also be used to add custom functions that
|
||||
wouldn't otherwise belong somewhere else.
|
||||
--]]
|
||||
|
||||
-- in fact, this probably belongs in Sprite.lua...
|
||||
function Sprite:cropto(w,h)
|
||||
self:CropTo(w,h)
|
||||
end
|
||||
|
||||
function Actor:SetSize(w,h)
|
||||
self:setsize(w,h)
|
||||
end
|
||||
|
||||
-- shorthand! this is tedious to type and makes things ugly so let's make it shorter.
|
||||
-- screen.w, screen.h, etc.
|
||||
local _screen = {
|
||||
w = SCREEN_WIDTH,
|
||||
h = SCREEN_HEIGHT,
|
||||
cx = SCREEN_CENTER_X,
|
||||
cy = SCREEN_CENTER_Y
|
||||
}
|
||||
@@ -1,68 +1,68 @@
|
||||
-- Override Lua's loadfile to use lua.ReadFile.
|
||||
function loadfile(file)
|
||||
local data, err = lua.ReadFile(file);
|
||||
if not data then
|
||||
return nil, ("what " .. file)
|
||||
end
|
||||
|
||||
local chunk, err = load(
|
||||
function()
|
||||
local ret = data
|
||||
data = nil
|
||||
return ret
|
||||
end,
|
||||
"@" .. file );
|
||||
if not chunk then return nil, err end
|
||||
|
||||
-- Set the environment, like loadfile does.
|
||||
setfenv( chunk, getfenv(2) );
|
||||
return chunk
|
||||
end
|
||||
|
||||
-- Override Lua's dofile to use our loadfile.
|
||||
function dofile(file)
|
||||
if not file then
|
||||
error( "dofile(nil) unsupported", 2 );
|
||||
end
|
||||
|
||||
local chunk, err = loadfile(file)
|
||||
if not chunk then
|
||||
error( err, 2 );
|
||||
end
|
||||
|
||||
return chunk
|
||||
end
|
||||
|
||||
-- Like ipairs(), but returns only values.
|
||||
function ivalues(t)
|
||||
local n = 0
|
||||
return function()
|
||||
n = n + 1
|
||||
return t[n];
|
||||
end
|
||||
end
|
||||
|
||||
Var = lua.GetThreadVariable
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
-- Override Lua's loadfile to use lua.ReadFile.
|
||||
function loadfile(file)
|
||||
local data, err = lua.ReadFile(file);
|
||||
if not data then
|
||||
return nil, ("what " .. file)
|
||||
end
|
||||
|
||||
local chunk, err = load(
|
||||
function()
|
||||
local ret = data
|
||||
data = nil
|
||||
return ret
|
||||
end,
|
||||
"@" .. file );
|
||||
if not chunk then return nil, err end
|
||||
|
||||
-- Set the environment, like loadfile does.
|
||||
setfenv( chunk, getfenv(2) );
|
||||
return chunk
|
||||
end
|
||||
|
||||
-- Override Lua's dofile to use our loadfile.
|
||||
function dofile(file)
|
||||
if not file then
|
||||
error( "dofile(nil) unsupported", 2 );
|
||||
end
|
||||
|
||||
local chunk, err = loadfile(file)
|
||||
if not chunk then
|
||||
error( err, 2 );
|
||||
end
|
||||
|
||||
return chunk
|
||||
end
|
||||
|
||||
-- Like ipairs(), but returns only values.
|
||||
function ivalues(t)
|
||||
local n = 0
|
||||
return function()
|
||||
n = n + 1
|
||||
return t[n];
|
||||
end
|
||||
end
|
||||
|
||||
Var = lua.GetThreadVariable
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
@@ -1,66 +1,66 @@
|
||||
--[[ sm-ssc compatibility helpers
|
||||
sm-ssc changes quite a few things which would make various SM4 content break.
|
||||
Also, certain things are deprecated/removed from sm-ssc (and sometimes SM4 too).
|
||||
--]]
|
||||
|
||||
--[[ Actor ]]
|
||||
function Actor:hidden(bHide)
|
||||
Warn("hidden is deprecated, use visible instead. (used on ".. self:GetName() ..")")
|
||||
self:visible(not bHide)
|
||||
end
|
||||
|
||||
-- for when horizalign and vertalign get killed by glenn:
|
||||
--[[
|
||||
function Actor:horizalign(v)
|
||||
local values = {
|
||||
left = 0,
|
||||
center = 0.5,
|
||||
right = 1
|
||||
}
|
||||
self:halign(values[v])
|
||||
end
|
||||
|
||||
function Actor:vertalign(v)
|
||||
local values = {
|
||||
top = 0,
|
||||
middle = 0.5,
|
||||
bottom = 1
|
||||
}
|
||||
self:valign(values[v])
|
||||
end
|
||||
--]]
|
||||
|
||||
--[[ ActorScroller: all of these got renamed, so alias the lowercase ones if
|
||||
things are going to look for them. ]]
|
||||
function ActorScroller:getsecondtodestination()
|
||||
self:GetSecondsToDestination()
|
||||
end
|
||||
|
||||
function ActorScroller:setsecondsperitem(secs)
|
||||
self:SetSecondsPerItem(secs)
|
||||
end
|
||||
|
||||
function ActorScroller:setnumsubdivisions(subs)
|
||||
self:SetNumSubdivisions(subs)
|
||||
end
|
||||
|
||||
function ActorScroller:scrollthroughallitems()
|
||||
self:ScrollThroughAllItems()
|
||||
end
|
||||
|
||||
function ActorScroller:scrollwithpadding(fPadStart,fPadEnd)
|
||||
self:ScrollWithPadding(fPadStart,fPadEnd)
|
||||
end
|
||||
|
||||
function ActorScroller:setfastcatchup(bFastCatchup)
|
||||
self:SetFastCatchup(bFastCatchup)
|
||||
end
|
||||
|
||||
-- renaming various StepMania functions to sm-ssc ones:
|
||||
if ScreenString then
|
||||
ScreenString = Screen.String
|
||||
end
|
||||
|
||||
if ScreenMetric then
|
||||
ScreenMetric = Screen.Metric
|
||||
--[[ sm-ssc compatibility helpers
|
||||
sm-ssc changes quite a few things which would make various SM4 content break.
|
||||
Also, certain things are deprecated/removed from sm-ssc (and sometimes SM4 too).
|
||||
--]]
|
||||
|
||||
--[[ Actor ]]
|
||||
function Actor:hidden(bHide)
|
||||
Warn("hidden is deprecated, use visible instead. (used on ".. self:GetName() ..")")
|
||||
self:visible(not bHide)
|
||||
end
|
||||
|
||||
-- for when horizalign and vertalign get killed by glenn:
|
||||
--[[
|
||||
function Actor:horizalign(v)
|
||||
local values = {
|
||||
left = 0,
|
||||
center = 0.5,
|
||||
right = 1
|
||||
}
|
||||
self:halign(values[v])
|
||||
end
|
||||
|
||||
function Actor:vertalign(v)
|
||||
local values = {
|
||||
top = 0,
|
||||
middle = 0.5,
|
||||
bottom = 1
|
||||
}
|
||||
self:valign(values[v])
|
||||
end
|
||||
--]]
|
||||
|
||||
--[[ ActorScroller: all of these got renamed, so alias the lowercase ones if
|
||||
things are going to look for them. ]]
|
||||
function ActorScroller:getsecondtodestination()
|
||||
self:GetSecondsToDestination()
|
||||
end
|
||||
|
||||
function ActorScroller:setsecondsperitem(secs)
|
||||
self:SetSecondsPerItem(secs)
|
||||
end
|
||||
|
||||
function ActorScroller:setnumsubdivisions(subs)
|
||||
self:SetNumSubdivisions(subs)
|
||||
end
|
||||
|
||||
function ActorScroller:scrollthroughallitems()
|
||||
self:ScrollThroughAllItems()
|
||||
end
|
||||
|
||||
function ActorScroller:scrollwithpadding(fPadStart,fPadEnd)
|
||||
self:ScrollWithPadding(fPadStart,fPadEnd)
|
||||
end
|
||||
|
||||
function ActorScroller:setfastcatchup(bFastCatchup)
|
||||
self:SetFastCatchup(bFastCatchup)
|
||||
end
|
||||
|
||||
-- renaming various StepMania functions to sm-ssc ones:
|
||||
if ScreenString then
|
||||
ScreenString = Screen.String
|
||||
end
|
||||
|
||||
if ScreenMetric then
|
||||
ScreenMetric = Screen.Metric
|
||||
end
|
||||
@@ -1,169 +1,169 @@
|
||||
-- Convenience aliases:
|
||||
left = "HorizAlign_Left";
|
||||
center = "HorizAlign_Center";
|
||||
right = "HorizAlign_Right";
|
||||
top = "VertAlign_Top";
|
||||
middle = "VertAlign_Middle";
|
||||
bottom = "VertAlign_Bottom";
|
||||
|
||||
function Actor:ease(t, fEase)
|
||||
-- Optimizations:
|
||||
-- fEase = -100 is equivalent to TweenType_Accelerate.
|
||||
if fEase == -100 then
|
||||
self:accelerate(t);
|
||||
return;
|
||||
end
|
||||
|
||||
-- fEase = 0 is equivalent to TweenType_Linear.
|
||||
if fEase == 0 then
|
||||
self:linear(t);
|
||||
return;
|
||||
end
|
||||
|
||||
-- fEase = +100 is equivalent to TweenType_Decelerate.
|
||||
if fEase == 100 then
|
||||
self:decelerate(t);
|
||||
return;
|
||||
end
|
||||
|
||||
self:tween( t, "TweenType_Bezier",
|
||||
{
|
||||
0,
|
||||
scale(fEase, -100, 100, 0/3, 2/3),
|
||||
scale(fEase, -100, 100, 1/3, 3/3),
|
||||
1
|
||||
}
|
||||
);
|
||||
end
|
||||
-- Notes On Beziers --
|
||||
-- They can be 1D ( Quadratic ) or 2D ( Bezier )
|
||||
-- 1D:
|
||||
-- XA XB YC YD
|
||||
-- 2D:
|
||||
-- XA XB XC XD YA YB YC YD
|
||||
-- In 1D Quads, XA XB are beginning time and size, YC YD are ending time and size
|
||||
-- In 2D Quads, X
|
||||
local BounceBeginBezier =
|
||||
{
|
||||
0, 0,
|
||||
0.42, -0.42,
|
||||
2/3, 0.3,
|
||||
1, 1
|
||||
}
|
||||
function Actor:bouncebegin(t)
|
||||
self:tween( t, "TweenType_Bezier", BounceBeginBezier );
|
||||
end
|
||||
|
||||
local BounceEndBezier =
|
||||
{
|
||||
0,0,
|
||||
1/3, 0.7,
|
||||
0.58, 1.42,
|
||||
1, 1
|
||||
}
|
||||
function Actor:bounceend(t)
|
||||
self:tween( t, "TweenType_Bezier", BounceEndBezier );
|
||||
end
|
||||
|
||||
local SmoothBezier =
|
||||
{
|
||||
0, 0, 1, 1
|
||||
}
|
||||
function Actor:smooth(t)
|
||||
self:tween( t, "TweenType_Bezier", SmoothBezier );
|
||||
end
|
||||
-- SSC Additions
|
||||
local DropBezier =
|
||||
{
|
||||
0 , 0,
|
||||
1/3 , 1,
|
||||
2/3 , 0.5,
|
||||
1 , 1,
|
||||
}
|
||||
function Actor:drop(t)
|
||||
self:tween( t, "TweenType_Bezier", DropBezier );
|
||||
end
|
||||
-- Hide if b is true, but don't unhide if b is false.
|
||||
function Actor:hide_if(b)
|
||||
if b then
|
||||
self:visible(false)
|
||||
end
|
||||
end
|
||||
|
||||
function Actor:player(p)
|
||||
self:visible( GAMESTATE:IsHumanPlayer(p) )
|
||||
end
|
||||
|
||||
function ActorFrame:propagatecommand(...)
|
||||
self:propagate(1);
|
||||
self:playcommand(...);
|
||||
self:propagate(0);
|
||||
end
|
||||
|
||||
-- Shortcut for alignment.
|
||||
-- cmd(align,0.5,0.5) -- align center
|
||||
-- cmd(align,0.0,0.0) -- align top-left
|
||||
-- cmd(align,0.5,0.0) -- align top-center
|
||||
function Actor:align(h, v)
|
||||
self:halign( h );
|
||||
self:valign( v );
|
||||
end
|
||||
|
||||
function Actor:FullScreen()
|
||||
self:stretchto( 0,0,SCREEN_WIDTH,SCREEN_HEIGHT );
|
||||
end
|
||||
|
||||
--[[ Typical background sizes:
|
||||
320x240 - DDR 1st-Extreme, most NVLM_ZK songs
|
||||
640x480 - most simfiles in distribution today are this big.
|
||||
768x480 - 16:10 aspect ratio backgrounds
|
||||
854x480 - pump it up pro
|
||||
]]
|
||||
-- "Most backgrounds are 640x480. Some are 768x480. Stretch the 4:3 ones."
|
||||
function Actor:scale_or_crop_background()
|
||||
if (self:GetWidth() * 3) / 4 == self:GetHeight() then
|
||||
self:stretchto( 0,0,SCREEN_WIDTH,SCREEN_HEIGHT );
|
||||
else
|
||||
self:scaletocover( 0,0,SCREEN_WIDTH,SCREEN_HEIGHT );
|
||||
end
|
||||
end
|
||||
|
||||
function Actor:Center()
|
||||
self:x(SCREEN_CENTER_X)
|
||||
self:y(SCREEN_CENTER_Y)
|
||||
end
|
||||
|
||||
function Actor:bezier(...)
|
||||
local a = {...}
|
||||
local b = {}
|
||||
local c = 0
|
||||
assert((a == 9 or a == 5), "bad number of arguments for Actor:bezier()")
|
||||
for i=3,c do
|
||||
b[#b+1] = a[i]
|
||||
end
|
||||
self:tween(a[2], "TweenMode_Bezier", b)
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-- Convenience aliases:
|
||||
left = "HorizAlign_Left";
|
||||
center = "HorizAlign_Center";
|
||||
right = "HorizAlign_Right";
|
||||
top = "VertAlign_Top";
|
||||
middle = "VertAlign_Middle";
|
||||
bottom = "VertAlign_Bottom";
|
||||
|
||||
function Actor:ease(t, fEase)
|
||||
-- Optimizations:
|
||||
-- fEase = -100 is equivalent to TweenType_Accelerate.
|
||||
if fEase == -100 then
|
||||
self:accelerate(t);
|
||||
return;
|
||||
end
|
||||
|
||||
-- fEase = 0 is equivalent to TweenType_Linear.
|
||||
if fEase == 0 then
|
||||
self:linear(t);
|
||||
return;
|
||||
end
|
||||
|
||||
-- fEase = +100 is equivalent to TweenType_Decelerate.
|
||||
if fEase == 100 then
|
||||
self:decelerate(t);
|
||||
return;
|
||||
end
|
||||
|
||||
self:tween( t, "TweenType_Bezier",
|
||||
{
|
||||
0,
|
||||
scale(fEase, -100, 100, 0/3, 2/3),
|
||||
scale(fEase, -100, 100, 1/3, 3/3),
|
||||
1
|
||||
}
|
||||
);
|
||||
end
|
||||
-- Notes On Beziers --
|
||||
-- They can be 1D ( Quadratic ) or 2D ( Bezier )
|
||||
-- 1D:
|
||||
-- XA XB YC YD
|
||||
-- 2D:
|
||||
-- XA XB XC XD YA YB YC YD
|
||||
-- In 1D Quads, XA XB are beginning time and size, YC YD are ending time and size
|
||||
-- In 2D Quads, X
|
||||
local BounceBeginBezier =
|
||||
{
|
||||
0, 0,
|
||||
0.42, -0.42,
|
||||
2/3, 0.3,
|
||||
1, 1
|
||||
}
|
||||
function Actor:bouncebegin(t)
|
||||
self:tween( t, "TweenType_Bezier", BounceBeginBezier );
|
||||
end
|
||||
|
||||
local BounceEndBezier =
|
||||
{
|
||||
0,0,
|
||||
1/3, 0.7,
|
||||
0.58, 1.42,
|
||||
1, 1
|
||||
}
|
||||
function Actor:bounceend(t)
|
||||
self:tween( t, "TweenType_Bezier", BounceEndBezier );
|
||||
end
|
||||
|
||||
local SmoothBezier =
|
||||
{
|
||||
0, 0, 1, 1
|
||||
}
|
||||
function Actor:smooth(t)
|
||||
self:tween( t, "TweenType_Bezier", SmoothBezier );
|
||||
end
|
||||
-- SSC Additions
|
||||
local DropBezier =
|
||||
{
|
||||
0 , 0,
|
||||
1/3 , 1,
|
||||
2/3 , 0.5,
|
||||
1 , 1,
|
||||
}
|
||||
function Actor:drop(t)
|
||||
self:tween( t, "TweenType_Bezier", DropBezier );
|
||||
end
|
||||
-- Hide if b is true, but don't unhide if b is false.
|
||||
function Actor:hide_if(b)
|
||||
if b then
|
||||
self:visible(false)
|
||||
end
|
||||
end
|
||||
|
||||
function Actor:player(p)
|
||||
self:visible( GAMESTATE:IsHumanPlayer(p) )
|
||||
end
|
||||
|
||||
function ActorFrame:propagatecommand(...)
|
||||
self:propagate(1);
|
||||
self:playcommand(...);
|
||||
self:propagate(0);
|
||||
end
|
||||
|
||||
-- Shortcut for alignment.
|
||||
-- cmd(align,0.5,0.5) -- align center
|
||||
-- cmd(align,0.0,0.0) -- align top-left
|
||||
-- cmd(align,0.5,0.0) -- align top-center
|
||||
function Actor:align(h, v)
|
||||
self:halign( h );
|
||||
self:valign( v );
|
||||
end
|
||||
|
||||
function Actor:FullScreen()
|
||||
self:stretchto( 0,0,SCREEN_WIDTH,SCREEN_HEIGHT );
|
||||
end
|
||||
|
||||
--[[ Typical background sizes:
|
||||
320x240 - DDR 1st-Extreme, most NVLM_ZK songs
|
||||
640x480 - most simfiles in distribution today are this big.
|
||||
768x480 - 16:10 aspect ratio backgrounds
|
||||
854x480 - pump it up pro
|
||||
]]
|
||||
-- "Most backgrounds are 640x480. Some are 768x480. Stretch the 4:3 ones."
|
||||
function Actor:scale_or_crop_background()
|
||||
if (self:GetWidth() * 3) / 4 == self:GetHeight() then
|
||||
self:stretchto( 0,0,SCREEN_WIDTH,SCREEN_HEIGHT );
|
||||
else
|
||||
self:scaletocover( 0,0,SCREEN_WIDTH,SCREEN_HEIGHT );
|
||||
end
|
||||
end
|
||||
|
||||
function Actor:Center()
|
||||
self:x(SCREEN_CENTER_X)
|
||||
self:y(SCREEN_CENTER_Y)
|
||||
end
|
||||
|
||||
function Actor:bezier(...)
|
||||
local a = {...}
|
||||
local b = {}
|
||||
local c = 0
|
||||
assert((a == 9 or a == 5), "bad number of arguments for Actor:bezier()")
|
||||
for i=3,c do
|
||||
b[#b+1] = a[i]
|
||||
end
|
||||
self:tween(a[2], "TweenMode_Bezier", b)
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
@@ -1,234 +1,234 @@
|
||||
-- Convert "@/path/file" to "/path/".
|
||||
local function DebugPathToRealPath( p )
|
||||
if not p or p:sub( 1, 1 ) ~= "@" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local Path = p:sub( 2 )
|
||||
local pos = Path:find_last( '/' )
|
||||
return string.sub( Path, 1, pos )
|
||||
end
|
||||
|
||||
local function MergeTables( left, right )
|
||||
local ret = { }
|
||||
for key, val in pairs(left) do
|
||||
ret[key] = val
|
||||
end
|
||||
|
||||
for key, val in pairs(right) do
|
||||
if ret[key] then
|
||||
if type(val) == "function" and
|
||||
type(ret[key]) == "function" then
|
||||
local f1 = ret[key]
|
||||
local f2 = val
|
||||
val = function(...)
|
||||
f1(...)
|
||||
return f2(...)
|
||||
end
|
||||
else
|
||||
Warn( string.format( "%s\n\nOverriding \"%s\": %s with %s",
|
||||
debug.traceback(), key, type(ret[key]), type(val)) )
|
||||
end
|
||||
end
|
||||
|
||||
ret[key] = val
|
||||
end
|
||||
setmetatable( ret, getmetatable(left) )
|
||||
return ret
|
||||
end
|
||||
|
||||
DefMetatable = {
|
||||
__concat = function(left, right)
|
||||
return MergeTables( left, right )
|
||||
end
|
||||
}
|
||||
|
||||
-- This is used as follows:
|
||||
--
|
||||
-- t = Def.Class { table }
|
||||
Def = {}
|
||||
setmetatable( Def, {
|
||||
__index = function(self, Class)
|
||||
-- t is an actor definition table. name is the type
|
||||
-- given to Def. Fill in standard fields.
|
||||
return function(t)
|
||||
if not ActorUtil.IsRegisteredClass(Class) then
|
||||
error( Class .. " is not a registered actor class", 2 )
|
||||
end
|
||||
|
||||
t.Class = Class
|
||||
|
||||
local level = 2
|
||||
if t._Level then
|
||||
level = t._Level + 1
|
||||
end
|
||||
local info = debug.getinfo(level,"Sl");
|
||||
|
||||
-- Source file of caller:
|
||||
local Source = info.source
|
||||
t._Source = Source
|
||||
|
||||
t._Dir = DebugPathToRealPath( Source )
|
||||
|
||||
-- Line number of caller:
|
||||
t._Line = info.currentline
|
||||
|
||||
setmetatable( t, DefMetatable )
|
||||
return t
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
function ResolveRelativePath( path, level )
|
||||
if path:sub(1,1) ~= "/" then
|
||||
-- "Working directory":
|
||||
local sDir = DebugPathToRealPath( debug.getinfo(level+1,"S").source )
|
||||
assert( sDir )
|
||||
|
||||
path = sDir .. path
|
||||
end
|
||||
|
||||
path = ActorUtil.ResolvePath( path, level+1 )
|
||||
return path
|
||||
end
|
||||
|
||||
-- Load an actor template.
|
||||
function LoadActorFunc( path, level )
|
||||
level = level or 1
|
||||
|
||||
if path == "" then
|
||||
error( "Passing in a blank filename is a great way to eat up RAM. Good thing we warn you about this." )
|
||||
end
|
||||
|
||||
local ResolvedPath = ResolveRelativePath( path, level+1 )
|
||||
if not ResolvedPath then
|
||||
error( path .. ": not found", level+1 )
|
||||
end
|
||||
path = ResolvedPath
|
||||
|
||||
local Type = ActorUtil.GetFileType( path )
|
||||
Trace( "Loading " .. path .. ", type " .. tostring(Type) )
|
||||
|
||||
if Type == "FileType_Lua" then
|
||||
-- Load the file.
|
||||
local chunk, errmsg = loadfile( path )
|
||||
if not chunk then error(errmsg) end
|
||||
return chunk
|
||||
end
|
||||
|
||||
if Type == "FileType_Bitmap" or Type == "FileType_Movie" then
|
||||
return function()
|
||||
return Def.Sprite {
|
||||
_Level = level+1,
|
||||
Texture = path
|
||||
}
|
||||
end
|
||||
elseif Type == "FileType_Sound" then
|
||||
return function()
|
||||
return Def.Sound {
|
||||
_Level = level+1,
|
||||
File = path
|
||||
}
|
||||
end
|
||||
elseif Type == "FileType_Model" then
|
||||
return function()
|
||||
return Def.Model {
|
||||
_Level = level+1,
|
||||
Meshes = path,
|
||||
Materials = path,
|
||||
Bones = path
|
||||
}
|
||||
end
|
||||
elseif Type == "FileType_Directory" then
|
||||
return function()
|
||||
return Def.BGAnimation {
|
||||
_Level = level+1,
|
||||
AniDir = path
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
error( path .. ": unknown file type (" .. tostring(Type) .. ")", level+1 )
|
||||
end
|
||||
|
||||
-- Load and create an actor template.
|
||||
function LoadActor( path, ... )
|
||||
local t = LoadActorFunc( path, 2 )
|
||||
assert(t)
|
||||
return t(...)
|
||||
end
|
||||
|
||||
function LoadActorWithParams( path, params, ... )
|
||||
local t = LoadActorFunc( path, 2 )
|
||||
assert(t)
|
||||
return lua.RunWithThreadVariables( function(...) return t(...) end, params, ... )
|
||||
end
|
||||
|
||||
function LoadFont(a, b)
|
||||
local sSection = b and a or ""
|
||||
local sFile = b or a
|
||||
if sFile == "" or not sFile then
|
||||
sSection = "Common"
|
||||
sFile = "normal"
|
||||
end
|
||||
local sPath = THEME:GetPathF(sSection, sFile)
|
||||
return Def.BitmapText {
|
||||
_Level = 2,
|
||||
File = sPath
|
||||
}
|
||||
end
|
||||
|
||||
function WrapInActorFrame( t )
|
||||
return Def.ActorFrame { children = t }
|
||||
end
|
||||
|
||||
function StandardDecorationFromTable( MetricsName, t )
|
||||
if type(t) == "table" then
|
||||
t = t .. {
|
||||
InitCommand=function(self)
|
||||
self:name(MetricsName)
|
||||
ActorUtil.LoadAllCommandsAndSetXY(self,Var "LoadingScreen")
|
||||
end
|
||||
}
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
function StandardDecorationFromFile( MetricsName, FileName )
|
||||
local t = LoadActor( THEME:GetPathG(Var "LoadingScreen",FileName) )
|
||||
return StandardDecorationFromTable( MetricsName, t )
|
||||
end
|
||||
|
||||
function StandardDecorationFromFileOptional( MetricsName, FileName )
|
||||
if ShowStandardDecoration(MetricsName) then
|
||||
return StandardDecorationFromFile( MetricsName, FileName )
|
||||
end
|
||||
end
|
||||
|
||||
function ShowStandardDecoration( MetricsName )
|
||||
return THEME:GetMetric(Var "LoadingScreen","Show"..MetricsName)
|
||||
end
|
||||
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
-- Convert "@/path/file" to "/path/".
|
||||
local function DebugPathToRealPath( p )
|
||||
if not p or p:sub( 1, 1 ) ~= "@" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local Path = p:sub( 2 )
|
||||
local pos = Path:find_last( '/' )
|
||||
return string.sub( Path, 1, pos )
|
||||
end
|
||||
|
||||
local function MergeTables( left, right )
|
||||
local ret = { }
|
||||
for key, val in pairs(left) do
|
||||
ret[key] = val
|
||||
end
|
||||
|
||||
for key, val in pairs(right) do
|
||||
if ret[key] then
|
||||
if type(val) == "function" and
|
||||
type(ret[key]) == "function" then
|
||||
local f1 = ret[key]
|
||||
local f2 = val
|
||||
val = function(...)
|
||||
f1(...)
|
||||
return f2(...)
|
||||
end
|
||||
else
|
||||
Warn( string.format( "%s\n\nOverriding \"%s\": %s with %s",
|
||||
debug.traceback(), key, type(ret[key]), type(val)) )
|
||||
end
|
||||
end
|
||||
|
||||
ret[key] = val
|
||||
end
|
||||
setmetatable( ret, getmetatable(left) )
|
||||
return ret
|
||||
end
|
||||
|
||||
DefMetatable = {
|
||||
__concat = function(left, right)
|
||||
return MergeTables( left, right )
|
||||
end
|
||||
}
|
||||
|
||||
-- This is used as follows:
|
||||
--
|
||||
-- t = Def.Class { table }
|
||||
Def = {}
|
||||
setmetatable( Def, {
|
||||
__index = function(self, Class)
|
||||
-- t is an actor definition table. name is the type
|
||||
-- given to Def. Fill in standard fields.
|
||||
return function(t)
|
||||
if not ActorUtil.IsRegisteredClass(Class) then
|
||||
error( Class .. " is not a registered actor class", 2 )
|
||||
end
|
||||
|
||||
t.Class = Class
|
||||
|
||||
local level = 2
|
||||
if t._Level then
|
||||
level = t._Level + 1
|
||||
end
|
||||
local info = debug.getinfo(level,"Sl");
|
||||
|
||||
-- Source file of caller:
|
||||
local Source = info.source
|
||||
t._Source = Source
|
||||
|
||||
t._Dir = DebugPathToRealPath( Source )
|
||||
|
||||
-- Line number of caller:
|
||||
t._Line = info.currentline
|
||||
|
||||
setmetatable( t, DefMetatable )
|
||||
return t
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
function ResolveRelativePath( path, level )
|
||||
if path:sub(1,1) ~= "/" then
|
||||
-- "Working directory":
|
||||
local sDir = DebugPathToRealPath( debug.getinfo(level+1,"S").source )
|
||||
assert( sDir )
|
||||
|
||||
path = sDir .. path
|
||||
end
|
||||
|
||||
path = ActorUtil.ResolvePath( path, level+1 )
|
||||
return path
|
||||
end
|
||||
|
||||
-- Load an actor template.
|
||||
function LoadActorFunc( path, level )
|
||||
level = level or 1
|
||||
|
||||
if path == "" then
|
||||
error( "Passing in a blank filename is a great way to eat up RAM. Good thing we warn you about this." )
|
||||
end
|
||||
|
||||
local ResolvedPath = ResolveRelativePath( path, level+1 )
|
||||
if not ResolvedPath then
|
||||
error( path .. ": not found", level+1 )
|
||||
end
|
||||
path = ResolvedPath
|
||||
|
||||
local Type = ActorUtil.GetFileType( path )
|
||||
Trace( "Loading " .. path .. ", type " .. tostring(Type) )
|
||||
|
||||
if Type == "FileType_Lua" then
|
||||
-- Load the file.
|
||||
local chunk, errmsg = loadfile( path )
|
||||
if not chunk then error(errmsg) end
|
||||
return chunk
|
||||
end
|
||||
|
||||
if Type == "FileType_Bitmap" or Type == "FileType_Movie" then
|
||||
return function()
|
||||
return Def.Sprite {
|
||||
_Level = level+1,
|
||||
Texture = path
|
||||
}
|
||||
end
|
||||
elseif Type == "FileType_Sound" then
|
||||
return function()
|
||||
return Def.Sound {
|
||||
_Level = level+1,
|
||||
File = path
|
||||
}
|
||||
end
|
||||
elseif Type == "FileType_Model" then
|
||||
return function()
|
||||
return Def.Model {
|
||||
_Level = level+1,
|
||||
Meshes = path,
|
||||
Materials = path,
|
||||
Bones = path
|
||||
}
|
||||
end
|
||||
elseif Type == "FileType_Directory" then
|
||||
return function()
|
||||
return Def.BGAnimation {
|
||||
_Level = level+1,
|
||||
AniDir = path
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
error( path .. ": unknown file type (" .. tostring(Type) .. ")", level+1 )
|
||||
end
|
||||
|
||||
-- Load and create an actor template.
|
||||
function LoadActor( path, ... )
|
||||
local t = LoadActorFunc( path, 2 )
|
||||
assert(t)
|
||||
return t(...)
|
||||
end
|
||||
|
||||
function LoadActorWithParams( path, params, ... )
|
||||
local t = LoadActorFunc( path, 2 )
|
||||
assert(t)
|
||||
return lua.RunWithThreadVariables( function(...) return t(...) end, params, ... )
|
||||
end
|
||||
|
||||
function LoadFont(a, b)
|
||||
local sSection = b and a or ""
|
||||
local sFile = b or a
|
||||
if sFile == "" or not sFile then
|
||||
sSection = "Common"
|
||||
sFile = "normal"
|
||||
end
|
||||
local sPath = THEME:GetPathF(sSection, sFile)
|
||||
return Def.BitmapText {
|
||||
_Level = 2,
|
||||
File = sPath
|
||||
}
|
||||
end
|
||||
|
||||
function WrapInActorFrame( t )
|
||||
return Def.ActorFrame { children = t }
|
||||
end
|
||||
|
||||
function StandardDecorationFromTable( MetricsName, t )
|
||||
if type(t) == "table" then
|
||||
t = t .. {
|
||||
InitCommand=function(self)
|
||||
self:name(MetricsName)
|
||||
ActorUtil.LoadAllCommandsAndSetXY(self,Var "LoadingScreen")
|
||||
end
|
||||
}
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
function StandardDecorationFromFile( MetricsName, FileName )
|
||||
local t = LoadActor( THEME:GetPathG(Var "LoadingScreen",FileName) )
|
||||
return StandardDecorationFromTable( MetricsName, t )
|
||||
end
|
||||
|
||||
function StandardDecorationFromFileOptional( MetricsName, FileName )
|
||||
if ShowStandardDecoration(MetricsName) then
|
||||
return StandardDecorationFromFile( MetricsName, FileName )
|
||||
end
|
||||
end
|
||||
|
||||
function ShowStandardDecoration( MetricsName )
|
||||
return THEME:GetMetric(Var "LoadingScreen","Show"..MetricsName)
|
||||
end
|
||||
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
@@ -1,195 +1,195 @@
|
||||
--[[
|
||||
[en] The Branch table replaces the various functions used for branching in the
|
||||
StepMania 4 default theme.
|
||||
Lines with a single string (e.g. TitleMenu = "ScreenTitleMenu") are referenced
|
||||
in the metrics as Branch.keyname.
|
||||
If the line is a function, you'll have to use Branch.keyname() instead.
|
||||
--]]
|
||||
|
||||
-- used for various SMOnline-enabled screens:
|
||||
function SMOnlineScreen()
|
||||
for pn in ivalues(GAMESTATE:GetHumanPlayers()) do
|
||||
if not IsSMOnlineLoggedIn(pn) then
|
||||
return "ScreenSMOnlineLogin"
|
||||
end
|
||||
end
|
||||
return "ScreenNetRoom"
|
||||
end
|
||||
|
||||
function SelectMusicOrCourse()
|
||||
if IsNetSMOnline() then
|
||||
return "ScreenNetSelectMusic";
|
||||
elseif GAMESTATE:IsCourseMode() then
|
||||
return "ScreenSelectCourse"
|
||||
else
|
||||
return "ScreenSelectMusic"
|
||||
end
|
||||
end
|
||||
|
||||
-- functions used for Routine mode
|
||||
function IsRoutine()
|
||||
return GAMESTATE:GetCurrentStyle() and GAMESTATE:GetCurrentStyle():GetStyleType() == "StyleType_TwoPlayersSharedSides";
|
||||
end
|
||||
|
||||
Branch = {
|
||||
Init = function()
|
||||
if GAMESTATE:GetCoinMode() == 'CoinMode_Home' then
|
||||
return "ScreenInit"
|
||||
else
|
||||
return "ScreenInit"
|
||||
end
|
||||
end,
|
||||
AfterInit = function()
|
||||
if GAMESTATE:GetCoinMode() == 'CoinMode_Home' then
|
||||
return Branch.TitleMenu()
|
||||
else
|
||||
return "ScreenLogo"
|
||||
end
|
||||
end,
|
||||
TitleMenu = function()
|
||||
-- home mode is the most assumed use of sm-ssc.
|
||||
if GAMESTATE:GetCoinMode() == "CoinMode_Home" then
|
||||
return "ScreenTitleMenu"
|
||||
end
|
||||
-- arcade junk:
|
||||
if GAMESTATE:GetCoinsNeededToJoin() > GAMESTATE:GetCoins() then
|
||||
-- if no credits are inserted, don't show the Join screen. SM4 has
|
||||
-- this as the initial screen, but that means we'd be stuck in a
|
||||
-- loop with ScreenInit. No good.
|
||||
return "ScreenTitleJoin"
|
||||
else
|
||||
return "ScreenTitleJoin"
|
||||
end
|
||||
end,
|
||||
StartGame = function()
|
||||
-- Check to see if there are 0 songs installed. Also make sure to check
|
||||
-- that the additional song count is also 0, because there is
|
||||
-- a possibility someone will use their existing StepMania simfile
|
||||
-- collection with sm-ssc via AdditionalFolders/AdditionalSongFolders.
|
||||
if SONGMAN:GetNumSongs() == 0 and SONGMAN:GetNumAdditionalSongs() == 0 then
|
||||
return "ScreenHowToInstallSongs";
|
||||
end;
|
||||
return "ScreenSelectProfile";
|
||||
end,
|
||||
AfterProfileLoad = function()
|
||||
return "ScreenSelectProfile"
|
||||
end,
|
||||
AfterSelectProfile = function()
|
||||
if ( THEME:GetMetric("Common","AutoSetStyle") == true ) then
|
||||
if IsNetConnected() then
|
||||
-- use SelectStyle in online...
|
||||
return "ScreenSelectStyle"
|
||||
else
|
||||
return "ScreenSelectPlayMode"
|
||||
end
|
||||
else
|
||||
return "ScreenSelectStyle"
|
||||
end
|
||||
end,
|
||||
AfterSelectPlayMode = function()
|
||||
if IsNetConnected() then
|
||||
ReportStyle()
|
||||
GAMESTATE:ApplyGameCommand("playmode,regular")
|
||||
end
|
||||
if IsNetSMOnline() then
|
||||
return SMOnlineScreen()
|
||||
end
|
||||
if IsNetConnected() then
|
||||
return "ScreenNetRoom"
|
||||
end
|
||||
return "ScreenSelectPlayMode"
|
||||
end,
|
||||
AfterSelectStyle = function()
|
||||
if CHARMAN:GetAllCharacters() ~= nil then
|
||||
return "ScreenSelectCharacter"
|
||||
else
|
||||
return "ScreenGameInformation"
|
||||
end
|
||||
end,
|
||||
AfterProfileSave = function()
|
||||
-- Might be a little too broken? -- Midiman
|
||||
if GAMESTATE:IsEventMode() then
|
||||
return SelectMusicOrCourse()
|
||||
elseif STATSMAN:GetCurStageStats():AllFailed() then
|
||||
return "ScreenGameOver"
|
||||
elseif GAMESTATE:GetSmallestNumStagesLeftForAnyHumanPlayer() == 0 then
|
||||
return "ScreenEvaluationSummary"
|
||||
else
|
||||
return SelectMusicOrCourse()
|
||||
end
|
||||
end,
|
||||
GetGameInformationScreen = function()
|
||||
bTrue = PREFSMAN:GetPreference("ShowInstructions")
|
||||
return (bTrue and GoToMusic() or "ScreenGameInformation")
|
||||
end,
|
||||
AfterSMOLogin = SMOnlineScreen(),
|
||||
BackOutOfPlayerOptions = function()
|
||||
return SelectMusicOrCourse()
|
||||
end,
|
||||
BackOutOfStageInformation = function()
|
||||
return SelectMusicOrCourse()
|
||||
end,
|
||||
AfterSelectMusic = function()
|
||||
if SCREENMAN:GetTopScreen():GetGoToOptions() then
|
||||
return SelectFirstOptionsScreen()
|
||||
else
|
||||
return "ScreenStageInformation"
|
||||
end
|
||||
end,
|
||||
PlayerOptions = function()
|
||||
local pm = GAMESTATE:GetPlayMode()
|
||||
local restricted = { "PlayMode_Oni", "PlayMode_Rave",
|
||||
--"PlayMode_Battle" -- ??
|
||||
};
|
||||
local optionsScreen = "ScreenPlayerOptions"
|
||||
for i=1,#restricted do
|
||||
if restricted[i] == pm then
|
||||
optionsScreen = "ScreenPlayerOptionsRestricted"
|
||||
end;
|
||||
end
|
||||
if SCREENMAN:GetTopScreen():GetGoToOptions() then
|
||||
return optionsScreen;
|
||||
else
|
||||
return "ScreenStageInformation";
|
||||
end
|
||||
end,
|
||||
SongOptions = function()
|
||||
if SCREENMAN:GetTopScreen():GetGoToOptions() then
|
||||
return "ScreenSongOptions"
|
||||
else
|
||||
return "ScreenStageInformation"
|
||||
end
|
||||
end,
|
||||
GameplayScreen = function()
|
||||
if IsRoutine() then
|
||||
return "ScreenGameplayShared"
|
||||
end
|
||||
return "ScreenGameplay"
|
||||
end,
|
||||
AfterGameplay = function()
|
||||
-- pick an evaluation screen based on settings.
|
||||
if IsNetSMOnline() then
|
||||
return "ScreenNetEvaluation"
|
||||
else
|
||||
-- todo: account for courses etc?
|
||||
return "ScreenEvaluationNormal"
|
||||
end
|
||||
end,
|
||||
AfterEvaluation = function()
|
||||
if GAMESTATE:GetSmallestNumStagesLeftForAnyHumanPlayer() >= 1 then
|
||||
return "ScreenProfileSave"
|
||||
else
|
||||
return "ScreenEvaluationSummary"
|
||||
end
|
||||
end,
|
||||
AfterSummary = "ScreenProfileSaveSummary",
|
||||
Network = function()
|
||||
return IsNetConnected() and "ScreenTitleMenu" or "ScreenTitleMenu"
|
||||
end,
|
||||
QuickSetupStart = "ScreenQuickSetupOverview",
|
||||
QuickSetupA = "ScreenQuickSetupPhaseOne",
|
||||
QuickSetupB = "ScreenQuickSetupPhaseTwo",
|
||||
QuickSetupC = "ScreenQuickSetupPhaseThree",
|
||||
QuickSetupD = "ScreenQuickSetupPhaseFour",
|
||||
QuickSetupFinished = "ScreenQuickSetupFinished"
|
||||
}
|
||||
--[[
|
||||
[en] The Branch table replaces the various functions used for branching in the
|
||||
StepMania 4 default theme.
|
||||
Lines with a single string (e.g. TitleMenu = "ScreenTitleMenu") are referenced
|
||||
in the metrics as Branch.keyname.
|
||||
If the line is a function, you'll have to use Branch.keyname() instead.
|
||||
--]]
|
||||
|
||||
-- used for various SMOnline-enabled screens:
|
||||
function SMOnlineScreen()
|
||||
for pn in ivalues(GAMESTATE:GetHumanPlayers()) do
|
||||
if not IsSMOnlineLoggedIn(pn) then
|
||||
return "ScreenSMOnlineLogin"
|
||||
end
|
||||
end
|
||||
return "ScreenNetRoom"
|
||||
end
|
||||
|
||||
function SelectMusicOrCourse()
|
||||
if IsNetSMOnline() then
|
||||
return "ScreenNetSelectMusic";
|
||||
elseif GAMESTATE:IsCourseMode() then
|
||||
return "ScreenSelectCourse"
|
||||
else
|
||||
return "ScreenSelectMusic"
|
||||
end
|
||||
end
|
||||
|
||||
-- functions used for Routine mode
|
||||
function IsRoutine()
|
||||
return GAMESTATE:GetCurrentStyle() and GAMESTATE:GetCurrentStyle():GetStyleType() == "StyleType_TwoPlayersSharedSides";
|
||||
end
|
||||
|
||||
Branch = {
|
||||
Init = function()
|
||||
if GAMESTATE:GetCoinMode() == 'CoinMode_Home' then
|
||||
return "ScreenInit"
|
||||
else
|
||||
return "ScreenInit"
|
||||
end
|
||||
end,
|
||||
AfterInit = function()
|
||||
if GAMESTATE:GetCoinMode() == 'CoinMode_Home' then
|
||||
return Branch.TitleMenu()
|
||||
else
|
||||
return "ScreenLogo"
|
||||
end
|
||||
end,
|
||||
TitleMenu = function()
|
||||
-- home mode is the most assumed use of sm-ssc.
|
||||
if GAMESTATE:GetCoinMode() == "CoinMode_Home" then
|
||||
return "ScreenTitleMenu"
|
||||
end
|
||||
-- arcade junk:
|
||||
if GAMESTATE:GetCoinsNeededToJoin() > GAMESTATE:GetCoins() then
|
||||
-- if no credits are inserted, don't show the Join screen. SM4 has
|
||||
-- this as the initial screen, but that means we'd be stuck in a
|
||||
-- loop with ScreenInit. No good.
|
||||
return "ScreenTitleJoin"
|
||||
else
|
||||
return "ScreenTitleJoin"
|
||||
end
|
||||
end,
|
||||
StartGame = function()
|
||||
-- Check to see if there are 0 songs installed. Also make sure to check
|
||||
-- that the additional song count is also 0, because there is
|
||||
-- a possibility someone will use their existing StepMania simfile
|
||||
-- collection with sm-ssc via AdditionalFolders/AdditionalSongFolders.
|
||||
if SONGMAN:GetNumSongs() == 0 and SONGMAN:GetNumAdditionalSongs() == 0 then
|
||||
return "ScreenHowToInstallSongs";
|
||||
end;
|
||||
return "ScreenSelectProfile";
|
||||
end,
|
||||
AfterProfileLoad = function()
|
||||
return "ScreenSelectProfile"
|
||||
end,
|
||||
AfterSelectProfile = function()
|
||||
if ( THEME:GetMetric("Common","AutoSetStyle") == true ) then
|
||||
if IsNetConnected() then
|
||||
-- use SelectStyle in online...
|
||||
return "ScreenSelectStyle"
|
||||
else
|
||||
return "ScreenSelectPlayMode"
|
||||
end
|
||||
else
|
||||
return "ScreenSelectStyle"
|
||||
end
|
||||
end,
|
||||
AfterSelectPlayMode = function()
|
||||
if IsNetConnected() then
|
||||
ReportStyle()
|
||||
GAMESTATE:ApplyGameCommand("playmode,regular")
|
||||
end
|
||||
if IsNetSMOnline() then
|
||||
return SMOnlineScreen()
|
||||
end
|
||||
if IsNetConnected() then
|
||||
return "ScreenNetRoom"
|
||||
end
|
||||
return "ScreenSelectPlayMode"
|
||||
end,
|
||||
AfterSelectStyle = function()
|
||||
if CHARMAN:GetAllCharacters() ~= nil then
|
||||
return "ScreenSelectCharacter"
|
||||
else
|
||||
return "ScreenGameInformation"
|
||||
end
|
||||
end,
|
||||
AfterProfileSave = function()
|
||||
-- Might be a little too broken? -- Midiman
|
||||
if GAMESTATE:IsEventMode() then
|
||||
return SelectMusicOrCourse()
|
||||
elseif STATSMAN:GetCurStageStats():AllFailed() then
|
||||
return "ScreenGameOver"
|
||||
elseif GAMESTATE:GetSmallestNumStagesLeftForAnyHumanPlayer() == 0 then
|
||||
return "ScreenEvaluationSummary"
|
||||
else
|
||||
return SelectMusicOrCourse()
|
||||
end
|
||||
end,
|
||||
GetGameInformationScreen = function()
|
||||
bTrue = PREFSMAN:GetPreference("ShowInstructions")
|
||||
return (bTrue and GoToMusic() or "ScreenGameInformation")
|
||||
end,
|
||||
AfterSMOLogin = SMOnlineScreen(),
|
||||
BackOutOfPlayerOptions = function()
|
||||
return SelectMusicOrCourse()
|
||||
end,
|
||||
BackOutOfStageInformation = function()
|
||||
return SelectMusicOrCourse()
|
||||
end,
|
||||
AfterSelectMusic = function()
|
||||
if SCREENMAN:GetTopScreen():GetGoToOptions() then
|
||||
return SelectFirstOptionsScreen()
|
||||
else
|
||||
return "ScreenStageInformation"
|
||||
end
|
||||
end,
|
||||
PlayerOptions = function()
|
||||
local pm = GAMESTATE:GetPlayMode()
|
||||
local restricted = { "PlayMode_Oni", "PlayMode_Rave",
|
||||
--"PlayMode_Battle" -- ??
|
||||
};
|
||||
local optionsScreen = "ScreenPlayerOptions"
|
||||
for i=1,#restricted do
|
||||
if restricted[i] == pm then
|
||||
optionsScreen = "ScreenPlayerOptionsRestricted"
|
||||
end;
|
||||
end
|
||||
if SCREENMAN:GetTopScreen():GetGoToOptions() then
|
||||
return optionsScreen;
|
||||
else
|
||||
return "ScreenStageInformation";
|
||||
end
|
||||
end,
|
||||
SongOptions = function()
|
||||
if SCREENMAN:GetTopScreen():GetGoToOptions() then
|
||||
return "ScreenSongOptions"
|
||||
else
|
||||
return "ScreenStageInformation"
|
||||
end
|
||||
end,
|
||||
GameplayScreen = function()
|
||||
if IsRoutine() then
|
||||
return "ScreenGameplayShared"
|
||||
end
|
||||
return "ScreenGameplay"
|
||||
end,
|
||||
AfterGameplay = function()
|
||||
-- pick an evaluation screen based on settings.
|
||||
if IsNetSMOnline() then
|
||||
return "ScreenNetEvaluation"
|
||||
else
|
||||
-- todo: account for courses etc?
|
||||
return "ScreenEvaluationNormal"
|
||||
end
|
||||
end,
|
||||
AfterEvaluation = function()
|
||||
if GAMESTATE:GetSmallestNumStagesLeftForAnyHumanPlayer() >= 1 then
|
||||
return "ScreenProfileSave"
|
||||
else
|
||||
return "ScreenEvaluationSummary"
|
||||
end
|
||||
end,
|
||||
AfterSummary = "ScreenProfileSaveSummary",
|
||||
Network = function()
|
||||
return IsNetConnected() and "ScreenTitleMenu" or "ScreenTitleMenu"
|
||||
end,
|
||||
QuickSetupStart = "ScreenQuickSetupOverview",
|
||||
QuickSetupA = "ScreenQuickSetupPhaseOne",
|
||||
QuickSetupB = "ScreenQuickSetupPhaseTwo",
|
||||
QuickSetupC = "ScreenQuickSetupPhaseThree",
|
||||
QuickSetupD = "ScreenQuickSetupPhaseFour",
|
||||
QuickSetupFinished = "ScreenQuickSetupFinished"
|
||||
}
|
||||
|
||||
@@ -1,180 +1,180 @@
|
||||
-- SSC Color Module and Library
|
||||
local nilColor = color("0,0,0,0")
|
||||
-- Original Color Module.
|
||||
Color = {
|
||||
-- Color Library
|
||||
-- These colors are pure swatch colors and are here purely to be used
|
||||
-- on demand without having to type color("stuff") or dig through
|
||||
-- a palette to get the color you want.
|
||||
Black = color("0,0,0,1"),
|
||||
White = color("1,1,1,1"),
|
||||
Red = color("#ed1c24"),
|
||||
Blue = color("#00aeef"),
|
||||
Green = color("#39b54a"),
|
||||
Yellow = color("#fff200"),
|
||||
Orange = color("#f7941d"),
|
||||
Purple = color("#92278f"),
|
||||
Outline = color("0,0,0,0.5"),
|
||||
Invisible = color("1,1,1,0"),
|
||||
Stealth = nilColor,
|
||||
-- Color Functions
|
||||
-- These functions alter colors in a certain way so that you can make
|
||||
-- new ones without having to copy a color or find a new one.
|
||||
--[[ Brightness(fInput)
|
||||
Hue(hInput)
|
||||
Saturation(hInput)
|
||||
Alpha(hInput)
|
||||
HSV(iHue,fSaturation,fValue or any other overload) --]]
|
||||
Alpha = function(cColor,fAlpha)
|
||||
local c = cColor;
|
||||
return { c[1],c[2],c[3],fAlpha };
|
||||
end
|
||||
}
|
||||
-- Remapped Color Module, since some themes are crazy
|
||||
Colors = Color;
|
||||
|
||||
GameColor = {
|
||||
PlayerColors = {
|
||||
PLAYER_1 = color("#ef403d"),
|
||||
PLAYER_2 = color("#0089cf"),
|
||||
},
|
||||
Difficulty = {
|
||||
--[[ These are for 'Custom' Difficulty Ranks. It can be very useful
|
||||
in some cases, especially to apply new colors for stuff you
|
||||
couldn't before. (huh? -aj) ]]
|
||||
Beginner = color("#ff32f8"), -- light cyan
|
||||
Easy = color("#2cff00"), -- green
|
||||
Medium = color("#fee600"), -- yellow
|
||||
Hard = color("#ff2f39"), -- red
|
||||
Challenge = color("#1cd8ff"), -- light blue
|
||||
Edit = color("0.8,0.8,0.8,1"), -- gray
|
||||
Couple = color("#ed0972"), -- hot pink
|
||||
Routine = color("#ff9a00"), -- orange
|
||||
--[[ These are for courses, so let's slap them here in case someone
|
||||
wanted to use Difficulty in Course and Step regions. ]]
|
||||
Difficulty_Beginner = color("#ff32f8"), -- purple
|
||||
Difficulty_Easy = color("#2cff00"), -- green
|
||||
Difficulty_Medium = color("#fee600"), -- yellow
|
||||
Difficulty_Hard = color("#ff2f39"), -- red
|
||||
Difficulty_Challenge = color("#1cd8ff"), -- light blue
|
||||
Difficulty_Edit = color("0.8,0.8,0.8,1"), -- gray
|
||||
Difficulty_Couple = color("#ed0972"), -- hot pink
|
||||
Difficulty_Routine = color("#ff9a00") -- orange
|
||||
},
|
||||
Stage = {
|
||||
Stage_1st = color("#00ffc7"),
|
||||
Stage_2nd = color("#58ff00"),
|
||||
Stage_3rd = color("#f400ff"),
|
||||
Stage_4th = color("#00ffda"),
|
||||
Stage_5th = color("#ed00ff"),
|
||||
Stage_6th = color("#73ff00"),
|
||||
Stage_Next = color("#73ff00"),
|
||||
Stage_Final = color("#ff0707"),
|
||||
Stage_Extra1 = color("#fafa00"),
|
||||
Stage_Extra2 = color("#ff0707"),
|
||||
Stage_Nonstop = color("#FFFFFF"),
|
||||
Stage_Oni = color("#FFFFFF"),
|
||||
Stage_Endless = color("#FFFFFF"),
|
||||
Stage_Event = color("#FFFFFF"),
|
||||
Stage_Demo = color("#FFFFFF")
|
||||
},
|
||||
Judgment = {
|
||||
JudgmentLine_W1 = color("#bfeaff"),
|
||||
JudgmentLine_W2 = color("#fff568"),
|
||||
JudgmentLine_W3 = color("#a4ff00"),
|
||||
JudgmentLine_W4 = color("#34bfff"),
|
||||
JudgmentLine_W5 = color("#e44dff"),
|
||||
JudgmentLine_Held = color("#FFFFFF"),
|
||||
JudgmentLine_Miss = color("#ff3c3c"),
|
||||
JudgmentLine_MaxCombo = color("#ffc600")
|
||||
},
|
||||
};
|
||||
GameColor.Difficulty["Crazy"] = GameColor.Difficulty["Hard"];
|
||||
GameColor.Difficulty["Freestyle"] = GameColor.Difficulty["Easy"];
|
||||
GameColor.Difficulty["Nightmare"] = GameColor.Difficulty["Challenge"];
|
||||
GameColor.Difficulty["HalfDouble"] = GameColor.Difficulty["Medium"];
|
||||
|
||||
--[[ Fallbacks ]]
|
||||
function Color(c)
|
||||
return Colors[c]
|
||||
end
|
||||
|
||||
function BoostColor( cColor, fBoost )
|
||||
local c = cColor
|
||||
return { c[1]*fBoost, c[2]*fBoost, c[3]*fBoost, c[4] }
|
||||
end
|
||||
|
||||
function ColorLightTone(c)
|
||||
return { c[1]+(c[1]/2), c[2]+(c[2]/2), c[3]+(c[3]/2), c[4] }
|
||||
end
|
||||
|
||||
function ColorMidTone(c)
|
||||
return { c[1]/1.5, c[2]/1.5, c[3]/1.5, c[4] }
|
||||
end
|
||||
|
||||
function ColorDarkTone(c)
|
||||
return { c[1]/2, c[2]/2, c[3]/2, c[4] }
|
||||
end
|
||||
|
||||
function PlayerColor( pn )
|
||||
if pn == PLAYER_1 then
|
||||
return color("#ef403d") -- pink-red
|
||||
end
|
||||
if pn == PLAYER_2 then
|
||||
return color("#0089cf") -- sea-blue
|
||||
end
|
||||
return color("1,1,1,1")
|
||||
end
|
||||
function PlayerScoreColor( pn )
|
||||
if pn == PLAYER_1 then
|
||||
return color("#ef403d") -- pink-red
|
||||
end
|
||||
if pn == PLAYER_2 then
|
||||
return color("#0089cf") -- sea-blue
|
||||
end
|
||||
return color("1,1,1,1")
|
||||
end
|
||||
|
||||
function CustomDifficultyToColor( sCustomDifficulty )
|
||||
return GameColor.Difficulty[sCustomDifficulty]
|
||||
end
|
||||
|
||||
function CustomDifficultyToDarkColor( sCustomDifficulty )
|
||||
local c = GameColor.Difficulty[sCustomDifficulty]
|
||||
return { c[1]/2, c[2]/2, c[3]/2, c[4] }
|
||||
end
|
||||
|
||||
function CustomDifficultyToLightColor( sCustomDifficulty )
|
||||
local c = GameColor.Difficulty[sCustomDifficulty]
|
||||
return { scale(c[1],0,1,0.5,1), scale(c[2],0,1,0.5,1), scale(c[3],0,1,0.5,1), c[4] }
|
||||
end
|
||||
|
||||
function StepsOrTrailToColor(StepsOrTrail)
|
||||
return CustomDifficultyToColor( StepsOrTrailToCustomDifficulty(stepsOrTrail) )
|
||||
end
|
||||
|
||||
function StageToColor( stage )
|
||||
local c = GameColor.Stage[stage]
|
||||
if c then
|
||||
return c
|
||||
end
|
||||
return color("#000000")
|
||||
end
|
||||
|
||||
function StageToStrokeColor( stage )
|
||||
local c = GameColor.Stage[stage]
|
||||
return { c[1]/2, c[2]/2, c[3]/2, c[4] }
|
||||
end
|
||||
|
||||
function JudgmentLineToColor( i )
|
||||
local c = GameColor.Judgment[i]
|
||||
if c then
|
||||
return c
|
||||
end
|
||||
return color("#000000")
|
||||
end
|
||||
|
||||
function JudgmentLineToStrokeColor( i )
|
||||
local c = GameColor.Judgment[i]
|
||||
return { c[1]/2, c[2]/2, c[3]/2, c[4] }
|
||||
-- SSC Color Module and Library
|
||||
local nilColor = color("0,0,0,0")
|
||||
-- Original Color Module.
|
||||
Color = {
|
||||
-- Color Library
|
||||
-- These colors are pure swatch colors and are here purely to be used
|
||||
-- on demand without having to type color("stuff") or dig through
|
||||
-- a palette to get the color you want.
|
||||
Black = color("0,0,0,1"),
|
||||
White = color("1,1,1,1"),
|
||||
Red = color("#ed1c24"),
|
||||
Blue = color("#00aeef"),
|
||||
Green = color("#39b54a"),
|
||||
Yellow = color("#fff200"),
|
||||
Orange = color("#f7941d"),
|
||||
Purple = color("#92278f"),
|
||||
Outline = color("0,0,0,0.5"),
|
||||
Invisible = color("1,1,1,0"),
|
||||
Stealth = nilColor,
|
||||
-- Color Functions
|
||||
-- These functions alter colors in a certain way so that you can make
|
||||
-- new ones without having to copy a color or find a new one.
|
||||
--[[ Brightness(fInput)
|
||||
Hue(hInput)
|
||||
Saturation(hInput)
|
||||
Alpha(hInput)
|
||||
HSV(iHue,fSaturation,fValue or any other overload) --]]
|
||||
Alpha = function(cColor,fAlpha)
|
||||
local c = cColor;
|
||||
return { c[1],c[2],c[3],fAlpha };
|
||||
end
|
||||
}
|
||||
-- Remapped Color Module, since some themes are crazy
|
||||
Colors = Color;
|
||||
|
||||
GameColor = {
|
||||
PlayerColors = {
|
||||
PLAYER_1 = color("#ef403d"),
|
||||
PLAYER_2 = color("#0089cf"),
|
||||
},
|
||||
Difficulty = {
|
||||
--[[ These are for 'Custom' Difficulty Ranks. It can be very useful
|
||||
in some cases, especially to apply new colors for stuff you
|
||||
couldn't before. (huh? -aj) ]]
|
||||
Beginner = color("#ff32f8"), -- light cyan
|
||||
Easy = color("#2cff00"), -- green
|
||||
Medium = color("#fee600"), -- yellow
|
||||
Hard = color("#ff2f39"), -- red
|
||||
Challenge = color("#1cd8ff"), -- light blue
|
||||
Edit = color("0.8,0.8,0.8,1"), -- gray
|
||||
Couple = color("#ed0972"), -- hot pink
|
||||
Routine = color("#ff9a00"), -- orange
|
||||
--[[ These are for courses, so let's slap them here in case someone
|
||||
wanted to use Difficulty in Course and Step regions. ]]
|
||||
Difficulty_Beginner = color("#ff32f8"), -- purple
|
||||
Difficulty_Easy = color("#2cff00"), -- green
|
||||
Difficulty_Medium = color("#fee600"), -- yellow
|
||||
Difficulty_Hard = color("#ff2f39"), -- red
|
||||
Difficulty_Challenge = color("#1cd8ff"), -- light blue
|
||||
Difficulty_Edit = color("0.8,0.8,0.8,1"), -- gray
|
||||
Difficulty_Couple = color("#ed0972"), -- hot pink
|
||||
Difficulty_Routine = color("#ff9a00") -- orange
|
||||
},
|
||||
Stage = {
|
||||
Stage_1st = color("#00ffc7"),
|
||||
Stage_2nd = color("#58ff00"),
|
||||
Stage_3rd = color("#f400ff"),
|
||||
Stage_4th = color("#00ffda"),
|
||||
Stage_5th = color("#ed00ff"),
|
||||
Stage_6th = color("#73ff00"),
|
||||
Stage_Next = color("#73ff00"),
|
||||
Stage_Final = color("#ff0707"),
|
||||
Stage_Extra1 = color("#fafa00"),
|
||||
Stage_Extra2 = color("#ff0707"),
|
||||
Stage_Nonstop = color("#FFFFFF"),
|
||||
Stage_Oni = color("#FFFFFF"),
|
||||
Stage_Endless = color("#FFFFFF"),
|
||||
Stage_Event = color("#FFFFFF"),
|
||||
Stage_Demo = color("#FFFFFF")
|
||||
},
|
||||
Judgment = {
|
||||
JudgmentLine_W1 = color("#bfeaff"),
|
||||
JudgmentLine_W2 = color("#fff568"),
|
||||
JudgmentLine_W3 = color("#a4ff00"),
|
||||
JudgmentLine_W4 = color("#34bfff"),
|
||||
JudgmentLine_W5 = color("#e44dff"),
|
||||
JudgmentLine_Held = color("#FFFFFF"),
|
||||
JudgmentLine_Miss = color("#ff3c3c"),
|
||||
JudgmentLine_MaxCombo = color("#ffc600")
|
||||
},
|
||||
};
|
||||
GameColor.Difficulty["Crazy"] = GameColor.Difficulty["Hard"];
|
||||
GameColor.Difficulty["Freestyle"] = GameColor.Difficulty["Easy"];
|
||||
GameColor.Difficulty["Nightmare"] = GameColor.Difficulty["Challenge"];
|
||||
GameColor.Difficulty["HalfDouble"] = GameColor.Difficulty["Medium"];
|
||||
|
||||
--[[ Fallbacks ]]
|
||||
function Color(c)
|
||||
return Colors[c]
|
||||
end
|
||||
|
||||
function BoostColor( cColor, fBoost )
|
||||
local c = cColor
|
||||
return { c[1]*fBoost, c[2]*fBoost, c[3]*fBoost, c[4] }
|
||||
end
|
||||
|
||||
function ColorLightTone(c)
|
||||
return { c[1]+(c[1]/2), c[2]+(c[2]/2), c[3]+(c[3]/2), c[4] }
|
||||
end
|
||||
|
||||
function ColorMidTone(c)
|
||||
return { c[1]/1.5, c[2]/1.5, c[3]/1.5, c[4] }
|
||||
end
|
||||
|
||||
function ColorDarkTone(c)
|
||||
return { c[1]/2, c[2]/2, c[3]/2, c[4] }
|
||||
end
|
||||
|
||||
function PlayerColor( pn )
|
||||
if pn == PLAYER_1 then
|
||||
return color("#ef403d") -- pink-red
|
||||
end
|
||||
if pn == PLAYER_2 then
|
||||
return color("#0089cf") -- sea-blue
|
||||
end
|
||||
return color("1,1,1,1")
|
||||
end
|
||||
function PlayerScoreColor( pn )
|
||||
if pn == PLAYER_1 then
|
||||
return color("#ef403d") -- pink-red
|
||||
end
|
||||
if pn == PLAYER_2 then
|
||||
return color("#0089cf") -- sea-blue
|
||||
end
|
||||
return color("1,1,1,1")
|
||||
end
|
||||
|
||||
function CustomDifficultyToColor( sCustomDifficulty )
|
||||
return GameColor.Difficulty[sCustomDifficulty]
|
||||
end
|
||||
|
||||
function CustomDifficultyToDarkColor( sCustomDifficulty )
|
||||
local c = GameColor.Difficulty[sCustomDifficulty]
|
||||
return { c[1]/2, c[2]/2, c[3]/2, c[4] }
|
||||
end
|
||||
|
||||
function CustomDifficultyToLightColor( sCustomDifficulty )
|
||||
local c = GameColor.Difficulty[sCustomDifficulty]
|
||||
return { scale(c[1],0,1,0.5,1), scale(c[2],0,1,0.5,1), scale(c[3],0,1,0.5,1), c[4] }
|
||||
end
|
||||
|
||||
function StepsOrTrailToColor(StepsOrTrail)
|
||||
return CustomDifficultyToColor( StepsOrTrailToCustomDifficulty(stepsOrTrail) )
|
||||
end
|
||||
|
||||
function StageToColor( stage )
|
||||
local c = GameColor.Stage[stage]
|
||||
if c then
|
||||
return c
|
||||
end
|
||||
return color("#000000")
|
||||
end
|
||||
|
||||
function StageToStrokeColor( stage )
|
||||
local c = GameColor.Stage[stage]
|
||||
return { c[1]/2, c[2]/2, c[3]/2, c[4] }
|
||||
end
|
||||
|
||||
function JudgmentLineToColor( i )
|
||||
local c = GameColor.Judgment[i]
|
||||
if c then
|
||||
return c
|
||||
end
|
||||
return color("#000000")
|
||||
end
|
||||
|
||||
function JudgmentLineToStrokeColor( i )
|
||||
local c = GameColor.Judgment[i]
|
||||
return { c[1]/2, c[2]/2, c[3]/2, c[4] }
|
||||
end
|
||||
@@ -1,97 +1,97 @@
|
||||
if not debug then
|
||||
-- stubs
|
||||
debug = {}
|
||||
debug.traceback = function() return "" end
|
||||
return
|
||||
end
|
||||
|
||||
-- Override debug.traceback.
|
||||
function debug.traceback(...)
|
||||
local thread = coroutine.running()
|
||||
local msg = ""
|
||||
local level = 1
|
||||
local args = {...}
|
||||
|
||||
if type(args[1]) == "thread" then
|
||||
thread = args[1]
|
||||
table.remove(args)
|
||||
end
|
||||
if type(args[1]) == "string" then
|
||||
msg = args[1]
|
||||
table.remove(args)
|
||||
end
|
||||
if type(args[1]) == "number" then
|
||||
level = args[1]
|
||||
table.remove(args)
|
||||
end
|
||||
|
||||
if thread == coroutine.running() then
|
||||
level = level + 1 -- skip this function
|
||||
end
|
||||
|
||||
local stack = {}
|
||||
repeat
|
||||
local info = debug.getinfo(level, "Sln")
|
||||
table.insert( stack, info )
|
||||
level = level + 1
|
||||
until not info
|
||||
|
||||
if #stack == 0 then
|
||||
return ""
|
||||
end
|
||||
|
||||
-- The original caller is usually C; remove it.
|
||||
if( stack[#stack].what == "C" ) then
|
||||
table.remove( stack )
|
||||
end
|
||||
local function FormatFrame(level, frame)
|
||||
local sFrameInfo = ""
|
||||
sFrameInfo = sFrameInfo .. "#" .. level .. " "
|
||||
if( frame.what == "tail" ) then
|
||||
-- sFrameInfo = sFrameInfo .. "(tail call)"
|
||||
-- return sFrameInfo
|
||||
elseif( frame.what == "main" ) then
|
||||
sFrameInfo = sFrameInfo .. "main in "
|
||||
elseif frame.name then
|
||||
sFrameInfo = sFrameInfo .. frame.name .. "() in "
|
||||
else
|
||||
sFrameInfo = sFrameInfo .. "... in "
|
||||
end
|
||||
sFrameInfo = sFrameInfo .. frame.short_src
|
||||
|
||||
if frame.currentline ~= -1 then
|
||||
sFrameInfo = sFrameInfo .. ":" .. frame.currentline
|
||||
end
|
||||
|
||||
return sFrameInfo
|
||||
end
|
||||
|
||||
local FrameInfo = {}
|
||||
for level, frame in ipairs(stack) do
|
||||
FrameInfo[level] = FormatFrame(level, frame)
|
||||
end
|
||||
return table.concat( FrameInfo, "\n" )
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
if not debug then
|
||||
-- stubs
|
||||
debug = {}
|
||||
debug.traceback = function() return "" end
|
||||
return
|
||||
end
|
||||
|
||||
-- Override debug.traceback.
|
||||
function debug.traceback(...)
|
||||
local thread = coroutine.running()
|
||||
local msg = ""
|
||||
local level = 1
|
||||
local args = {...}
|
||||
|
||||
if type(args[1]) == "thread" then
|
||||
thread = args[1]
|
||||
table.remove(args)
|
||||
end
|
||||
if type(args[1]) == "string" then
|
||||
msg = args[1]
|
||||
table.remove(args)
|
||||
end
|
||||
if type(args[1]) == "number" then
|
||||
level = args[1]
|
||||
table.remove(args)
|
||||
end
|
||||
|
||||
if thread == coroutine.running() then
|
||||
level = level + 1 -- skip this function
|
||||
end
|
||||
|
||||
local stack = {}
|
||||
repeat
|
||||
local info = debug.getinfo(level, "Sln")
|
||||
table.insert( stack, info )
|
||||
level = level + 1
|
||||
until not info
|
||||
|
||||
if #stack == 0 then
|
||||
return ""
|
||||
end
|
||||
|
||||
-- The original caller is usually C; remove it.
|
||||
if( stack[#stack].what == "C" ) then
|
||||
table.remove( stack )
|
||||
end
|
||||
local function FormatFrame(level, frame)
|
||||
local sFrameInfo = ""
|
||||
sFrameInfo = sFrameInfo .. "#" .. level .. " "
|
||||
if( frame.what == "tail" ) then
|
||||
-- sFrameInfo = sFrameInfo .. "(tail call)"
|
||||
-- return sFrameInfo
|
||||
elseif( frame.what == "main" ) then
|
||||
sFrameInfo = sFrameInfo .. "main in "
|
||||
elseif frame.name then
|
||||
sFrameInfo = sFrameInfo .. frame.name .. "() in "
|
||||
else
|
||||
sFrameInfo = sFrameInfo .. "... in "
|
||||
end
|
||||
sFrameInfo = sFrameInfo .. frame.short_src
|
||||
|
||||
if frame.currentline ~= -1 then
|
||||
sFrameInfo = sFrameInfo .. ":" .. frame.currentline
|
||||
end
|
||||
|
||||
return sFrameInfo
|
||||
end
|
||||
|
||||
local FrameInfo = {}
|
||||
for level, frame in ipairs(stack) do
|
||||
FrameInfo[level] = FormatFrame(level, frame)
|
||||
end
|
||||
return table.concat( FrameInfo, "\n" )
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
function Enum:Compare( e1, e2 )
|
||||
local Reverse = self:Reverse()
|
||||
local Value1 = Reverse[e1]
|
||||
local Value2 = Reverse[e2]
|
||||
|
||||
assert( Value1, tostring(e1) .. " is not an enum of type " .. self:GetName() )
|
||||
assert( Value2, tostring(e2) .. " is not an enum of type " .. self:GetName() )
|
||||
|
||||
-- Nil enums correspond to "invalid". These compare greater
|
||||
-- than any valid enum value, to line up with the equivalent
|
||||
-- C++ code.
|
||||
|
||||
-- should this be changed to math.huge()? -shake
|
||||
if not e1 then
|
||||
Value1 = 99999999
|
||||
end
|
||||
if not e2 then
|
||||
Value2 = 99999999
|
||||
end
|
||||
return Value1 - Value2
|
||||
end
|
||||
|
||||
function ToEnumShortString( e )
|
||||
local pos = string.find( e, '_' )
|
||||
assert( pos, "'" .. e .. "' is not an enum value" )
|
||||
return string.sub( e, pos+1 )
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
function Enum:Compare( e1, e2 )
|
||||
local Reverse = self:Reverse()
|
||||
local Value1 = Reverse[e1]
|
||||
local Value2 = Reverse[e2]
|
||||
|
||||
assert( Value1, tostring(e1) .. " is not an enum of type " .. self:GetName() )
|
||||
assert( Value2, tostring(e2) .. " is not an enum of type " .. self:GetName() )
|
||||
|
||||
-- Nil enums correspond to "invalid". These compare greater
|
||||
-- than any valid enum value, to line up with the equivalent
|
||||
-- C++ code.
|
||||
|
||||
-- should this be changed to math.huge()? -shake
|
||||
if not e1 then
|
||||
Value1 = 99999999
|
||||
end
|
||||
if not e2 then
|
||||
Value2 = 99999999
|
||||
end
|
||||
return Value1 - Value2
|
||||
end
|
||||
|
||||
function ToEnumShortString( e )
|
||||
local pos = string.find( e, '_' )
|
||||
assert( pos, "'" .. e .. "' is not an enum value" )
|
||||
return string.sub( e, pos+1 )
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
function HelpDisplay:setfromsongorcourse()
|
||||
local Artists = {}
|
||||
local AltArtists = {}
|
||||
|
||||
local Song = GAMESTATE:GetCurrentSong()
|
||||
local Trail = GAMESTATE:GetCurrentTrail( GAMESTATE:GetMasterPlayerNumber() )
|
||||
if Song then
|
||||
table.insert( Artists, Song:GetDisplayArtist() )
|
||||
table.insert( AltArtists, Song:GetTranslitArtist() )
|
||||
elseif Trail then
|
||||
Artists, AltArtists = Trail:GetArtists()
|
||||
end
|
||||
|
||||
self:settips( Artists, AltArtists )
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
function HelpDisplay:setfromsongorcourse()
|
||||
local Artists = {}
|
||||
local AltArtists = {}
|
||||
|
||||
local Song = GAMESTATE:GetCurrentSong()
|
||||
local Trail = GAMESTATE:GetCurrentTrail( GAMESTATE:GetMasterPlayerNumber() )
|
||||
if Song then
|
||||
table.insert( Artists, Song:GetDisplayArtist() )
|
||||
table.insert( AltArtists, Song:GetTranslitArtist() )
|
||||
elseif Trail then
|
||||
Artists, AltArtists = Trail:GetArtists()
|
||||
end
|
||||
|
||||
self:settips( Artists, AltArtists )
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
function Actor:LyricCommand(side)
|
||||
self:settext( Var "LyricText" )
|
||||
|
||||
self:stoptweening()
|
||||
self:shadowlengthx(0)
|
||||
self:shadowlengthy(5)
|
||||
self:strokecolor(color("#000000"))
|
||||
|
||||
local Zoom = SCREEN_WIDTH / (self:GetZoomedWidth()+1)
|
||||
if( Zoom > 1 ) then
|
||||
Zoom = 1
|
||||
end
|
||||
self:zoomx( Zoom )
|
||||
|
||||
local lyricColor = Var "LyricColor"
|
||||
local Factor = 1
|
||||
if side == "Back" then
|
||||
Factor = 0.5
|
||||
elseif side == "Front" then
|
||||
Factor = 0.9
|
||||
end
|
||||
self:diffuse( {
|
||||
lyricColor[1] * Factor,
|
||||
lyricColor[2] * Factor,
|
||||
lyricColor[3] * Factor,
|
||||
lyricColor[4] * Factor } )
|
||||
|
||||
if side == "Front" then
|
||||
self:cropright(1)
|
||||
else
|
||||
self:cropleft(0)
|
||||
end
|
||||
|
||||
self:diffusealpha(0)
|
||||
self:linear(0.2)
|
||||
self:diffusealpha(0.75)
|
||||
self:linear( Var "LyricDuration" * 0.75)
|
||||
if side == "Front" then
|
||||
self:cropright(0)
|
||||
else
|
||||
self:cropleft(1)
|
||||
end
|
||||
self:sleep( Var "LyricDuration" * 0.25 )
|
||||
self:linear(0.2)
|
||||
self:diffusealpha(0)
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
function Actor:LyricCommand(side)
|
||||
self:settext( Var "LyricText" )
|
||||
|
||||
self:stoptweening()
|
||||
self:shadowlengthx(0)
|
||||
self:shadowlengthy(5)
|
||||
self:strokecolor(color("#000000"))
|
||||
|
||||
local Zoom = SCREEN_WIDTH / (self:GetZoomedWidth()+1)
|
||||
if( Zoom > 1 ) then
|
||||
Zoom = 1
|
||||
end
|
||||
self:zoomx( Zoom )
|
||||
|
||||
local lyricColor = Var "LyricColor"
|
||||
local Factor = 1
|
||||
if side == "Back" then
|
||||
Factor = 0.5
|
||||
elseif side == "Front" then
|
||||
Factor = 0.9
|
||||
end
|
||||
self:diffuse( {
|
||||
lyricColor[1] * Factor,
|
||||
lyricColor[2] * Factor,
|
||||
lyricColor[3] * Factor,
|
||||
lyricColor[4] * Factor } )
|
||||
|
||||
if side == "Front" then
|
||||
self:cropright(1)
|
||||
else
|
||||
self:cropleft(0)
|
||||
end
|
||||
|
||||
self:diffusealpha(0)
|
||||
self:linear(0.2)
|
||||
self:diffusealpha(0.75)
|
||||
self:linear( Var "LyricDuration" * 0.75)
|
||||
if side == "Front" then
|
||||
self:cropright(0)
|
||||
else
|
||||
self:cropleft(1)
|
||||
end
|
||||
self:sleep( Var "LyricDuration" * 0.25 )
|
||||
self:linear(0.2)
|
||||
self:diffusealpha(0)
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
@@ -1,120 +1,120 @@
|
||||
-- Sample options menu item.
|
||||
function OptionsRowTest()
|
||||
local function Set(self,list,pn)
|
||||
if list[1] then
|
||||
Trace("FOO: 1")
|
||||
end
|
||||
if list[2] then
|
||||
Trace("FOO: 2")
|
||||
end
|
||||
end
|
||||
return
|
||||
{
|
||||
-- Name is used to retrieve the header and explanation text.
|
||||
Name = "Foo",
|
||||
|
||||
-- Flags for this row. Note that as this table only defines
|
||||
-- a row, not a menu, only row settings can be set here, not
|
||||
-- OptionMenuFlags.
|
||||
LayoutType = "ShowAllInRow",
|
||||
SelectType = "SelectMultiple",
|
||||
OneChoiceForAllPlayers = false,
|
||||
ExportOnChange = false,
|
||||
|
||||
-- Choices are not resolved as metrics, since they might
|
||||
-- be dynamic. Add THEME Lua hooks if we want to translate
|
||||
-- these.
|
||||
Choices = { "Option1", "Option2" },
|
||||
-- Or:
|
||||
-- for i = 1,20 do Choices[i] = "Option " .. i end
|
||||
|
||||
-- Set list[1] to true if Option1 should be selected, and
|
||||
-- list[2] if Option2 should be selected. This will be
|
||||
-- called once per enabled player.
|
||||
LoadSelections = function(self,list,pn)
|
||||
list[1] = true
|
||||
end,
|
||||
SaveSelections = Set
|
||||
}
|
||||
end
|
||||
|
||||
-- This option row loads and saves the results to a table. For example, if you
|
||||
-- have options "fast" and "slow", and the name of the option is "run", then the
|
||||
-- table will be set to table["run"] = "fast" (or "slow"), and loaded appropriately.
|
||||
-- (This could handle SelectMultiple, by saving the result to a table, eg.
|
||||
-- table["run"]["fast"] = true.)
|
||||
|
||||
OptionRowTable =
|
||||
{
|
||||
SaveTo = nil, -- set this
|
||||
Default = nil, -- set this
|
||||
|
||||
LoadSelections = function(self, list, pn)
|
||||
local Sort = self.SaveTo[self.Name] or self.Default
|
||||
-- Find the index of the current sort.
|
||||
local Index = FindValue(self.RawChoices, Sort) or 1
|
||||
list[Index] = true
|
||||
end,
|
||||
|
||||
SaveSelections = function(self, list, pn)
|
||||
local Selection = FindSelection( list )
|
||||
self.SaveTo[self.Name] = self.RawChoices[Selection]
|
||||
end
|
||||
}
|
||||
|
||||
function OptionsRandomJukebox()
|
||||
local function AllChoices()
|
||||
Trace('all choices')
|
||||
local ret = { 'Off', 'Random' }
|
||||
return ret
|
||||
end
|
||||
|
||||
local t =
|
||||
{
|
||||
-- Name is used to retrieve the header and explanation text.
|
||||
Name = "OptionsRandomJukebox",
|
||||
LayoutType = "ShowAllInRow",
|
||||
SelectType = "SelectOne",
|
||||
OneChoiceForAllPlayers = true,
|
||||
ExportOnChange = false,
|
||||
Choices = AllChoices(),
|
||||
LoadSelections = function(self, list, pn)
|
||||
list[1] = true
|
||||
end,
|
||||
SaveSelections = function(self, list, pn)
|
||||
local val
|
||||
if list[1] then
|
||||
val = false
|
||||
else
|
||||
val = true
|
||||
end
|
||||
GAMESTATE:SetJukeboxUsesModifiers(val)
|
||||
end
|
||||
}
|
||||
setmetatable( t, t )
|
||||
return t
|
||||
end
|
||||
|
||||
-- (c) 2005 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-- Sample options menu item.
|
||||
function OptionsRowTest()
|
||||
local function Set(self,list,pn)
|
||||
if list[1] then
|
||||
Trace("FOO: 1")
|
||||
end
|
||||
if list[2] then
|
||||
Trace("FOO: 2")
|
||||
end
|
||||
end
|
||||
return
|
||||
{
|
||||
-- Name is used to retrieve the header and explanation text.
|
||||
Name = "Foo",
|
||||
|
||||
-- Flags for this row. Note that as this table only defines
|
||||
-- a row, not a menu, only row settings can be set here, not
|
||||
-- OptionMenuFlags.
|
||||
LayoutType = "ShowAllInRow",
|
||||
SelectType = "SelectMultiple",
|
||||
OneChoiceForAllPlayers = false,
|
||||
ExportOnChange = false,
|
||||
|
||||
-- Choices are not resolved as metrics, since they might
|
||||
-- be dynamic. Add THEME Lua hooks if we want to translate
|
||||
-- these.
|
||||
Choices = { "Option1", "Option2" },
|
||||
-- Or:
|
||||
-- for i = 1,20 do Choices[i] = "Option " .. i end
|
||||
|
||||
-- Set list[1] to true if Option1 should be selected, and
|
||||
-- list[2] if Option2 should be selected. This will be
|
||||
-- called once per enabled player.
|
||||
LoadSelections = function(self,list,pn)
|
||||
list[1] = true
|
||||
end,
|
||||
SaveSelections = Set
|
||||
}
|
||||
end
|
||||
|
||||
-- This option row loads and saves the results to a table. For example, if you
|
||||
-- have options "fast" and "slow", and the name of the option is "run", then the
|
||||
-- table will be set to table["run"] = "fast" (or "slow"), and loaded appropriately.
|
||||
-- (This could handle SelectMultiple, by saving the result to a table, eg.
|
||||
-- table["run"]["fast"] = true.)
|
||||
|
||||
OptionRowTable =
|
||||
{
|
||||
SaveTo = nil, -- set this
|
||||
Default = nil, -- set this
|
||||
|
||||
LoadSelections = function(self, list, pn)
|
||||
local Sort = self.SaveTo[self.Name] or self.Default
|
||||
-- Find the index of the current sort.
|
||||
local Index = FindValue(self.RawChoices, Sort) or 1
|
||||
list[Index] = true
|
||||
end,
|
||||
|
||||
SaveSelections = function(self, list, pn)
|
||||
local Selection = FindSelection( list )
|
||||
self.SaveTo[self.Name] = self.RawChoices[Selection]
|
||||
end
|
||||
}
|
||||
|
||||
function OptionsRandomJukebox()
|
||||
local function AllChoices()
|
||||
Trace('all choices')
|
||||
local ret = { 'Off', 'Random' }
|
||||
return ret
|
||||
end
|
||||
|
||||
local t =
|
||||
{
|
||||
-- Name is used to retrieve the header and explanation text.
|
||||
Name = "OptionsRandomJukebox",
|
||||
LayoutType = "ShowAllInRow",
|
||||
SelectType = "SelectOne",
|
||||
OneChoiceForAllPlayers = true,
|
||||
ExportOnChange = false,
|
||||
Choices = AllChoices(),
|
||||
LoadSelections = function(self, list, pn)
|
||||
list[1] = true
|
||||
end,
|
||||
SaveSelections = function(self, list, pn)
|
||||
local val
|
||||
if list[1] then
|
||||
val = false
|
||||
else
|
||||
val = true
|
||||
end
|
||||
GAMESTATE:SetJukeboxUsesModifiers(val)
|
||||
end
|
||||
}
|
||||
setmetatable( t, t )
|
||||
return t
|
||||
end
|
||||
|
||||
-- (c) 2005 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
@@ -1,150 +1,150 @@
|
||||
local g_metrics_group = nil;
|
||||
local g_element = nil;
|
||||
|
||||
SSC = (ProductID() == "sm-ssc");
|
||||
|
||||
function LoadFallbackB()
|
||||
-- Load the fallback BGA for the element that is currently being loaded.
|
||||
-- The fallback metrics group and element name will come either from LuaThreadVars
|
||||
-- (loading from C++) or from the Lua globals above (loading from Lua).
|
||||
|
||||
--Warn( "g_element " .. (g_element or "") );
|
||||
--Warn( "MatchingElement " .. (Var 'MatchingElement' or "") );
|
||||
--Warn( "g_metrics_group " .. (g_metrics_group or "") );
|
||||
--Warn( "MatchingMetricsGroup " .. (Var 'MatchingMetricsGroup' or "") );
|
||||
|
||||
local metrics_group = g_metrics_group or Var 'MatchingMetricsGroup';
|
||||
local element = g_element or Var 'MatchingElement';
|
||||
local fallback = THEME:GetMetric(metrics_group,'Fallback');
|
||||
|
||||
local old_metrics_group = g_metrics_group;
|
||||
local old_element = g_element;
|
||||
|
||||
local path;
|
||||
path, g_metrics_group, g_element = THEME:GetPathInfoB(fallback,element);
|
||||
--Trace('path ' .. path );
|
||||
local t = LoadActor( path );
|
||||
|
||||
g_metrics_group = old_metrics_group;
|
||||
g_element = old_element;
|
||||
|
||||
return t;
|
||||
end
|
||||
|
||||
function FormatNumSongsPlayed( num )
|
||||
local s = num..' song';
|
||||
if s == 1 then
|
||||
s = s .. ' ';
|
||||
else
|
||||
s = s .. 's';
|
||||
end
|
||||
return s..' played';
|
||||
end
|
||||
|
||||
function JudgmentTransformCommand( self, params )
|
||||
local x = 0
|
||||
local y = -30
|
||||
if params.bReverse then y = y * -1 end
|
||||
-- This makes no sense and wasn't even being used due to misspelling.
|
||||
-- if bCentered then y = y * 2 end
|
||||
self:x( x )
|
||||
self:y( y )
|
||||
end
|
||||
|
||||
function JudgmentTransformSharedCommand( self, params )
|
||||
local x = -120
|
||||
local y = -30
|
||||
if params.bReverse then y = 30 end
|
||||
if params.Player == PLAYER_1 then x = 120 end
|
||||
self:x( x )
|
||||
self:y( y )
|
||||
end
|
||||
|
||||
function ComboTransformCommand( self, params )
|
||||
local x = 0
|
||||
local y = 30
|
||||
if params.bReverse then y = y * -1 end
|
||||
|
||||
if params.bCentered then
|
||||
if params.bReverse then
|
||||
y = y - 30
|
||||
else
|
||||
y = y + 40
|
||||
end
|
||||
end
|
||||
self:x( x )
|
||||
self:y( y )
|
||||
end
|
||||
|
||||
function GetEditModeSubScreens()
|
||||
return
|
||||
"ScreenMiniMenuEditHelp," ..
|
||||
"ScreenMiniMenuMainMenu," ..
|
||||
"ScreenMiniMenuAreaMenu," ..
|
||||
"ScreenMiniMenuStepsInformation," ..
|
||||
"ScreenMiniMenuSongInformation," ..
|
||||
"ScreenMiniMenuBackgroundChange," ..
|
||||
"ScreenMiniMenuInsertTapAttack," ..
|
||||
"ScreenMiniMenuInsertCourseAttack," ..
|
||||
"ScreenMiniMenuCourseDisplay," ..
|
||||
"ScreenEditOptions";
|
||||
end
|
||||
|
||||
function GetCoursesToShowRanking()
|
||||
local CoursesToShowRanking = PREFSMAN:GetPreference("CoursesToShowRanking")
|
||||
if CoursesToShowRanking ~= "" then return CoursesToShowRanking end
|
||||
return "Courses/Default/MostPlayed_01-04.crs,Courses/Default/MostPlayed_05-08.crs,Courses/Default/MostPlayed_09-12.crs"
|
||||
end
|
||||
|
||||
-- Get a metric from the currently-loading screen. This is only valid while loading
|
||||
-- an actor, such as from File or InitCommand attributes; not from commands.
|
||||
Screen = {
|
||||
Metric = function ( sName )
|
||||
local sClass = Var "LoadingScreen"
|
||||
return THEME:GetMetric( sClass, sName )
|
||||
end,
|
||||
String = function ( sName )
|
||||
local sClass = Var "LoadingScreen";
|
||||
return THEME:GetString( sClass, sName )
|
||||
end
|
||||
};
|
||||
|
||||
function TextBannerAfterSet(self,param)
|
||||
local Title=self:GetChild("Title");
|
||||
local Subtitle=self:GetChild("Subtitle");
|
||||
--local Artist=self:GetChild("Artist");
|
||||
if Subtitle:GetText() == "" then
|
||||
(cmd(maxwidth,208;y,0;zoom,1.0;))(Title);
|
||||
(cmd(visible,false))(Subtitle);
|
||||
--(cmd(zoom,0.66;maxwidth,300;y,7))(Artist);
|
||||
else
|
||||
-- subtitle below
|
||||
(cmd(zoom,1;y,-6;zoom,0.9;))(Title);
|
||||
(cmd(visible,true;zoom,0.6;y,7))(Subtitle);
|
||||
--(cmd(zoom,0.66;maxwidth,300;y,9))(Artist);
|
||||
end
|
||||
end
|
||||
|
||||
-- (c) 2005 Chris Danford
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
local g_metrics_group = nil;
|
||||
local g_element = nil;
|
||||
|
||||
SSC = (ProductID() == "sm-ssc");
|
||||
|
||||
function LoadFallbackB()
|
||||
-- Load the fallback BGA for the element that is currently being loaded.
|
||||
-- The fallback metrics group and element name will come either from LuaThreadVars
|
||||
-- (loading from C++) or from the Lua globals above (loading from Lua).
|
||||
|
||||
--Warn( "g_element " .. (g_element or "") );
|
||||
--Warn( "MatchingElement " .. (Var 'MatchingElement' or "") );
|
||||
--Warn( "g_metrics_group " .. (g_metrics_group or "") );
|
||||
--Warn( "MatchingMetricsGroup " .. (Var 'MatchingMetricsGroup' or "") );
|
||||
|
||||
local metrics_group = g_metrics_group or Var 'MatchingMetricsGroup';
|
||||
local element = g_element or Var 'MatchingElement';
|
||||
local fallback = THEME:GetMetric(metrics_group,'Fallback');
|
||||
|
||||
local old_metrics_group = g_metrics_group;
|
||||
local old_element = g_element;
|
||||
|
||||
local path;
|
||||
path, g_metrics_group, g_element = THEME:GetPathInfoB(fallback,element);
|
||||
--Trace('path ' .. path );
|
||||
local t = LoadActor( path );
|
||||
|
||||
g_metrics_group = old_metrics_group;
|
||||
g_element = old_element;
|
||||
|
||||
return t;
|
||||
end
|
||||
|
||||
function FormatNumSongsPlayed( num )
|
||||
local s = num..' song';
|
||||
if s == 1 then
|
||||
s = s .. ' ';
|
||||
else
|
||||
s = s .. 's';
|
||||
end
|
||||
return s..' played';
|
||||
end
|
||||
|
||||
function JudgmentTransformCommand( self, params )
|
||||
local x = 0
|
||||
local y = -30
|
||||
if params.bReverse then y = y * -1 end
|
||||
-- This makes no sense and wasn't even being used due to misspelling.
|
||||
-- if bCentered then y = y * 2 end
|
||||
self:x( x )
|
||||
self:y( y )
|
||||
end
|
||||
|
||||
function JudgmentTransformSharedCommand( self, params )
|
||||
local x = -120
|
||||
local y = -30
|
||||
if params.bReverse then y = 30 end
|
||||
if params.Player == PLAYER_1 then x = 120 end
|
||||
self:x( x )
|
||||
self:y( y )
|
||||
end
|
||||
|
||||
function ComboTransformCommand( self, params )
|
||||
local x = 0
|
||||
local y = 30
|
||||
if params.bReverse then y = y * -1 end
|
||||
|
||||
if params.bCentered then
|
||||
if params.bReverse then
|
||||
y = y - 30
|
||||
else
|
||||
y = y + 40
|
||||
end
|
||||
end
|
||||
self:x( x )
|
||||
self:y( y )
|
||||
end
|
||||
|
||||
function GetEditModeSubScreens()
|
||||
return
|
||||
"ScreenMiniMenuEditHelp," ..
|
||||
"ScreenMiniMenuMainMenu," ..
|
||||
"ScreenMiniMenuAreaMenu," ..
|
||||
"ScreenMiniMenuStepsInformation," ..
|
||||
"ScreenMiniMenuSongInformation," ..
|
||||
"ScreenMiniMenuBackgroundChange," ..
|
||||
"ScreenMiniMenuInsertTapAttack," ..
|
||||
"ScreenMiniMenuInsertCourseAttack," ..
|
||||
"ScreenMiniMenuCourseDisplay," ..
|
||||
"ScreenEditOptions";
|
||||
end
|
||||
|
||||
function GetCoursesToShowRanking()
|
||||
local CoursesToShowRanking = PREFSMAN:GetPreference("CoursesToShowRanking")
|
||||
if CoursesToShowRanking ~= "" then return CoursesToShowRanking end
|
||||
return "Courses/Default/MostPlayed_01-04.crs,Courses/Default/MostPlayed_05-08.crs,Courses/Default/MostPlayed_09-12.crs"
|
||||
end
|
||||
|
||||
-- Get a metric from the currently-loading screen. This is only valid while loading
|
||||
-- an actor, such as from File or InitCommand attributes; not from commands.
|
||||
Screen = {
|
||||
Metric = function ( sName )
|
||||
local sClass = Var "LoadingScreen"
|
||||
return THEME:GetMetric( sClass, sName )
|
||||
end,
|
||||
String = function ( sName )
|
||||
local sClass = Var "LoadingScreen";
|
||||
return THEME:GetString( sClass, sName )
|
||||
end
|
||||
};
|
||||
|
||||
function TextBannerAfterSet(self,param)
|
||||
local Title=self:GetChild("Title");
|
||||
local Subtitle=self:GetChild("Subtitle");
|
||||
--local Artist=self:GetChild("Artist");
|
||||
if Subtitle:GetText() == "" then
|
||||
(cmd(maxwidth,208;y,0;zoom,1.0;))(Title);
|
||||
(cmd(visible,false))(Subtitle);
|
||||
--(cmd(zoom,0.66;maxwidth,300;y,7))(Artist);
|
||||
else
|
||||
-- subtitle below
|
||||
(cmd(zoom,1;y,-6;zoom,0.9;))(Title);
|
||||
(cmd(visible,true;zoom,0.6;y,7))(Subtitle);
|
||||
--(cmd(zoom,0.66;maxwidth,300;y,9))(Artist);
|
||||
end
|
||||
end
|
||||
|
||||
-- (c) 2005 Chris Danford
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
@@ -1,119 +1,119 @@
|
||||
-- Serialize the table "t".
|
||||
function Serialize(t)
|
||||
local ret = ""
|
||||
local queue = { }
|
||||
local already_queued = { }
|
||||
|
||||
-- Convert a value to an identifier. If we encounter a table that we've never seen before,
|
||||
-- it's an anonymous table and we'll create a name for it; for example, in t = { [ {10} ] = 1 },
|
||||
-- "{10}" has no name.
|
||||
local next_id = 1
|
||||
local function convert_to_identifier( v, name )
|
||||
-- print("convert_to_identifier: " .. (name or "nil"))
|
||||
if type(v) == "string" then
|
||||
return string.format("%q", v)
|
||||
elseif type(v) == "nil" then
|
||||
return "nil"
|
||||
elseif type(v) == "boolean" then
|
||||
if v then return "true" end
|
||||
return "false"
|
||||
elseif type(v) == "number" then
|
||||
return string.format("%i", v)
|
||||
elseif type(v) == "table" then
|
||||
if already_queued[v] then
|
||||
return already_queued[v]
|
||||
end
|
||||
|
||||
-- Create the table. If we have no name, give it one; be sure to make it local.
|
||||
if not name then
|
||||
name = "tab" .. next_id
|
||||
next_id = next_id + 1
|
||||
ret = ret .. "local " .. name .. " = { }\n"
|
||||
else
|
||||
-- The name is probably something like "x[1][2][3]", so don't emit "local".
|
||||
ret = ret .. name .. " = { }\n"
|
||||
end
|
||||
|
||||
for i, tab in pairs(v) do
|
||||
local to_fill = { ["name"] = name .. "[" .. convert_to_identifier(i) .. "]", with = tab }
|
||||
table.insert( queue, to_fill )
|
||||
end
|
||||
|
||||
already_queued[v] = name
|
||||
return name
|
||||
else
|
||||
return '"UNSUPPORTED TYPE (' .. type(v) .. ')"', true
|
||||
end
|
||||
end
|
||||
|
||||
local top_name = convert_to_identifier( t )
|
||||
|
||||
while table.getn(queue) > 0 do
|
||||
local to_fill = table.remove( queue, 1 )
|
||||
local str = convert_to_identifier( to_fill.with, to_fill.name )
|
||||
-- Assign the result. If to_fill.with is a non-anonymous table, we just created
|
||||
-- it ("ret[1] = { }"); don't redundantly write "ret[1] = ret[1]".
|
||||
if to_fill.name ~= str then
|
||||
ret = ret .. to_fill.name .. " = " .. str .. "\n"
|
||||
end
|
||||
end
|
||||
ret = ret .. "return " .. top_name
|
||||
return ret
|
||||
end
|
||||
|
||||
-- Recursively deep-copy a table.
|
||||
function DeepCopy(From, To, already_copied)
|
||||
if not To then To = {} end
|
||||
|
||||
already_copied = already_copied or { }
|
||||
already_copied[From] = To
|
||||
|
||||
for a, b in pairs(From) do
|
||||
local aCopy, bCopy
|
||||
if type(a) ~= "table" then
|
||||
aCopy = a
|
||||
elseif already_copied[a] then
|
||||
aCopy = already_copied[a]
|
||||
else
|
||||
aCopy = {}
|
||||
DeepCopy( a, aCopy, already_copied )
|
||||
end
|
||||
|
||||
if type(b) ~= "table" then
|
||||
bCopy = b
|
||||
elseif already_copied[b] then
|
||||
bCopy = already_copied[b]
|
||||
else
|
||||
bCopy = {}
|
||||
DeepCopy( b, bCopy, already_copied )
|
||||
end
|
||||
|
||||
To[aCopy] = bCopy
|
||||
end
|
||||
|
||||
return To
|
||||
end
|
||||
|
||||
-- (c) 2005 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-- Serialize the table "t".
|
||||
function Serialize(t)
|
||||
local ret = ""
|
||||
local queue = { }
|
||||
local already_queued = { }
|
||||
|
||||
-- Convert a value to an identifier. If we encounter a table that we've never seen before,
|
||||
-- it's an anonymous table and we'll create a name for it; for example, in t = { [ {10} ] = 1 },
|
||||
-- "{10}" has no name.
|
||||
local next_id = 1
|
||||
local function convert_to_identifier( v, name )
|
||||
-- print("convert_to_identifier: " .. (name or "nil"))
|
||||
if type(v) == "string" then
|
||||
return string.format("%q", v)
|
||||
elseif type(v) == "nil" then
|
||||
return "nil"
|
||||
elseif type(v) == "boolean" then
|
||||
if v then return "true" end
|
||||
return "false"
|
||||
elseif type(v) == "number" then
|
||||
return string.format("%i", v)
|
||||
elseif type(v) == "table" then
|
||||
if already_queued[v] then
|
||||
return already_queued[v]
|
||||
end
|
||||
|
||||
-- Create the table. If we have no name, give it one; be sure to make it local.
|
||||
if not name then
|
||||
name = "tab" .. next_id
|
||||
next_id = next_id + 1
|
||||
ret = ret .. "local " .. name .. " = { }\n"
|
||||
else
|
||||
-- The name is probably something like "x[1][2][3]", so don't emit "local".
|
||||
ret = ret .. name .. " = { }\n"
|
||||
end
|
||||
|
||||
for i, tab in pairs(v) do
|
||||
local to_fill = { ["name"] = name .. "[" .. convert_to_identifier(i) .. "]", with = tab }
|
||||
table.insert( queue, to_fill )
|
||||
end
|
||||
|
||||
already_queued[v] = name
|
||||
return name
|
||||
else
|
||||
return '"UNSUPPORTED TYPE (' .. type(v) .. ')"', true
|
||||
end
|
||||
end
|
||||
|
||||
local top_name = convert_to_identifier( t )
|
||||
|
||||
while table.getn(queue) > 0 do
|
||||
local to_fill = table.remove( queue, 1 )
|
||||
local str = convert_to_identifier( to_fill.with, to_fill.name )
|
||||
-- Assign the result. If to_fill.with is a non-anonymous table, we just created
|
||||
-- it ("ret[1] = { }"); don't redundantly write "ret[1] = ret[1]".
|
||||
if to_fill.name ~= str then
|
||||
ret = ret .. to_fill.name .. " = " .. str .. "\n"
|
||||
end
|
||||
end
|
||||
ret = ret .. "return " .. top_name
|
||||
return ret
|
||||
end
|
||||
|
||||
-- Recursively deep-copy a table.
|
||||
function DeepCopy(From, To, already_copied)
|
||||
if not To then To = {} end
|
||||
|
||||
already_copied = already_copied or { }
|
||||
already_copied[From] = To
|
||||
|
||||
for a, b in pairs(From) do
|
||||
local aCopy, bCopy
|
||||
if type(a) ~= "table" then
|
||||
aCopy = a
|
||||
elseif already_copied[a] then
|
||||
aCopy = already_copied[a]
|
||||
else
|
||||
aCopy = {}
|
||||
DeepCopy( a, aCopy, already_copied )
|
||||
end
|
||||
|
||||
if type(b) ~= "table" then
|
||||
bCopy = b
|
||||
elseif already_copied[b] then
|
||||
bCopy = already_copied[b]
|
||||
else
|
||||
bCopy = {}
|
||||
DeepCopy( b, bCopy, already_copied )
|
||||
end
|
||||
|
||||
To[aCopy] = bCopy
|
||||
end
|
||||
|
||||
return To
|
||||
end
|
||||
|
||||
-- (c) 2005 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
-- Can this be moved into some other file? Feels like clutter. -shake
|
||||
-- Play the sound on the given player's side. Must set SupportPan = true
|
||||
-- on load.
|
||||
function ActorSound:playforplayer(pn)
|
||||
local fBalance = SOUND:GetPlayerBalance(pn)
|
||||
self:get():SetProperty("Pan", fBalance)
|
||||
self:play()
|
||||
end
|
||||
|
||||
-- (c) 2007 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-- Can this be moved into some other file? Feels like clutter. -shake
|
||||
-- Play the sound on the given player's side. Must set SupportPan = true
|
||||
-- on load.
|
||||
function ActorSound:playforplayer(pn)
|
||||
local fBalance = SOUND:GetPlayerBalance(pn)
|
||||
self:get():SetProperty("Pan", fBalance)
|
||||
self:play()
|
||||
end
|
||||
|
||||
-- (c) 2007 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
@@ -1,89 +1,89 @@
|
||||
function Sprite:LoadFromSongBanner(song)
|
||||
if song then
|
||||
local Path = song:GetBannerPath()
|
||||
if not Path then
|
||||
Path = THEME:GetPathG("Common","fallback banner")
|
||||
end
|
||||
|
||||
self:LoadBanner( Path )
|
||||
else
|
||||
self:LoadBanner( THEME:GetPathG("Common","fallback banner") )
|
||||
end
|
||||
end
|
||||
|
||||
function Sprite:LoadFromSongBackground(song)
|
||||
local Path = song:GetBackgroundPath()
|
||||
if not Path then
|
||||
Path = THEME:GetPathG("Common","fallback background")
|
||||
end
|
||||
|
||||
self:LoadBackground( Path )
|
||||
end
|
||||
|
||||
function LoadSongBackground()
|
||||
return Def.Sprite {
|
||||
InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y),
|
||||
BeginCommand=cmd(LoadFromSongBackground,GAMESTATE:GetCurrentSong();scale_or_crop_background)
|
||||
}
|
||||
end
|
||||
|
||||
function Sprite:LoadFromCurrentSongBackground()
|
||||
local song = GAMESTATE:GetCurrentSong();
|
||||
if not song then
|
||||
local trail = GAMESTATE:GetCurrentTrail(GAMESTATE:GetMasterPlayerNumber());
|
||||
local e = trail:GetEntries()
|
||||
if #e > 0 then
|
||||
song = e[1]:GetSong();
|
||||
end
|
||||
end
|
||||
|
||||
if not song then return end
|
||||
|
||||
self:LoadFromSongBackground(song);
|
||||
end
|
||||
|
||||
function Sprite:position( f )
|
||||
self:GetTexture():position( f )
|
||||
end
|
||||
|
||||
function Sprite:loop( f )
|
||||
self:GetTexture():loop( f )
|
||||
end
|
||||
|
||||
function Sprite:rate( f )
|
||||
self:GetTexture():rate( f )
|
||||
end
|
||||
|
||||
function Sprite.LinearFrames(NumFrames, Seconds)
|
||||
local Frames = {}
|
||||
for i = 0,NumFrames-1 do
|
||||
Frames[#Frames+1] = {
|
||||
Frame = i,
|
||||
Delay = (1/NumFrames)*Seconds
|
||||
}
|
||||
end
|
||||
return Frames
|
||||
end
|
||||
|
||||
-- (c) 2005 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
function Sprite:LoadFromSongBanner(song)
|
||||
if song then
|
||||
local Path = song:GetBannerPath()
|
||||
if not Path then
|
||||
Path = THEME:GetPathG("Common","fallback banner")
|
||||
end
|
||||
|
||||
self:LoadBanner( Path )
|
||||
else
|
||||
self:LoadBanner( THEME:GetPathG("Common","fallback banner") )
|
||||
end
|
||||
end
|
||||
|
||||
function Sprite:LoadFromSongBackground(song)
|
||||
local Path = song:GetBackgroundPath()
|
||||
if not Path then
|
||||
Path = THEME:GetPathG("Common","fallback background")
|
||||
end
|
||||
|
||||
self:LoadBackground( Path )
|
||||
end
|
||||
|
||||
function LoadSongBackground()
|
||||
return Def.Sprite {
|
||||
InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y),
|
||||
BeginCommand=cmd(LoadFromSongBackground,GAMESTATE:GetCurrentSong();scale_or_crop_background)
|
||||
}
|
||||
end
|
||||
|
||||
function Sprite:LoadFromCurrentSongBackground()
|
||||
local song = GAMESTATE:GetCurrentSong();
|
||||
if not song then
|
||||
local trail = GAMESTATE:GetCurrentTrail(GAMESTATE:GetMasterPlayerNumber());
|
||||
local e = trail:GetEntries()
|
||||
if #e > 0 then
|
||||
song = e[1]:GetSong();
|
||||
end
|
||||
end
|
||||
|
||||
if not song then return end
|
||||
|
||||
self:LoadFromSongBackground(song);
|
||||
end
|
||||
|
||||
function Sprite:position( f )
|
||||
self:GetTexture():position( f )
|
||||
end
|
||||
|
||||
function Sprite:loop( f )
|
||||
self:GetTexture():loop( f )
|
||||
end
|
||||
|
||||
function Sprite:rate( f )
|
||||
self:GetTexture():rate( f )
|
||||
end
|
||||
|
||||
function Sprite.LinearFrames(NumFrames, Seconds)
|
||||
local Frames = {}
|
||||
for i = 0,NumFrames-1 do
|
||||
Frames[#Frames+1] = {
|
||||
Frame = i,
|
||||
Delay = (1/NumFrames)*Seconds
|
||||
}
|
||||
end
|
||||
return Frames
|
||||
end
|
||||
|
||||
-- (c) 2005 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
@@ -1,112 +1,112 @@
|
||||
function AreStagePlayerModsForced()
|
||||
local bExtraStage = GAMESTATE:IsAnExtraStage()
|
||||
local bOni = GAMESTATE:GetPlayMode() == "PlayMode_Oni"
|
||||
return bExtraStage or bOni
|
||||
end
|
||||
|
||||
function AreStageSongModsForced()
|
||||
local bExtraStage = GAMESTATE:IsAnExtraStage()
|
||||
local pm = GAMESTATE:GetPlayMode()
|
||||
local bOni = pm == "PlayMode_Oni"
|
||||
local bBattle = pm == "PlayMode_Battle"
|
||||
local bRave = pm == "PlayMode_Rave"
|
||||
return bExtraStage or bOni or bBattle or bRave
|
||||
end
|
||||
|
||||
function ScreenSelectMusic:setupmusicstagemods()
|
||||
Trace( "setupmusicstagemods" )
|
||||
local pm = GAMESTATE:GetPlayMode()
|
||||
|
||||
if pm == "PlayMode_Battle" or pm == "PlayMode_Rave" then
|
||||
-- FIX DAT BUG;
|
||||
local sFail = "";
|
||||
if GetGamePref("DefaultFail") then
|
||||
sFail = string.format("Fail%s", GetGamePref("DefaultFail") );
|
||||
else
|
||||
sFail = "Failoff";
|
||||
end;
|
||||
--
|
||||
local so = GAMESTATE:GetDefaultSongOptions() .. "," .. sFail;
|
||||
GAMESTATE:SetSongOptions( "ModsLevel_Stage", so );
|
||||
MESSAGEMAN:Broadcast( "SongOptionsChanged" );
|
||||
elseif GAMESTATE:IsAnExtraStage() then
|
||||
if GAMESTATE:GetPreferredSongGroup() == "---Group All---" then
|
||||
local song = GAMESTATE:GetCurrentSong()
|
||||
GAMESTATE:SetPreferredSongGroup( song:GetGroupName() )
|
||||
end
|
||||
|
||||
local bExtra2 = GAMESTATE:IsExtraStage2()
|
||||
local style = GAMESTATE:GetCurrentStyle()
|
||||
local song, steps = SONGMAN:GetExtraStageInfo( bExtra2, style )
|
||||
local po, so
|
||||
if bExtra2 then
|
||||
po = THEME:GetMetric("SongManager","OMESPlayerModifiers");
|
||||
so = THEME:GetMetric("SongManager","OMESStageModifiers");
|
||||
else
|
||||
po = THEME:GetMetric("SongManager","ExtraStagePlayerModifiers");
|
||||
so = THEME:GetMetric("SongManager","ExtraStageStageModifiers");
|
||||
end
|
||||
local difficulty = steps:GetDifficulty()
|
||||
local Reverse = PlayerNumber:Reverse()
|
||||
|
||||
GAMESTATE:SetCurrentSong( song )
|
||||
GAMESTATE:SetPreferredSong( song )
|
||||
|
||||
for pn in ivalues(GAMESTATE:GetHumanPlayers()) do
|
||||
GAMESTATE:SetCurrentSteps( pn, steps )
|
||||
GAMESTATE:GetPlayerState(pn):SetPlayerOptions( "ModsLevel_Stage", po )
|
||||
GAMESTATE:SetPreferredDifficulty( pn, difficulty )
|
||||
MESSAGEMAN:Broadcast( "PlayerOptionsChanged", {PlayerNumber = pn} )
|
||||
end
|
||||
|
||||
|
||||
|
||||
GAMESTATE:SetSongOptions( "ModsLevel_Stage", so )
|
||||
MESSAGEMAN:Broadcast( "SongOptionsChanged" )
|
||||
end
|
||||
end
|
||||
|
||||
function ScreenSelectMusic:setupcoursestagemods()
|
||||
local mode = GAMESTATE:GetPlayMode()
|
||||
|
||||
if mode == "PlayMode_Oni" then
|
||||
local po = "clearall,default"
|
||||
-- Let SSMusic set battery.
|
||||
-- local so = "failimmediate,battery"
|
||||
local so = "failimmediate"
|
||||
local Reverse = PlayerNumber:Reverse()
|
||||
|
||||
for pn in ivalues(GAMESTATE:GetHumanPlayers()) do
|
||||
GAMESTATE:GetPlayerState(pn):SetPlayerOptions( "ModsLevel_Stage", po )
|
||||
MESSAGEMAN:Broadcast( "PlayerOptionsChanged", {PlayerNumber = pn} )
|
||||
end
|
||||
|
||||
GAMESTATE:SetSongOptions( "ModsLevel_Stage", so )
|
||||
MESSAGEMAN:Broadcast( "SongOptionsChanged" )
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- (c) 2006-2007 Steve Checkoway
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
function AreStagePlayerModsForced()
|
||||
local bExtraStage = GAMESTATE:IsAnExtraStage()
|
||||
local bOni = GAMESTATE:GetPlayMode() == "PlayMode_Oni"
|
||||
return bExtraStage or bOni
|
||||
end
|
||||
|
||||
function AreStageSongModsForced()
|
||||
local bExtraStage = GAMESTATE:IsAnExtraStage()
|
||||
local pm = GAMESTATE:GetPlayMode()
|
||||
local bOni = pm == "PlayMode_Oni"
|
||||
local bBattle = pm == "PlayMode_Battle"
|
||||
local bRave = pm == "PlayMode_Rave"
|
||||
return bExtraStage or bOni or bBattle or bRave
|
||||
end
|
||||
|
||||
function ScreenSelectMusic:setupmusicstagemods()
|
||||
Trace( "setupmusicstagemods" )
|
||||
local pm = GAMESTATE:GetPlayMode()
|
||||
|
||||
if pm == "PlayMode_Battle" or pm == "PlayMode_Rave" then
|
||||
-- FIX DAT BUG;
|
||||
local sFail = "";
|
||||
if GetGamePref("DefaultFail") then
|
||||
sFail = string.format("Fail%s", GetGamePref("DefaultFail") );
|
||||
else
|
||||
sFail = "Failoff";
|
||||
end;
|
||||
--
|
||||
local so = GAMESTATE:GetDefaultSongOptions() .. "," .. sFail;
|
||||
GAMESTATE:SetSongOptions( "ModsLevel_Stage", so );
|
||||
MESSAGEMAN:Broadcast( "SongOptionsChanged" );
|
||||
elseif GAMESTATE:IsAnExtraStage() then
|
||||
if GAMESTATE:GetPreferredSongGroup() == "---Group All---" then
|
||||
local song = GAMESTATE:GetCurrentSong()
|
||||
GAMESTATE:SetPreferredSongGroup( song:GetGroupName() )
|
||||
end
|
||||
|
||||
local bExtra2 = GAMESTATE:IsExtraStage2()
|
||||
local style = GAMESTATE:GetCurrentStyle()
|
||||
local song, steps = SONGMAN:GetExtraStageInfo( bExtra2, style )
|
||||
local po, so
|
||||
if bExtra2 then
|
||||
po = THEME:GetMetric("SongManager","OMESPlayerModifiers");
|
||||
so = THEME:GetMetric("SongManager","OMESStageModifiers");
|
||||
else
|
||||
po = THEME:GetMetric("SongManager","ExtraStagePlayerModifiers");
|
||||
so = THEME:GetMetric("SongManager","ExtraStageStageModifiers");
|
||||
end
|
||||
local difficulty = steps:GetDifficulty()
|
||||
local Reverse = PlayerNumber:Reverse()
|
||||
|
||||
GAMESTATE:SetCurrentSong( song )
|
||||
GAMESTATE:SetPreferredSong( song )
|
||||
|
||||
for pn in ivalues(GAMESTATE:GetHumanPlayers()) do
|
||||
GAMESTATE:SetCurrentSteps( pn, steps )
|
||||
GAMESTATE:GetPlayerState(pn):SetPlayerOptions( "ModsLevel_Stage", po )
|
||||
GAMESTATE:SetPreferredDifficulty( pn, difficulty )
|
||||
MESSAGEMAN:Broadcast( "PlayerOptionsChanged", {PlayerNumber = pn} )
|
||||
end
|
||||
|
||||
|
||||
|
||||
GAMESTATE:SetSongOptions( "ModsLevel_Stage", so )
|
||||
MESSAGEMAN:Broadcast( "SongOptionsChanged" )
|
||||
end
|
||||
end
|
||||
|
||||
function ScreenSelectMusic:setupcoursestagemods()
|
||||
local mode = GAMESTATE:GetPlayMode()
|
||||
|
||||
if mode == "PlayMode_Oni" then
|
||||
local po = "clearall,default"
|
||||
-- Let SSMusic set battery.
|
||||
-- local so = "failimmediate,battery"
|
||||
local so = "failimmediate"
|
||||
local Reverse = PlayerNumber:Reverse()
|
||||
|
||||
for pn in ivalues(GAMESTATE:GetHumanPlayers()) do
|
||||
GAMESTATE:GetPlayerState(pn):SetPlayerOptions( "ModsLevel_Stage", po )
|
||||
MESSAGEMAN:Broadcast( "PlayerOptionsChanged", {PlayerNumber = pn} )
|
||||
end
|
||||
|
||||
GAMESTATE:SetSongOptions( "ModsLevel_Stage", so )
|
||||
MESSAGEMAN:Broadcast( "SongOptionsChanged" )
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- (c) 2006-2007 Steve Checkoway
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
@@ -1,207 +1,207 @@
|
||||
-- Find a key in tab with the given value.
|
||||
function FindValue(tab, value)
|
||||
for key, name in tab do
|
||||
if value == name then
|
||||
return key
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Return the index of a true value in list.
|
||||
function FindSelection( list )
|
||||
for index, on in list do
|
||||
if on then
|
||||
return index
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Look up each value in a table, returning a table with the resulting strings.
|
||||
function TableStringLookup( t, group )
|
||||
local ret = { }
|
||||
for key, val in t do
|
||||
Trace(val)
|
||||
ret[key] = THEME:GetString(group,val)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function split( delimiter, text )
|
||||
local list = {}
|
||||
local pos = 1
|
||||
while 1 do
|
||||
local first,last = string.find( text, delimiter, pos )
|
||||
if first then
|
||||
table.insert( list, string.sub(text, pos, first-1) )
|
||||
pos = last+1
|
||||
else
|
||||
table.insert( list, string.sub(text, pos) )
|
||||
break
|
||||
end
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
function join( delimiter, list )
|
||||
local ret = list[1]
|
||||
for i = 2,table.getn(list) do
|
||||
ret = ret .. delimiter .. list[i]
|
||||
end
|
||||
return ret or ""
|
||||
end
|
||||
|
||||
function wrap(val,n)
|
||||
local x = val
|
||||
Trace( "wrap "..x.." "..n )
|
||||
if x<0 then
|
||||
x = x + (math.ceil(-x/n)+1)*n
|
||||
end
|
||||
Trace( "adjusted "..x )
|
||||
local ret = math.mod(x,n)
|
||||
Trace( "ret "..ret )
|
||||
return ret
|
||||
end
|
||||
|
||||
function fapproach( val, other_val, to_move )
|
||||
if val == other_val then
|
||||
return val -- already done!
|
||||
end
|
||||
|
||||
local delta = other_val - val
|
||||
local sign = delta / math.abs(delta)
|
||||
local toMove = sign*to_move
|
||||
|
||||
if math.abs(toMove) > math.abs(delta) then
|
||||
toMove = delta -- snap
|
||||
end
|
||||
|
||||
val = val + toMove
|
||||
return val
|
||||
end
|
||||
|
||||
function tableshuffle( t )
|
||||
local ret = { }
|
||||
for i=1,table.getn(t) do
|
||||
table.insert( ret, math.random(i), t[i] )
|
||||
end
|
||||
return ret
|
||||
end
|
||||
table.shuffle = tableshuffle
|
||||
|
||||
function tableslice( t, num )
|
||||
local ret = { }
|
||||
for i=1,table.getn(t) do
|
||||
table.insert( ret, i, t[i] )
|
||||
end
|
||||
return ret
|
||||
end
|
||||
table.slice = tableslice
|
||||
|
||||
-- add together the contents of a table
|
||||
function table.sum( t )
|
||||
local sum = 0
|
||||
for i=1,#t do
|
||||
sum = sum + t[i]
|
||||
end
|
||||
return sum
|
||||
end
|
||||
|
||||
-- average of all table values
|
||||
function table.average( t )
|
||||
return table.sum( t ) / #t
|
||||
end
|
||||
|
||||
-- furthest value from the average of a given table
|
||||
function table.deviation( t )
|
||||
local offset = math.abs(table.average(t))
|
||||
for i=1,#t do
|
||||
offset = math.max(math.abs(t[i]), offset)
|
||||
end
|
||||
return offset
|
||||
end
|
||||
-- See if this exists
|
||||
function table.search( t, sFind )
|
||||
for i=1,#t do
|
||||
if t[i] == sFind then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Retreive the entry that has this
|
||||
function table.find( t, sFind )
|
||||
for i=1,#t do
|
||||
if t[i] == sFind then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function round(val, decimal)
|
||||
if (decimal) then
|
||||
return math.floor( (val * 10^decimal) + 0.5) / (10^decimal)
|
||||
else
|
||||
return math.floor(val+0.5)
|
||||
end
|
||||
end
|
||||
|
||||
function GetRandomSongBackground()
|
||||
for i=0,50 do
|
||||
local song = SONGMAN:GetRandomSong()
|
||||
if song then
|
||||
local path = song:GetBackgroundPath()
|
||||
if path then
|
||||
return path
|
||||
end
|
||||
end
|
||||
end
|
||||
return THEME:GetPathG("", "_blank")
|
||||
end
|
||||
|
||||
function GetSongBackground()
|
||||
local song = GAMESTATE:GetCurrentSong()
|
||||
if song then
|
||||
local path = song:GetBackgroundPath()
|
||||
if path then
|
||||
return path
|
||||
end
|
||||
end
|
||||
return THEME:GetPathG("Common","fallback background")
|
||||
end
|
||||
|
||||
function StepsOrTrailToCustomDifficulty( stepsOrTrail )
|
||||
if lua.CheckType("Steps", stepsOrTrail) then
|
||||
return StepsToCustomDifficulty( stepsOrTrail )
|
||||
end
|
||||
if lua.CheckType("Trail", stepsOrTrail) then
|
||||
return TrailToCustomDifficulty( stepsOrTrail )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- (c) 2005 Glenn Maynard, Chris Danford
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-- Find a key in tab with the given value.
|
||||
function FindValue(tab, value)
|
||||
for key, name in tab do
|
||||
if value == name then
|
||||
return key
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Return the index of a true value in list.
|
||||
function FindSelection( list )
|
||||
for index, on in list do
|
||||
if on then
|
||||
return index
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Look up each value in a table, returning a table with the resulting strings.
|
||||
function TableStringLookup( t, group )
|
||||
local ret = { }
|
||||
for key, val in t do
|
||||
Trace(val)
|
||||
ret[key] = THEME:GetString(group,val)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function split( delimiter, text )
|
||||
local list = {}
|
||||
local pos = 1
|
||||
while 1 do
|
||||
local first,last = string.find( text, delimiter, pos )
|
||||
if first then
|
||||
table.insert( list, string.sub(text, pos, first-1) )
|
||||
pos = last+1
|
||||
else
|
||||
table.insert( list, string.sub(text, pos) )
|
||||
break
|
||||
end
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
function join( delimiter, list )
|
||||
local ret = list[1]
|
||||
for i = 2,table.getn(list) do
|
||||
ret = ret .. delimiter .. list[i]
|
||||
end
|
||||
return ret or ""
|
||||
end
|
||||
|
||||
function wrap(val,n)
|
||||
local x = val
|
||||
Trace( "wrap "..x.." "..n )
|
||||
if x<0 then
|
||||
x = x + (math.ceil(-x/n)+1)*n
|
||||
end
|
||||
Trace( "adjusted "..x )
|
||||
local ret = math.mod(x,n)
|
||||
Trace( "ret "..ret )
|
||||
return ret
|
||||
end
|
||||
|
||||
function fapproach( val, other_val, to_move )
|
||||
if val == other_val then
|
||||
return val -- already done!
|
||||
end
|
||||
|
||||
local delta = other_val - val
|
||||
local sign = delta / math.abs(delta)
|
||||
local toMove = sign*to_move
|
||||
|
||||
if math.abs(toMove) > math.abs(delta) then
|
||||
toMove = delta -- snap
|
||||
end
|
||||
|
||||
val = val + toMove
|
||||
return val
|
||||
end
|
||||
|
||||
function tableshuffle( t )
|
||||
local ret = { }
|
||||
for i=1,table.getn(t) do
|
||||
table.insert( ret, math.random(i), t[i] )
|
||||
end
|
||||
return ret
|
||||
end
|
||||
table.shuffle = tableshuffle
|
||||
|
||||
function tableslice( t, num )
|
||||
local ret = { }
|
||||
for i=1,table.getn(t) do
|
||||
table.insert( ret, i, t[i] )
|
||||
end
|
||||
return ret
|
||||
end
|
||||
table.slice = tableslice
|
||||
|
||||
-- add together the contents of a table
|
||||
function table.sum( t )
|
||||
local sum = 0
|
||||
for i=1,#t do
|
||||
sum = sum + t[i]
|
||||
end
|
||||
return sum
|
||||
end
|
||||
|
||||
-- average of all table values
|
||||
function table.average( t )
|
||||
return table.sum( t ) / #t
|
||||
end
|
||||
|
||||
-- furthest value from the average of a given table
|
||||
function table.deviation( t )
|
||||
local offset = math.abs(table.average(t))
|
||||
for i=1,#t do
|
||||
offset = math.max(math.abs(t[i]), offset)
|
||||
end
|
||||
return offset
|
||||
end
|
||||
-- See if this exists
|
||||
function table.search( t, sFind )
|
||||
for i=1,#t do
|
||||
if t[i] == sFind then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Retreive the entry that has this
|
||||
function table.find( t, sFind )
|
||||
for i=1,#t do
|
||||
if t[i] == sFind then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function round(val, decimal)
|
||||
if (decimal) then
|
||||
return math.floor( (val * 10^decimal) + 0.5) / (10^decimal)
|
||||
else
|
||||
return math.floor(val+0.5)
|
||||
end
|
||||
end
|
||||
|
||||
function GetRandomSongBackground()
|
||||
for i=0,50 do
|
||||
local song = SONGMAN:GetRandomSong()
|
||||
if song then
|
||||
local path = song:GetBackgroundPath()
|
||||
if path then
|
||||
return path
|
||||
end
|
||||
end
|
||||
end
|
||||
return THEME:GetPathG("", "_blank")
|
||||
end
|
||||
|
||||
function GetSongBackground()
|
||||
local song = GAMESTATE:GetCurrentSong()
|
||||
if song then
|
||||
local path = song:GetBackgroundPath()
|
||||
if path then
|
||||
return path
|
||||
end
|
||||
end
|
||||
return THEME:GetPathG("Common","fallback background")
|
||||
end
|
||||
|
||||
function StepsOrTrailToCustomDifficulty( stepsOrTrail )
|
||||
if lua.CheckType("Steps", stepsOrTrail) then
|
||||
return StepsToCustomDifficulty( stepsOrTrail )
|
||||
end
|
||||
if lua.CheckType("Trail", stepsOrTrail) then
|
||||
return TrailToCustomDifficulty( stepsOrTrail )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- (c) 2005 Glenn Maynard, Chris Danford
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, and/or sell copies of the Software, and to permit persons to
|
||||
-- whom the Software is furnished to do so, provided that the above
|
||||
-- copyright notice(s) and this permission notice appear in all copies of
|
||||
-- the Software and that both the above copyright notice(s) and this
|
||||
-- permission notice appear in supporting documentation.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
-- THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
-- INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
-- OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
-- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
@@ -1,311 +1,311 @@
|
||||
--[[
|
||||
Custom Speed Mods v2.0 (for sm-ssc)
|
||||
by AJ Kelly of KKI Labs ( http://kki.ajworld.net/ )
|
||||
|
||||
changelog:
|
||||
|
||||
v2.0 (for sm-ssc)
|
||||
Giant rewrite of the speed mod parser.
|
||||
This rewrite comes with the following changes/features:
|
||||
* Speed mods are now tied to profiles.
|
||||
This is arguably the biggest change, as it allows the speed mods to be
|
||||
portable, as well as per-profile.
|
||||
Thanks to this, we can now support reading SpeedMods from a USB stick or
|
||||
other external storage. (I didn't test writing yet, but it should work.)
|
||||
|
||||
* Data/SpeedMods.txt is the fallback.
|
||||
Previously, all speed mods were stored in {SM4 folder}/Data/SpeedMods.txt.
|
||||
For compatibility reasons, this file is still read by the script.
|
||||
|
||||
This version of Custom Speed Mods will only run on sm-ssc for the time being,
|
||||
DO NOT use it in themes for StepMania 4 alpha versions.
|
||||
--------------------------------------------------------------------------------
|
||||
v1.4
|
||||
* Try to auto-set the speed mod to 1.0 if:
|
||||
1) The player hasn't already chosen a speed mod
|
||||
2) The player's custom speed mod collection starts with a value under 1x.
|
||||
Due to the way the custom speed mods were coded, it will always pick the
|
||||
first value, even if it's not 1.0x.
|
||||
|
||||
v1.3
|
||||
* strip whitespace out of file in case people use it.
|
||||
(I don't think it really works but SM seems to think the mods are legal)
|
||||
* fixed an error related to using the fallback return value.
|
||||
|
||||
v1.2
|
||||
* small fixes
|
||||
* more comments
|
||||
|
||||
v1.1
|
||||
* Cleaned up code some, I think.
|
||||
________________________________________________________________________________
|
||||
anticipated future changes:
|
||||
* M-Mod support (when sm-ssc imntegrates it)
|
||||
]]
|
||||
|
||||
-- ProfileDir(slot): gets the profile dir for slot,
|
||||
-- where slot is a 'ProfileSlot_*' enum value.
|
||||
local function ProfileDir(slot)
|
||||
local profileDir = PROFILEMAN:GetProfileDir(slot)
|
||||
return profileDir or nil
|
||||
end
|
||||
|
||||
-- Tries to parse the file at path. If successful, returns a table of mods.
|
||||
-- If it can't open the file, it will write a fallback set of mods.
|
||||
local function ParseSpeedModFile(path)
|
||||
local file = RageFileUtil.CreateRageFile()
|
||||
if file:Open(path, 1) then
|
||||
-- success
|
||||
local contents = file:Read()
|
||||
mods = split(',',contents)
|
||||
|
||||
-- strip any whitespace
|
||||
for i=1,#mods do
|
||||
string.gsub(mods[i], "%s", "")
|
||||
end
|
||||
|
||||
file:destroy()
|
||||
return mods
|
||||
else
|
||||
-- error; write a fallback mod file and return it
|
||||
local fallbackString = "0.5x,0.75x,1x,1.75x,2x,2.25x,2.5x,C150,C300"
|
||||
Trace("[CustomSpeedMods]: Could not read SpeedMods; writing fallback to "..path)
|
||||
file:Open(path, 2)
|
||||
file:Write(fallbackString)
|
||||
file:destroy()
|
||||
return split(',',fallbackString)
|
||||
end
|
||||
end
|
||||
|
||||
-- MarkDupes(src,parent)
|
||||
-- Marks duplicates in src from any matches in parent.
|
||||
-- the overall mods are usually used as the parent.
|
||||
local function MarkDupes(src,parent)
|
||||
for iPar=1,#parent do
|
||||
for iSrc=1,#src do
|
||||
if parent[iPar] == src[iSrc] then
|
||||
src[iSrc] = "XXX"
|
||||
end
|
||||
end
|
||||
end
|
||||
return src
|
||||
end
|
||||
|
||||
-- RemoveMarked(src)
|
||||
-- Removes any values marked for deletion.
|
||||
local function RemoveMarked(src)
|
||||
for iSrc=1,#src do
|
||||
if src[iSrc] == "XXX" then
|
||||
table.remove(src,iSrc)
|
||||
end
|
||||
end
|
||||
return src
|
||||
end
|
||||
|
||||
-- MergeTables(parent,child)
|
||||
-- Adds the child's contents to the parent.
|
||||
-- the overall mods are usually used as the parent.
|
||||
local function MergeTables(parent,child)
|
||||
child = RemoveMarked(child)
|
||||
if #child == 0 then
|
||||
return parent
|
||||
end
|
||||
|
||||
local addMe = true
|
||||
for iC=1,#child do
|
||||
--[[
|
||||
for iP=1,#parent do
|
||||
if addMe then
|
||||
-- check if that's the case.
|
||||
-- why am I doing this anyways?
|
||||
-- by the time these tables are passed in,
|
||||
-- dupes should be gone.
|
||||
end
|
||||
end
|
||||
]]
|
||||
if addMe then
|
||||
table.insert(parent,child[iC])
|
||||
end
|
||||
end
|
||||
return parent
|
||||
end
|
||||
|
||||
-- code in this function is based off of code in
|
||||
-- http://astrofra.com/weblog/files/sort.lua
|
||||
local function AnonSort(t)
|
||||
local index_min
|
||||
for i=1,#t,1 do
|
||||
index_min = i
|
||||
for j=i+1,#t,1 do
|
||||
if (t[j] < t[index_min]) then
|
||||
index_min = j
|
||||
end
|
||||
end
|
||||
t[i], t[index_min] = t[index_min], t[i]
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function SpeedModSort(tab)
|
||||
local xMods = {}
|
||||
local cMods = {}
|
||||
--local mMods = {}
|
||||
|
||||
-- convert to numbers so sorting works:
|
||||
for i=1,#tab do
|
||||
local typ,val
|
||||
-- xxx: If people use a floating point CMod (e.g. C420.50),
|
||||
-- it will get rounded. C420.50 gets rounded to 421, btw. -aj
|
||||
if string.find(tab[i],"C%d") then
|
||||
typ = cMods
|
||||
val = string.gsub(tab[i], "C", "")
|
||||
elseif string.find(tab[i],"M%d") then
|
||||
Trace("[CustomSpeedMods] OpenITG's M-Mods are not supported yet in sm-ssc.")
|
||||
--typ = mMods
|
||||
--val = string.gsub(tab[i], "M", "")
|
||||
else
|
||||
typ = xMods
|
||||
val = string.gsub(tab[i], "x", "")
|
||||
end
|
||||
table.insert(typ,tonumber(val))
|
||||
end
|
||||
|
||||
-- sort xMods
|
||||
xMods = AnonSort(xMods)
|
||||
-- sort cMods
|
||||
cMods = AnonSort(cMods)
|
||||
-- sort mMods
|
||||
--mMods = AnonSort(mMods)
|
||||
local fin = {}
|
||||
-- convert it back to a string since that's what it expects
|
||||
for i=1,#xMods do
|
||||
table.insert(fin, xMods[i].."x")
|
||||
end
|
||||
for i=1,#cMods do
|
||||
table.insert(fin, "C"..cMods[i])
|
||||
end
|
||||
--for i=1,#mMods do table.insert(fin, "M"..mMods[i]); end;
|
||||
return fin
|
||||
end
|
||||
|
||||
-- parse everything
|
||||
local function GetSpeedMods()
|
||||
local finalMods = {}
|
||||
|
||||
local baseFilename = "SpeedMods.txt"
|
||||
local profileDirs = {
|
||||
Fallback = "Data/",
|
||||
Machine = ProfileDir('ProfileSlot_Machine'),
|
||||
PlayerNumber_P1 = ProfileDir('ProfileSlot_Player1'),
|
||||
PlayerNumber_P2 = ProfileDir('ProfileSlot_Player2')
|
||||
}
|
||||
|
||||
-- figure out how many players we have to deal with.
|
||||
local numPlayers = GAMESTATE:GetNumPlayersEnabled()
|
||||
-- load fallback
|
||||
local fallbackMods = ParseSpeedModFile(profileDirs.Fallback..baseFilename)
|
||||
|
||||
-- load machine
|
||||
local machineMods = ParseSpeedModFile(profileDirs.Machine..baseFilename)
|
||||
|
||||
local playerMods = {}
|
||||
for pn in ivalues(GAMESTATE:GetHumanPlayers()) do
|
||||
-- file loading logic per player;
|
||||
-- only bother if it's not the machine profile though.
|
||||
if PROFILEMAN:IsPersistentProfile(pn) or
|
||||
MEMCARDMAN:GetCardState(pn) == 'MemoryCardState_ready' then
|
||||
playerMods[#playerMods+1] = ParseSpeedModFile(profileDirs[pn]..baseFilename)
|
||||
end
|
||||
end
|
||||
|
||||
-- with all loaded... the merging BEGINS!!
|
||||
finalMods = fallbackMods
|
||||
-- mine for duplicates, first pass (fallback <-> machine)
|
||||
machineMods = MarkDupes(machineMods,finalMods)
|
||||
for ply=1,#playerMods do
|
||||
playerMods[ply] = MarkDupes(playerMods[ply],finalMods)
|
||||
end
|
||||
-- remove XXX, first pass
|
||||
machineMods = RemoveMarked(machineMods);
|
||||
for ply=1,#playerMods do
|
||||
playerMods[ply] = RemoveMarked(playerMods[ply])
|
||||
end
|
||||
-- mine for duplicates, second pass (machine <-> player)
|
||||
for ply=1,#playerMods do
|
||||
playerMods[ply] = MarkDupes(playerMods[ply],machineMods)
|
||||
end
|
||||
-- remove XXX, second pass
|
||||
machineMods = RemoveMarked(machineMods)
|
||||
for ply=1,#playerMods do
|
||||
playerMods[ply] = RemoveMarked(playerMods[ply])
|
||||
end
|
||||
|
||||
-- merge zone
|
||||
finalMods = MergeTables(finalMods,machineMods)
|
||||
for ply=1,#playerMods do
|
||||
finalMods = MergeTables(finalMods,playerMods[ply])
|
||||
end
|
||||
|
||||
-- final removal of XXX before sorting
|
||||
finalMods = RemoveMarked(finalMods)
|
||||
-- sort the mods before returning them
|
||||
return SpeedModSort(finalMods)
|
||||
end
|
||||
|
||||
function SpeedMods()
|
||||
-- here we see the option menu itself.
|
||||
local t = {
|
||||
Name = "Speed",
|
||||
LayoutType = "ShowAllInRow",
|
||||
SelectType = "SelectOne",
|
||||
OneChoiceForAllPlayers = false,
|
||||
ExportOnChange = false,
|
||||
Choices = GetSpeedMods(),
|
||||
|
||||
LoadSelections = function(self, list, pn)
|
||||
local pMods = GAMESTATE:GetPlayerState(pn):GetPlayerOptionsString("ModsLevel_Preferred")
|
||||
for i = 1,table.getn(self.Choices) do
|
||||
if string.find(pMods, self.Choices[i]) then
|
||||
list[i] = true
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- if we've reached this point, try to find 1x or 1.0x instead,
|
||||
-- in case the player has defined a speed mod under 1.0x
|
||||
for i = 1,table.getn(self.Choices) do
|
||||
if self.Choices[i] == "1x" or self.Choices[i] == "1.0x" then
|
||||
list[i] = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end,
|
||||
SaveSelections = function(self, list, pn)
|
||||
for i = 1,table.getn(self.Choices) do
|
||||
if list[i] then
|
||||
local PlayerState = GAMESTATE:GetPlayerState(pn)
|
||||
PlayerState:SetPlayerOptions("ModsLevel_Preferred",self.Choices[i])
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
setmetatable( t, t )
|
||||
return t
|
||||
end
|
||||
|
||||
--[[
|
||||
Copyright © 2008-2009 AJ Kelly/KKI Labs.
|
||||
Use freely, so long this notice and the above documentation remains.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
--[[
|
||||
Custom Speed Mods v2.0 (for sm-ssc)
|
||||
by AJ Kelly of KKI Labs ( http://kki.ajworld.net/ )
|
||||
|
||||
changelog:
|
||||
|
||||
v2.0 (for sm-ssc)
|
||||
Giant rewrite of the speed mod parser.
|
||||
This rewrite comes with the following changes/features:
|
||||
* Speed mods are now tied to profiles.
|
||||
This is arguably the biggest change, as it allows the speed mods to be
|
||||
portable, as well as per-profile.
|
||||
Thanks to this, we can now support reading SpeedMods from a USB stick or
|
||||
other external storage. (I didn't test writing yet, but it should work.)
|
||||
|
||||
* Data/SpeedMods.txt is the fallback.
|
||||
Previously, all speed mods were stored in {SM4 folder}/Data/SpeedMods.txt.
|
||||
For compatibility reasons, this file is still read by the script.
|
||||
|
||||
This version of Custom Speed Mods will only run on sm-ssc for the time being,
|
||||
DO NOT use it in themes for StepMania 4 alpha versions.
|
||||
--------------------------------------------------------------------------------
|
||||
v1.4
|
||||
* Try to auto-set the speed mod to 1.0 if:
|
||||
1) The player hasn't already chosen a speed mod
|
||||
2) The player's custom speed mod collection starts with a value under 1x.
|
||||
Due to the way the custom speed mods were coded, it will always pick the
|
||||
first value, even if it's not 1.0x.
|
||||
|
||||
v1.3
|
||||
* strip whitespace out of file in case people use it.
|
||||
(I don't think it really works but SM seems to think the mods are legal)
|
||||
* fixed an error related to using the fallback return value.
|
||||
|
||||
v1.2
|
||||
* small fixes
|
||||
* more comments
|
||||
|
||||
v1.1
|
||||
* Cleaned up code some, I think.
|
||||
________________________________________________________________________________
|
||||
anticipated future changes:
|
||||
* M-Mod support (when sm-ssc imntegrates it)
|
||||
]]
|
||||
|
||||
-- ProfileDir(slot): gets the profile dir for slot,
|
||||
-- where slot is a 'ProfileSlot_*' enum value.
|
||||
local function ProfileDir(slot)
|
||||
local profileDir = PROFILEMAN:GetProfileDir(slot)
|
||||
return profileDir or nil
|
||||
end
|
||||
|
||||
-- Tries to parse the file at path. If successful, returns a table of mods.
|
||||
-- If it can't open the file, it will write a fallback set of mods.
|
||||
local function ParseSpeedModFile(path)
|
||||
local file = RageFileUtil.CreateRageFile()
|
||||
if file:Open(path, 1) then
|
||||
-- success
|
||||
local contents = file:Read()
|
||||
mods = split(',',contents)
|
||||
|
||||
-- strip any whitespace
|
||||
for i=1,#mods do
|
||||
string.gsub(mods[i], "%s", "")
|
||||
end
|
||||
|
||||
file:destroy()
|
||||
return mods
|
||||
else
|
||||
-- error; write a fallback mod file and return it
|
||||
local fallbackString = "0.5x,0.75x,1x,1.75x,2x,2.25x,2.5x,C150,C300"
|
||||
Trace("[CustomSpeedMods]: Could not read SpeedMods; writing fallback to "..path)
|
||||
file:Open(path, 2)
|
||||
file:Write(fallbackString)
|
||||
file:destroy()
|
||||
return split(',',fallbackString)
|
||||
end
|
||||
end
|
||||
|
||||
-- MarkDupes(src,parent)
|
||||
-- Marks duplicates in src from any matches in parent.
|
||||
-- the overall mods are usually used as the parent.
|
||||
local function MarkDupes(src,parent)
|
||||
for iPar=1,#parent do
|
||||
for iSrc=1,#src do
|
||||
if parent[iPar] == src[iSrc] then
|
||||
src[iSrc] = "XXX"
|
||||
end
|
||||
end
|
||||
end
|
||||
return src
|
||||
end
|
||||
|
||||
-- RemoveMarked(src)
|
||||
-- Removes any values marked for deletion.
|
||||
local function RemoveMarked(src)
|
||||
for iSrc=1,#src do
|
||||
if src[iSrc] == "XXX" then
|
||||
table.remove(src,iSrc)
|
||||
end
|
||||
end
|
||||
return src
|
||||
end
|
||||
|
||||
-- MergeTables(parent,child)
|
||||
-- Adds the child's contents to the parent.
|
||||
-- the overall mods are usually used as the parent.
|
||||
local function MergeTables(parent,child)
|
||||
child = RemoveMarked(child)
|
||||
if #child == 0 then
|
||||
return parent
|
||||
end
|
||||
|
||||
local addMe = true
|
||||
for iC=1,#child do
|
||||
--[[
|
||||
for iP=1,#parent do
|
||||
if addMe then
|
||||
-- check if that's the case.
|
||||
-- why am I doing this anyways?
|
||||
-- by the time these tables are passed in,
|
||||
-- dupes should be gone.
|
||||
end
|
||||
end
|
||||
]]
|
||||
if addMe then
|
||||
table.insert(parent,child[iC])
|
||||
end
|
||||
end
|
||||
return parent
|
||||
end
|
||||
|
||||
-- code in this function is based off of code in
|
||||
-- http://astrofra.com/weblog/files/sort.lua
|
||||
local function AnonSort(t)
|
||||
local index_min
|
||||
for i=1,#t,1 do
|
||||
index_min = i
|
||||
for j=i+1,#t,1 do
|
||||
if (t[j] < t[index_min]) then
|
||||
index_min = j
|
||||
end
|
||||
end
|
||||
t[i], t[index_min] = t[index_min], t[i]
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function SpeedModSort(tab)
|
||||
local xMods = {}
|
||||
local cMods = {}
|
||||
--local mMods = {}
|
||||
|
||||
-- convert to numbers so sorting works:
|
||||
for i=1,#tab do
|
||||
local typ,val
|
||||
-- xxx: If people use a floating point CMod (e.g. C420.50),
|
||||
-- it will get rounded. C420.50 gets rounded to 421, btw. -aj
|
||||
if string.find(tab[i],"C%d") then
|
||||
typ = cMods
|
||||
val = string.gsub(tab[i], "C", "")
|
||||
elseif string.find(tab[i],"M%d") then
|
||||
Trace("[CustomSpeedMods] OpenITG's M-Mods are not supported yet in sm-ssc.")
|
||||
--typ = mMods
|
||||
--val = string.gsub(tab[i], "M", "")
|
||||
else
|
||||
typ = xMods
|
||||
val = string.gsub(tab[i], "x", "")
|
||||
end
|
||||
table.insert(typ,tonumber(val))
|
||||
end
|
||||
|
||||
-- sort xMods
|
||||
xMods = AnonSort(xMods)
|
||||
-- sort cMods
|
||||
cMods = AnonSort(cMods)
|
||||
-- sort mMods
|
||||
--mMods = AnonSort(mMods)
|
||||
local fin = {}
|
||||
-- convert it back to a string since that's what it expects
|
||||
for i=1,#xMods do
|
||||
table.insert(fin, xMods[i].."x")
|
||||
end
|
||||
for i=1,#cMods do
|
||||
table.insert(fin, "C"..cMods[i])
|
||||
end
|
||||
--for i=1,#mMods do table.insert(fin, "M"..mMods[i]); end;
|
||||
return fin
|
||||
end
|
||||
|
||||
-- parse everything
|
||||
local function GetSpeedMods()
|
||||
local finalMods = {}
|
||||
|
||||
local baseFilename = "SpeedMods.txt"
|
||||
local profileDirs = {
|
||||
Fallback = "Data/",
|
||||
Machine = ProfileDir('ProfileSlot_Machine'),
|
||||
PlayerNumber_P1 = ProfileDir('ProfileSlot_Player1'),
|
||||
PlayerNumber_P2 = ProfileDir('ProfileSlot_Player2')
|
||||
}
|
||||
|
||||
-- figure out how many players we have to deal with.
|
||||
local numPlayers = GAMESTATE:GetNumPlayersEnabled()
|
||||
-- load fallback
|
||||
local fallbackMods = ParseSpeedModFile(profileDirs.Fallback..baseFilename)
|
||||
|
||||
-- load machine
|
||||
local machineMods = ParseSpeedModFile(profileDirs.Machine..baseFilename)
|
||||
|
||||
local playerMods = {}
|
||||
for pn in ivalues(GAMESTATE:GetHumanPlayers()) do
|
||||
-- file loading logic per player;
|
||||
-- only bother if it's not the machine profile though.
|
||||
if PROFILEMAN:IsPersistentProfile(pn) or
|
||||
MEMCARDMAN:GetCardState(pn) == 'MemoryCardState_ready' then
|
||||
playerMods[#playerMods+1] = ParseSpeedModFile(profileDirs[pn]..baseFilename)
|
||||
end
|
||||
end
|
||||
|
||||
-- with all loaded... the merging BEGINS!!
|
||||
finalMods = fallbackMods
|
||||
-- mine for duplicates, first pass (fallback <-> machine)
|
||||
machineMods = MarkDupes(machineMods,finalMods)
|
||||
for ply=1,#playerMods do
|
||||
playerMods[ply] = MarkDupes(playerMods[ply],finalMods)
|
||||
end
|
||||
-- remove XXX, first pass
|
||||
machineMods = RemoveMarked(machineMods);
|
||||
for ply=1,#playerMods do
|
||||
playerMods[ply] = RemoveMarked(playerMods[ply])
|
||||
end
|
||||
-- mine for duplicates, second pass (machine <-> player)
|
||||
for ply=1,#playerMods do
|
||||
playerMods[ply] = MarkDupes(playerMods[ply],machineMods)
|
||||
end
|
||||
-- remove XXX, second pass
|
||||
machineMods = RemoveMarked(machineMods)
|
||||
for ply=1,#playerMods do
|
||||
playerMods[ply] = RemoveMarked(playerMods[ply])
|
||||
end
|
||||
|
||||
-- merge zone
|
||||
finalMods = MergeTables(finalMods,machineMods)
|
||||
for ply=1,#playerMods do
|
||||
finalMods = MergeTables(finalMods,playerMods[ply])
|
||||
end
|
||||
|
||||
-- final removal of XXX before sorting
|
||||
finalMods = RemoveMarked(finalMods)
|
||||
-- sort the mods before returning them
|
||||
return SpeedModSort(finalMods)
|
||||
end
|
||||
|
||||
function SpeedMods()
|
||||
-- here we see the option menu itself.
|
||||
local t = {
|
||||
Name = "Speed",
|
||||
LayoutType = "ShowAllInRow",
|
||||
SelectType = "SelectOne",
|
||||
OneChoiceForAllPlayers = false,
|
||||
ExportOnChange = false,
|
||||
Choices = GetSpeedMods(),
|
||||
|
||||
LoadSelections = function(self, list, pn)
|
||||
local pMods = GAMESTATE:GetPlayerState(pn):GetPlayerOptionsString("ModsLevel_Preferred")
|
||||
for i = 1,table.getn(self.Choices) do
|
||||
if string.find(pMods, self.Choices[i]) then
|
||||
list[i] = true
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- if we've reached this point, try to find 1x or 1.0x instead,
|
||||
-- in case the player has defined a speed mod under 1.0x
|
||||
for i = 1,table.getn(self.Choices) do
|
||||
if self.Choices[i] == "1x" or self.Choices[i] == "1.0x" then
|
||||
list[i] = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end,
|
||||
SaveSelections = function(self, list, pn)
|
||||
for i = 1,table.getn(self.Choices) do
|
||||
if list[i] then
|
||||
local PlayerState = GAMESTATE:GetPlayerState(pn)
|
||||
PlayerState:SetPlayerOptions("ModsLevel_Preferred",self.Choices[i])
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
setmetatable( t, t )
|
||||
return t
|
||||
end
|
||||
|
||||
--[[
|
||||
Copyright © 2008-2009 AJ Kelly/KKI Labs.
|
||||
Use freely, so long this notice and the above documentation remains.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]
|
||||
@@ -1,70 +1,70 @@
|
||||
-- freem, inc. DateTime for StepMania
|
||||
-- todo: accept format parameters for things
|
||||
|
||||
-- reference: http://us.php.net/manual/en/function.date.php
|
||||
local dateChars = {
|
||||
--[[ day ]]
|
||||
'd', -- Day of the month, 2 digits with leading zeros (01-31)
|
||||
'D', -- A textual representation of a day, three letters ("Mon"-"Sun")
|
||||
'j', -- Day of the month without leading zeros (1-31)
|
||||
'l', -- A full textual representation of the day of the week
|
||||
'N', -- ISO-8601 numeric representation of the day of the week (1=Mon,7=Sun)
|
||||
'S', -- English ordinal suffix for the day of the month, 2 characters
|
||||
'w', -- Numeric representation of the day of the week (0=Sun,6=Sat)
|
||||
'z', -- The day of the year (0-365)
|
||||
--[[ week ]]
|
||||
'W', -- ISO-8601 week number of year, weeks starting on Monday
|
||||
--[[ month ]]
|
||||
'F', -- A full textual representation of a month, such as January or March
|
||||
'm', -- Numeric representation of a month, with leading zeros
|
||||
'M', -- A short textual representation of a month, three letters
|
||||
'n', -- Numeric representation of a month, without leading zeros
|
||||
't', -- Number of days in the given month
|
||||
--[[ year ]]
|
||||
'L', -- Whether it's a leap year (1 or 0)
|
||||
'o', -- (sux) ISO-8601 year number
|
||||
'Y', -- A full numeric representation of a year, 4 digits
|
||||
'y', -- (sux) A two digit representation of a year
|
||||
--[[ time ]]
|
||||
'a', -- Lowercase Ante meridiem and Post meridiem
|
||||
'A', -- Uppercase Ante meridiem and Post meridiem
|
||||
'B', -- Swatch Beats
|
||||
'g', -- 12-hour format of an hour without leading zeros
|
||||
'G', -- 24-hour format of an hour without leading zeros
|
||||
'h', -- 12-hour format of an hour with leading zeros
|
||||
'H', -- 24-hour format of an hour with leading zeros
|
||||
'i', -- Minutes with leading zeros
|
||||
's', -- Seconds, with leading zeros
|
||||
'u', -- Microseconds
|
||||
--[[ timezone ]]
|
||||
'e', -- Timezone identifier
|
||||
'I', -- Whether or not the date is in daylight saving time
|
||||
'O', -- Difference to Greenwich time (GMT) in hours
|
||||
'P', -- Difference to Greenwich time (GMT) with colon between hours and minutes
|
||||
'T', -- Timezone abbreviation
|
||||
'Z', -- Timezone offset in seconds.
|
||||
--[[ full datetime ]]
|
||||
'c', -- ISO 8601 date
|
||||
'r', -- RFC 2822 formatted date
|
||||
'U' -- Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
|
||||
}
|
||||
|
||||
function date(format,...)
|
||||
if ... then
|
||||
-- convert value
|
||||
else
|
||||
-- convert current time
|
||||
end
|
||||
end
|
||||
|
||||
Date = {
|
||||
Today = function()
|
||||
return string.format("%i%02i%02i", Year(), (MonthOfYear()+1), DayOfMonth())
|
||||
end
|
||||
}
|
||||
|
||||
Time = {
|
||||
Now = function()
|
||||
return string.format( "%02i:%02i:%02i", Hour(), Minute(), Second() )
|
||||
end
|
||||
-- freem, inc. DateTime for StepMania
|
||||
-- todo: accept format parameters for things
|
||||
|
||||
-- reference: http://us.php.net/manual/en/function.date.php
|
||||
local dateChars = {
|
||||
--[[ day ]]
|
||||
'd', -- Day of the month, 2 digits with leading zeros (01-31)
|
||||
'D', -- A textual representation of a day, three letters ("Mon"-"Sun")
|
||||
'j', -- Day of the month without leading zeros (1-31)
|
||||
'l', -- A full textual representation of the day of the week
|
||||
'N', -- ISO-8601 numeric representation of the day of the week (1=Mon,7=Sun)
|
||||
'S', -- English ordinal suffix for the day of the month, 2 characters
|
||||
'w', -- Numeric representation of the day of the week (0=Sun,6=Sat)
|
||||
'z', -- The day of the year (0-365)
|
||||
--[[ week ]]
|
||||
'W', -- ISO-8601 week number of year, weeks starting on Monday
|
||||
--[[ month ]]
|
||||
'F', -- A full textual representation of a month, such as January or March
|
||||
'm', -- Numeric representation of a month, with leading zeros
|
||||
'M', -- A short textual representation of a month, three letters
|
||||
'n', -- Numeric representation of a month, without leading zeros
|
||||
't', -- Number of days in the given month
|
||||
--[[ year ]]
|
||||
'L', -- Whether it's a leap year (1 or 0)
|
||||
'o', -- (sux) ISO-8601 year number
|
||||
'Y', -- A full numeric representation of a year, 4 digits
|
||||
'y', -- (sux) A two digit representation of a year
|
||||
--[[ time ]]
|
||||
'a', -- Lowercase Ante meridiem and Post meridiem
|
||||
'A', -- Uppercase Ante meridiem and Post meridiem
|
||||
'B', -- Swatch Beats
|
||||
'g', -- 12-hour format of an hour without leading zeros
|
||||
'G', -- 24-hour format of an hour without leading zeros
|
||||
'h', -- 12-hour format of an hour with leading zeros
|
||||
'H', -- 24-hour format of an hour with leading zeros
|
||||
'i', -- Minutes with leading zeros
|
||||
's', -- Seconds, with leading zeros
|
||||
'u', -- Microseconds
|
||||
--[[ timezone ]]
|
||||
'e', -- Timezone identifier
|
||||
'I', -- Whether or not the date is in daylight saving time
|
||||
'O', -- Difference to Greenwich time (GMT) in hours
|
||||
'P', -- Difference to Greenwich time (GMT) with colon between hours and minutes
|
||||
'T', -- Timezone abbreviation
|
||||
'Z', -- Timezone offset in seconds.
|
||||
--[[ full datetime ]]
|
||||
'c', -- ISO 8601 date
|
||||
'r', -- RFC 2822 formatted date
|
||||
'U' -- Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
|
||||
}
|
||||
|
||||
function date(format,...)
|
||||
if ... then
|
||||
-- convert value
|
||||
else
|
||||
-- convert current time
|
||||
end
|
||||
end
|
||||
|
||||
Date = {
|
||||
Today = function()
|
||||
return string.format("%i%02i%02i", Year(), (MonthOfYear()+1), DayOfMonth())
|
||||
end
|
||||
}
|
||||
|
||||
Time = {
|
||||
Now = function()
|
||||
return string.format( "%02i:%02i:%02i", Hour(), Minute(), Second() )
|
||||
end
|
||||
}
|
||||
@@ -1,44 +1,44 @@
|
||||
--[[
|
||||
EnvUtils2: Environmental Variable Utilities
|
||||
Written by AJ Kelly of KKI Labs / Version 2.0
|
||||
|
||||
This code is a rewrite of what typically exists in EnvUtils.lua
|
||||
(as seen in dubaiOne), hereafter referred to as EnvUtils1.
|
||||
|
||||
I felt it was time for a simplification of the code.
|
||||
This new version should also work better and be less confusing.
|
||||
--]]
|
||||
|
||||
-- Env table global
|
||||
envTable = GAMESTATE:Env()
|
||||
|
||||
-- setenv(name,value)
|
||||
-- Sets aside an entry for /name/ and puts /value/ into it.
|
||||
-- Unlike EnvUtils1, this is the only setenv function available to you.
|
||||
-- If you need to store more than one value, you're welcome to use a
|
||||
-- table as /value/, it should work just fine.
|
||||
function setenv(name,value)
|
||||
envTable[name] = value
|
||||
end
|
||||
|
||||
-- getenv(name)
|
||||
-- This will return whatever value is at envTable[name].
|
||||
function getenv(name)
|
||||
return envTable[name]
|
||||
end
|
||||
|
||||
--[[
|
||||
Copyright © 2008 AJ Kelly/KKI Labs
|
||||
Use freely.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
--[[
|
||||
EnvUtils2: Environmental Variable Utilities
|
||||
Written by AJ Kelly of KKI Labs / Version 2.0
|
||||
|
||||
This code is a rewrite of what typically exists in EnvUtils.lua
|
||||
(as seen in dubaiOne), hereafter referred to as EnvUtils1.
|
||||
|
||||
I felt it was time for a simplification of the code.
|
||||
This new version should also work better and be less confusing.
|
||||
--]]
|
||||
|
||||
-- Env table global
|
||||
envTable = GAMESTATE:Env()
|
||||
|
||||
-- setenv(name,value)
|
||||
-- Sets aside an entry for /name/ and puts /value/ into it.
|
||||
-- Unlike EnvUtils1, this is the only setenv function available to you.
|
||||
-- If you need to store more than one value, you're welcome to use a
|
||||
-- table as /value/, it should work just fine.
|
||||
function setenv(name,value)
|
||||
envTable[name] = value
|
||||
end
|
||||
|
||||
-- getenv(name)
|
||||
-- This will return whatever value is at envTable[name].
|
||||
function getenv(name)
|
||||
return envTable[name]
|
||||
end
|
||||
|
||||
--[[
|
||||
Copyright © 2008 AJ Kelly/KKI Labs
|
||||
Use freely.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]
|
||||
@@ -1,147 +1,147 @@
|
||||
-- GamePreferences: Clone of AJ's User Preferences "Module"
|
||||
-- Written by AJ Kelly of KKI Labs / Version 2.11-ssc
|
||||
-- (modified slightly for Cerulean Skies 2's disregard of the name of the
|
||||
-- themeinfo variable lol :p)
|
||||
|
||||
--[[
|
||||
the first released version was broken.
|
||||
this version aims to be simpler, and therefore work.
|
||||
|
||||
[changelog]
|
||||
|
||||
v2.11-ssc
|
||||
Remove EnvUtils references; we have it in sm-ssc.
|
||||
|
||||
v2.1-ssc
|
||||
sm-ssc version of UserPrefs. We can now assume players have certain
|
||||
functionality, like RageFile:GetError().
|
||||
|
||||
v2.1
|
||||
Added type specific GetUserPref functions.
|
||||
|
||||
[usage]
|
||||
First, edit PrefPath to match your theme.
|
||||
If you use ThemeInfo, then you shouldn't have to edit this.
|
||||
|
||||
If you're not using ThemeInfo, then you can replace
|
||||
|
||||
".. themeInfo.Name .." with the theme's folder name.
|
||||
|
||||
ThemeInfo is documented at http://kki.ajworld.net/wiki/ThemeInfo.lua
|
||||
|
||||
After that's set up, read the docs.
|
||||
]]
|
||||
local PrefPath = "Data/GamePrefs/"
|
||||
|
||||
--[[ begin internal stuff; no need to edit below this line. ]]
|
||||
|
||||
-- Local internal function to write envs. ___Not for themer use.___
|
||||
local function WriteEnv(envName,envValue)
|
||||
return setenv(envName,envValue)
|
||||
end
|
||||
|
||||
function ReadGamePrefFromFile(name)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
local fullFilename = PrefPath..name..".cfg"
|
||||
local option
|
||||
|
||||
if f:Open(fullFilename,1) then
|
||||
option = tostring( f:Read() )
|
||||
WriteEnv(name,option)
|
||||
f:destroy()
|
||||
return option
|
||||
else
|
||||
local fError = f:GetError()
|
||||
Trace( "[FileUtils] Error reading ".. fullFilename ..": ".. fError )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function WriteGamePrefToFile(name,value)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
local fullFilename = PrefPath..name..".cfg"
|
||||
|
||||
if f:Open(fullFilename, 2) then
|
||||
f:Write( tostring(value) )
|
||||
WriteEnv(name,value)
|
||||
else
|
||||
local fError = f:GetError()
|
||||
Trace( "[FileUtils] Error writing to ".. fullFilename ..": ".. fError )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return false
|
||||
end
|
||||
|
||||
f:destroy()
|
||||
return true
|
||||
end
|
||||
|
||||
--[[ end internal functions; still don't edit below this line ]]
|
||||
|
||||
function GetGamePref(name)
|
||||
return ReadGamePrefFromFile(name)
|
||||
end
|
||||
|
||||
function SetGamePref(name,value)
|
||||
return WriteGamePrefToFile(name,value)
|
||||
end
|
||||
|
||||
--[[ type specific, for when you want to be lazy ]]
|
||||
-- XXX: make set funcs, since I hate dealing with colors and I know
|
||||
-- other themers would too.
|
||||
|
||||
-- GetUserPrefB: boolean
|
||||
function GetGamePrefB(name)
|
||||
-- this one is a bit trickier.
|
||||
local pref = ReadGamePrefFromFile(name)
|
||||
|
||||
if type(pref) == "string" then
|
||||
pref = string.lower(pref)
|
||||
if pref == "true" or cmp == "t" then
|
||||
return true
|
||||
elseif pref == "false" or cmp == "f" then
|
||||
return false
|
||||
else
|
||||
Trace("Error in GetUserPrefB(".. name ..") converting from string" )
|
||||
return false
|
||||
end
|
||||
elseif type(pref) == "number" then
|
||||
-- both 0 and -1 are false; if you want to change this,
|
||||
-- feel free to remove "or pref == -1".
|
||||
if pref == 0 or pref == -1 then
|
||||
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- GetUserPrefC: color
|
||||
function GetGamePrefC(name)
|
||||
-- XXX: make sure it's grabbing a string that can be turned into a color
|
||||
-- and also possibly handle HSV values too.
|
||||
return color( ReadGamePrefFromFile(name) )
|
||||
end
|
||||
|
||||
-- GetUserPrefN: numbers (integers, floats)
|
||||
function GetGamePrefN(name)
|
||||
return tonumber( ReadGamePrefFromFile(name) )
|
||||
end
|
||||
|
||||
--[[
|
||||
Copyright © 2008-2009 AJ Kelly/KKI Labs
|
||||
All rights reserved.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-- GamePreferences: Clone of AJ's User Preferences "Module"
|
||||
-- Written by AJ Kelly of KKI Labs / Version 2.11-ssc
|
||||
-- (modified slightly for Cerulean Skies 2's disregard of the name of the
|
||||
-- themeinfo variable lol :p)
|
||||
|
||||
--[[
|
||||
the first released version was broken.
|
||||
this version aims to be simpler, and therefore work.
|
||||
|
||||
[changelog]
|
||||
|
||||
v2.11-ssc
|
||||
Remove EnvUtils references; we have it in sm-ssc.
|
||||
|
||||
v2.1-ssc
|
||||
sm-ssc version of UserPrefs. We can now assume players have certain
|
||||
functionality, like RageFile:GetError().
|
||||
|
||||
v2.1
|
||||
Added type specific GetUserPref functions.
|
||||
|
||||
[usage]
|
||||
First, edit PrefPath to match your theme.
|
||||
If you use ThemeInfo, then you shouldn't have to edit this.
|
||||
|
||||
If you're not using ThemeInfo, then you can replace
|
||||
|
||||
".. themeInfo.Name .." with the theme's folder name.
|
||||
|
||||
ThemeInfo is documented at http://kki.ajworld.net/wiki/ThemeInfo.lua
|
||||
|
||||
After that's set up, read the docs.
|
||||
]]
|
||||
local PrefPath = "Data/GamePrefs/"
|
||||
|
||||
--[[ begin internal stuff; no need to edit below this line. ]]
|
||||
|
||||
-- Local internal function to write envs. ___Not for themer use.___
|
||||
local function WriteEnv(envName,envValue)
|
||||
return setenv(envName,envValue)
|
||||
end
|
||||
|
||||
function ReadGamePrefFromFile(name)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
local fullFilename = PrefPath..name..".cfg"
|
||||
local option
|
||||
|
||||
if f:Open(fullFilename,1) then
|
||||
option = tostring( f:Read() )
|
||||
WriteEnv(name,option)
|
||||
f:destroy()
|
||||
return option
|
||||
else
|
||||
local fError = f:GetError()
|
||||
Trace( "[FileUtils] Error reading ".. fullFilename ..": ".. fError )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function WriteGamePrefToFile(name,value)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
local fullFilename = PrefPath..name..".cfg"
|
||||
|
||||
if f:Open(fullFilename, 2) then
|
||||
f:Write( tostring(value) )
|
||||
WriteEnv(name,value)
|
||||
else
|
||||
local fError = f:GetError()
|
||||
Trace( "[FileUtils] Error writing to ".. fullFilename ..": ".. fError )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return false
|
||||
end
|
||||
|
||||
f:destroy()
|
||||
return true
|
||||
end
|
||||
|
||||
--[[ end internal functions; still don't edit below this line ]]
|
||||
|
||||
function GetGamePref(name)
|
||||
return ReadGamePrefFromFile(name)
|
||||
end
|
||||
|
||||
function SetGamePref(name,value)
|
||||
return WriteGamePrefToFile(name,value)
|
||||
end
|
||||
|
||||
--[[ type specific, for when you want to be lazy ]]
|
||||
-- XXX: make set funcs, since I hate dealing with colors and I know
|
||||
-- other themers would too.
|
||||
|
||||
-- GetUserPrefB: boolean
|
||||
function GetGamePrefB(name)
|
||||
-- this one is a bit trickier.
|
||||
local pref = ReadGamePrefFromFile(name)
|
||||
|
||||
if type(pref) == "string" then
|
||||
pref = string.lower(pref)
|
||||
if pref == "true" or cmp == "t" then
|
||||
return true
|
||||
elseif pref == "false" or cmp == "f" then
|
||||
return false
|
||||
else
|
||||
Trace("Error in GetUserPrefB(".. name ..") converting from string" )
|
||||
return false
|
||||
end
|
||||
elseif type(pref) == "number" then
|
||||
-- both 0 and -1 are false; if you want to change this,
|
||||
-- feel free to remove "or pref == -1".
|
||||
if pref == 0 or pref == -1 then
|
||||
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- GetUserPrefC: color
|
||||
function GetGamePrefC(name)
|
||||
-- XXX: make sure it's grabbing a string that can be turned into a color
|
||||
-- and also possibly handle HSV values too.
|
||||
return color( ReadGamePrefFromFile(name) )
|
||||
end
|
||||
|
||||
-- GetUserPrefN: numbers (integers, floats)
|
||||
function GetGamePrefN(name)
|
||||
return tonumber( ReadGamePrefFromFile(name) )
|
||||
end
|
||||
|
||||
--[[
|
||||
Copyright © 2008-2009 AJ Kelly/KKI Labs
|
||||
All rights reserved.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]
|
||||
@@ -1,270 +1,270 @@
|
||||
-- sm-ssc fallback theme | script ring 03 | Gameplay.lua
|
||||
-- [en] This file is used to store settings that should be different in each
|
||||
-- game mode.
|
||||
|
||||
-- shakesoda calls this pump.lua
|
||||
|
||||
-- GetExtraColorThreshold()
|
||||
-- [en] returns the difficulty threshold in meter
|
||||
-- for songs that should be counted as boss songs.
|
||||
function GetExtraColorThreshold()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Modes = {
|
||||
dance = 10,
|
||||
pump = 15,
|
||||
beat = 12,
|
||||
kb7 = 10,
|
||||
para = 10,
|
||||
techno = 10,
|
||||
lights = 10, -- lights shouldn't be playable
|
||||
}
|
||||
return Modes[sGame]
|
||||
end
|
||||
|
||||
-- GameCompatibleModes:
|
||||
-- [en] returns possible modes for ScreenSelectPlayMode
|
||||
function GameCompatibleModes()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Modes = {
|
||||
dance = "Single,Double,Solo,Versus,Couple",
|
||||
pump = "Single,Double,HalfDouble,Versus,Couple",
|
||||
beat = "5Keys,7Keys,10Keys,14Keys",
|
||||
kb7 = "KB7",
|
||||
para = "Single",
|
||||
techno = "Single4,Single5,Single8,Double4,Double8",
|
||||
lights = "Single" -- lights shouldn't be playable
|
||||
}
|
||||
return Modes[sGame]
|
||||
end
|
||||
|
||||
function SelectProfileKeys()
|
||||
local sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
if sGame == "pump" then
|
||||
return "Up,Down,Start,Back,Center,DownLeft,DownRight"
|
||||
elseif sGame == "dance" then
|
||||
return "Up,Down,Start,Back,Up2,Down2"
|
||||
else
|
||||
return "Up,Down,Start,Back"
|
||||
end
|
||||
end
|
||||
|
||||
-- ScoreKeeperClass:
|
||||
-- [en] Determines the correct ScoreKeeper class to use.
|
||||
function ScoreKeeperClass()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local ScoreKeepers = {
|
||||
-- xxx: allow for ScoreKeeperShared when needed
|
||||
dance = "ScoreKeeperNormal",
|
||||
pump = "ScoreKeeperNormal",
|
||||
beat = "ScoreKeeperNormal",
|
||||
kb7 = "ScoreKeeperNormal",
|
||||
para = "ScoreKeeperNormal",
|
||||
techno = "ScoreKeeperNormal",
|
||||
ez2 = "ScoreKeeperNormal",
|
||||
ds3ddx = "ScoreKeeperNormal",
|
||||
maniax = "ScoreKeeperNormal",
|
||||
guitar = "ScoreKeeperGuitar"
|
||||
}
|
||||
return ScoreKeepers[sGame]
|
||||
end
|
||||
|
||||
-- ComboContinue:
|
||||
-- [en]
|
||||
function ComboContinue()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Continue = {
|
||||
dance = GAMESTATE:GetPlayMode() == "PlayMode_Oni" and "TapNoteScore_W2" or "TapNoteScore_W3",
|
||||
pump = "TapNoteScore_W3",
|
||||
beat = "TapNoteScore_W3",
|
||||
kb7 = "TapNoteScore_W3",
|
||||
para = "TapNoteScore_W4"
|
||||
}
|
||||
return Continue[sGame]
|
||||
end
|
||||
|
||||
function ComboMaintain()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Maintain = {
|
||||
dance = "TapNoteScore_W3",
|
||||
pump = "TapNoteScore_W4",
|
||||
beat = "TapNoteScore_W3",
|
||||
kb7 = "TapNoteScore_W3",
|
||||
para = "TapNoteScore_W4"
|
||||
}
|
||||
return Maintain[sGame]
|
||||
end
|
||||
|
||||
function ComboPerRow()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
if sGame == "pump" then
|
||||
return true
|
||||
elseif GAMESTATE:GetPlayMode() == "PlayMode_Oni" then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- these need cleanup really.
|
||||
function HitCombo()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Combo = {
|
||||
dance = 2,
|
||||
pump = 4,
|
||||
beat = 2,
|
||||
kb7 = 2,
|
||||
para = 2,
|
||||
guitar = 2
|
||||
}
|
||||
return Combo[sGame]
|
||||
end
|
||||
|
||||
function MissCombo()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Combo = {
|
||||
dance = 2,
|
||||
pump = 4,
|
||||
beat = 0,
|
||||
kb7 = 0,
|
||||
para = 0,
|
||||
guitar = 0
|
||||
}
|
||||
return Combo[sGame]
|
||||
end
|
||||
|
||||
-- FailCombo:
|
||||
-- [en] The combo that causes game failure.
|
||||
function FailCombo()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Combo = {
|
||||
dance = -1, -- ITG uses 30
|
||||
pump = 51, -- Pump Pro uses 30, real Pump uses 51
|
||||
beat = -1,
|
||||
kb7 = -1,
|
||||
para = -1,
|
||||
guitar = -1
|
||||
}
|
||||
return Combo[sGame]
|
||||
end
|
||||
|
||||
function RoutineSkinP1()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Combo = {
|
||||
dance = "midi-routine-p1",
|
||||
pump = "cmd-routine-p1",
|
||||
beat = "default",
|
||||
kb7 = "default",
|
||||
para = "default",
|
||||
guitar = "default"
|
||||
}
|
||||
return Combo[sGame]
|
||||
end
|
||||
|
||||
function RoutineSkinP2()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Combo = {
|
||||
dance = "midi-routine-p2",
|
||||
pump = "cmd-routine-p2",
|
||||
beat = "default",
|
||||
kb7 = "retrobar",
|
||||
para = "default",
|
||||
guitar = "default"
|
||||
}
|
||||
return Combo[sGame]
|
||||
end
|
||||
|
||||
-- todo: use tables for some of these -aj
|
||||
function HoldTiming()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return 0
|
||||
else
|
||||
return PREFSMAN:GetPreference("TimingWindowSecondsHold")
|
||||
end
|
||||
end
|
||||
|
||||
function ShowHoldJudgments()
|
||||
return not GAMESTATE:GetCurrentGame():GetName() == "pump"
|
||||
end
|
||||
|
||||
function HoldHeadStep()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function InitialHoldLife()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return 0.05
|
||||
else
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
function MaxHoldLife()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return 0.05
|
||||
else
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
function ImmediateHoldLetGo()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function RollBodyIncrementsCombo()
|
||||
return false
|
||||
--[[ if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end --]]
|
||||
end
|
||||
|
||||
function CheckpointsTapsSeparateJudgment()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ScoreMissedHoldsAndRolls()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local tNotePositions = {
|
||||
-- StepMania 3.9/4.0
|
||||
Normal = {
|
||||
-144,
|
||||
144,
|
||||
},
|
||||
-- ITG
|
||||
Lower = {
|
||||
-125,
|
||||
145,
|
||||
}
|
||||
}
|
||||
|
||||
function GetTapPosition( sType )
|
||||
bCategory = (sType == 'Standard') and 1 or 2
|
||||
-- true: Normal
|
||||
-- false: Lower
|
||||
bPreference = GetUserPrefB("UserPrefNotePosition") and "Normal" or "Lower"
|
||||
tNotePos = tNotePositions[bPreference]
|
||||
return tNotePos[bCategory]
|
||||
end
|
||||
|
||||
function ComboUnderField()
|
||||
return GetUserPrefB("UserPrefComboUnderField")
|
||||
-- sm-ssc fallback theme | script ring 03 | Gameplay.lua
|
||||
-- [en] This file is used to store settings that should be different in each
|
||||
-- game mode.
|
||||
|
||||
-- shakesoda calls this pump.lua
|
||||
|
||||
-- GetExtraColorThreshold()
|
||||
-- [en] returns the difficulty threshold in meter
|
||||
-- for songs that should be counted as boss songs.
|
||||
function GetExtraColorThreshold()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Modes = {
|
||||
dance = 10,
|
||||
pump = 15,
|
||||
beat = 12,
|
||||
kb7 = 10,
|
||||
para = 10,
|
||||
techno = 10,
|
||||
lights = 10, -- lights shouldn't be playable
|
||||
}
|
||||
return Modes[sGame]
|
||||
end
|
||||
|
||||
-- GameCompatibleModes:
|
||||
-- [en] returns possible modes for ScreenSelectPlayMode
|
||||
function GameCompatibleModes()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Modes = {
|
||||
dance = "Single,Double,Solo,Versus,Couple",
|
||||
pump = "Single,Double,HalfDouble,Versus,Couple",
|
||||
beat = "5Keys,7Keys,10Keys,14Keys",
|
||||
kb7 = "KB7",
|
||||
para = "Single",
|
||||
techno = "Single4,Single5,Single8,Double4,Double8",
|
||||
lights = "Single" -- lights shouldn't be playable
|
||||
}
|
||||
return Modes[sGame]
|
||||
end
|
||||
|
||||
function SelectProfileKeys()
|
||||
local sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
if sGame == "pump" then
|
||||
return "Up,Down,Start,Back,Center,DownLeft,DownRight"
|
||||
elseif sGame == "dance" then
|
||||
return "Up,Down,Start,Back,Up2,Down2"
|
||||
else
|
||||
return "Up,Down,Start,Back"
|
||||
end
|
||||
end
|
||||
|
||||
-- ScoreKeeperClass:
|
||||
-- [en] Determines the correct ScoreKeeper class to use.
|
||||
function ScoreKeeperClass()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local ScoreKeepers = {
|
||||
-- xxx: allow for ScoreKeeperShared when needed
|
||||
dance = "ScoreKeeperNormal",
|
||||
pump = "ScoreKeeperNormal",
|
||||
beat = "ScoreKeeperNormal",
|
||||
kb7 = "ScoreKeeperNormal",
|
||||
para = "ScoreKeeperNormal",
|
||||
techno = "ScoreKeeperNormal",
|
||||
ez2 = "ScoreKeeperNormal",
|
||||
ds3ddx = "ScoreKeeperNormal",
|
||||
maniax = "ScoreKeeperNormal",
|
||||
guitar = "ScoreKeeperGuitar"
|
||||
}
|
||||
return ScoreKeepers[sGame]
|
||||
end
|
||||
|
||||
-- ComboContinue:
|
||||
-- [en]
|
||||
function ComboContinue()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Continue = {
|
||||
dance = GAMESTATE:GetPlayMode() == "PlayMode_Oni" and "TapNoteScore_W2" or "TapNoteScore_W3",
|
||||
pump = "TapNoteScore_W3",
|
||||
beat = "TapNoteScore_W3",
|
||||
kb7 = "TapNoteScore_W3",
|
||||
para = "TapNoteScore_W4"
|
||||
}
|
||||
return Continue[sGame]
|
||||
end
|
||||
|
||||
function ComboMaintain()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Maintain = {
|
||||
dance = "TapNoteScore_W3",
|
||||
pump = "TapNoteScore_W4",
|
||||
beat = "TapNoteScore_W3",
|
||||
kb7 = "TapNoteScore_W3",
|
||||
para = "TapNoteScore_W4"
|
||||
}
|
||||
return Maintain[sGame]
|
||||
end
|
||||
|
||||
function ComboPerRow()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
if sGame == "pump" then
|
||||
return true
|
||||
elseif GAMESTATE:GetPlayMode() == "PlayMode_Oni" then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- these need cleanup really.
|
||||
function HitCombo()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Combo = {
|
||||
dance = 2,
|
||||
pump = 4,
|
||||
beat = 2,
|
||||
kb7 = 2,
|
||||
para = 2,
|
||||
guitar = 2
|
||||
}
|
||||
return Combo[sGame]
|
||||
end
|
||||
|
||||
function MissCombo()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Combo = {
|
||||
dance = 2,
|
||||
pump = 4,
|
||||
beat = 0,
|
||||
kb7 = 0,
|
||||
para = 0,
|
||||
guitar = 0
|
||||
}
|
||||
return Combo[sGame]
|
||||
end
|
||||
|
||||
-- FailCombo:
|
||||
-- [en] The combo that causes game failure.
|
||||
function FailCombo()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Combo = {
|
||||
dance = -1, -- ITG uses 30
|
||||
pump = 51, -- Pump Pro uses 30, real Pump uses 51
|
||||
beat = -1,
|
||||
kb7 = -1,
|
||||
para = -1,
|
||||
guitar = -1
|
||||
}
|
||||
return Combo[sGame]
|
||||
end
|
||||
|
||||
function RoutineSkinP1()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Combo = {
|
||||
dance = "midi-routine-p1",
|
||||
pump = "cmd-routine-p1",
|
||||
beat = "default",
|
||||
kb7 = "default",
|
||||
para = "default",
|
||||
guitar = "default"
|
||||
}
|
||||
return Combo[sGame]
|
||||
end
|
||||
|
||||
function RoutineSkinP2()
|
||||
sGame = GAMESTATE:GetCurrentGame():GetName()
|
||||
local Combo = {
|
||||
dance = "midi-routine-p2",
|
||||
pump = "cmd-routine-p2",
|
||||
beat = "default",
|
||||
kb7 = "retrobar",
|
||||
para = "default",
|
||||
guitar = "default"
|
||||
}
|
||||
return Combo[sGame]
|
||||
end
|
||||
|
||||
-- todo: use tables for some of these -aj
|
||||
function HoldTiming()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return 0
|
||||
else
|
||||
return PREFSMAN:GetPreference("TimingWindowSecondsHold")
|
||||
end
|
||||
end
|
||||
|
||||
function ShowHoldJudgments()
|
||||
return not GAMESTATE:GetCurrentGame():GetName() == "pump"
|
||||
end
|
||||
|
||||
function HoldHeadStep()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function InitialHoldLife()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return 0.05
|
||||
else
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
function MaxHoldLife()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return 0.05
|
||||
else
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
function ImmediateHoldLetGo()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function RollBodyIncrementsCombo()
|
||||
return false
|
||||
--[[ if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end --]]
|
||||
end
|
||||
|
||||
function CheckpointsTapsSeparateJudgment()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ScoreMissedHoldsAndRolls()
|
||||
if GAMESTATE:GetCurrentGame():GetName() == "pump" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local tNotePositions = {
|
||||
-- StepMania 3.9/4.0
|
||||
Normal = {
|
||||
-144,
|
||||
144,
|
||||
},
|
||||
-- ITG
|
||||
Lower = {
|
||||
-125,
|
||||
145,
|
||||
}
|
||||
}
|
||||
|
||||
function GetTapPosition( sType )
|
||||
bCategory = (sType == 'Standard') and 1 or 2
|
||||
-- true: Normal
|
||||
-- false: Lower
|
||||
bPreference = GetUserPrefB("UserPrefNotePosition") and "Normal" or "Lower"
|
||||
tNotePos = tNotePositions[bPreference]
|
||||
return tNotePos[bCategory]
|
||||
end
|
||||
|
||||
function ComboUnderField()
|
||||
return GetUserPrefB("UserPrefComboUnderField")
|
||||
end
|
||||
+248
-248
@@ -1,249 +1,249 @@
|
||||
--[[
|
||||
functions for using HSV colors in StepMania.
|
||||
Code adapted from http://www.cs.rit.edu/~ncs/color/t_convert.html
|
||||
|
||||
changelog:
|
||||
|
||||
v 1
|
||||
|
||||
= v1.1 =
|
||||
* Hue(color, newHue) changed to wrap around for invalid values.
|
||||
* Desaturate(color, percent) renamed to Saturation(color, percent).
|
||||
______________________________________________________________________________
|
||||
xxx: support HSL<->RGB (which is different) too?
|
||||
http://en.wikipedia.org/wiki/HSV_color_space#Conversion_from_RGB_to_HSL_or_HSV
|
||||
|
||||
HSL treats absolute brightness of a color at 0.5 in L, whereas
|
||||
HSV treats absolute brightness of a color at 1.0 in V.
|
||||
|
||||
Saturation is different too.
|
||||
]]
|
||||
|
||||
-- HasAlpha(c)
|
||||
function HasAlpha(c)
|
||||
if c[4] then
|
||||
return c[4]
|
||||
else
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
-- ColorToHSV(c)
|
||||
-- Takes in a normal color("") and returns a table with the HSV values.
|
||||
function ColorToHSV(c)
|
||||
local r = c[1]
|
||||
local g = c[2]
|
||||
local b = c[3]
|
||||
-- alpha requires error checking sometimes.
|
||||
local a = HasAlpha(c)
|
||||
|
||||
local h = 0
|
||||
local s = 0
|
||||
local v = 0
|
||||
|
||||
local min = math.min( r, g, b )
|
||||
local max = math.max( r, g, b )
|
||||
v = max
|
||||
|
||||
local delta = max - min
|
||||
|
||||
-- xxx: how do we deal with complete black?
|
||||
if min == 0 and max == 0 then
|
||||
-- we have complete darkness; make it cheap.
|
||||
return {
|
||||
Hue = 0,
|
||||
Sat = 0,
|
||||
Value = 0,
|
||||
Alpha = a
|
||||
}
|
||||
end
|
||||
|
||||
if max ~= 0 then
|
||||
s = delta / max -- rofl deltamax :|
|
||||
else
|
||||
-- r = g = b = 0; s = 0, v is undefined
|
||||
s = 0
|
||||
h = -1
|
||||
return {
|
||||
Hue = h,
|
||||
Sat = s,
|
||||
Value = v,
|
||||
Alpha = 1
|
||||
}
|
||||
end
|
||||
|
||||
if r == max then
|
||||
h = ( g - b ) / delta -- yellow/magenta
|
||||
elseif g == max then
|
||||
h = 2 + ( b - r ) / delta -- cyan/yellow
|
||||
else
|
||||
h = 4 + ( r - g ) / delta -- magenta/cyan
|
||||
end
|
||||
|
||||
h = h * 60 -- degrees
|
||||
|
||||
if h < 0 then
|
||||
h = h + 360
|
||||
end
|
||||
|
||||
return {
|
||||
Hue = h,
|
||||
Sat = s,
|
||||
Value = v,
|
||||
Alpha = a
|
||||
}
|
||||
end
|
||||
|
||||
-- HSVToColor(hsv)
|
||||
-- Converts a set of HSV values to a color. hsv is a table.
|
||||
-- See also: HSV(h, s, v)
|
||||
function HSVToColor(hsv)
|
||||
local i
|
||||
local f, q, p, t
|
||||
local r, g, b
|
||||
local h, s, v
|
||||
|
||||
local a
|
||||
|
||||
s = hsv.Sat
|
||||
v = hsv.Value
|
||||
|
||||
if hsv.Alpha then
|
||||
a = hsv.Alpha
|
||||
else
|
||||
a = 0
|
||||
end
|
||||
|
||||
if s == 0 then
|
||||
return { v, v, v, a }
|
||||
end
|
||||
|
||||
h = hsv.Hue / 60
|
||||
|
||||
i = math.floor(h)
|
||||
f = h - i
|
||||
p = v * (1-s)
|
||||
q = v * (1-s*f)
|
||||
t = v * (1-s*(1-f))
|
||||
|
||||
if i == 0 then
|
||||
return { v, t, p, a }
|
||||
elseif i == 1 then
|
||||
return { q, v, p, a }
|
||||
elseif i == 2 then
|
||||
return { p, v, t, a }
|
||||
elseif i == 3 then
|
||||
return { p, q, v, a }
|
||||
elseif i == 4 then
|
||||
return { t, p, v, a }
|
||||
else
|
||||
return { v, p, q, a }
|
||||
end
|
||||
end
|
||||
|
||||
-- ColorToHex(c)
|
||||
-- Takes in a normal color("") and returns the hex representation.
|
||||
-- Adapted from code in LuaBit (http://luaforge.net/projects/bit/),
|
||||
-- which is MIT licensed and copyright (C) 2006~2007 hanzhao.
|
||||
function ColorToHex(c)
|
||||
local r = c[1]
|
||||
local g = c[2]
|
||||
local b = c[3]
|
||||
local a = HasAlpha(c)
|
||||
|
||||
local function hex(value)
|
||||
value = math.ceil(value)
|
||||
|
||||
local hexVals = { 'A', 'B', 'C', 'D', 'E', 'F' }
|
||||
local out = ""
|
||||
local last = 0
|
||||
|
||||
while(value ~= 0) do
|
||||
last = math.mod(value, 16)
|
||||
if(last < 10) then
|
||||
out = tostring(last) .. out
|
||||
else
|
||||
out = hexVals[(last-10)+1] .. out
|
||||
end
|
||||
value = math.floor(value/16)
|
||||
end
|
||||
|
||||
if(out == "") then
|
||||
return "00"
|
||||
end
|
||||
|
||||
return string.format( "%02X", tonumber(out,16) )
|
||||
end
|
||||
|
||||
local rX = hex( scale(r, 0, 1, 0, 255) )
|
||||
local gX = hex( scale(g, 0, 1, 0, 255) )
|
||||
local bX = hex( scale(b, 0, 1, 0, 255) )
|
||||
local aX = hex( scale(a, 0, 1, 0, 255) )
|
||||
|
||||
return rX .. gX .. bX .. aX
|
||||
end
|
||||
|
||||
function HSVToHex(hsv)
|
||||
return ColorToHex( HSVToColor(hsv) )
|
||||
end
|
||||
|
||||
--[[ you should mainly use these functions ]]
|
||||
|
||||
-- this is the lazy one; use this when you mean fullly visible
|
||||
function HSV(h, s, v)
|
||||
local t = {
|
||||
Hue = h,
|
||||
Sat = s,
|
||||
Value = v,
|
||||
Alpha = 1
|
||||
}
|
||||
return HSVToColor(t)
|
||||
end
|
||||
|
||||
-- here's the proper one
|
||||
function HSVA(h, s, v, a)
|
||||
local t = {
|
||||
Hue = h,
|
||||
Sat = s,
|
||||
Value = v,
|
||||
Alpha = a
|
||||
}
|
||||
return HSVToColor(t)
|
||||
end
|
||||
|
||||
function Saturation(color,percent)
|
||||
local c = ColorToHSV(color)
|
||||
-- error checking
|
||||
if percent < 0 then
|
||||
percent = 0.0
|
||||
elseif percent > 1 then
|
||||
percent = 1.0
|
||||
end
|
||||
c.Sat = percent
|
||||
return HSVToColor(c)
|
||||
end
|
||||
|
||||
function Brightness(color,percent)
|
||||
local c = ColorToHSV(color)
|
||||
-- error checking
|
||||
if percent < 0 then
|
||||
percent = 0.0
|
||||
elseif percent > 1 then
|
||||
percent = 1.0
|
||||
end
|
||||
c.Value = percent
|
||||
return HSVToColor(c)
|
||||
end
|
||||
|
||||
function Hue(color,newHue)
|
||||
local c = ColorToHSV(color)
|
||||
-- handle wrapping
|
||||
if newHue < 0 then
|
||||
newHue = 360 + newHue
|
||||
elseif newHue > 360 then
|
||||
--newHue = math.mod(newHue, 360); -- ?? untested
|
||||
newHue = newHue - 360
|
||||
end
|
||||
c.Hue = newHue
|
||||
return HSVToColor(c)
|
||||
--[[
|
||||
functions for using HSV colors in StepMania.
|
||||
Code adapted from http://www.cs.rit.edu/~ncs/color/t_convert.html
|
||||
|
||||
changelog:
|
||||
|
||||
v 1
|
||||
|
||||
= v1.1 =
|
||||
* Hue(color, newHue) changed to wrap around for invalid values.
|
||||
* Desaturate(color, percent) renamed to Saturation(color, percent).
|
||||
______________________________________________________________________________
|
||||
xxx: support HSL<->RGB (which is different) too?
|
||||
http://en.wikipedia.org/wiki/HSV_color_space#Conversion_from_RGB_to_HSL_or_HSV
|
||||
|
||||
HSL treats absolute brightness of a color at 0.5 in L, whereas
|
||||
HSV treats absolute brightness of a color at 1.0 in V.
|
||||
|
||||
Saturation is different too.
|
||||
]]
|
||||
|
||||
-- HasAlpha(c)
|
||||
function HasAlpha(c)
|
||||
if c[4] then
|
||||
return c[4]
|
||||
else
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
-- ColorToHSV(c)
|
||||
-- Takes in a normal color("") and returns a table with the HSV values.
|
||||
function ColorToHSV(c)
|
||||
local r = c[1]
|
||||
local g = c[2]
|
||||
local b = c[3]
|
||||
-- alpha requires error checking sometimes.
|
||||
local a = HasAlpha(c)
|
||||
|
||||
local h = 0
|
||||
local s = 0
|
||||
local v = 0
|
||||
|
||||
local min = math.min( r, g, b )
|
||||
local max = math.max( r, g, b )
|
||||
v = max
|
||||
|
||||
local delta = max - min
|
||||
|
||||
-- xxx: how do we deal with complete black?
|
||||
if min == 0 and max == 0 then
|
||||
-- we have complete darkness; make it cheap.
|
||||
return {
|
||||
Hue = 0,
|
||||
Sat = 0,
|
||||
Value = 0,
|
||||
Alpha = a
|
||||
}
|
||||
end
|
||||
|
||||
if max ~= 0 then
|
||||
s = delta / max -- rofl deltamax :|
|
||||
else
|
||||
-- r = g = b = 0; s = 0, v is undefined
|
||||
s = 0
|
||||
h = -1
|
||||
return {
|
||||
Hue = h,
|
||||
Sat = s,
|
||||
Value = v,
|
||||
Alpha = 1
|
||||
}
|
||||
end
|
||||
|
||||
if r == max then
|
||||
h = ( g - b ) / delta -- yellow/magenta
|
||||
elseif g == max then
|
||||
h = 2 + ( b - r ) / delta -- cyan/yellow
|
||||
else
|
||||
h = 4 + ( r - g ) / delta -- magenta/cyan
|
||||
end
|
||||
|
||||
h = h * 60 -- degrees
|
||||
|
||||
if h < 0 then
|
||||
h = h + 360
|
||||
end
|
||||
|
||||
return {
|
||||
Hue = h,
|
||||
Sat = s,
|
||||
Value = v,
|
||||
Alpha = a
|
||||
}
|
||||
end
|
||||
|
||||
-- HSVToColor(hsv)
|
||||
-- Converts a set of HSV values to a color. hsv is a table.
|
||||
-- See also: HSV(h, s, v)
|
||||
function HSVToColor(hsv)
|
||||
local i
|
||||
local f, q, p, t
|
||||
local r, g, b
|
||||
local h, s, v
|
||||
|
||||
local a
|
||||
|
||||
s = hsv.Sat
|
||||
v = hsv.Value
|
||||
|
||||
if hsv.Alpha then
|
||||
a = hsv.Alpha
|
||||
else
|
||||
a = 0
|
||||
end
|
||||
|
||||
if s == 0 then
|
||||
return { v, v, v, a }
|
||||
end
|
||||
|
||||
h = hsv.Hue / 60
|
||||
|
||||
i = math.floor(h)
|
||||
f = h - i
|
||||
p = v * (1-s)
|
||||
q = v * (1-s*f)
|
||||
t = v * (1-s*(1-f))
|
||||
|
||||
if i == 0 then
|
||||
return { v, t, p, a }
|
||||
elseif i == 1 then
|
||||
return { q, v, p, a }
|
||||
elseif i == 2 then
|
||||
return { p, v, t, a }
|
||||
elseif i == 3 then
|
||||
return { p, q, v, a }
|
||||
elseif i == 4 then
|
||||
return { t, p, v, a }
|
||||
else
|
||||
return { v, p, q, a }
|
||||
end
|
||||
end
|
||||
|
||||
-- ColorToHex(c)
|
||||
-- Takes in a normal color("") and returns the hex representation.
|
||||
-- Adapted from code in LuaBit (http://luaforge.net/projects/bit/),
|
||||
-- which is MIT licensed and copyright (C) 2006~2007 hanzhao.
|
||||
function ColorToHex(c)
|
||||
local r = c[1]
|
||||
local g = c[2]
|
||||
local b = c[3]
|
||||
local a = HasAlpha(c)
|
||||
|
||||
local function hex(value)
|
||||
value = math.ceil(value)
|
||||
|
||||
local hexVals = { 'A', 'B', 'C', 'D', 'E', 'F' }
|
||||
local out = ""
|
||||
local last = 0
|
||||
|
||||
while(value ~= 0) do
|
||||
last = math.mod(value, 16)
|
||||
if(last < 10) then
|
||||
out = tostring(last) .. out
|
||||
else
|
||||
out = hexVals[(last-10)+1] .. out
|
||||
end
|
||||
value = math.floor(value/16)
|
||||
end
|
||||
|
||||
if(out == "") then
|
||||
return "00"
|
||||
end
|
||||
|
||||
return string.format( "%02X", tonumber(out,16) )
|
||||
end
|
||||
|
||||
local rX = hex( scale(r, 0, 1, 0, 255) )
|
||||
local gX = hex( scale(g, 0, 1, 0, 255) )
|
||||
local bX = hex( scale(b, 0, 1, 0, 255) )
|
||||
local aX = hex( scale(a, 0, 1, 0, 255) )
|
||||
|
||||
return rX .. gX .. bX .. aX
|
||||
end
|
||||
|
||||
function HSVToHex(hsv)
|
||||
return ColorToHex( HSVToColor(hsv) )
|
||||
end
|
||||
|
||||
--[[ you should mainly use these functions ]]
|
||||
|
||||
-- this is the lazy one; use this when you mean fullly visible
|
||||
function HSV(h, s, v)
|
||||
local t = {
|
||||
Hue = h,
|
||||
Sat = s,
|
||||
Value = v,
|
||||
Alpha = 1
|
||||
}
|
||||
return HSVToColor(t)
|
||||
end
|
||||
|
||||
-- here's the proper one
|
||||
function HSVA(h, s, v, a)
|
||||
local t = {
|
||||
Hue = h,
|
||||
Sat = s,
|
||||
Value = v,
|
||||
Alpha = a
|
||||
}
|
||||
return HSVToColor(t)
|
||||
end
|
||||
|
||||
function Saturation(color,percent)
|
||||
local c = ColorToHSV(color)
|
||||
-- error checking
|
||||
if percent < 0 then
|
||||
percent = 0.0
|
||||
elseif percent > 1 then
|
||||
percent = 1.0
|
||||
end
|
||||
c.Sat = percent
|
||||
return HSVToColor(c)
|
||||
end
|
||||
|
||||
function Brightness(color,percent)
|
||||
local c = ColorToHSV(color)
|
||||
-- error checking
|
||||
if percent < 0 then
|
||||
percent = 0.0
|
||||
elseif percent > 1 then
|
||||
percent = 1.0
|
||||
end
|
||||
c.Value = percent
|
||||
return HSVToColor(c)
|
||||
end
|
||||
|
||||
function Hue(color,newHue)
|
||||
local c = ColorToHSV(color)
|
||||
-- handle wrapping
|
||||
if newHue < 0 then
|
||||
newHue = 360 + newHue
|
||||
elseif newHue > 360 then
|
||||
--newHue = math.mod(newHue, 360); -- ?? untested
|
||||
newHue = newHue - 360
|
||||
end
|
||||
c.Hue = newHue
|
||||
return HSVToColor(c)
|
||||
end;
|
||||
@@ -1,119 +1,119 @@
|
||||
--[[
|
||||
IniFile: basically a Lua rewrite of SM's IniFile class that serves as the
|
||||
basis for the sm-ssc UserPrefs and ThemePrefs configuration systems.
|
||||
Note that this is a namespace, not a class per se.
|
||||
--]]
|
||||
|
||||
-- TODO: move this into a more general section
|
||||
-- func takes a key and a value
|
||||
function foreach_ordered( tbl, func )
|
||||
local keys = { }
|
||||
for k,_ in pairs(tbl) do keys[#keys+1] = k end
|
||||
|
||||
table.sort( keys )
|
||||
|
||||
-- iterate in sorted order
|
||||
for _,key in ipairs(keys) do func( key, tbl[key]) end
|
||||
end
|
||||
|
||||
-- redeclared here for my sanity's sake
|
||||
-- TODO: declare these as global variables
|
||||
local RageFile =
|
||||
{
|
||||
READ = 1,
|
||||
WRITE = 2,
|
||||
STREAMED = 4,
|
||||
SLOW_FLUSH = 8
|
||||
}
|
||||
|
||||
-- IniFile namespace
|
||||
IniFile =
|
||||
{
|
||||
StrToKeyVal = function( str )
|
||||
local _, _, key, value = str:find( "(.+)=(.*)" )
|
||||
|
||||
-- key is always a string, but value may be num, bool, or nil.
|
||||
-- do a few quick checks to see which one it is.
|
||||
|
||||
-- if it's a nil, convert it to an empty string and return
|
||||
if value == nil then value = ""; return key, value; end
|
||||
|
||||
-- if it's a number, convert it in place and return
|
||||
if tonumber(value) ~= nil then value = tonumber(value); return key, value; end
|
||||
|
||||
-- not a number, so let's try a boolean value
|
||||
if value == "true" then value = true;
|
||||
elseif value == "false" then value = false;
|
||||
end
|
||||
|
||||
return key, value
|
||||
end,
|
||||
|
||||
ReadFile = function( file_path )
|
||||
Trace( "IniFile.ReadFile( " .. file_path .. " )" )
|
||||
local file = RageFileUtil.CreateRageFile()
|
||||
|
||||
if not file:Open(file_path, RageFile.READ) then
|
||||
Warn( string.format("ReadFile(%s): %s",file_path,file:GetError()) )
|
||||
file:destroy()
|
||||
return { } -- return a blank table
|
||||
end
|
||||
|
||||
local tbl = { }
|
||||
local current = tbl
|
||||
|
||||
while not file:AtEOF() do
|
||||
local str = file:GetLine()
|
||||
|
||||
-- is this a section?
|
||||
local _, _, sec = str:find( "%[(.+)%]" )
|
||||
|
||||
-- if so, set focus there; otherwise, try to
|
||||
-- read a key/value pair (ignore blank lines)
|
||||
if sec then
|
||||
-- if this section doesn't exist, create it
|
||||
tbl[sec] = tbl[sec] and tbl[sec] or { }
|
||||
current = tbl[sec]
|
||||
Warn( "Switching section to " .. sec )
|
||||
else
|
||||
local k, v = IniFile.StrToKeyVal( str )
|
||||
if k and v then current[k] = v end
|
||||
end
|
||||
end
|
||||
|
||||
file:Close()
|
||||
file:destroy()
|
||||
|
||||
return tbl
|
||||
end,
|
||||
|
||||
WriteFile = function( file_path, tbl )
|
||||
Trace( "IniFile.WriteFile( " .. file_path .. " )" )
|
||||
local file = RageFileUtil.CreateRageFile()
|
||||
|
||||
if not file:Open(file_path, RageFile.WRITE) then
|
||||
Warn( string.format("WriteFile(%s): %s",file_path.file:GetError()) )
|
||||
file:destroy()
|
||||
return false
|
||||
end
|
||||
|
||||
-- declare functions so we can write with foreach_ordered
|
||||
local function put_pair( k, v )
|
||||
file:PutLine( string.format("%s=%s", k, tostring(v)) )
|
||||
end
|
||||
|
||||
local function put_section( section, pair )
|
||||
file:PutLine( "[" .. section .. "]" )
|
||||
foreach_ordered( pair, put_pair )
|
||||
file:PutLine("") -- put a blank line between sections
|
||||
end
|
||||
|
||||
-- each base key is a section and its value is a
|
||||
-- table of key-value pairs under that section.
|
||||
foreach_ordered( tbl, put_section )
|
||||
|
||||
file:Close()
|
||||
file:destroy()
|
||||
return true
|
||||
end
|
||||
};
|
||||
--[[
|
||||
IniFile: basically a Lua rewrite of SM's IniFile class that serves as the
|
||||
basis for the sm-ssc UserPrefs and ThemePrefs configuration systems.
|
||||
Note that this is a namespace, not a class per se.
|
||||
--]]
|
||||
|
||||
-- TODO: move this into a more general section
|
||||
-- func takes a key and a value
|
||||
function foreach_ordered( tbl, func )
|
||||
local keys = { }
|
||||
for k,_ in pairs(tbl) do keys[#keys+1] = k end
|
||||
|
||||
table.sort( keys )
|
||||
|
||||
-- iterate in sorted order
|
||||
for _,key in ipairs(keys) do func( key, tbl[key]) end
|
||||
end
|
||||
|
||||
-- redeclared here for my sanity's sake
|
||||
-- TODO: declare these as global variables
|
||||
local RageFile =
|
||||
{
|
||||
READ = 1,
|
||||
WRITE = 2,
|
||||
STREAMED = 4,
|
||||
SLOW_FLUSH = 8
|
||||
}
|
||||
|
||||
-- IniFile namespace
|
||||
IniFile =
|
||||
{
|
||||
StrToKeyVal = function( str )
|
||||
local _, _, key, value = str:find( "(.+)=(.*)" )
|
||||
|
||||
-- key is always a string, but value may be num, bool, or nil.
|
||||
-- do a few quick checks to see which one it is.
|
||||
|
||||
-- if it's a nil, convert it to an empty string and return
|
||||
if value == nil then value = ""; return key, value; end
|
||||
|
||||
-- if it's a number, convert it in place and return
|
||||
if tonumber(value) ~= nil then value = tonumber(value); return key, value; end
|
||||
|
||||
-- not a number, so let's try a boolean value
|
||||
if value == "true" then value = true;
|
||||
elseif value == "false" then value = false;
|
||||
end
|
||||
|
||||
return key, value
|
||||
end,
|
||||
|
||||
ReadFile = function( file_path )
|
||||
Trace( "IniFile.ReadFile( " .. file_path .. " )" )
|
||||
local file = RageFileUtil.CreateRageFile()
|
||||
|
||||
if not file:Open(file_path, RageFile.READ) then
|
||||
Warn( string.format("ReadFile(%s): %s",file_path,file:GetError()) )
|
||||
file:destroy()
|
||||
return { } -- return a blank table
|
||||
end
|
||||
|
||||
local tbl = { }
|
||||
local current = tbl
|
||||
|
||||
while not file:AtEOF() do
|
||||
local str = file:GetLine()
|
||||
|
||||
-- is this a section?
|
||||
local _, _, sec = str:find( "%[(.+)%]" )
|
||||
|
||||
-- if so, set focus there; otherwise, try to
|
||||
-- read a key/value pair (ignore blank lines)
|
||||
if sec then
|
||||
-- if this section doesn't exist, create it
|
||||
tbl[sec] = tbl[sec] and tbl[sec] or { }
|
||||
current = tbl[sec]
|
||||
Warn( "Switching section to " .. sec )
|
||||
else
|
||||
local k, v = IniFile.StrToKeyVal( str )
|
||||
if k and v then current[k] = v end
|
||||
end
|
||||
end
|
||||
|
||||
file:Close()
|
||||
file:destroy()
|
||||
|
||||
return tbl
|
||||
end,
|
||||
|
||||
WriteFile = function( file_path, tbl )
|
||||
Trace( "IniFile.WriteFile( " .. file_path .. " )" )
|
||||
local file = RageFileUtil.CreateRageFile()
|
||||
|
||||
if not file:Open(file_path, RageFile.WRITE) then
|
||||
Warn( string.format("WriteFile(%s): %s",file_path.file:GetError()) )
|
||||
file:destroy()
|
||||
return false
|
||||
end
|
||||
|
||||
-- declare functions so we can write with foreach_ordered
|
||||
local function put_pair( k, v )
|
||||
file:PutLine( string.format("%s=%s", k, tostring(v)) )
|
||||
end
|
||||
|
||||
local function put_section( section, pair )
|
||||
file:PutLine( "[" .. section .. "]" )
|
||||
foreach_ordered( pair, put_pair )
|
||||
file:PutLine("") -- put a blank line between sections
|
||||
end
|
||||
|
||||
-- each base key is a section and its value is a
|
||||
-- table of key-value pairs under that section.
|
||||
foreach_ordered( tbl, put_section )
|
||||
|
||||
file:Close()
|
||||
file:destroy()
|
||||
return true
|
||||
end
|
||||
};
|
||||
|
||||
@@ -1,252 +1,252 @@
|
||||
-- ProductivityHelpers: A set of useful aliases for theming.
|
||||
-- This is the sm-ssc version. You should not be using this in themes for
|
||||
-- SM4 right now... We'll post an updated version soon.
|
||||
|
||||
--[[ Globals ]]
|
||||
function IsArcade()
|
||||
local sPayMode = GAMESTATE:GetCoinMode();
|
||||
local bIsArcade = (sPayMode ~= 'CoinMode_Home');
|
||||
return bIsArcade;
|
||||
end
|
||||
|
||||
function IsHome()
|
||||
local sPayMode = GAMESTATE:GetCoinMode();
|
||||
local bIsHome = (sPayMode == 'CoinMode_Home');
|
||||
return bIsHome;
|
||||
end
|
||||
|
||||
function IsFreePlay()
|
||||
if IsArcade() then
|
||||
return (GAMESTATE:GetCoinMode() == 'CoinMode_Free');
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function Center1Player()
|
||||
if GAMESTATE:GetCurrentStyle():GetStyleType() == "StyleType_OnePlayerTwoSides" then
|
||||
return true
|
||||
elseif PREFSMAN:GetPreference("Center1Player") then
|
||||
if GAMESTATE:GetCurrentStyle():GetStyleType() == "StyleType_OnePlayerOneSide" then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
--[[ return PREFSMAN:GetPreference("Center1Player") and
|
||||
THEME:GetMetric("ScreenGameplay","AllowCenter1Player") and
|
||||
not GAMESTATE:GetPlayMode("PlayMode_Battle") and
|
||||
not GAMESTATE:GetPlayMode("PlayMode_Rave") and
|
||||
GAMESTATE:GetCurrentStyle():GetStyleType() == "StyleType_OnePlayerOneSide"; --]]
|
||||
end
|
||||
|
||||
--[[ 3.9 Conditionals ]]
|
||||
Condition = {
|
||||
Hour = function()
|
||||
return Hour()
|
||||
end,
|
||||
IsDemonstration = function()
|
||||
return GAMESTATE:IsDemonstration()
|
||||
end,
|
||||
CurSong = function(sSongName)
|
||||
return GAMESTATE:GetCurrentSong():GetDisplayMainTitle() == sSongName
|
||||
end,
|
||||
DayOfMonth = function()
|
||||
return DayOfMonth()
|
||||
end,
|
||||
MonthOfYear = function()
|
||||
return MonthOfYear()
|
||||
end,
|
||||
UsingModifier = function(pnPlayer, sModifier)
|
||||
return GAMESTATE:PlayerIsUsingModifier( pnPlayer, sModifier );
|
||||
end,
|
||||
}
|
||||
--[[ 3.9 Functions ]]
|
||||
Game = {
|
||||
GetStage = function()
|
||||
|
||||
end,
|
||||
}
|
||||
--[[ Aliases ]]
|
||||
|
||||
-- Blend Modes
|
||||
-- Aliases for blend modes.
|
||||
Blend = {
|
||||
Normal = 'BlendMode_Normal',
|
||||
Add = 'BlendMode_Add',
|
||||
Modulate = 'BlendMode_Modulate',
|
||||
Multiply = 'BlendMode_WeightedMultiply',
|
||||
Invert = 'BlendMode_InvertDest',
|
||||
NoEffect = 'BlendMode_NoEffect',
|
||||
}
|
||||
|
||||
-- Health Declarations
|
||||
-- Used primarily for lifebars.
|
||||
Health = {
|
||||
Max = 'HealthState_Hot',
|
||||
Alive = 'HealthState_Alive',
|
||||
Danger = 'HealthState_Danger',
|
||||
Dead = 'HealthState_Dead'
|
||||
}
|
||||
|
||||
-- Make graphics their true size at any resolution.
|
||||
--[[
|
||||
Note: for screens taller than wide (i.e. phones, sideways displays),
|
||||
you'll need to get width rather than height (I just don't feel like
|
||||
uglyfying my code just to handle rare cases). -shake
|
||||
--]]
|
||||
|
||||
-- useful
|
||||
function GetReal()
|
||||
local theme = THEME:GetMetric("Common","ScreenHeight")
|
||||
local res = PREFSMAN:GetPreference("DisplayHeight")
|
||||
return theme/res
|
||||
end
|
||||
|
||||
function GetRealInverse()
|
||||
local theme = THEME:GetMetric("Common","ScreenHeight")
|
||||
local res = PREFSMAN:GetPreference("DisplayHeight")
|
||||
return res/theme
|
||||
end
|
||||
|
||||
function Actor:Real()
|
||||
-- scale back down to real pixels.
|
||||
self:basezoom(GetReal())
|
||||
-- don't make this ugly
|
||||
self:SetTextureFiltering(false)
|
||||
end
|
||||
|
||||
-- Scale things back up after they have already been scaled down.
|
||||
function Actor:RealInverse()
|
||||
-- scale back up to theme resolution
|
||||
self:basezoom(GetRealInverse())
|
||||
self:SetTextureFiltering(true)
|
||||
end
|
||||
|
||||
--[[ Actor commands ]]
|
||||
function Actor:CenterX()
|
||||
self:x(SCREEN_CENTER_X)
|
||||
end
|
||||
|
||||
function Actor:CenterY()
|
||||
self:y(SCREEN_CENTER_Y)
|
||||
end
|
||||
|
||||
-- xy(actorX,actorY)
|
||||
-- Sets the x and y of an actor in one command.
|
||||
function Actor:xy(actorX,actorY)
|
||||
self:x(actorX)
|
||||
self:y(actorY)
|
||||
end
|
||||
|
||||
-- MaskSource([clearzbuffer])
|
||||
-- Sets an actor up as the source for a mask. Clears zBuffer by default.
|
||||
function Actor:MaskSource(noclear)
|
||||
self:clearzbuffer(noclear or true)
|
||||
self:zwrite(true)
|
||||
self:blend('BlendMode_NoEffect')
|
||||
end
|
||||
|
||||
-- MaskDest()
|
||||
-- Sets an actor up to be masked by anything with MaskSource().
|
||||
function Actor:MaskDest()
|
||||
self:ztest(true)
|
||||
end
|
||||
|
||||
-- Thump()
|
||||
-- A customized version of pulse that is more appealing for on-beat
|
||||
-- effects;
|
||||
function Actor:thump(fEffectPeriod)
|
||||
self:pulse()
|
||||
if fEffectPeriod ~= nil then
|
||||
self:effecttiming(0,0,0.75*fEffectPeriod,0.25*fEffectPeriod)
|
||||
else
|
||||
self:effecttiming(0,0,0.75,0.25)
|
||||
end
|
||||
-- The default effectmagnitude will make this effect look very bad.
|
||||
self:effectmagnitude(1,1.125,1)
|
||||
end
|
||||
|
||||
-- Heartbeat()
|
||||
-- A customized version of pulse that is more appealing for on-beat
|
||||
-- effects;
|
||||
function Actor:heartbeat(fEffectPeriod)
|
||||
self:pulse()
|
||||
if fEffectPeriod ~= nil then
|
||||
self:effecttiming(0,0.125*fEffectPeriod,0.125*fEffectPeriod,0.75*fEffectPeriod);
|
||||
else
|
||||
self:effecttiming(0,0.125,0.125,0.75);
|
||||
end
|
||||
self:effecmagnitude(1,1.125,1)
|
||||
end
|
||||
|
||||
--[[ BitmapText commands ]]
|
||||
|
||||
-- PixelFont()
|
||||
-- An alias that turns off texture filtering.
|
||||
-- Named because it works best with pixel fonts.
|
||||
function BitmapText:PixelFont()
|
||||
self:SetTextureFiltering(false)
|
||||
end
|
||||
|
||||
-- Stroke(color)
|
||||
-- Sets the text's stroke color.
|
||||
function BitmapText:Stroke(c)
|
||||
self:strokecolor( c )
|
||||
end
|
||||
|
||||
-- NoStroke()
|
||||
-- Removes any stroke.
|
||||
function BitmapText:NoStroke()
|
||||
self:strokecolor( color("0,0,0,0") )
|
||||
end
|
||||
|
||||
-- Set Text With Format (contributed by Daisuke Master)
|
||||
-- this function is my hero - shake
|
||||
function BitmapText:settextf(...)
|
||||
self:settext(string.format(...))
|
||||
end
|
||||
|
||||
-- DiffuseAndStroke(diffuse,stroke)
|
||||
-- Set diffuse and stroke at the same time.
|
||||
function BitmapText:DiffuseAndStroke(diffuseC,strokeC)
|
||||
self:diffuse(diffuseC)
|
||||
self:strokecolor(strokeC)
|
||||
end;
|
||||
--[[ end BitmapText commands ]]
|
||||
|
||||
--[[ ----------------------------------------------------------------------- ]]
|
||||
|
||||
--[[ helper functions ]]
|
||||
function tobool(v)
|
||||
if type(v) == "string" then
|
||||
local cmp = string.lower(v)
|
||||
if cmp == "true" or cmp == "t" then
|
||||
return true
|
||||
elseif cmp == "false" or cmp == "f" then
|
||||
return false
|
||||
end
|
||||
elseif type(v) == "number" then
|
||||
if v == 0 then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function pname(pn)
|
||||
return ToEnumShortString(pn)
|
||||
end
|
||||
|
||||
function math.round(num, pre)
|
||||
if pre and pre < 0 then pre = 0 end
|
||||
local mult = 10^(pre or 0)
|
||||
if num >= 0 then return math.floor(num*mult+.5)/mult
|
||||
else return math.ceil(num*mult-.5)/mult end
|
||||
end
|
||||
|
||||
--[[ end helper functions ]]
|
||||
-- this code is in the public domain.
|
||||
-- ProductivityHelpers: A set of useful aliases for theming.
|
||||
-- This is the sm-ssc version. You should not be using this in themes for
|
||||
-- SM4 right now... We'll post an updated version soon.
|
||||
|
||||
--[[ Globals ]]
|
||||
function IsArcade()
|
||||
local sPayMode = GAMESTATE:GetCoinMode();
|
||||
local bIsArcade = (sPayMode ~= 'CoinMode_Home');
|
||||
return bIsArcade;
|
||||
end
|
||||
|
||||
function IsHome()
|
||||
local sPayMode = GAMESTATE:GetCoinMode();
|
||||
local bIsHome = (sPayMode == 'CoinMode_Home');
|
||||
return bIsHome;
|
||||
end
|
||||
|
||||
function IsFreePlay()
|
||||
if IsArcade() then
|
||||
return (GAMESTATE:GetCoinMode() == 'CoinMode_Free');
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function Center1Player()
|
||||
if GAMESTATE:GetCurrentStyle():GetStyleType() == "StyleType_OnePlayerTwoSides" then
|
||||
return true
|
||||
elseif PREFSMAN:GetPreference("Center1Player") then
|
||||
if GAMESTATE:GetCurrentStyle():GetStyleType() == "StyleType_OnePlayerOneSide" then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
--[[ return PREFSMAN:GetPreference("Center1Player") and
|
||||
THEME:GetMetric("ScreenGameplay","AllowCenter1Player") and
|
||||
not GAMESTATE:GetPlayMode("PlayMode_Battle") and
|
||||
not GAMESTATE:GetPlayMode("PlayMode_Rave") and
|
||||
GAMESTATE:GetCurrentStyle():GetStyleType() == "StyleType_OnePlayerOneSide"; --]]
|
||||
end
|
||||
|
||||
--[[ 3.9 Conditionals ]]
|
||||
Condition = {
|
||||
Hour = function()
|
||||
return Hour()
|
||||
end,
|
||||
IsDemonstration = function()
|
||||
return GAMESTATE:IsDemonstration()
|
||||
end,
|
||||
CurSong = function(sSongName)
|
||||
return GAMESTATE:GetCurrentSong():GetDisplayMainTitle() == sSongName
|
||||
end,
|
||||
DayOfMonth = function()
|
||||
return DayOfMonth()
|
||||
end,
|
||||
MonthOfYear = function()
|
||||
return MonthOfYear()
|
||||
end,
|
||||
UsingModifier = function(pnPlayer, sModifier)
|
||||
return GAMESTATE:PlayerIsUsingModifier( pnPlayer, sModifier );
|
||||
end,
|
||||
}
|
||||
--[[ 3.9 Functions ]]
|
||||
Game = {
|
||||
GetStage = function()
|
||||
|
||||
end,
|
||||
}
|
||||
--[[ Aliases ]]
|
||||
|
||||
-- Blend Modes
|
||||
-- Aliases for blend modes.
|
||||
Blend = {
|
||||
Normal = 'BlendMode_Normal',
|
||||
Add = 'BlendMode_Add',
|
||||
Modulate = 'BlendMode_Modulate',
|
||||
Multiply = 'BlendMode_WeightedMultiply',
|
||||
Invert = 'BlendMode_InvertDest',
|
||||
NoEffect = 'BlendMode_NoEffect',
|
||||
}
|
||||
|
||||
-- Health Declarations
|
||||
-- Used primarily for lifebars.
|
||||
Health = {
|
||||
Max = 'HealthState_Hot',
|
||||
Alive = 'HealthState_Alive',
|
||||
Danger = 'HealthState_Danger',
|
||||
Dead = 'HealthState_Dead'
|
||||
}
|
||||
|
||||
-- Make graphics their true size at any resolution.
|
||||
--[[
|
||||
Note: for screens taller than wide (i.e. phones, sideways displays),
|
||||
you'll need to get width rather than height (I just don't feel like
|
||||
uglyfying my code just to handle rare cases). -shake
|
||||
--]]
|
||||
|
||||
-- useful
|
||||
function GetReal()
|
||||
local theme = THEME:GetMetric("Common","ScreenHeight")
|
||||
local res = PREFSMAN:GetPreference("DisplayHeight")
|
||||
return theme/res
|
||||
end
|
||||
|
||||
function GetRealInverse()
|
||||
local theme = THEME:GetMetric("Common","ScreenHeight")
|
||||
local res = PREFSMAN:GetPreference("DisplayHeight")
|
||||
return res/theme
|
||||
end
|
||||
|
||||
function Actor:Real()
|
||||
-- scale back down to real pixels.
|
||||
self:basezoom(GetReal())
|
||||
-- don't make this ugly
|
||||
self:SetTextureFiltering(false)
|
||||
end
|
||||
|
||||
-- Scale things back up after they have already been scaled down.
|
||||
function Actor:RealInverse()
|
||||
-- scale back up to theme resolution
|
||||
self:basezoom(GetRealInverse())
|
||||
self:SetTextureFiltering(true)
|
||||
end
|
||||
|
||||
--[[ Actor commands ]]
|
||||
function Actor:CenterX()
|
||||
self:x(SCREEN_CENTER_X)
|
||||
end
|
||||
|
||||
function Actor:CenterY()
|
||||
self:y(SCREEN_CENTER_Y)
|
||||
end
|
||||
|
||||
-- xy(actorX,actorY)
|
||||
-- Sets the x and y of an actor in one command.
|
||||
function Actor:xy(actorX,actorY)
|
||||
self:x(actorX)
|
||||
self:y(actorY)
|
||||
end
|
||||
|
||||
-- MaskSource([clearzbuffer])
|
||||
-- Sets an actor up as the source for a mask. Clears zBuffer by default.
|
||||
function Actor:MaskSource(noclear)
|
||||
self:clearzbuffer(noclear or true)
|
||||
self:zwrite(true)
|
||||
self:blend('BlendMode_NoEffect')
|
||||
end
|
||||
|
||||
-- MaskDest()
|
||||
-- Sets an actor up to be masked by anything with MaskSource().
|
||||
function Actor:MaskDest()
|
||||
self:ztest(true)
|
||||
end
|
||||
|
||||
-- Thump()
|
||||
-- A customized version of pulse that is more appealing for on-beat
|
||||
-- effects;
|
||||
function Actor:thump(fEffectPeriod)
|
||||
self:pulse()
|
||||
if fEffectPeriod ~= nil then
|
||||
self:effecttiming(0,0,0.75*fEffectPeriod,0.25*fEffectPeriod)
|
||||
else
|
||||
self:effecttiming(0,0,0.75,0.25)
|
||||
end
|
||||
-- The default effectmagnitude will make this effect look very bad.
|
||||
self:effectmagnitude(1,1.125,1)
|
||||
end
|
||||
|
||||
-- Heartbeat()
|
||||
-- A customized version of pulse that is more appealing for on-beat
|
||||
-- effects;
|
||||
function Actor:heartbeat(fEffectPeriod)
|
||||
self:pulse()
|
||||
if fEffectPeriod ~= nil then
|
||||
self:effecttiming(0,0.125*fEffectPeriod,0.125*fEffectPeriod,0.75*fEffectPeriod);
|
||||
else
|
||||
self:effecttiming(0,0.125,0.125,0.75);
|
||||
end
|
||||
self:effecmagnitude(1,1.125,1)
|
||||
end
|
||||
|
||||
--[[ BitmapText commands ]]
|
||||
|
||||
-- PixelFont()
|
||||
-- An alias that turns off texture filtering.
|
||||
-- Named because it works best with pixel fonts.
|
||||
function BitmapText:PixelFont()
|
||||
self:SetTextureFiltering(false)
|
||||
end
|
||||
|
||||
-- Stroke(color)
|
||||
-- Sets the text's stroke color.
|
||||
function BitmapText:Stroke(c)
|
||||
self:strokecolor( c )
|
||||
end
|
||||
|
||||
-- NoStroke()
|
||||
-- Removes any stroke.
|
||||
function BitmapText:NoStroke()
|
||||
self:strokecolor( color("0,0,0,0") )
|
||||
end
|
||||
|
||||
-- Set Text With Format (contributed by Daisuke Master)
|
||||
-- this function is my hero - shake
|
||||
function BitmapText:settextf(...)
|
||||
self:settext(string.format(...))
|
||||
end
|
||||
|
||||
-- DiffuseAndStroke(diffuse,stroke)
|
||||
-- Set diffuse and stroke at the same time.
|
||||
function BitmapText:DiffuseAndStroke(diffuseC,strokeC)
|
||||
self:diffuse(diffuseC)
|
||||
self:strokecolor(strokeC)
|
||||
end;
|
||||
--[[ end BitmapText commands ]]
|
||||
|
||||
--[[ ----------------------------------------------------------------------- ]]
|
||||
|
||||
--[[ helper functions ]]
|
||||
function tobool(v)
|
||||
if type(v) == "string" then
|
||||
local cmp = string.lower(v)
|
||||
if cmp == "true" or cmp == "t" then
|
||||
return true
|
||||
elseif cmp == "false" or cmp == "f" then
|
||||
return false
|
||||
end
|
||||
elseif type(v) == "number" then
|
||||
if v == 0 then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function pname(pn)
|
||||
return ToEnumShortString(pn)
|
||||
end
|
||||
|
||||
function math.round(num, pre)
|
||||
if pre and pre < 0 then pre = 0 end
|
||||
local mult = 10^(pre or 0)
|
||||
if num >= 0 then return math.floor(num*mult+.5)/mult
|
||||
else return math.ceil(num*mult-.5)/mult end
|
||||
end
|
||||
|
||||
--[[ end helper functions ]]
|
||||
-- this code is in the public domain.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,42 +1,42 @@
|
||||
-- theme library: juicy library that returns lua objects on demand.
|
||||
|
||||
Library = {
|
||||
GrooveRadar = function(self)
|
||||
local function radarSet(self,player)
|
||||
local selection = nil;
|
||||
if GAMESTATE:IsCourseMode() then
|
||||
if GAMESTATE:GetCurrentCourse() then
|
||||
selection = GAMESTATE:GetCurrentTrail(player);
|
||||
end;
|
||||
else
|
||||
if GAMESTATE:GetCurrentSong() then
|
||||
selection = GAMESTATE:GetCurrentSteps(player);
|
||||
end;
|
||||
end;
|
||||
if selection then
|
||||
self:SetFromRadarValues(player, selection:GetRadarValues(player));
|
||||
else
|
||||
self:SetEmpty(player);
|
||||
end;
|
||||
end
|
||||
--
|
||||
local t = Def.ActorFrame {
|
||||
Name="Radar";
|
||||
Def.GrooveRadar {
|
||||
OnCommand=cmd(zoom,0;sleep,0.583;decelerate,0.150;zoom,1);
|
||||
OffCommand=cmd(sleep,0.183;decelerate,0.167;zoom,0);
|
||||
CurrentSongChangedMessageCommand=function(self)
|
||||
for pn in ivalues(GAMESTATE:GetHumanPlayers()) do
|
||||
radarSet(self, pn);
|
||||
end;
|
||||
end;
|
||||
CurrentStepsP1ChangedMessageCommand=function(self) radarSet(self, PLAYER_1); end;
|
||||
CurrentStepsP2ChangedMessageCommand=function(self) radarSet(self, PLAYER_2); end;
|
||||
CurrentTrailP1ChangedMessageCommand=function(self) radarSet(self, PLAYER_1); end;
|
||||
CurrentTrailP2ChangedMessageCommand=function(self) radarSet(self, PLAYER_2); end;
|
||||
};
|
||||
};
|
||||
|
||||
return t;
|
||||
end;
|
||||
-- theme library: juicy library that returns lua objects on demand.
|
||||
|
||||
Library = {
|
||||
GrooveRadar = function(self)
|
||||
local function radarSet(self,player)
|
||||
local selection = nil;
|
||||
if GAMESTATE:IsCourseMode() then
|
||||
if GAMESTATE:GetCurrentCourse() then
|
||||
selection = GAMESTATE:GetCurrentTrail(player);
|
||||
end;
|
||||
else
|
||||
if GAMESTATE:GetCurrentSong() then
|
||||
selection = GAMESTATE:GetCurrentSteps(player);
|
||||
end;
|
||||
end;
|
||||
if selection then
|
||||
self:SetFromRadarValues(player, selection:GetRadarValues(player));
|
||||
else
|
||||
self:SetEmpty(player);
|
||||
end;
|
||||
end
|
||||
--
|
||||
local t = Def.ActorFrame {
|
||||
Name="Radar";
|
||||
Def.GrooveRadar {
|
||||
OnCommand=cmd(zoom,0;sleep,0.583;decelerate,0.150;zoom,1);
|
||||
OffCommand=cmd(sleep,0.183;decelerate,0.167;zoom,0);
|
||||
CurrentSongChangedMessageCommand=function(self)
|
||||
for pn in ivalues(GAMESTATE:GetHumanPlayers()) do
|
||||
radarSet(self, pn);
|
||||
end;
|
||||
end;
|
||||
CurrentStepsP1ChangedMessageCommand=function(self) radarSet(self, PLAYER_1); end;
|
||||
CurrentStepsP2ChangedMessageCommand=function(self) radarSet(self, PLAYER_2); end;
|
||||
CurrentTrailP1ChangedMessageCommand=function(self) radarSet(self, PLAYER_1); end;
|
||||
CurrentTrailP2ChangedMessageCommand=function(self) radarSet(self, PLAYER_2); end;
|
||||
};
|
||||
};
|
||||
|
||||
return t;
|
||||
end;
|
||||
}
|
||||
@@ -1,141 +1,141 @@
|
||||
--[[
|
||||
ThemePrefs: handles the underlying structure for ThemePrefs, so any themes
|
||||
built off of this can simply declare their prefs and default values, and
|
||||
access them through this system.
|
||||
|
||||
v0.7.1: Dec. 28, 2010. Added language support.
|
||||
v0.7.0: Dec. 15, 2010. Initial version.
|
||||
|
||||
vyhd wrote this for sm-ssc. <3 you guys
|
||||
--]]
|
||||
|
||||
-- local function to handle themed error strings
|
||||
-- (and to ensure we're getting all of them from the same section)
|
||||
local function GetString( name )
|
||||
return THEME:GetString( "ThemePrefs", name )
|
||||
end
|
||||
|
||||
function PrintTable( tbl )
|
||||
Trace( "Printing table" )
|
||||
for k,v in pairs(tbl) do
|
||||
Trace( ("[%s] -> %s"):format(tostring(k),tostring(v)) )
|
||||
end
|
||||
end
|
||||
|
||||
local ThemePrefsPath = "Save/ThemePrefs.ini";
|
||||
local FallbackTheme = "_fallback";
|
||||
|
||||
-- This will be set on load.
|
||||
local PrefsTable = nil;
|
||||
|
||||
-- Gets the name of the current theme using themeInfo
|
||||
-- if available and the ThemeManager name otherwise.
|
||||
local function GetThemeName()
|
||||
return themeInfo and themeInfo.Name or THEME:GetThemeDisplayName()
|
||||
end
|
||||
|
||||
-- Given a preference name, returns the table it's in. Checks the current
|
||||
-- theme first, then _fallback, then all other sections, in that order.
|
||||
local function ResolveTable( pref )
|
||||
-- check the section for this theme
|
||||
local name = GetThemeName()
|
||||
local val = PrefsTable[name][pref]
|
||||
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in %s"):format(pref,name) )
|
||||
return PrefsTable[name]
|
||||
end
|
||||
|
||||
-- not in the current theme; check the fallback if it exists
|
||||
if PrefsTable[FallbackTheme] then
|
||||
val = PrefsTable[FallbackTheme][pref]
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in fallback"):format(pref) )
|
||||
return PrefsTable[FallbackTheme]
|
||||
end
|
||||
end
|
||||
|
||||
-- not there either. check every section.
|
||||
-- XXX: we should do this less redundantly.
|
||||
for section, _ in pairs(PrefsTable) do
|
||||
val = PrefsTable[section][pref]
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in section %s"):format(pref,section) )
|
||||
return PrefsTable[section] end
|
||||
end
|
||||
|
||||
-- not found at all
|
||||
Trace( ("ResolveTable(%s): pref not found"):format(pref) )
|
||||
return nil
|
||||
end
|
||||
|
||||
ThemePrefs =
|
||||
{
|
||||
NeedsSaved = false,
|
||||
|
||||
-- Loads preferences from Save/ThemePrefs.ini, then adds theme
|
||||
-- preferences (and default values if applicable) to PrefsTable.
|
||||
-- Only read from disk once, when _fallback calls this; we just
|
||||
-- need the base set once to add prefs onto.
|
||||
Init = function( prefs, bLoadFromDisk )
|
||||
-- If we don't have IniFile, we can't read/write from/to disk
|
||||
if not IniFile then Warn( GetString("IniFileMissing") ) end
|
||||
|
||||
Trace( ("ThemePrefs.Init(prefs, %s)"):format(tostring(bLoadFromDisk)) )
|
||||
if bLoadFromDisk then
|
||||
Trace( "ThemePrefs.Init: loading from disk" )
|
||||
if not ThemePrefs.Load() then return false end
|
||||
end
|
||||
|
||||
Trace( "ThemePrefs.Init: not loading from disk" )
|
||||
|
||||
-- create the section if it doesn't exist
|
||||
local section = GetThemeName()
|
||||
PrefsTable[section] = PrefsTable[section] and PrefsTable[section] or { }
|
||||
|
||||
Trace( "Using section " .. section )
|
||||
|
||||
-- if the key doesn't exist, add it with our default value
|
||||
for k, tbl in pairs(prefs) do
|
||||
if not PrefsTable[section][k] then
|
||||
Trace( k .. " doesn't exist, creating" )
|
||||
PrefsTable[section][k] = tbl.Default
|
||||
end
|
||||
end
|
||||
|
||||
PrintTable( PrefsTable[section] )
|
||||
end,
|
||||
|
||||
Load = function()
|
||||
if not IniFile then return false end
|
||||
PrefsTable = IniFile.ReadFile( ThemePrefsPath )
|
||||
return true
|
||||
end,
|
||||
|
||||
Save = function()
|
||||
Trace( "ThemePrefs.Save" )
|
||||
if not IniFile then return false end
|
||||
if not NeedsSaved then return end
|
||||
NeedsSaved = false
|
||||
IniFile.WriteFile( ThemePrefsPath, PrefsTable )
|
||||
end,
|
||||
|
||||
Get = function( name )
|
||||
Trace( ("ThemePrefs.Get(%s)"):format(name) )
|
||||
local tbl = ResolveTable(name)
|
||||
if tbl then return tbl[name] end
|
||||
Warn( "Get: "..GetString("UnknownPreference"):format(name) )
|
||||
return nil
|
||||
end,
|
||||
|
||||
Set = function( name, value )
|
||||
Trace( ("ThemePrefs.Set(%s, %s)"):format(name, tostring(value)) )
|
||||
local tbl = ResolveTable(name)
|
||||
if tbl then tbl[name] = value; NeedsSaved = true; return end
|
||||
Warn( "Set: "..GetString("UnknownPreference"):format(name) )
|
||||
end,
|
||||
};
|
||||
|
||||
-- global aliases
|
||||
GetThemePref = ThemePrefs.Get
|
||||
SetThemePref = ThemePrefs.Set
|
||||
--[[
|
||||
ThemePrefs: handles the underlying structure for ThemePrefs, so any themes
|
||||
built off of this can simply declare their prefs and default values, and
|
||||
access them through this system.
|
||||
|
||||
v0.7.1: Dec. 28, 2010. Added language support.
|
||||
v0.7.0: Dec. 15, 2010. Initial version.
|
||||
|
||||
vyhd wrote this for sm-ssc. <3 you guys
|
||||
--]]
|
||||
|
||||
-- local function to handle themed error strings
|
||||
-- (and to ensure we're getting all of them from the same section)
|
||||
local function GetString( name )
|
||||
return THEME:GetString( "ThemePrefs", name )
|
||||
end
|
||||
|
||||
function PrintTable( tbl )
|
||||
Trace( "Printing table" )
|
||||
for k,v in pairs(tbl) do
|
||||
Trace( ("[%s] -> %s"):format(tostring(k),tostring(v)) )
|
||||
end
|
||||
end
|
||||
|
||||
local ThemePrefsPath = "Save/ThemePrefs.ini";
|
||||
local FallbackTheme = "_fallback";
|
||||
|
||||
-- This will be set on load.
|
||||
local PrefsTable = nil;
|
||||
|
||||
-- Gets the name of the current theme using themeInfo
|
||||
-- if available and the ThemeManager name otherwise.
|
||||
local function GetThemeName()
|
||||
return themeInfo and themeInfo.Name or THEME:GetThemeDisplayName()
|
||||
end
|
||||
|
||||
-- Given a preference name, returns the table it's in. Checks the current
|
||||
-- theme first, then _fallback, then all other sections, in that order.
|
||||
local function ResolveTable( pref )
|
||||
-- check the section for this theme
|
||||
local name = GetThemeName()
|
||||
local val = PrefsTable[name][pref]
|
||||
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in %s"):format(pref,name) )
|
||||
return PrefsTable[name]
|
||||
end
|
||||
|
||||
-- not in the current theme; check the fallback if it exists
|
||||
if PrefsTable[FallbackTheme] then
|
||||
val = PrefsTable[FallbackTheme][pref]
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in fallback"):format(pref) )
|
||||
return PrefsTable[FallbackTheme]
|
||||
end
|
||||
end
|
||||
|
||||
-- not there either. check every section.
|
||||
-- XXX: we should do this less redundantly.
|
||||
for section, _ in pairs(PrefsTable) do
|
||||
val = PrefsTable[section][pref]
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in section %s"):format(pref,section) )
|
||||
return PrefsTable[section] end
|
||||
end
|
||||
|
||||
-- not found at all
|
||||
Trace( ("ResolveTable(%s): pref not found"):format(pref) )
|
||||
return nil
|
||||
end
|
||||
|
||||
ThemePrefs =
|
||||
{
|
||||
NeedsSaved = false,
|
||||
|
||||
-- Loads preferences from Save/ThemePrefs.ini, then adds theme
|
||||
-- preferences (and default values if applicable) to PrefsTable.
|
||||
-- Only read from disk once, when _fallback calls this; we just
|
||||
-- need the base set once to add prefs onto.
|
||||
Init = function( prefs, bLoadFromDisk )
|
||||
-- If we don't have IniFile, we can't read/write from/to disk
|
||||
if not IniFile then Warn( GetString("IniFileMissing") ) end
|
||||
|
||||
Trace( ("ThemePrefs.Init(prefs, %s)"):format(tostring(bLoadFromDisk)) )
|
||||
if bLoadFromDisk then
|
||||
Trace( "ThemePrefs.Init: loading from disk" )
|
||||
if not ThemePrefs.Load() then return false end
|
||||
end
|
||||
|
||||
Trace( "ThemePrefs.Init: not loading from disk" )
|
||||
|
||||
-- create the section if it doesn't exist
|
||||
local section = GetThemeName()
|
||||
PrefsTable[section] = PrefsTable[section] and PrefsTable[section] or { }
|
||||
|
||||
Trace( "Using section " .. section )
|
||||
|
||||
-- if the key doesn't exist, add it with our default value
|
||||
for k, tbl in pairs(prefs) do
|
||||
if not PrefsTable[section][k] then
|
||||
Trace( k .. " doesn't exist, creating" )
|
||||
PrefsTable[section][k] = tbl.Default
|
||||
end
|
||||
end
|
||||
|
||||
PrintTable( PrefsTable[section] )
|
||||
end,
|
||||
|
||||
Load = function()
|
||||
if not IniFile then return false end
|
||||
PrefsTable = IniFile.ReadFile( ThemePrefsPath )
|
||||
return true
|
||||
end,
|
||||
|
||||
Save = function()
|
||||
Trace( "ThemePrefs.Save" )
|
||||
if not IniFile then return false end
|
||||
if not NeedsSaved then return end
|
||||
NeedsSaved = false
|
||||
IniFile.WriteFile( ThemePrefsPath, PrefsTable )
|
||||
end,
|
||||
|
||||
Get = function( name )
|
||||
Trace( ("ThemePrefs.Get(%s)"):format(name) )
|
||||
local tbl = ResolveTable(name)
|
||||
if tbl then return tbl[name] end
|
||||
Warn( "Get: "..GetString("UnknownPreference"):format(name) )
|
||||
return nil
|
||||
end,
|
||||
|
||||
Set = function( name, value )
|
||||
Trace( ("ThemePrefs.Set(%s, %s)"):format(name, tostring(value)) )
|
||||
local tbl = ResolveTable(name)
|
||||
if tbl then tbl[name] = value; NeedsSaved = true; return end
|
||||
Warn( "Set: "..GetString("UnknownPreference"):format(name) )
|
||||
end,
|
||||
};
|
||||
|
||||
-- global aliases
|
||||
GetThemePref = ThemePrefs.Get
|
||||
SetThemePref = ThemePrefs.Set
|
||||
|
||||
@@ -1,164 +1,164 @@
|
||||
--[[
|
||||
ThemePrefsRows: you give it the choices, values, and params, and it'll
|
||||
generate the rest; quirky behavior to be outlined below. Documentation
|
||||
will be provided once this system is stabilized.
|
||||
|
||||
v0.5.2: Dec. 28, 2010. Throw an error for default/value type mismatches.
|
||||
v0.5.1: Dec. 27, 2010. Fix Choices not necessarily being strings.
|
||||
v0.5.0: Dec. 15, 2010. Initial version. Not very well tested.
|
||||
|
||||
vyhd wrote this for sm-ssc
|
||||
--]]
|
||||
|
||||
-- unless overridden, these parameters will be used for the OptionsRow
|
||||
local DefaultParams =
|
||||
{
|
||||
LayoutType = "ShowAllInRow",
|
||||
SelectType = "SelectOne",
|
||||
OneChoiceForAllPlayers = true,
|
||||
ExportOnChange = false,
|
||||
EnabledForPlayers = nil,
|
||||
ReloadRowMessages = nil,
|
||||
|
||||
-- takes a function(self, list, pn);
|
||||
-- if not used, we use the default
|
||||
LoadSelections = nil,
|
||||
SaveSelections = nil,
|
||||
}
|
||||
|
||||
-- local alias to simplify error reporting
|
||||
local function GetString( name )
|
||||
return THEME:GetString( "ThemePrefsRows", name )
|
||||
end
|
||||
|
||||
local function DefaultLoad( pref, default, choices, values )
|
||||
return function(self, list, pn)
|
||||
local val = ThemePrefs.Get( pref )
|
||||
|
||||
-- if our current value is here, set focus to that
|
||||
for i=1, #choices do
|
||||
if values[i] == val then list[i] = true return end
|
||||
end
|
||||
|
||||
-- try the default value
|
||||
for i=1, #choices do
|
||||
if values[i] == default then list[i] = true return end
|
||||
end
|
||||
|
||||
-- set to the first value and output a warning
|
||||
Warn( GetString("NoDefaultInValues"):format(pref) )
|
||||
list[1] = true
|
||||
end
|
||||
end
|
||||
|
||||
local function DefaultSave( pref, choices, values )
|
||||
local msg = "ThemePrefChanged"
|
||||
local params = { Name = pref }
|
||||
|
||||
return function(self, list, pn)
|
||||
for i=1, #choices do
|
||||
if list[i] then ThemePrefs.Set( pref, values[i] ) break end
|
||||
MESSAGEMAN:Broadcast( msg, params )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This function checks for mismatches between the default value and the
|
||||
-- values table passed to the ThemePrefRow, e.g. it will return false if
|
||||
-- you have a boolean default and an integer value. I'm somewhat stricter
|
||||
-- about types than Lua is because I don't like the unpredictability and
|
||||
-- complexity of coercing values transparently in a bunch of places.
|
||||
local function TypesMatch( Values, Default )
|
||||
local DefaultType = type(Default)
|
||||
|
||||
for i, value in ipairs(Values) do
|
||||
local ValueType = type(value)
|
||||
if ValueType ~= DefaultType then
|
||||
Warn( GetString("TypeMismatch"):format(DefaultType, i, ValueType) )
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function CreateThemePrefRow( pref, tbl )
|
||||
-- can't make an option handler without options
|
||||
if not tbl.Choices then return nil end
|
||||
|
||||
local Choices = tbl.Choices
|
||||
local Default = tbl.Default
|
||||
local Values = tbl.Values and tbl.Values or Choices
|
||||
local Params = tbl.Params and tbl.Params or { }
|
||||
|
||||
-- if the choices aren't strings, make them strings now
|
||||
for i, str in ipairs(Choices) do
|
||||
Choices[i] = tostring( Choices[i] )
|
||||
end
|
||||
|
||||
-- check to see that Values and Choices have the same length
|
||||
if #Choices ~= #Values then
|
||||
Warn( GetString("ChoicesSizeMismatch") )
|
||||
return nil
|
||||
end
|
||||
|
||||
-- check to see that everything in Values matches the type of Default
|
||||
if not TypesMatch( Values, Default ) then return nil end
|
||||
|
||||
-- set the name and choices here; we'll do the rest below
|
||||
local Handler = { Name = pref, Choices = Choices }
|
||||
|
||||
-- add all the keys in DefaultParams, get the value from
|
||||
-- Params if it exists and DefaultParams otherwise
|
||||
-- (note that we explicitly check for nil, due to bools.)
|
||||
for k, _ in pairs(DefaultParams) do
|
||||
Handler[k] = Params[k] ~= nil and Params[k] or DefaultParams[k]
|
||||
end
|
||||
|
||||
-- if we don't have LoadSelections and SaveSelections, make them
|
||||
if not Handler.LoadSelections then
|
||||
Handler.LoadSelections = DefaultLoad( pref, Default, Choices, Values )
|
||||
end
|
||||
|
||||
if not Handler.SaveSelections then
|
||||
Handler.SaveSelections = DefaultSave( pref, Choices, Values )
|
||||
end
|
||||
|
||||
return Handler
|
||||
end
|
||||
|
||||
-- All OptionsRows for preferences are stuck in this table, accessible
|
||||
-- through GetRow('name') in the namespace or ThemePrefRow('name') in
|
||||
-- the global namespace. (I like to keep pollution to a minimum.)
|
||||
local Rows = { }
|
||||
|
||||
ThemePrefsRows =
|
||||
{
|
||||
IsInitted = false,
|
||||
|
||||
Init = function( prefs )
|
||||
for pref, tbl in pairs(prefs) do
|
||||
Rows[pref] = CreateThemePrefRow( pref, tbl )
|
||||
end
|
||||
end,
|
||||
|
||||
GetRow = function( pref )
|
||||
Trace( ("GetRow(%s), type %s"):format(pref, type(Rows[pref])) )
|
||||
return Rows[pref]
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
-- Global namespace alias
|
||||
ThemePrefRow = ThemePrefsRows.GetRow
|
||||
|
||||
-- UGLY: declare this here, even though it's in the previous namespace,
|
||||
-- so we can have one call to initialize both systems (ThemePrefsRow is
|
||||
-- declared after ThemePrefs, so it can't actually be in that file...)
|
||||
|
||||
ThemePrefs.InitAll = function( prefs )
|
||||
Trace( "ThemePrefs.InitAll( prefs )" )
|
||||
|
||||
ThemePrefs.Init( prefs, true )
|
||||
ThemePrefsRows.Init( prefs )
|
||||
end
|
||||
--[[
|
||||
ThemePrefsRows: you give it the choices, values, and params, and it'll
|
||||
generate the rest; quirky behavior to be outlined below. Documentation
|
||||
will be provided once this system is stabilized.
|
||||
|
||||
v0.5.2: Dec. 28, 2010. Throw an error for default/value type mismatches.
|
||||
v0.5.1: Dec. 27, 2010. Fix Choices not necessarily being strings.
|
||||
v0.5.0: Dec. 15, 2010. Initial version. Not very well tested.
|
||||
|
||||
vyhd wrote this for sm-ssc
|
||||
--]]
|
||||
|
||||
-- unless overridden, these parameters will be used for the OptionsRow
|
||||
local DefaultParams =
|
||||
{
|
||||
LayoutType = "ShowAllInRow",
|
||||
SelectType = "SelectOne",
|
||||
OneChoiceForAllPlayers = true,
|
||||
ExportOnChange = false,
|
||||
EnabledForPlayers = nil,
|
||||
ReloadRowMessages = nil,
|
||||
|
||||
-- takes a function(self, list, pn);
|
||||
-- if not used, we use the default
|
||||
LoadSelections = nil,
|
||||
SaveSelections = nil,
|
||||
}
|
||||
|
||||
-- local alias to simplify error reporting
|
||||
local function GetString( name )
|
||||
return THEME:GetString( "ThemePrefsRows", name )
|
||||
end
|
||||
|
||||
local function DefaultLoad( pref, default, choices, values )
|
||||
return function(self, list, pn)
|
||||
local val = ThemePrefs.Get( pref )
|
||||
|
||||
-- if our current value is here, set focus to that
|
||||
for i=1, #choices do
|
||||
if values[i] == val then list[i] = true return end
|
||||
end
|
||||
|
||||
-- try the default value
|
||||
for i=1, #choices do
|
||||
if values[i] == default then list[i] = true return end
|
||||
end
|
||||
|
||||
-- set to the first value and output a warning
|
||||
Warn( GetString("NoDefaultInValues"):format(pref) )
|
||||
list[1] = true
|
||||
end
|
||||
end
|
||||
|
||||
local function DefaultSave( pref, choices, values )
|
||||
local msg = "ThemePrefChanged"
|
||||
local params = { Name = pref }
|
||||
|
||||
return function(self, list, pn)
|
||||
for i=1, #choices do
|
||||
if list[i] then ThemePrefs.Set( pref, values[i] ) break end
|
||||
MESSAGEMAN:Broadcast( msg, params )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This function checks for mismatches between the default value and the
|
||||
-- values table passed to the ThemePrefRow, e.g. it will return false if
|
||||
-- you have a boolean default and an integer value. I'm somewhat stricter
|
||||
-- about types than Lua is because I don't like the unpredictability and
|
||||
-- complexity of coercing values transparently in a bunch of places.
|
||||
local function TypesMatch( Values, Default )
|
||||
local DefaultType = type(Default)
|
||||
|
||||
for i, value in ipairs(Values) do
|
||||
local ValueType = type(value)
|
||||
if ValueType ~= DefaultType then
|
||||
Warn( GetString("TypeMismatch"):format(DefaultType, i, ValueType) )
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function CreateThemePrefRow( pref, tbl )
|
||||
-- can't make an option handler without options
|
||||
if not tbl.Choices then return nil end
|
||||
|
||||
local Choices = tbl.Choices
|
||||
local Default = tbl.Default
|
||||
local Values = tbl.Values and tbl.Values or Choices
|
||||
local Params = tbl.Params and tbl.Params or { }
|
||||
|
||||
-- if the choices aren't strings, make them strings now
|
||||
for i, str in ipairs(Choices) do
|
||||
Choices[i] = tostring( Choices[i] )
|
||||
end
|
||||
|
||||
-- check to see that Values and Choices have the same length
|
||||
if #Choices ~= #Values then
|
||||
Warn( GetString("ChoicesSizeMismatch") )
|
||||
return nil
|
||||
end
|
||||
|
||||
-- check to see that everything in Values matches the type of Default
|
||||
if not TypesMatch( Values, Default ) then return nil end
|
||||
|
||||
-- set the name and choices here; we'll do the rest below
|
||||
local Handler = { Name = pref, Choices = Choices }
|
||||
|
||||
-- add all the keys in DefaultParams, get the value from
|
||||
-- Params if it exists and DefaultParams otherwise
|
||||
-- (note that we explicitly check for nil, due to bools.)
|
||||
for k, _ in pairs(DefaultParams) do
|
||||
Handler[k] = Params[k] ~= nil and Params[k] or DefaultParams[k]
|
||||
end
|
||||
|
||||
-- if we don't have LoadSelections and SaveSelections, make them
|
||||
if not Handler.LoadSelections then
|
||||
Handler.LoadSelections = DefaultLoad( pref, Default, Choices, Values )
|
||||
end
|
||||
|
||||
if not Handler.SaveSelections then
|
||||
Handler.SaveSelections = DefaultSave( pref, Choices, Values )
|
||||
end
|
||||
|
||||
return Handler
|
||||
end
|
||||
|
||||
-- All OptionsRows for preferences are stuck in this table, accessible
|
||||
-- through GetRow('name') in the namespace or ThemePrefRow('name') in
|
||||
-- the global namespace. (I like to keep pollution to a minimum.)
|
||||
local Rows = { }
|
||||
|
||||
ThemePrefsRows =
|
||||
{
|
||||
IsInitted = false,
|
||||
|
||||
Init = function( prefs )
|
||||
for pref, tbl in pairs(prefs) do
|
||||
Rows[pref] = CreateThemePrefRow( pref, tbl )
|
||||
end
|
||||
end,
|
||||
|
||||
GetRow = function( pref )
|
||||
Trace( ("GetRow(%s), type %s"):format(pref, type(Rows[pref])) )
|
||||
return Rows[pref]
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
-- Global namespace alias
|
||||
ThemePrefRow = ThemePrefsRows.GetRow
|
||||
|
||||
-- UGLY: declare this here, even though it's in the previous namespace,
|
||||
-- so we can have one call to initialize both systems (ThemePrefsRow is
|
||||
-- declared after ThemePrefs, so it can't actually be in that file...)
|
||||
|
||||
ThemePrefs.InitAll = function( prefs )
|
||||
Trace( "ThemePrefs.InitAll( prefs )" )
|
||||
|
||||
ThemePrefs.Init( prefs, true )
|
||||
ThemePrefsRows.Init( prefs )
|
||||
end
|
||||
|
||||
@@ -1,147 +1,147 @@
|
||||
-- UserPreferences: User Preferences "Module"
|
||||
-- Written by AJ Kelly of KKI Labs / Version 2.11-ssc
|
||||
-- (modified slightly for Cerulean Skies 2's disregard of the name of the
|
||||
-- themeinfo variable lol :p)
|
||||
|
||||
--[[
|
||||
the first released version was broken.
|
||||
this version aims to be simpler, and therefore work.
|
||||
|
||||
[changelog]
|
||||
|
||||
v2.11-ssc
|
||||
Remove EnvUtils references; we have it in sm-ssc.
|
||||
|
||||
v2.1-ssc
|
||||
sm-ssc version of UserPrefs. We can now assume players have certain
|
||||
functionality, like RageFile:GetError().
|
||||
|
||||
v2.1
|
||||
Added type specific GetUserPref functions.
|
||||
|
||||
[usage]
|
||||
First, edit PrefPath to match your theme.
|
||||
If you use ThemeInfo, then you shouldn't have to edit this.
|
||||
|
||||
If you're not using ThemeInfo, then you can replace
|
||||
|
||||
".. themeInfo.Name .." with the theme's folder name.
|
||||
|
||||
ThemeInfo is documented at http://kki.ajworld.net/wiki/ThemeInfo.lua
|
||||
|
||||
After that's set up, read the docs.
|
||||
]]
|
||||
local PrefPath = "Data/UserPrefs/".. THEME:GetThemeDisplayName() .."/"
|
||||
|
||||
--[[ begin internal stuff; no need to edit below this line. ]]
|
||||
|
||||
-- Local internal function to write envs. ___Not for themer use.___
|
||||
local function WriteEnv(envName,envValue)
|
||||
return setenv(envName,envValue)
|
||||
end
|
||||
|
||||
function ReadPrefFromFile(name)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
local fullFilename = PrefPath..name..".cfg"
|
||||
local option
|
||||
|
||||
if f:Open(fullFilename,1) then
|
||||
option = tostring( f:Read() )
|
||||
WriteEnv(name,option)
|
||||
f:destroy()
|
||||
return option
|
||||
else
|
||||
local fError = f:GetError()
|
||||
Trace( "[FileUtils] Error reading ".. fullFilename ..": ".. fError )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function WritePrefToFile(name,value)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
local fullFilename = PrefPath..name..".cfg"
|
||||
|
||||
if f:Open(fullFilename, 2) then
|
||||
f:Write( tostring(value) )
|
||||
WriteEnv(name,value)
|
||||
else
|
||||
local fError = f:GetError()
|
||||
Trace( "[FileUtils] Error writing to ".. fullFilename ..": ".. fError )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return false
|
||||
end
|
||||
|
||||
f:destroy()
|
||||
return true
|
||||
end
|
||||
|
||||
--[[ end internal functions; still don't edit below this line ]]
|
||||
|
||||
function GetUserPref(name)
|
||||
return ReadPrefFromFile(name)
|
||||
end
|
||||
|
||||
function SetUserPref(name,value)
|
||||
return WritePrefToFile(name,value)
|
||||
end
|
||||
|
||||
--[[ type specific, for when you want to be lazy ]]
|
||||
-- XXX: make set funcs, since I hate dealing with colors and I know
|
||||
-- other themers would too.
|
||||
|
||||
-- GetUserPrefB: boolean
|
||||
function GetUserPrefB(name)
|
||||
-- this one is a bit trickier.
|
||||
local pref = ReadPrefFromFile(name)
|
||||
|
||||
if type(pref) == "string" then
|
||||
pref = string.lower(pref)
|
||||
if pref == "true" or cmp == "t" then
|
||||
return true
|
||||
elseif pref == "false" or cmp == "f" then
|
||||
return false
|
||||
else
|
||||
Trace("Error in GetUserPrefB(".. name ..") converting from string" )
|
||||
return false
|
||||
end
|
||||
elseif type(pref) == "number" then
|
||||
-- both 0 and -1 are false; if you want to change this,
|
||||
-- feel free to remove "or pref == -1".
|
||||
if pref == 0 or pref == -1 then
|
||||
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- GetUserPrefC: color
|
||||
function GetUserPrefC(name)
|
||||
-- XXX: make sure it's grabbing a string that can be turned into a color
|
||||
-- and also possibly handle HSV values too.
|
||||
return color( ReadPrefFromFile(name) )
|
||||
end
|
||||
|
||||
-- GetUserPrefN: numbers (integers, floats)
|
||||
function GetUserPrefN(name)
|
||||
return tonumber( ReadPrefFromFile(name) )
|
||||
end
|
||||
|
||||
--[[
|
||||
Copyright © 2008-2009 AJ Kelly/KKI Labs
|
||||
All rights reserved.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-- UserPreferences: User Preferences "Module"
|
||||
-- Written by AJ Kelly of KKI Labs / Version 2.11-ssc
|
||||
-- (modified slightly for Cerulean Skies 2's disregard of the name of the
|
||||
-- themeinfo variable lol :p)
|
||||
|
||||
--[[
|
||||
the first released version was broken.
|
||||
this version aims to be simpler, and therefore work.
|
||||
|
||||
[changelog]
|
||||
|
||||
v2.11-ssc
|
||||
Remove EnvUtils references; we have it in sm-ssc.
|
||||
|
||||
v2.1-ssc
|
||||
sm-ssc version of UserPrefs. We can now assume players have certain
|
||||
functionality, like RageFile:GetError().
|
||||
|
||||
v2.1
|
||||
Added type specific GetUserPref functions.
|
||||
|
||||
[usage]
|
||||
First, edit PrefPath to match your theme.
|
||||
If you use ThemeInfo, then you shouldn't have to edit this.
|
||||
|
||||
If you're not using ThemeInfo, then you can replace
|
||||
|
||||
".. themeInfo.Name .." with the theme's folder name.
|
||||
|
||||
ThemeInfo is documented at http://kki.ajworld.net/wiki/ThemeInfo.lua
|
||||
|
||||
After that's set up, read the docs.
|
||||
]]
|
||||
local PrefPath = "Data/UserPrefs/".. THEME:GetThemeDisplayName() .."/"
|
||||
|
||||
--[[ begin internal stuff; no need to edit below this line. ]]
|
||||
|
||||
-- Local internal function to write envs. ___Not for themer use.___
|
||||
local function WriteEnv(envName,envValue)
|
||||
return setenv(envName,envValue)
|
||||
end
|
||||
|
||||
function ReadPrefFromFile(name)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
local fullFilename = PrefPath..name..".cfg"
|
||||
local option
|
||||
|
||||
if f:Open(fullFilename,1) then
|
||||
option = tostring( f:Read() )
|
||||
WriteEnv(name,option)
|
||||
f:destroy()
|
||||
return option
|
||||
else
|
||||
local fError = f:GetError()
|
||||
Trace( "[FileUtils] Error reading ".. fullFilename ..": ".. fError )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function WritePrefToFile(name,value)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
local fullFilename = PrefPath..name..".cfg"
|
||||
|
||||
if f:Open(fullFilename, 2) then
|
||||
f:Write( tostring(value) )
|
||||
WriteEnv(name,value)
|
||||
else
|
||||
local fError = f:GetError()
|
||||
Trace( "[FileUtils] Error writing to ".. fullFilename ..": ".. fError )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return false
|
||||
end
|
||||
|
||||
f:destroy()
|
||||
return true
|
||||
end
|
||||
|
||||
--[[ end internal functions; still don't edit below this line ]]
|
||||
|
||||
function GetUserPref(name)
|
||||
return ReadPrefFromFile(name)
|
||||
end
|
||||
|
||||
function SetUserPref(name,value)
|
||||
return WritePrefToFile(name,value)
|
||||
end
|
||||
|
||||
--[[ type specific, for when you want to be lazy ]]
|
||||
-- XXX: make set funcs, since I hate dealing with colors and I know
|
||||
-- other themers would too.
|
||||
|
||||
-- GetUserPrefB: boolean
|
||||
function GetUserPrefB(name)
|
||||
-- this one is a bit trickier.
|
||||
local pref = ReadPrefFromFile(name)
|
||||
|
||||
if type(pref) == "string" then
|
||||
pref = string.lower(pref)
|
||||
if pref == "true" or cmp == "t" then
|
||||
return true
|
||||
elseif pref == "false" or cmp == "f" then
|
||||
return false
|
||||
else
|
||||
Trace("Error in GetUserPrefB(".. name ..") converting from string" )
|
||||
return false
|
||||
end
|
||||
elseif type(pref) == "number" then
|
||||
-- both 0 and -1 are false; if you want to change this,
|
||||
-- feel free to remove "or pref == -1".
|
||||
if pref == 0 or pref == -1 then
|
||||
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- GetUserPrefC: color
|
||||
function GetUserPrefC(name)
|
||||
-- XXX: make sure it's grabbing a string that can be turned into a color
|
||||
-- and also possibly handle HSV values too.
|
||||
return color( ReadPrefFromFile(name) )
|
||||
end
|
||||
|
||||
-- GetUserPrefN: numbers (integers, floats)
|
||||
function GetUserPrefN(name)
|
||||
return tonumber( ReadPrefFromFile(name) )
|
||||
end
|
||||
|
||||
--[[
|
||||
Copyright © 2008-2009 AJ Kelly/KKI Labs
|
||||
All rights reserved.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
]]
|
||||
@@ -1,32 +1,32 @@
|
||||
-- fileutils: quick and dirty, not user prefs oriented file io
|
||||
File = {
|
||||
Write = function(path,buf)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
if f:Open(path, 2) then
|
||||
f:Write( tostring(buf) )
|
||||
f:destroy()
|
||||
return true
|
||||
else
|
||||
Trace( "[FileUtils] Error writing to ".. path ..": ".. f:GetError() )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return false
|
||||
end
|
||||
end,
|
||||
Read = function(path)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
local ret = ""
|
||||
if f:Open(path, 1) then
|
||||
ret = tostring( f:Read() )
|
||||
f:destroy()
|
||||
return ret
|
||||
else
|
||||
Trace( "[FileUtils] Error reading from ".. path ..": ".. f:GetError() )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return nil
|
||||
end
|
||||
end
|
||||
}
|
||||
-- this code if public domain and/or has no copyright, depending on your
|
||||
-- fileutils: quick and dirty, not user prefs oriented file io
|
||||
File = {
|
||||
Write = function(path,buf)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
if f:Open(path, 2) then
|
||||
f:Write( tostring(buf) )
|
||||
f:destroy()
|
||||
return true
|
||||
else
|
||||
Trace( "[FileUtils] Error writing to ".. path ..": ".. f:GetError() )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return false
|
||||
end
|
||||
end,
|
||||
Read = function(path)
|
||||
local f = RageFileUtil.CreateRageFile()
|
||||
local ret = ""
|
||||
if f:Open(path, 1) then
|
||||
ret = tostring( f:Read() )
|
||||
f:destroy()
|
||||
return ret
|
||||
else
|
||||
Trace( "[FileUtils] Error reading from ".. path ..": ".. f:GetError() )
|
||||
f:ClearError()
|
||||
f:destroy()
|
||||
return nil
|
||||
end
|
||||
end
|
||||
}
|
||||
-- this code if public domain and/or has no copyright, depending on your
|
||||
-- country's laws. I wish for you to use this code freely, without restriction.
|
||||
@@ -1,26 +1,26 @@
|
||||
-- supported aspect ratios; some of which I will ignore
|
||||
-- only really pay attention to any ratio marked with a star;
|
||||
-- I don't think anyone uses 3:4, 1:1, or 8:3.
|
||||
-- (Archer added 5:4 later and I didn't account for it yet.)
|
||||
AspectRatios = {
|
||||
ThreeFour = 0.75, -- (576x760 at 1024x768)
|
||||
OneOne = 1.0, -- 480x480 (uses Y)
|
||||
FiveFour = 1.25, -- 600x480 (1280x1024 is a real use case)
|
||||
FourThree = 1.33333, --* 640x480
|
||||
SixteenTen = 1.6, --* 720x480
|
||||
SixteenNine = 1.77778, --* 853x480
|
||||
EightThree = 2.66666 -- 1280x480
|
||||
}
|
||||
|
||||
function IsUsingWideScreen()
|
||||
return GetScreenAspectRatio() >= 1.6
|
||||
end
|
||||
|
||||
-- take and use it as you like, I don't care -aj
|
||||
-- (although I should mention this file was specific to moonlight and was pretty
|
||||
-- bad before some editing. -aj)
|
||||
|
||||
-- this one is good though:
|
||||
function WideScale(AR4_3, AR16_9)
|
||||
return scale( SCREEN_WIDTH, 640, 854, AR4_3, AR16_9 )
|
||||
-- supported aspect ratios; some of which I will ignore
|
||||
-- only really pay attention to any ratio marked with a star;
|
||||
-- I don't think anyone uses 3:4, 1:1, or 8:3.
|
||||
-- (Archer added 5:4 later and I didn't account for it yet.)
|
||||
AspectRatios = {
|
||||
ThreeFour = 0.75, -- (576x760 at 1024x768)
|
||||
OneOne = 1.0, -- 480x480 (uses Y)
|
||||
FiveFour = 1.25, -- 600x480 (1280x1024 is a real use case)
|
||||
FourThree = 1.33333, --* 640x480
|
||||
SixteenTen = 1.6, --* 720x480
|
||||
SixteenNine = 1.77778, --* 853x480
|
||||
EightThree = 2.66666 -- 1280x480
|
||||
}
|
||||
|
||||
function IsUsingWideScreen()
|
||||
return GetScreenAspectRatio() >= 1.6
|
||||
end
|
||||
|
||||
-- take and use it as you like, I don't care -aj
|
||||
-- (although I should mention this file was specific to moonlight and was pretty
|
||||
-- bad before some editing. -aj)
|
||||
|
||||
-- this one is good though:
|
||||
function WideScale(AR4_3, AR16_9)
|
||||
return scale( SCREEN_WIDTH, 640, 854, AR4_3, AR16_9 )
|
||||
end
|
||||
@@ -1,92 +1,92 @@
|
||||
sm-ssc Scripts Directory: Introduction
|
||||
--------------------------------------------------------------------------------
|
||||
Hello, and welcome to the sm-ssc Scripts directory. You'll notice that our Lua
|
||||
scripts have numbers at the beginning of them. This is to control the order of
|
||||
execution.
|
||||
|
||||
In sm-ssc, scripts in subdirectories of Scripts/ (e.g. Scripts/01/somescript.lua)
|
||||
are loaded before scripts in the root of Scripts/ (e.g. Scripts/01 base.lua).
|
||||
This is important to know when making a theme for sm-ssc. It's also important
|
||||
to know that StepMania 4 (as of alpha 5) will not read scripts in subdirectories.
|
||||
|
||||
In sm-ssc, there are five rings of script execution:
|
||||
|
||||
00 - Initialization
|
||||
________________________________________________________________________________
|
||||
01 - Base
|
||||
There are three base scripts. "01 base.lua" is taken from StepMania 4's default
|
||||
theme and sets up very important function overrides and the "Var" alias (for
|
||||
lua.GetThreadVariable). The other two base scripts are sm-ssc specific.
|
||||
|
||||
"01 alias.lua" contains non-compatibility aliases. To quote the file itself:
|
||||
"This is mainly here for making commands case-insensitive without needing to
|
||||
clutter up the C++ code. It can also be used to add custom functions that
|
||||
wouldn't otherwise belong somewhere else."
|
||||
|
||||
"01 compat.lua" sets up compatibility aliases for some commands. Some commands
|
||||
were deprecated in sm-ssc (e.g. hidden), while others were renamed. If a problem
|
||||
was solved differently in sm-ssc, the corresponding StepMania 4 functions should
|
||||
live in here, and not the C++ code. (The prime example of this being
|
||||
PlayerStageStats:IsFullComboW* from SM4, whereas we have
|
||||
PlayerStageStats:FullComboOfScore, with the tap note score being passed in.)
|
||||
________________________________________________________________________________
|
||||
02 - Defaults
|
||||
The "02" scripts are pretty much the same scripts you'd find in StepMania 4's
|
||||
default theme. Some scripts do exhibit differences, however. The most notable
|
||||
of these changes is to "02 Color.lua", which adds a color library to the old
|
||||
StepMania 4 Colors script.
|
||||
________________________________________________________________________________
|
||||
03 - Extensions
|
||||
Scripts that extend normal (StepMania 4 default theme) functionality belong
|
||||
in the fourth ring. A number of these scripts come from KKI Labs (EnvUtils2,
|
||||
CustomSpeedMods, UserPreferences2), while others are from other themes (HSV)
|
||||
or written for sm-ssc (DateTime, Gameplay).
|
||||
________________________________________________________________________________
|
||||
04 - ?
|
||||
FileUtils and WidescreenHelpers are in the fifth ring. To be honest, I don't
|
||||
know why they were moved out here. -aj
|
||||
|
||||
================================================================================
|
||||
previously:
|
||||
SMOKE WEED '98 Scripts Directory Organization,
|
||||
or "An applied case of application of prefixes to control order of execution".
|
||||
|
||||
Based on the original document for NCRX by Synikal, updated for SW98 by various
|
||||
members of the NAKET Team.
|
||||
-------------------------------------------------------------------------------
|
||||
The general idea is that the order of execution in some scripts does matter.
|
||||
We can use filenames in order to load certain files before others.
|
||||
|
||||
It is important to note that you do not always need to follow this order,
|
||||
especially if certain scripts do not require any dependencies. Typically,
|
||||
most scripts do not require hierarchy setup, only certain situations
|
||||
require it.
|
||||
|
||||
Here is how we see the general hierarchy at NAKET HQ:
|
||||
|
||||
00 = Initialization. Things that get called at the beginning of a theme.
|
||||
This is good for things that are required by everything. It's considered bad
|
||||
form to execute your own code before init, but there are ways around it if you
|
||||
do need to go around it.
|
||||
|
||||
Examples include 00 init.lua (SM4 default) and 00 themeInfo.lua (various themes).
|
||||
|
||||
01 = Base. After the initialization, the base layer goes on top and adds more
|
||||
core functionality to StepMania themes.
|
||||
|
||||
Examples include 01 base.lua (SM4 default) and various 01 files in sm-ssc's
|
||||
fallback theme. In sm-ssc, these are treated differently than in normal SM4;
|
||||
01 files are used for aliasing/compatibility commands, which are just as
|
||||
important as 01 base.lua.
|
||||
----
|
||||
From here on out, these aren't officially used by the normal StepMania
|
||||
developers; they were invented by other themers.
|
||||
|
||||
02 = Extensions. Generally, these are third party extensions, such as the KKI
|
||||
Labs stuff or vyhd's Genre Generator.
|
||||
|
||||
03 = Theme-specific. This layer came into existence with dubaiOne/moonlight.
|
||||
|
||||
It should be noted that this is still talking about StepMania 4 alphas, as
|
||||
sm-ssc introduces loading Scripts/folderA, Scripts/folderB, etc. (just not
|
||||
sm-ssc Scripts Directory: Introduction
|
||||
--------------------------------------------------------------------------------
|
||||
Hello, and welcome to the sm-ssc Scripts directory. You'll notice that our Lua
|
||||
scripts have numbers at the beginning of them. This is to control the order of
|
||||
execution.
|
||||
|
||||
In sm-ssc, scripts in subdirectories of Scripts/ (e.g. Scripts/01/somescript.lua)
|
||||
are loaded before scripts in the root of Scripts/ (e.g. Scripts/01 base.lua).
|
||||
This is important to know when making a theme for sm-ssc. It's also important
|
||||
to know that StepMania 4 (as of alpha 5) will not read scripts in subdirectories.
|
||||
|
||||
In sm-ssc, there are five rings of script execution:
|
||||
|
||||
00 - Initialization
|
||||
________________________________________________________________________________
|
||||
01 - Base
|
||||
There are three base scripts. "01 base.lua" is taken from StepMania 4's default
|
||||
theme and sets up very important function overrides and the "Var" alias (for
|
||||
lua.GetThreadVariable). The other two base scripts are sm-ssc specific.
|
||||
|
||||
"01 alias.lua" contains non-compatibility aliases. To quote the file itself:
|
||||
"This is mainly here for making commands case-insensitive without needing to
|
||||
clutter up the C++ code. It can also be used to add custom functions that
|
||||
wouldn't otherwise belong somewhere else."
|
||||
|
||||
"01 compat.lua" sets up compatibility aliases for some commands. Some commands
|
||||
were deprecated in sm-ssc (e.g. hidden), while others were renamed. If a problem
|
||||
was solved differently in sm-ssc, the corresponding StepMania 4 functions should
|
||||
live in here, and not the C++ code. (The prime example of this being
|
||||
PlayerStageStats:IsFullComboW* from SM4, whereas we have
|
||||
PlayerStageStats:FullComboOfScore, with the tap note score being passed in.)
|
||||
________________________________________________________________________________
|
||||
02 - Defaults
|
||||
The "02" scripts are pretty much the same scripts you'd find in StepMania 4's
|
||||
default theme. Some scripts do exhibit differences, however. The most notable
|
||||
of these changes is to "02 Color.lua", which adds a color library to the old
|
||||
StepMania 4 Colors script.
|
||||
________________________________________________________________________________
|
||||
03 - Extensions
|
||||
Scripts that extend normal (StepMania 4 default theme) functionality belong
|
||||
in the fourth ring. A number of these scripts come from KKI Labs (EnvUtils2,
|
||||
CustomSpeedMods, UserPreferences2), while others are from other themes (HSV)
|
||||
or written for sm-ssc (DateTime, Gameplay).
|
||||
________________________________________________________________________________
|
||||
04 - ?
|
||||
FileUtils and WidescreenHelpers are in the fifth ring. To be honest, I don't
|
||||
know why they were moved out here. -aj
|
||||
|
||||
================================================================================
|
||||
previously:
|
||||
SMOKE WEED '98 Scripts Directory Organization,
|
||||
or "An applied case of application of prefixes to control order of execution".
|
||||
|
||||
Based on the original document for NCRX by Synikal, updated for SW98 by various
|
||||
members of the NAKET Team.
|
||||
-------------------------------------------------------------------------------
|
||||
The general idea is that the order of execution in some scripts does matter.
|
||||
We can use filenames in order to load certain files before others.
|
||||
|
||||
It is important to note that you do not always need to follow this order,
|
||||
especially if certain scripts do not require any dependencies. Typically,
|
||||
most scripts do not require hierarchy setup, only certain situations
|
||||
require it.
|
||||
|
||||
Here is how we see the general hierarchy at NAKET HQ:
|
||||
|
||||
00 = Initialization. Things that get called at the beginning of a theme.
|
||||
This is good for things that are required by everything. It's considered bad
|
||||
form to execute your own code before init, but there are ways around it if you
|
||||
do need to go around it.
|
||||
|
||||
Examples include 00 init.lua (SM4 default) and 00 themeInfo.lua (various themes).
|
||||
|
||||
01 = Base. After the initialization, the base layer goes on top and adds more
|
||||
core functionality to StepMania themes.
|
||||
|
||||
Examples include 01 base.lua (SM4 default) and various 01 files in sm-ssc's
|
||||
fallback theme. In sm-ssc, these are treated differently than in normal SM4;
|
||||
01 files are used for aliasing/compatibility commands, which are just as
|
||||
important as 01 base.lua.
|
||||
----
|
||||
From here on out, these aren't officially used by the normal StepMania
|
||||
developers; they were invented by other themers.
|
||||
|
||||
02 = Extensions. Generally, these are third party extensions, such as the KKI
|
||||
Labs stuff or vyhd's Genre Generator.
|
||||
|
||||
03 = Theme-specific. This layer came into existence with dubaiOne/moonlight.
|
||||
|
||||
It should be noted that this is still talking about StepMania 4 alphas, as
|
||||
sm-ssc introduces loading Scripts/folderA, Scripts/folderB, etc. (just not
|
||||
Scripts/folderA/folderB/ although why would you need that?)
|
||||
Reference in New Issue
Block a user