@name Monskiller Dashboard v2
@inputs RPM Gear Fuel Capacity Active
@persist [GColor OColor MColor NColor GearColor InColor]:vector
@persist [GMaterial OMaterial NMaterial]:string E:entity [Table AlphaV]:table ReverseGear Angled
@persist KPH RPMMax KPHMax HLimit Scale Osc I OnColor OffColor RpmStep KphStep N NumStepR NumStepK
@trigger Active

    ######################################################
    #                                                    #
    #                  Holo Dashboard v2                 #
    #             Made by Monskiller (// Dak)            #
    #             SteamID: STEAM_0:1:36968257            #
    #             Created on: December 16, 2014          #
    #             Updated on: February 06, 2015          #
    #               Requires Sprops models               #
    # Needs convar wire_holograms_modelany set to 1 or 2 #
    #                                                    #
    ######################################################

    interval(100)
if (first()|duped()){
    #### Settings ####
    
    # RPM Settings #
    RPMMax = 10000     # Max RPM of your car
    RpmStep = 1000     # Division step on RPM gauge (not lower than 1000)
    
    # Speed Settings #
    KPHMax = 160      # Top speed
    KphStep = 20      # Division step on speed gauge 
    
    # Other Settings #
    Angled = 0        # Setting for angled numbers
    Scale = 1         # Scale of the holoboard. Won't render propperly beyond 30 (But why that big anyway?)
    ReverseGear = 6   # Set your reverse gear here, if it's 1 all gears get shifted down by 1, default is 0 (Reverse = -1)
    HLimit = 101      # Max ammount of holos that'll spawn. Unused holos get deleted
                      # Hints will tell you if there aren't enough holos or how many have been used
    
    # Material Settings #
    GMaterial = "sprops/textures/sprops_metal5"   # Gauge face material
    OMaterial = "sprops/textures/sprops_metal5"   # Gauge outer ring material
    NMaterial = "models/debug/debugwhite"         # Needles and tickmarks material (Changing not recommended)
    
    # Coolour Settings #
    GColor = vec(20)         # Gauge face colour
    OColor = vec(150)        # Outer ring colour
    MColor = vec(0,98,255)   # Needle knob colour
    NColor = vec(255,0,0)    # Needle colour
    GearColor = vec(255,0,0) # Gear counter colour
    InColor = vec(255)       # Tickmark colour
    
    # Alpha Settings for gear counter #
    OnColor  = 255    # On colour of segments
    OffColor = 10     # Off colour of segments
    
    # --------------------------------------------------------------------------------------------------------------- #
    # --------------------------------------------------------------------------------------------------------------- #
    # --------------------------------------------------------------------------------------------------------------- #
    
    # Some calculations of gauge steps 
    RPMMax = ceil(RPMMax/RpmStep)*RpmStep
    KPHMax = ceil(KPHMax/KphStep)*KphStep
    RpmStep = max(RpmStep, 1000)
    RpmStep = RPMMax/RpmStep+1
    KphStep = KPHMax/KphStep+1
    NumStepR = (RPMMax/1000)/(RpmStep-1)
    NumStepK = KPHMax/(KphStep-1)
    Angled = clamp(Angled, 0, 1)
    
    E = entity()
    E:setAlpha(0)
    
    # Main holo function
    function void holoSet( Idx:number, Position:vector, Scale:vector, Angle:angle, 
        Model:string, Color, Material )
    {
        holoPos( Idx, Position )
        holoScaleUnits( Idx, Scale )
        holoAng( Idx, Angle )
        holoModel( Idx, Model )
        holoColor( Idx, Color==1? GColor : Color==2? OColor : Color==3? MColor : 
        Color==4? NColor : Color==5? GearColor : InColor )
        holoMaterial( Idx, Material==1? GMaterial : Material==2? OMaterial : NMaterial )
    }
    
    # Holo lable function
    function number holoLable( Idx:number, Position:vector, Angle:number, Label:string, Parent:entity )
    {
        local Width = ( Label:length() - 1 ) * 0.2
        
        for( N = 0, Label:length() - 1 )
        {
            local Offset = vec( sin( Angle ), cos( Angle ), 0 ) * ( N * 0.2 - Width / 2 )
            local Char = Label:index( N + 1 )
            local Asc = toByte( Char )
            
            if( !inrange( Asc, 33, 126 ) | Asc == 92 | Asc == 96 )
            { # nothing to do if it's a space or invalid char
                continue
            } # 48-57 is numbers # 65-90 is uppercase letters
            elseif( inrange( Asc, 97, 122 ) )
            { # lowercase letters
                Char = "l_" + Char
            }
            holoSet( Idx, Parent:toWorld( ( Position + Offset )*Scale ),
                vec(1,1,1)/3.5*Scale, Parent:toWorld( ang( 0, -90 - Angle, 90 ) ),
                "models/sprops/misc/alphanum/alphanum_" + Char + ".mdl",
                6, 5 )
            holoParent( Idx, Parent )
            holoDisableShading( Idx, 1 )
            Idx++
        }
        
        return Idx
    }
    
    # Ignition animation (Needle flick)
    function start(){
        if (~Active & Active) {
            timer("oscillate",10)
        }
        if (clk("oscillate")) {
            if (Active) {
                Osc += clamp(181 - Osc, 0, 3)
                timer("oscillate",10)
            } else {
                Osc = 0
            }
            if(Osc<181){
                holoAng(3, E:toWorld(ang(0,-sin(Osc)*240-60,0)))
                holoAng(7, E:toWorld(ang(0,-sin(Osc)*240-60,0)))
                holoAng(11, E:toWorld(ang(0,-sin(Osc)*80+40,0)))
            }else{}
        }
    }
    
    # Gauge functions
    function board(){
        local FuelA=clamp(Fuel/Capacity,0,1)*80-40
        
        local Mix=clamp(Fuel/(Capacity/100*20)-1,0,1)
        local RPMMix=clamp((RPMMax-RPM)/(RPMMax/100*10)-1.8,0,1)
        
        local RPMA=clamp(RPM/RPMMax,0,1)*240+60
        local KPHA=clamp(KPH/KPHMax,0,1)*240+60
        
        if(!Capacity){FuelA=40,Mix=1}
        holoAng(3, E:toWorld(ang(0,-RPMA,0)))
        holoAng(7, E:toWorld(ang(0,-KPHA,0)))
        holoAng(11, E:toWorld(ang(0,FuelA,0)))
        holoColor(12, mix(MColor, vec(230,0,0), Mix))
        holoColor(3, mix(MColor, vec(230,0,0), RPMMix))
    }
    
    # Alpha value table for 9-Segment display (Gear counter)
    AlphaV = table(
        "1" = array( 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1 ), #-Middle Center
        "2" = array( 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1 ), #-Midele Top
        "3" = array( 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1 ), #-Middle Bottom
        "4" = array( 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1 ), #-Right Top
        "5" = array( 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1 ), #-Left Top
        "6" = array( 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 ), #-Right Bottom
        "7" = array( 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0 ), #-Left Bottom
        "8" = array( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), #-Gear segment
        "9" = array( 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 )  #-Gear segment
    )
    
    # 9-Segment display function
    function gearD(){
        local Add = ReverseGear==1? 1 : 0
        Gear = (ReverseGear&Gear==ReverseGear)? -1+Add : Gear
        foreach (K, V:array = AlphaV) {
            local In = K:toNumber() + 12
            holoAlpha(In, V[Gear+2-Add, number] ? OnColor : OffColor)
	       }    
    }
    
    # Table containing all needed values to set the holos
    Table = table(
                #RPM Gauge
        array( 1,  vec(0,-3.2,0), vec(5,5,0.3),     vec(),        "hq_cylinder",   1, 1, 0, 0 ),
        array( 2,  vec(0,0,0.2),  vec(5.2,5.2,5.2), vec(),        "hq_torus_thin", 2, 2, 0, 1 ),
        array( 3,  vec(0,0,0.25), vec(2.6,2.6,2.6), vec(),        "hq_torus_thin", 3, 3, 1, 1 ),
        array( 4,  vec(1.7,0,0),  vec(0.3,0.05,1),  vec(0,90,90), "prism",         4, 3, 1, 3 ),
                #Speed Gauge
        array( 5,  vec(0,3.2,0),  vec(5,5,0.3),      vec(),        "hq_cylinder",   1, 1, 0, 0 ),
        array( 6,  vec(0,0,0.2),  vec(5.2,5.2,5.2),  vec(),        "hq_torus_thin", 2, 2, 0, 5 ),
        array( 7,  vec(0,0,0.25), vec(0.5,0.5,0.2),  vec(),        "hq_cylinder",   3, 3, 1, 5 ),
        array( 8,  vec(0.9,0,0),  vec(0.4,0.05,2.7), vec(0,90,90), "prism",         4, 3, 1, 7 ),
               #Fuel Gauge
        array( 9,  vec(2,0,0),     vec(2,2,0.1),       vec(),         "hq_cylinder",   1, 1, 0, 0 ),
        array( 10, vec(0,0,0.1),   vec(2.1,2.1,2.1),   vec(),         "hq_torus_thin", 2, 2, 0, 9 ),
        array( 11, vec(0.7,0,0.1), vec(0.2,0.2,0.1),   vec(),         "hq_cylinder",   3, 3, 1, 9 ),
        array( 12, vec(-0.7,0,0),  vec(0.17,0.02,1.3), vec(0,-90,90), "prism",         4, 3, 1, 11 ),
                #9-Segment Display
        array( 13, vec(0,0,0.2),       vec(0.4), vec(-90,0,0), "models/segment.mdl", 5, 3, 1, 1 ),
        array( 14, vec(0,0,0.76),      vec(0.4), vec(),        "models/segment.mdl", 5, 3, 1, 13 ),
        array( 15, vec(0,0,-0.76),     vec(0.4), vec(),        "models/segment.mdl", 5, 3, 1, 13 ),
        array( 16, vec(0,0.4,0.4),     vec(0.4), vec(0,0,90),  "models/segment.mdl", 5, 3, 1, 13 ),
        array( 17, vec(0,-0.4,0.4),    vec(0.4), vec(0,0,90),  "models/segment.mdl", 5, 3, 1, 13 ),
        array( 18, vec(0,0.4,-0.4),    vec(0.4), vec(0,0,90),  "models/segment.mdl", 5, 3, 1, 13 ),
        array( 19, vec(0,-0.4,-0.4),   vec(0.4), vec(0,0,90),  "models/segment.mdl", 5, 3, 1, 13 ),
        array( 20, vec(0.02,-0.1,0.3), vec(0.5,0.4,0.2)/1.3, vec(0,0,-70), "models/segment.mdl", 5, 3, 1, 13 ),
        array( 21, vec(0.02,0.1,-0.3), vec(0.5,0.4,0.2)/1.3, vec(0,0,-70), "models/segment.mdl", 5, 3, 1, 13 )
    )
    I = 0
    timer( "holoC", 1 )
}

# Spawning holos every 1 tick delay
if( clk( "holoC" ) ){
    while( holoCanCreate() & I < HLimit ){
        I++
        holoCreate( I )
    }
    if( I < HLimit ){
        timer( "holoC", 1 )
    }
    else{
        stoptimer( "holoC" )
        timer( "setH", 1 )
    }    
}

# First setting block for base gauges, needles and gear cunter
if( clk( "setH" ) ){
    stoptimer( "setH" )
    I = 1
    
    for(In = 1, Table:count()){
        local Ex = Table[In, array][9, number]   
        local T = Table[In, array]
        holoParent(In, Ex? holoEntity(Ex) : E )
        holoSet( In, holoEntity(In):parent():toWorld( T[2, vector] * Scale ), T[3, vector] * Scale, 
                 holoEntity(In):parent():toWorld( T[4, angle] ), T[5, string], 
                 T[6, number], T[7, number] )
        holoDisableShading(In, T[8, number] )
        I++
    }
    timer( "RPM", 500 )
}

# First gauge (RPM) setting block
if( clk( "RPM" ) ){
    stoptimer( "RPM" )
    N = 0
    for(Ang = 150, 390, 240 / (RpmStep - 1)){
        holoSet(I, holoEntity(1):toWorld( vec( sin(Ang)*2.3, cos(Ang)*2.3, 0.2 )*Scale ), vec( 1, 1, 1 )/5*Scale, 
                holoEntity(1):toWorld(ang( 0, -Ang + 90, 0 )),
                "models/sprops/rectangles_thin/size_1/rect_3x12x1_5.mdl",
                6, 3 )
        holoParent( I, holoEntity(1) )
        holoDisableShading( I, 1 )
        I++
        I = holoLable( I, vec( sin(Ang)*2, cos(Ang)*2, 0.15 ), Angled? Ang + 90 : 0, round( N, 1 ):toString(), holoEntity(1) )
        N += NumStepR
    }
    I = holoLable( I, vec( 1.6, 0, 0.15 ), 0, "RPM x1000", holoEntity(1) )
    timer( "KPH", 500 )
}

# Second gauge (RPM) setting block
if( clk( "KPH" ) ){
    stoptimer( "KPH" )
    N = 0
    for(Ang = 150, 390, 240 / (KphStep - 1)){
        holoSet(I, holoEntity(5):toWorld( vec( sin(Ang)*2.3, cos(Ang)*2.3, 0.2 )*Scale ), vec( 1, 1, 1 )/5*Scale, 
                holoEntity(5):toWorld(ang( 0, -Ang + 90, 0 )),
                "models/sprops/rectangles_thin/size_1/rect_3x12x1_5.mdl",
                6, 3 )
        holoParent( I, holoEntity(5) )
        holoDisableShading( I, 1 )
        I++
        I = holoLable( I, vec( sin(Ang)*1.9, cos(Ang)*1.9, 0.15 ), Angled? Ang + 90 : 0, round( N, 1 ):toString(), holoEntity(5) )
        N += NumStepK
    }
    I = holoLable( I, vec( 1.6, 0, 0.15 ), 0, "KPH", holoEntity(5) )
    timer( "Fuel", 500 )
}

# Third gauge (Fuel) setting block
if( clk( "Fuel" ) ){
    V = 1
    stoptimer( "Fuel" )
    for(Ang = -130, -50, 80 / 4){
        holoSet(I, holoEntity(11):toWorld( vec( sin(Ang)*1.3, cos(Ang)*1.3, 0 )*Scale ), vec( 1, 1, 1 )/8*Scale, 
                holoEntity(11):toWorld(ang( 0, -Ang + 90, 0 )),
                "models/sprops/rectangles_thin/size_1/rect_3x12x1_5.mdl",
                6, 3 )
        holoParent( I, holoEntity(9) )
        holoDisableShading( I, 1 )
        I++
        I = holoLable( I, vec( sin( -130 )*0.1, cos( -130 )*1.2, 0.05 ), 0, "F", holoEntity(9) )
        I = holoLable( I, vec( sin( -50 )*0.1, cos( -50 )*1.2, 0.05 ), 0, "E", holoEntity(9) )
    }
    if( I-1 > HLimit ){
        hint( "Not enought holograms! Increase the limit to " + (I-1), 4 )
    }else{
        for( Del = I, HLimit ){
            holoDelete( Del )
        }
    }
    hint( "Dashboard is ready to use. " + I + " Used holos.", 3 )
}

# Looped function
start()    
if(clk()&Osc>170){
    KPH=toUnit("km/h", entity():vel():length())
    board()
    if(changed(Gear)){
        gearD()  
    }
}