@name ByBFeller
@inputs Scr:wirelink User:entity PlayScr:wirelink Amt Sound:entity
@inputs Ranger_Walkway MaxHeight:entity
@persist [Players Plates]:table Prize State Price
@persist Countdown Def_Countdown [Music CountdownSounds]:array
@persist Available:table CurPlate TimerMod
@outputs Eject SetColorEnt:entity SetColor:vector
@outputs DoorEnter DoorExit DoorWalkway
@outputs VanishState Vanishing:entity VanishTime
@trigger all
#SetColorEnt:setColor(SetColor)
if (first()) {
    #################
    Price=0
    Def_Countdown=30
    TimerMod=1
    Prize=500
    Music=array(
        "ui/gamestartup1.mp3",
        "ui/gamestartup2.mp3",
        # "ui/gamestartup3.mp3",
        "ui/gamestartup4.mp3",
        "ui/gamestartup5.mp3",
        "ui/gamestartup6.mp3",
        "ui/gamestartup7.mp3",
        "ui/gamestartup8.mp3",
        "ui/gamestartup9.mp3",
        "ui/gamestartup10.mp3",
        "ui/gamestartup11.mp3",
        "ui/gamestartup12.mp3",
        "ui/gamestartup13.mp3",
        # "ui/gamestartup14.mp3",
        "ui/gamestartup15.mp3",
        "ui/gamestartup16.mp3",
        "music/hl2_song20_submix0.mp3",
        "music/hl2_song3.mp3",
        "music/vlvx_song23.mp3",
        "music/vlvx_song25.mp3",
        "music/vlvx_song27.mp3",
        "music/vlvx_song21.mp3"
    )
    CountdownSounds=array(
        30="vo/announcer_begins_30sec.wav",
        20="vo/announcer_begins_20sec.wav",
        10="vo/announcer_begins_10sec.wav",
        5="vo/announcer_begins_5sec.wav",
        4="vo/announcer_begins_4sec.wav",
        3="vo/announcer_begins_3sec.wav",
        2="vo/announcer_begins_2sec.wav",
        1="vo/announcer_begins_1sec.wav"
    )
    #################
    State=0
    DoorEnter=1
    DoorWalkway=1
    Countdown=Def_Countdown
    PlayScr:egpClear()
    # Say
    function say(S:string) {
        printColor(vec(255,255,0),"[ByBFeller] ",vec(255),S)
    }
    
    # ingame
    function number inGame(P:entity) {
        for (I=1, Players:count()) {
            if (Players[I,entity]==P) {return 1}
        }
        return 0
    }
    
    # Gather plates
    findByModel("models/hunter/plates/plate1x1.mdl")
    local Things=findToArray()
    foreach(I,V:entity=Things) {
        if (V:owner()==owner() & (V:getMaterial()=="sprites/heatwave" | V:getMaterial()=="phoenix_storms/cube")) {
            Plates[Plates:count()+1,wirelink]=V:wirelink()
            Plates[Plates:count(),wirelink]["Fade",number]=0
        }
    }
    say(Plates:count()+" plates found")
    
    # Screens
    function hotBG(Scr:wirelink) {
        Scr:egpClear()
        Scr:egpBox(300,vec2(256),vec2(512))
        Scr:egpColor(300,vec(64))
        local Lines=5
        local Dist=512/Lines
        CurSelection=0
        for (I=1, Lines+2) {
            Scr:egpLine(I+200,vec2(Dist*(I-2),-5),vec2(Dist*I,517))
            Scr:egpSize(I+200,30)
            Scr:egpMaterial(I+200,"gui/gradient_down")
            Scr:egpColor(I+200,vec(32))
        }
    }
    
    # Login screen
    hotBG(PlayScr)
    PlayScr:egpBox(1,vec2(256),vec2(512,80))
        PlayScr:egpColor(1,vec(148,148,148))
        
    PlayScr:egpText(2,"Loading...",vec2(256))
        PlayScr:egpAlign(2,1,0)
        PlayScr:egpSize(2,30)
        
    PlayScr:egpText(3,"ByB Feller",vec2(256))
        PlayScr:egpAlign(3,1,2)
        PlayScr:egpSize(3,40)
    
    # Game screen
    Scr:egpClear()
    Scr:egpText(1,"ByB Feller",vec2(256,60))
        Scr:egpSize(1,70)
        Scr:egpAlign(1,1,2)
    
    Scr:egpText(2,"Waiting for Players",vec2(256,60))
        Scr:egpAlign(2,1,0)
        Scr:egpSize(2,40)
    
    ## Fancy timer lines 30-90
    ## Fancy timer lines parents 230-260
    ## Fancy timer text 25
    for (I=1, 30) {
        Scr:egpBox(29+I,vec2(256,300),vec2(0,50))
        Scr:egpBox(229+I,vec2(0,-150),vec2(33,10))
        Scr:egpParent(229+I,29+I)
        Scr:egpAngle(29+I,(360/30)*I)
        Scr:egpColor(229+I,vec(0,255,0))
    }
    Scr:egpText(25,"0",vec2(256,300))
    Scr:egpAlign(25,1,1)
    Scr:egpSize(25,120)
    Scr:egpColor(25,vec(0,255,0))
    function setTimer(Cur,Max) {
        local Unit=Cur/Max
        local Lines=clamp(ceil(Unit*30),0,30)
        local Color=(vec(0,255,0)-vec(255,0,0))*Unit+vec(255,0,0)
        for (I=1, 30) {
            Scr:egpColor(229+I,Color)
            Scr:egpAlpha(229+I,255)
        }
        for (I=1, 30-Lines) {
            Scr:egpAlpha(229+I,0)
        }
        Scr:egpColor(25,Color)
        Scr:egpSetText(25,""+Cur)
    }
    setTimer(30,30)
    timer("AutoDisco",100)
    
    #finish game
    function finishGame() {
        local Victory=array(
            "vo/announcer_am_flawlessvictory01.wav",
            "vo/announcer_am_flawlessvictory02.wav",
            "vo/announcer_am_flawlessvictory03.wav",
            "vo/announcer_victory.wav",
            "vo/announcer_we_succeeded.wav",
            "vo/announcer_success.wav"
        )
        Sound:soundPlay(1,0,Victory[randint(Victory:count()),string])
        say("Game finished.")
        if (Players:count()==1) {
            local Winner=Players[1,entity]
            say(Winner:name()+" won!")
        } else {
            say("No player won.")
        }
        Players=table()
        Available=table()
        TimerMod=1
        soundStop(0)
        soundStop(2)
        Scr:egpSetText(2,"Waiting for players")
        DoorWalkway=1
        State=4
        CurPlate=0
        Countdown=Def_Countdown
        setTimer(Countdown,Def_Countdown)
        timer("Reset",5000)
    }
}

if (State==0 & Amt>=Price) {
    PlayScr:egpSetText(2,"Press Anywhere to Join")
    PlayScr:egpColor(1,vec(0,172,0))
    if (User & !inGame(User)) {
        if (User:pos():distance(PlayScr:entity():pos())<65) {
            Players[Players:count()+1,entity]=User
            # print(Players:count(),User)
            say(User:name()+" has joined the game.")
            DoorEnter=0
            DoorExit=1
            Eject=Price
            if (Players:count()==2) 
                {Countdown=Def_Countdown timer("Countdown",1000)}
                else {Countdown=clamp(Countdown+5,0,30) setTimer(Countdown,30) Sound:soundPlay(1,0,"vo/announcer_time_added.wav")}
            timer("NoEject",10)
            timer("DoorSwapper",1000)
        }
    }
} elseif (State!=0) {
    PlayScr:egpColor(1,vec(172,0,0))
    PlayScr:egpSetText(2,"Game in progress")
} elseif (Amt<=Price) {
    PlayScr:egpColor(1,vec(140))
    PlayScr:egpSetText(2,"Insert $"+(Price-Amt)+" to join.")
}

if (clk("AutoDisco")) {
    if (State==0) {
        SetColorEnt=Plates[randint(Plates:count()),wirelink]:entity()
        SetColor=hsv2rgb(random(255),1,1)
    }
    timer("AutoDisco",100)
}

if (clk("NoEject")) {
    Eject=0
}

if (clk("DoorSwapper")) {
    if (Ranger_Walkway==0) {
        DoorExit=0
        DoorEnter=1
    } else {
        timer("DoorSwapper",1000)
    }
}

if (clk("Countdown") & State==0 & Players:count()>=2) {
    Countdown--
    setTimer(Countdown,30)
    local SoundId=CountdownSounds[Countdown,string]
    if (SoundId) {Sound:soundPlay(1,0,SoundId)}
    if (Countdown>0) {
        timer("Countdown",1000)
    } else {Scr:egpSetText(2,"Please enter the arena") State=1 timer("CheckArena",100)}
}
if (clk("CheckArena")) {
    StartReady=1
    for (I=1, Players:count()) {
        local V=Players[I,entity]
        # print(V:pos():z(),MaxHeight:pos():z())
        if (V:pos():z()>MaxHeight:pos():z()) {
            StartReady=0
            #print(_HUD_PRINTCENTER,"[ByBFeller] "+V:name()+" is not in the arena!")
            Scr:egpSetText(2,V:name()+", please enter the arena.")
        }
    }
    if (StartReady) {
        DoorWalkway=0
        timer("Start",100)
        State=2
        Scr:egpSetText(2,"Starting game...")
    } else {
        timer("CheckArena",100)
    }
}

if (clk("Start")) {
    Scr:egpSetText(2,"Game in progress")
    say("Game start!")
    local SoundId=Music[randint(Music:count()),string]
    Sound:soundPlay(0,0,SoundId)
    CurDel=0
    Available=Plates:clone()
    #setTimer(Available:count(),Plates:count())
    CurPlate=0
    timer("ColorFloor",10)
    timer("FailPlayers",100)
    timer("PlateSelect",5000)
}
if (clk("ColorFloor")) {
    CurPlate++
    setTimer(CurPlate,Plates:count())
    SetColorEnt=Plates[CurPlate,wirelink]:entity()
    SetColor=vec(255)
    Plates[CurPlate,wirelink]["Fade",number]=0
    if (CurPlate<Plates:count()) {timer("ColorFloor",100)}
}

if (clk("PlateSelect") & Players:count()>1) {
    if (Available:count()>1) {
        CurPlate=randint(Available:count())
        SetColorEnt=Available[CurPlate,wirelink]:entity()
        SetColor=vec(255,0,0)
        #
        Vanishing=Available[CurPlate,wirelink]:entity()
        timer("VanishToggle",100)
        #
        
    } else { # move to overtime
        say("Game moved to overtime!")
        TimerMod=TimerMod*0.5
        Available=Plates:clone()
        soundStop(0)
        timer("Overtime",3000)
        soundPlay(1,0,"vo/announcer_overtime.wav")
        Scr:egpSetText(2,"Overtime: "+(1/TimerMod)+"x Speed")
        CurPlate=0
        timer("ColorFloor",10)
    }
}
if (clk("VanishToggle")) {
    VanishState=1
    Available[CurPlate,wirelink]["Fade",number]=1
    VanishTime=randint(700,2000)*TimerMod
    timer("RemovePlate",VanishTime)
}
if (clk("Overtime") & Players:count()>1) {
    Available=Plates:clone()
    local SoundId=Music[randint(Music:count()),string]
    Sound:soundPlay(0,0,SoundId)
    soundPitch(0,150)
    timer("PlateSelect",10)
}

if (clk("RemovePlate") & Players:count()>1) {
    #Available[CurPlate,wirelink]["Fade",number]=1
    VanishState=0
    Available:removeWirelink(CurPlate)
    setTimer(Available:count(),Plates:count())
    timer("PlateSelect",randint(200,3000)*TimerMod)
}

if (clk("FailPlayers") & State==2) {
    for (I=1, Players:count()) {
        local V=Players[I,entity]
        if (V & V:pos():z()<MaxHeight:pos():z()-30) {
            Players:removeEntity(I)
            say(V:name()+" has failed!")
            Scr:entity():soundPlay(3,0,"ambient/alarms/klaxon1.wav")
            if (Players:count()<=1) {
                VanishState=0
                finishGame()
                for (I=1, Plates:count()) {
                    Plates[I,wirelink]["Fade",number]=1
                }
                break
            }
        }
    }
    timer("FailPlayers",100)
}
if (clk("Reset")) {
    State=0
    for (I=1, Plates:count()) {
        Plates[I,wirelink]["Fade",number]=0
    }
}
