2011-04-29 14:58:59 -04:00
local PlayerIndexes = { PlayerNumber_P1 = 1 , PlayerNumber_P2 = 1 }
-- Reads mods from a file
-- keywords: Speed, Noteskins, None, Clear
local function ReadMods ()
local file = THEME : GetCurrentThemeDirectory () .. "mods.txt"
local mods = File.Read ( file )
if not mods
or mods == ""
then
local buff = ";Set mods here, one per line or various in one separated with commas \r\n ;Keywords: 'Speed', 'Noteskins', 'None', 'Clear' \r\n Speeds \r\n Noteskins"
File.Write ( file , buff )
return {
ReadSpeedMods ();
NOTESKIN : GetNoteSkinNames ();
"Clear" ;
}
end
mods = string.gsub ( mods , " \r " , "" )
mods = split ( " \n " , mods )
local ret = {}
local clear = false
for k , v in ipairs ( mods ) do
if string.sub ( v , 1 , 1 ) == ";"
or v == ""
then
--skip
elseif v == "Speeds" then
table.insert ( ret , ReadSpeedMods ())
elseif v == "Noteskins" then
table.insert ( ret , NOTESKIN : GetNoteSkinNames ())
else
local ModToAdd = string.gsub ( v , "%s" , "" )
if string.find ( ModToAdd , "," ) ~= nil then
ModToAdd = split ( "," , ModToAdd )
if ModToAdd [ 1 ] ~= "None" then
table.insert ( ModToAdd , 1 , "None" )
end
table.insert ( ret , ModToAdd )
else
if ModToAdd == "Clear" then
if not clear then table.insert ( ret , ModToAdd ) end
clear = true
end
end
end
end
-- This will happen...
if not clear then table.insert ( ret , "Clear" ) end
return ret
end
local modslist = ReadMods ()
-- Displays the mods with actorscrollers
local function OptionsListDisplay ( player )
local function GetPlayerMods ()
local playerstate = GAMESTATE : GetPlayerState ( player )
local playermods = playerstate : GetPlayerOptionsArray ( 'ModsLevel_Preferred' )
return playermods
end
local make = {}
-- iterate modslist entries
for k , v in ipairs ( modslist ) do
-- not kinopio
local RowToAdd
if type ( v ) == "table" then
-- it's a table, make it a scroller
local choices = {}
-- build the choices
for i , j in ipairs ( v ) do
choices [ i ] = LoadFont () .. { Text = j };
end
RowToAdd = Def.ActorScroller {
NumItemsToDraw = 3 ;
SecondsPerItem = 0.075 ;
-- init indexes here
-- I like how InitCommand is not allowed to be played or queued
-- (HURR TOO MUCH COMMANDS ARG!)
SetChoicesCommand = function ( self )
local found = false
--SCREENMAN:SystemMessage(join(",", defmods))
for idx , Mod in ipairs ( GetPlayerMods ()) do
-- In before I forgot what's this: those are the nod entries
for jdx , Nod in ipairs ( v ) do
if Mod == Nod then
found = true
self : SetCurrentAndDestinationItem ( jdx - 1 );
break
end
end
end
-- oops, no defaults, set them
if not found then
for idx , Mod in ipairs ( v ) do
if Mod == "1x"
or Mod == "default"
or Mod == "None"
then
self : SetCurrentAndDestinationItem ( idx - 1 );
break
else
self : SetCurrentAndDestinationItem ( 0 );
end
end
end
end ;
CleanModsMessageCommand = function ( self , params )
if player ~= params.PlayerNumber then return end
self : playcommand ( "SetChoices" );
end ;
InitCommand = function ( self )
self : SetLoop ( true );
self : playcommand ( "SetChoices" );
end ;
TransformFunction = function ( self , offset , itemIndex , numItems )
self : x ( offset * 100 );
local focus = math.abs ( offset )
focus = scale ( focus , 0 , 1 , 1 , 0.75 )
self : zoom ( focus )
end ;
ChoiceSwapMessageCommand = function ( self , params )
if params.PlayerNumber ~= player then return end
if params.Row ~= k then return end
local index = params.Index
--SCREENMAN:SystemMessage(ToEnumShortString(player).." row mods index: "..index);
if params.bHasLooped then
self : SetCurrentAndDestinationItem ( - 1 )
end
self : SetDestinationItem ( index - 1 )
end ;
-- actors are wrapped here:
children = choices ;
};
elseif type ( v ) == "string" then
-- it's not, make single switchable choice
RowToAdd = Def.ActorFrame {
LoadFont () .. {
Text = v ;
-- init highlights here
SetChoicesCommand = function ( self )
local cc = color ( "#000000" )
for idx , Mod in ipairs ( GetPlayerMods ()) do
if Mod == v then
cc = color ( "#ffffff" )
break
end
end
if v == "Clear" then
cc = color ( "#0000ff" )
end
self : diffuse ( cc );
end ;
InitCommand = function ( self )
self : playcommand ( "SetChoices" );
end ;
-- Following commands you'll understand (I've heard that somewhere...)
CleanModsMessageCommand = function ( self , params )
--if v == "Clear" then return end
if player ~= params.PlayerNumber then return end
self : playcommand ( "SetChoices" );
--self:diffuse(color("#000000"));
end ;
-- cmd(diffuse,color("#000000"));
ChoiceToggleMessageCommand = function ( self , params )
if params.PlayerNumber ~= player then return end
if params.Row ~= k then return end
local cc = color ( "#ffffff" )
if not params.Activated then
cc = color ( "#000000" )
end
--self:visible(params.Activated)
-- why the fuck is not coloring itself? oh I think I got it... duh!
self : diffuse ( cc )
end ;
}
}
else
--table.remove(modslist,k)
--Def.Actor { };
end
make [ k ] = RowToAdd
end
return Def.ActorFrame {
Draw.RoundBox ( 300 , 320 , 50 , 50 , color ( "1,0,1,0.5" ));
Draw.RoundBox ( 300 , 50 , 25 , 25 , color ( "1,0,0,0.5" ));
Def.ActorScroller {
Name = "OptionsListScroller" ;
NumItemsToDraw = 5 ;
SecondsPerItem = 0.075 ;
InitCommand = function ( self )
self : SetLoop ( true );
end ;
TransformFunction = function ( self , offset , itemIndex , numItems )
self : y ( offset * 50 );
end ;
children = make ;
};
}
end
-- Internals
return Def.ActorFrame {
OptionsListDisplay ( PLAYER_1 ) .. {
Name = "OptionsListDisplay" .. PLAYER_1 ;
Condition = GAMESTATE : IsHumanPlayer ( PLAYER_1 );
InitCommand = function ( self )
if # GAMESTATE : GetHumanPlayers () == 1
and PREFSMAN : GetPreference ( "Center1Player" )
then
self : CenterX ()
else
self : FromLeft ( 160 )
end
self : CenterY ();
end ;
};
OptionsListDisplay ( PLAYER_2 ) .. {
Name = "OptionsListDisplay" .. PLAYER_2 ;
Condition = GAMESTATE : IsHumanPlayer ( PLAYER_2 );
InitCommand = function ( self )
if # GAMESTATE : GetHumanPlayers () == 1
and PREFSMAN : GetPreference ( "Center1Player" )
then
self : CenterX ()
else
self : FromRight ( - 160 )
end
self : CenterY ();
end ;
};
-- Everything here and beyond is pure magic
CodeMessageCommand = function ( self , params )
-- I'm reusing code from CustomCodeDetector
local code = params.Name
local player = params.PlayerNumber
local movement = "none"
local modscleared = false
if not GAMESTATE : IsHumanPlayer ( player ) then return end ;
if code == "Back" then
--SCREENMAN:SystemMessage(ToEnumShortString(player).." closed the oplist")
SCREENMAN : GetTopScreen (): Cancel ();
elseif code == "Prev" then
PlayerIndexes [ player ] = PlayerIndexes [ player ] - 1
if PlayerIndexes [ player ] < 1 then
PlayerIndexes [ player ] = # modslist
movement = "first"
end
--SCREENMAN:SystemMessage(ToEnumShortString(player).." index: "..PlayerIndexes[player]);
elseif code == "Next" then
PlayerIndexes [ player ] = PlayerIndexes [ player ] + 1
if PlayerIndexes [ player ] > # modslist then
PlayerIndexes [ player ] = 1
movement = "last"
end
--SCREENMAN:SystemMessage(ToEnumShortString(player).." index: "..PlayerIndexes[player]);
elseif code == "Toggle" then
-- changes will be done here
-- get playerstate and playermods
local playerstate = GAMESTATE : GetPlayerState ( player )
local playermods = playerstate : GetPlayerOptionsArray ( 'ModsLevel_Preferred' )
-- let's check in what index we are
local ModToAdd = modslist [ PlayerIndexes [ player ]]
--the mod is a table, scroll those
if type ( ModToAdd ) == "table" then
-- iteration, once again, like in the custom code detector I made :x
local index = 1
local found = false
local looped = false
for i , j in ipairs ( playermods ) do
for k , l in ipairs ( ModToAdd ) do
if j == l then
found = true
index = k + 1
if index > # ModToAdd then
index = 1
looped = true
end
--replace
playermods [ i ] = ModToAdd [ index ]
break
end
end
end
-- looks like nothing was found, we can assume those are the default mods
-- (1x and default noteskin) they are not listed for some reason...
if not found then
-- set the first on the list (nono, better list 1x and default)
for k , v in ipairs ( ModToAdd ) do
if v == "1x"
or v == "default"
then
index = k + 1
if index > # ModToAdd then
index = 1
looped = true
end
table.insert ( playermods , ModToAdd [ index ])
break
elseif v == "None" then
table.insert ( playermods , ModToAdd [ 2 ])
index = 2
end
end
end
-- send message broadcasts to be able to move things on the oplist displays
MESSAGEMAN : Broadcast ( "ChoiceSwap" ,{ Row = PlayerIndexes [ player ]; Index = index ; PlayerNumber = player ; bHasLooped = looped })
elseif ModToAdd == "Clear" then
local defaultmods = PREFSMAN : GetPreference ( "DefaultModifiers" )
playermods = split ( "," , defaultmods )
modscleared = true
--MESSAGEMAN:Broadcast("CleanMods",{ PlayerNumber = player });
else
-- if type(ModToAdd) == "string" then end
-- we know it's a string...
local found = false
for i , j in ipairs ( playermods ) do
if j == ModToAdd then
-- remove it
found = true
table.remove ( playermods , i )
break
end
end
if not found then
table.insert ( playermods , ModToAdd )
end
MESSAGEMAN : Broadcast ( "ChoiceToggle" ,{ Row = PlayerIndexes [ player ]; Activated = not found ; PlayerNumber = player })
end
-- let's check if noteskins aren't missing (we're avoiding crashes here...)
local found = false
-- iterate again uh
for i , j in ipairs ( playermods ) do
-- yes because noteskins are stored in the second slot...
for k , l in ipairs ( modslist [ 2 ]) do
if j == l then
found = true
break
end
end
end
-- apparently there aren't any noteskins...
if not found then
table.insert ( playermods , "default" )
end
-- everything is ready to be set
playermods = join ( ", " , playermods )
playerstate : SetPlayerOptions ( 'ModsLevel_Preferred' , playermods )
-- and thats pretty much it :D
end
if modscleared then
MESSAGEMAN : Broadcast ( "CleanMods" ,{ PlayerNumber = player });
end
--this moves the scroller...
local scroller = self : GetChild ( "OptionsListDisplay" .. player ): GetChild ( "OptionsListScroller" )
if movement ~= "none" then
local tomove
if movement == "first" then
tomove = PlayerIndexes [ player ]
elseif movement == "last" then
tomove = PlayerIndexes [ player ] - 2
end
scroller : SetCurrentAndDestinationItem ( tomove );
end
scroller : SetDestinationItem ( PlayerIndexes [ player ] - 1 );
end ;
2011-04-07 16:42:16 -07:00
};