@name Holo CTF4
@inputs 
@outputs [Teams Players]:array 
@outputs [FlagDist Holder Stander Score PlTeams]:table#GoalDist:array 
#@outputs Pl:vector Fl:vector Gl:vector
@persist [PlTeams Play Holder Score ScoreDelta]:table
@persist [Players Teams Goals Flags Colors]:array 
@persist [SI Ready GravitySteal TakeDistance]:number
@persist 
#@persist Holos:array
@trigger 
#@model models/props_junk/TrashDumpster02b.mdl
#@model models/props_junk/gnome.mdl
@model models/props_lab/huladoll.mdl
#4 team Capture the flag by Captain Maim (STEAM_0:1:8017844)

#Holographic allocation offset values. 
#Additive offsets
GI=0 #Goal Indicator Offset 1-4
FI=4 #Flag indicator Offset 5-8
PI=8 #Personal Flag Indicator Offset 9-12
TI=50 #Team Indicator Offset 50-numplayersingame
#multiplicative offset
SC=3 #Score Indicator Offset 

if(ops()>2500){exit()}
interval(100)
MaxScore=5

#Manual player scanner
Alt=1
if(!Ready){
    if(!Alt){
        #findInSphere(entity():pos(),100000)       
        #findByClass("player")
        Players=players()

    }
    if(Alt){    
        for(C=1,30){if(entity(C):isPlayer()){Players[C,entity]=entity(C)}}
    }
    Play=table()
    for(C=1,Players:count()){
        ID=toString(Players[C,entity]:id())
        Play[ID,number]=C
    }
}


runOnChat(1)
Chat=lastSaid()
K=chatClk()
ChatO=entity():owner():lastSaid()

if(first()){
GravitySteal=1 #default setting for this
TakeDistance=300 #how far away can you steal a flag?
Colors[1,vector]=vec(0,0,255)
Colors[2,vector]=vec(255,0,0)
Colors[3,vector]=vec(65,163,0)
Colors[4,vector]=vec(255,255,0)
Score=table()
Holos=array()

}

#Command string table
Setup="S"
Command="CTF"     #This must be said to activate ANYTHING
Flagword="flag"   #This must be said in with a color to place flag and goal
BFW="blue"        #This spesifies blue
RFW="red"         #This spesifies red 
GFW="green"       #This spesifies green
YFW="yellow"      #This spesifies Yellow
Removeword="remove" #only the chip owner can remove a team with this + a color
Lock="Lock"         #only the chip owner can lock the setup and start the game
Unlock="Unlock"     #only the chip owner can unlock setup and stop the game
All="all"           #Testing purposes
Teamed="team"       #Sets your team or combined with all sets all to a team
GstealOn="gson"     #allow stealing via gravity gun
GstealOff="gsoff"   #disallow gravity gun stealing of flags
Reset="reset"

#String search checks This finds out if something was said.
Com=Chat:find(Command)

H=vec(0,0,15) #height multiplyer for flags


#This determnies the action taken when a spesific word combo is spoken
if(K&Com){
    Words=array()
    SpokeO=entity():owner()
    Spoke=lastSpoke()
    Locked=ChatO:find(Lock)
    Unlocked=ChatO:find(Unlock)
    RemovedWord=Chat:find(Removeword)
    RemoveWord=ChatO:find(Removeword)
    FlagWord=Chat:find(Flagword)
    Words[1,number]=Chat:find(BFW)
    Words[2,number]=Chat:find(RFW)
    Words[3,number]=Chat:find(GFW)
    Words[4,number]=Chat:find(YFW)
    Words[5,number]=ChatO:find(All)
    Words[6,number]=Chat:find(Teamed)
    GStealOn=ChatO:find(GstealOn)
    GStealOff=ChatO:find(GstealOff)
    SETUP=ChatO:find(Setup)
    RESET=ChatO:find(Reset)
    #Diagnostics
    #print("Anyone: "+Chat)
    #print("Owner: "+ChatO)
    #print("Locked: "+Locked)
    #print("Unlocked: "+Unlocked)
    #print("RemovedWord: "+RemovedWord)
    #print("RemoveWord: "+RemoveWord)
    #print("FlagWord: "+FlagWord)
    #print("Words table:")
    #printTable(Words)
    #print("GStealOn: "+GStealOn)
    #print("GStealOff: "+GStealOff)
    #print("SETUP: "+SETUP)

    if(RESET){reset()}
#Chat processor
#test setup function
    if(SETUP){
        for(C=1,Words:count()){Words[C,number]=1}
        FlagWord=1
        timer("Locked",500)
    }
    #manual setup funtion (normal) 

    if(!Ready){
    if(GStealOn){GravitySteal=1 print("Flag stealing is On")}
    if(GStealOff){GravitySteal=0 print("Flag stealing is Off")}
        for(C=1,Words:count()){
            if(Words[C,number]){
                if(C>=1&C<=4){
                    if(RemoveWord){
                        print("Removing team: "+C)
                        Goals[C,vector]=vec(0,0,0) 
                        Flags[C,vector]=vec(0,0,0)
                        Teams[C,number]=1 #Deactivate Team
                    }
                    if(FlagWord&Teams[C,number]!=2){
                        print("Placing Team: "+C)
                        Teams[C,number]=2 #Activate Team
                        Goals[C,vector]=Spoke:aimPos() 
                        Flags[C,vector]=Spoke:aimPos()+H*vec(0,0,C)
                    }
                    
            }
            if(Words[6,number]){ #Someone said "team" Did they also say a color?
                if(RemovedWord){
                    IDP=toString(Play[toString(Spoke:id()),number])
                    IDPn=Play[toString(Spoke:id()),number]
                    holoDelete(IDP:toNumber()+TI)
                    PlTeams[IDP,number]=0
                    PlTeams[IDPn,entity]=noentity()
                }
                for(D=1,4){ #what team did he want to be on? 
                    IDP=toString(Play[toString(Spoke:id()),number])
                    IDPn=Play[toString(Spoke:id()),number]
                    if(Words[D,number]){ 
                        PlTeams[IDP,number]=D
                        PlTeams[IDPn,entity]=Players[IDP:toNumber(),entity] 
                        holoDelete(IDP:toNumber()+TI)
                        
                    }  
                        
                    if(Words[5,number]){
                            if(Words[6,number]){
                            InTeams=table()
                                    for(D=1,4){
                                        
                                        DS=toString(D)
                                        if(Words[D,number]){InTeams[DS,number]=1}
                                    }
                                    TeamCount=InTeams:count()
                                    for(D=1,Players:count()){
                                        DS=toString(D)
                                        
                                        CycleStart=D%InTeams:count()
                                        if(!CycleStart){CycleEnd=InTeams:count()}else{CycleEnd=0}
                                        Cycle=CycleStart+CycleEnd
                                        PlTeams[DS,number]=Cycle 
                                        PlTeams[D,entity]=Players[D,entity]
                                        holoDelete(D+TI)
                                    }  
                                     
                                }
                            }
                    }
                            if(RemoveWord&FlagWord){for(D=1,Teams:count()){Teams[D,number]=1}
                                Flags=array()
                                Goals=array()
                             }
                            if(SETUP){
                                for(D=1,4){
                                    if(FlagWord&Teams[D,number]!=2){
                                    Teams[D,number]=2
                                    Offset=170
                                    Goals[D,vector]=SpokeO:aimPos()+vec(0,Offset*(D-1),0)
                                    Flags[D,vector]=SpokeO:aimPos()+H*vec(0,0,D)+vec(0,Offset*(D-1),0)
                                    }           
                               }     
                            }
                    }       
            }
        }
    }
}

if(clk("Locked")){Locked=1}
    if(Locked){Ready=1 print("Setup is locked! Game is Ready!")}
    if(Unlocked){Ready=0 print("Setup is Unlocked Game Paused")}
if(ops()>3000){exit()}
#if the setup is locked this means the game is ready. 
if(Ready){

Min=70

#Find closest players to all flags who's within the min dist
FlagDist=table()
PlayDist=array()
Stander=table()

for(C=1,4){ #get distances between players and flag points
    CS=toString(C)
    for(D=1,Players:count()){
        #DS=toString(D)
        PlayDist[D,number]=Flags[C,vector]:distance(PlTeams[D,entity]:pos())
    }
    
    FlagDist[C,number]=PlayDist:min()<Min#+1
    #printTable(FlagDist)
    #assign a flag holder if applicable
    for(D=1,Players:count()){
        CS=toString(C)
        DS=toString(D)
        PlT=PlTeams[DS,number] #player team number
        #print("PlT "+PlT+" FlagDist "+FlagDist[CS,number]+" C "+C+" D "+D)
        if(PlT&FlagDist[C,number]){
            
            Stander[CS,entity]=Players[PlayDist:minIndex(),entity]   #who is standing in a goal zone?     
            #####THIS PART IS FLAWED It's not accounting for D and contaminats the search
            
            
        } 
        
    }
    if((PlT!=C)&!Holder[CS,entity]){ #Pickup flags
        #print("PlT: "+PlT+" C Team "+C+" D "+D)
        #printTable(PlTeams)
        #print("Holder: "+D+" "+Holder[DS,entity]:id())
        Holder[CS,entity]=Players[PlayDist:minIndex(),entity]
    }
}
#Gravity gun flag stealing code
if(GravitySteal){
    PlC=PlTeams:count()/2
    for(C=1,PlC){
        CS=toString(C) 
        PC=PlTeams[C,entity]
        Weap=PC:weapon():type()=="weapon_physcannon"
        Take=PC:keyAttack2()
        #print(C+"  "+Weap+"  "+Take)
        for(D=1,4){
            DS=toString(D)
            PD=Holder[DS,entity]
            if(PD){Dist=PC:pos():distance(PD:pos())}else{Dist=TakeDistance*2}
            CanTake=Dist<TakeDistance
            #print(C+" "+D+" Distance: "+Dist)
            #if(PC:name()=="Captain Maim"){print(C+" "+D+" "+Dist+"<"+TakeDistance)}
            if(PC:aimEntity()==PD&Weap&PD&Take&CanTake){
                Holder[DS,entity]=PlTeams[C,entity]
                
            }
        }
    }
}

#Do something when someone is near a flag or goal
for(C=1,4){
    CS=toString(C)
    Pla=Holder[CS,entity]
        for(D=1,Players:count()){
            DS=toString(D)
            Home=PlTeams[DS,number]&Stander[CS,entity]==Players[D,entity]&C==PlTeams[DS,number]
            NotHome=PlTeams[DS,number]&Stander[CS,entity]==Players[D,entity]&C!=PlTeams[DS,number]
            
            if(NotHome){
           
            #print("He's not home!"+C+"PLTeam "+PlTeams[DS,number]+" D:"+D)
            #If I think of anything I can put here. 
            }
            if(!Players[D,entity]:isAlive()){
                for(E=1,4){
                    ES=toString(E)
                    if(Players[D,entity]==Holder[ES,entity]){
                        Holder[ES,entity]=noentity()
                        holoUnparent(E+4)
                    }
                }
            }
            if(Home){
             
             #print("He's home "+PlTeams[DS,number]+" D:"+D)   
                for(E=1,4){
                    ES=toString(E)
                    DS=toString(D)
                    if(Players[D,entity]==Holder[ES,entity]){
                        #if(PlTeams[DS,number]!=E){Score[CS,number]=Score[CS,number]+1} #Cumulative Scoring
                        if(PlTeams[DS,number]!=E){
                            Score[ES,number]=Score[ES,number]+1
                            ScoreDelta[ES,number]=2
                            Sizer=vec(SI,SI,SI*Score[ES,number])
                        } #Elimination Scoring
                            
#                            F=-1
#                            Set=C+4*(SC+E)
#                            holoScale(Set+F,Sizer) F++ 
#                            X=Set+F
#                            print("State: "+X+" E:"+E)
#                            holoScale(Set+F,Sizer) F++
#                            X=Set+F
#                            print("State: "+X+" E:"+E)
#                            holoScale(Set+F,Sizer) F++
#                            X=Set+F
#                            print("State: "+X+" E:"+E)
#                            holoScale(Set+F,Sizer) F++
#                            X=Set+F
#                            print("State: "+X+" E:"+E)

                        if(Score[ES,number]>=MaxScore){
                            holoDelete(E)
                            holoDelete(E+4)
                            Teams[E,number]=1
                            Goals[E,vector]=vec(0,0,0)
                            Flags[E,vector]=vec(0,0,0)
                            
                            print("Team: "+E+" Has been defeated!")
                        }
                        Holder[ES,entity]=noentity()
                        #printTable(Holder)
                        holoUnparent(E+4)
                    }
                }
            
            }
        }
        holoPos(C+4,Flags[C,vector])

    if(FlagDist[C,number]-1){
        if(Pla:isAlive()){
            
            holoPos(C+4,Pla:pos()+H*vec(0,0,C)+vec(0,0,Pla:height()))
            holoParent(C+4,Holder[CS,entity])
        
                
            }
        }
    }
}#end ready


#Holographic Flag and Goal Design
timer("holo",750)

if(clk("holo")){

    SG=10 #scale Goal
    SF=2  #Scale flag
    SI=0.25  #scale team indicator 
    ScaleG=vec(SG,SG,SG/4)
    ScaleF=vec(SF,SF,SF)
    ScaleI=vec(SI,SI,SI)
    ScaleP=vec(SI,SI,SI)/4
    AngG=ang(0,0,0)
    AngF=ang(0,0,0)
    AngI=ang(0,0,0)
    Stand=vec(0,0,73)
    #Sit=vec(0,0,37)
    R=70
    Ang=10
    
    for(C=1,4){
        CS=toString(C)
        for(D=1,PlTeams:count()/2){
            DS=toString(D)
    #        PosH=holoEntity(D+8):pos()
    #        PosP=Players[D,entity]:pos()
    #        if(Players[D,entity]:isCrouch()&(PosH+Sit)!=(PosP+Sit)){holoPos(D+8,PosP+Sit)}
    #        if(!Players[D,entity]:isCrouch()&(PosH+Stand)!=(PosP+Stand)){holoPos(D+8,PosP+Stand)}
            if(PlTeams[DS,number]&!holoEntity(D+TI)){  
    	           #Indicators
               #TI=50
                holoCreate(D+TI,PlTeams[D,entity]:pos()+Stand,ScaleI)
                holoColor(D+TI,Colors[PlTeams[DS,number],vector])
                holoParent(D+TI,PlTeams[D,entity])
                holoAlpha(D+TI,128+64)
            }
        }
        if(Teams[C,number]==2){
                #GI=0 FI=4
            if(!holoEntity(C+GI)&Score[CS,number]<MaxScore){
                #Goals covers 1-4
                holoCreate(C+GI,Goals[C,vector],ScaleG,AngG,Colors[C,vector])
                holoModel(C+GI,"torus")
                holoShadow(C+GI,1)
                #flags 5-8
                holoCreate(C+FI,Flags[C,vector],ScaleF,AngF,Colors[C,vector])
                holoModel(C+FI,"icosphere")
                holoShadow(C+FI,1)
                holoAlpha(C+FI,128)
                #Personal Flag holder indicators
                #PI=8  9-12
                if(Holder[CS,entity]){
                Radius=5
                HAng=Holder[CS,entity]:eyeAngles()+ang(0,45,0)
                Dir=vec(Radius*cos(HAng:yaw()),Radius*sin(HAng:pitch()),0)
                if(!holoEntity(C+PI)){
                holoCreate(C+PI,Holder[CS,entity]:pos()+Dir,ScaleP,ang(),Colors[C,vector])
                holoAlpha(C+PI,192)
                }else{holoPos(C+PI,Holder[CS,entity]:pos()+Dir)}
                }elseif(holoEntity(C+PI)){holoDelete(C+PI)}
                #Indicators 40-44
                Set=40+C 
                
                Ind=Goals[C,vector]+vec(cos(5*Ang)*R,R*sin(5*Ang),20)
                Size=vec(SI,SI,SI*MaxScore)
                holoCreate(Set,Ind,Size,ang(0,0,0),vec(0,0,0))
    
                #SC=3
                #Scoreboard 24-56
                for(D=1,4){
                    Ind=vec(cos(D*Ang)*R,R*sin(D*Ang),20)
                    Off=Goals[C,vector]+Ind
                    S=vec(SI,SI,0)
                    Color=Colors[D,vector]
                    Set=C+4*(SC+D) # This covers a range of 24 to 56
                    #print("Setup: "+Set+" "+C+" "+D)
                    holoCreate(Set,Off,S,ang(0,0,0),Color)
                    
                   
                }
    
                
            }
    
        }
        #SC=3
        if(Teams[C,number]==1){
            holoDelete(C)   #goals
            holoDelete(C+4) #flags
            holoDelete(C+4*(SC+1))#blue
            holoDelete(C+4*(SC+2))#red
            holoDelete(C+4*(SC+3))#green
            holoDelete(C+4*(SC+4))#yellow
            holoDelete(C+40)#black
            for(D=1,PlTeams:count()){
                holoDelete(D+50)#team indicator
            }
        }
    }
    for(C=1,4){
        CS=toString(C)
        if(ScoreDelta[CS,number]==2){
            Sizer=vec(SI,SI,SI*Score[CS,number])
            ScoreDelta[CS,number]=1
            holoScale(1+4*(SC+C),Sizer)
            holoScale(2+4*(SC+C),Sizer)
            holoScale(3+4*(SC+C),Sizer)
            holoScale(4+4*(SC+C),Sizer)
    
        }
    }
}#0
