@name Music Board v2
@persist [ TRUE FALSE ]
@persist [ E ]:entity
@persist [ BarStart BarEnd BarCount ] [ Board BoardLength Reader Tempo Power Loop ]
@persist [ Time ]
if (first()) {
    
    E = entity()
    
    TRUE = 1        
    FALSE = 0       
    
    Board = 0     
    Reader = 1      
    
    Time = 1        
    Tempo = 250     
    
    Power = FALSE 
    Loop = FALSE    
 

    function void togglePower(Bool:number) {
        Power = Bool
        Time = 1
    }
   
    function number isOn() {
        return Power    
    }
    
    function void toggleLoop(Bool:number) {
        Loop = Bool    
    }
   
    function number isLooped() {
        return Loop    
    }
    
    function void setBoardLength(Length:number) {
        BoardLength = Length   
    }    
    
    function number getBoardLength() {
        return BoardLength    
    }   
     
    function void setBarStart(Index:number) {
        BarStart = Index    
    }    
    
    function number getBarStart() {
        return BarStart    
    }   
   
    function void setBarEnd(Index:number) {
        BarEnd = Index   
    }
   
    function number getBarEnd() {
        return BarEnd   
    }  
    
    function void setBarCount(StartIndex:number, EndIndex:number) {
        setBarStart(StartIndex)
        setBarEnd(EndIndex)
        BarCount = ( getBarEnd() - getBarStart() )    
    }    
   
    function number getBarCount() {
        return BarCount    
    }    
   
    function number entity:isTalking() {
        return chatClk(This)    
    }
   
    function array entity:getChat() {
        return This:lastSaid():explode(" ")
    }
    
   
    function void createBoard(Start, End, Count, Length) {
        holoCreate( Board )
        holoPos( Board, E:toWorld( vec( Length / 2, 0, 0) ) )
        holoScaleUnits( Board, vec( Length, 100, 1 ) )
        holoColor( Board, vec(0,100,200) )
        
        holoCreate( Reader )
        holoPos( Reader, E:toWorld(vec(0,0,1)) )
        holoScaleUnits( Reader, vec(1, 101, 1) )
        holoColor( Reader, vec(255,255,255) )
        
        for (I = Start, End) {
            holoCreate( I )
            holoScaleUnits( I, vec(1, 101, 2) )    
            holoPos( I, E:toWorld( vec( (Length / Count) * (I - Start), 0, 0 ) ) )
            holoColor( I, vec( 25, 25, 25 ) )
        }
    }
    
   
    function void resetHolos() {
        holoDeleteAll()   
    }
    
   
    function void parseChat(Chat:array) {
        local Commands = array("start", "end", "length", "on", "off", "loop")
        
        for (I = 1, Chat:count()) {
            local Word = Chat[I,string]:lower()
            
            for (J = 1, Commands:count()) {
                local Command = Commands[J,string]:lower()
                
                if (Word == Command) {
                    hideChat(TRUE)
                    
                    switch(Word) {
                        case "start", setBarStart(Chat[I + 1, string]:toNumber()), break
                        case "end", setBarEnd(Chat[I + 1, string]:toNumber()), break
                        case "length", setBoardLength(Chat[I + 1, string]:toNumber()), break
                        case "on", togglePower(TRUE), break
                        case "off", togglePower(FALSE), break
                        case "loop", toggleLoop(Chat[I + 1, string]:toNumber()), break
                    }
                }
            }   
        }         
    }
    
   
    function void checkChat() {
        
        runOnChat(1)
        
        if (owner():isTalking()) {
            parseChat(owner():getChat())  
            
            local IsFormatted = (getBarStart() > 0 & getBarEnd() > 0)
            
            if (IsFormatted & !isOn()) {
                resetHolos()
                setBarCount(getBarStart(), getBarEnd())
                createBoard(getBarStart(), getBarEnd(), getBarCount(), getBoardLength())        
            }    
        }    
    }
    
    
    function void readMusic() {  
        
        interval(Tempo) #// The time delay between each Reader bar movement
        local Pos = E:toWorld(vec(Time * (getBoardLength() / getBarCount()) / 8, 0, 1)) #// The amount the bar moves per Time unit
        holoPos( Reader, Pos )
        
        Time++
        
        if ((Time * (getBoardLength() / getBarCount())) / 8 > getBoardLength()) {
            if (isLooped() == FALSE) {
                togglePower(FALSE)    
            }
            Time = 1
        }
    }
    
 
    function void run() {
        checkChat()    
                
        if (isOn() == TRUE) {
            readMusic()    
        }
    }
}

run()

