@name Joystick Actuated Construction Killbot
@inputs [Turret User RTCam Num CamCon JAna JHat JBut]:wirelink
#@inputs [Grabber Forcer]:wirelink
@inputs Mode:string Config:table FireCount Isolated
@outputs # [Position OE AimPos]:vector Minus Activated On Tool:string
@outputs #Loc:array 
@outputs LeftClick RightClick Reload Mode:string Freeze Isolate Config:table
@persist [Self Enemy]:entity [Inertia Angle]:angle 
@persist Counter [Loc Tools Stools Parts]:array
@persist Minus Activated On RTOn X Y Z Time RS InertiaConstant Position:vector
@persist 
@persist Joymode ToolSel
@trigger Minus On N8 N2 N6 N4 Enter Plus RTOn 
CHASIS="models/props_combine/combine_light002a.mdl"
if(Joymode){
    if(JAna:entity()){
        Xaxis=JAna["1",number] #Left stick X
        Yaxis=JAna["2",number] #Left Stick Y
        Xaxis2=JAna["3",number] #Right Stick X
        Yaxis2=JAna["4",number] #Right Stick Y
        Zaxis=JAna["5",number] #Trigger analog (Left down, right up)
        Lstick=JAna["6",number] #Left Stick button
        Rstick=JAna["7",number] #Right stick button
        But9=JAna["8",number] #Center Ring left 
    }
    if(JHat:entity()){
        HatU=JHat["1",number] #Hat up
        HatD=JHat["2",number] #Hat Down
        HatL=JHat["3",number] #Hat Left
        HatR=JHat["4",number] #Hat Right
        HatC=JHat["5",number] #Hat Centered
        But9=JHat["6",number] #Center Ring Left
        But10=JHat["7",number] #Center Ring Right
        But13=JHat["8",number] #Center Ring Middle
    }
    if(JBut:entity()){
        But1=JBut["1",number] #Square / 1
        But2=JBut["2",number] #X / 2
        But3=JBut["3",number] #Circle / 3
        But4=JBut["4",number] #Triangle /4
        But5=JBut["5",number] #Left front button
        But6=JBut["6",number] #Right front button
        But7=JBut["7",number] #Left trigger
        But8=JBut["8",number] #Right trigger
    }
}

runOnChat(1)
timer("RTCam",1000)
if(Minus&clk("RTCam")){
    Activated=!Activated
    RTCam["Hide",number]=Activated
}
if(chatClk()){
    O=owner()
    Chat=O:lastSaid()
    Name="J.A.C.K."
    Cmd="JACK"
    On1="on"
    On0="off"
    Menu="menu" #stool turret menu
    Help="help"
    Joystick="joy"
    Keyboard="key"
    Brk=" "
#    Fast="fast"
#    Slow="slow"
    
    CMD=Chat:find(Cmd)
    if(CMD){
        ON1=Chat:find(On1)
        ON0=Chat:find(On0)
        MENU=Chat:find(Menu)
        BRK=Chat:find(Brk)
        HELP=Chat:find(Help)
        JOYSTICK=Chat:find(Joystick)
        KEYBOARD=Chat:find(Keyboard)
#        FAST=Chat:find(Fast)
#        SLOW=Chat:find(Slow)

            if(ON1){
                On=1 
                Position=entity():pos()+vec(0,0,100)
                print(Name+" is on")
            }
            if(ON0){
                On=0
                print(Name+" is on")
            }
            if(BRK&(!ON1|!ON0|!MENU)){
                
                STOOL=Stools[Chat:explode(Brk)[2,string]:toNumber(),string]
                if(STOOL){
                    Mode=STOOL
                    print("Setting STool to: "+STOOL)
                    print("Registering '"+Mode+"' as the current tool")
                    #Stool["Mode",string]=STOOL
                    
                    #STool=Stool["Mode",string]
                }
                
            }
            if(KEYBOARD){Joymode=0 print("enabling keyboard/mouse mode")}
            if(JOYSTICK){Joymode=1 print("enabling joystick mode")}
            if(MENU){
                printTable(Stools)
                print("Type '"+Cmd+" ' and the number of stool")
            }
            if(HELP){
                print("Commands are ")
                print(Menu+" lists all stools")
                print("'"+Brk+"' is the break character")
                print(On1+" turns it on")
                print(On0+" turns it off")
            }
    }
}


if(!Joymode){
    #Get the numpad
    N0 = Num:number("0")
    N1 = Num:number("1")
    N2 = Num:number("2")
    N3 = Num:number("3")
    N4 = Num:number("4")
    N5 = Num:number("5")
    N6 = Num:number("6")
    N7 = Num:number("7")
    N8 = Num:number("8")
    N9 = Num:number("9")
    Slash = Num:number("/")
    Astrix = Num:number("*")
    Minus = Num:number("-")
    Plus = Num:number("+")
    Enter = Num:number("enter")
    Del = Num:number(".")
}

timer("ToolSel",150)
if(clk("ToolSel")){
    if(HatL){ToolSel--}
    if(HatR){ToolSel++}
    if(HatR|HatL){
        if(ToolSel<1){ToolSel=Stools:count()}
        if(ToolSel>Stools:count()){ToolSel=1}
        
        print("Curret STool to: "+ToolSel+" - "+Stools[ToolSel,string])
        #print("Registering '"+Mode+"' as the current tool")
        
    }
    if(HatD){
    
    Mode=Stools[ToolSel,string]
    print("Tool set to "+Mode)
    }
}
Turret["Fire",number]=N0|But6 #Fire the turret
User["Fire",number]=N5|But1 #activate user
#Grabber["Grab",number]=Del|But5 #grab it
#Grabber["Strength",number]=100000

#Stool["Isolate",number]=1

#Forcer["Force",number]=(N1|HatU)*10000
#Forcer["OffsetForce",number]=(N1|HatU)*1000
#Forcer["Velocity",number]=(N1|HatU)*10000
#Forcer["Length",number]=1000

timer("stool",250)
if(clk("stool")){
    #Stool["LeftClick",number]=N7  #left click 
    #Stool["RightClick",number]=N9 #right click
    #Stool["Reload",number]=N3    #reload
    LeftClick=N7|But2
    RightClick=N9|But3
    Reload=N3|But4
}
if(dupefinished()){reset()}
O=owner()

if(first()|!Position|duped()){
    Position=entity():pos()+vec(0,0,100)
    X=Position:x()
    Y=Position:y()
    Z=Position:z()
    timer("delay",1500)
    Direction=vec(entity():angles())
    RTOn=0
}

if(!Position){Position=entity():pos()+vec(0,0,100)}

if(clk("delay")){
    Direction=owner():eye() 
}
if(dupefinished()|first()){
    Parts=entity():getConstraints()
    #1
    #States where the RT Camera is
    Tools:pushEntity(RTCam:entity():isConstrainedTo())
    
    
  
    #2
    #States the turret entity and it's relative location
    Tools:pushEntity(Turret:entity())
    
    #3
    #States the stool turret entity and it's relative location
    #Tools:pushEntity(Stool:entity():isConstrainedTo())
    for(C=1,Parts:count()){
        if((Parts[C,entity]:type()=="stool_turret")|(Parts[C,entity]:model()=="models/weapons/w_physics.mdl")){
            Tools:pushEntity(Parts[C,entity]:isConstrainedTo())
            Stool=Parts[C,entity]
            break
        }
        
    }
    
    #4 Robot chasis
#    for(C=1,Parts:count()){
#        if(Parts[C,entity]:model()==CHASIS){
#            Chasis=Parts[C,entity]
#            Tools:pushEntity(Chasis)  
#            break
#        }
#    }
    
    #4
    #States the forcer entity and it's relative location
    #Tools:pushEntity(Forcer:entity())#:isConstrainedTo()
    
    #5
    #States the grabber entity and it's relative location
    #Tools:pushEntity(Grabber:entity())#:isConstrainedTo()
    
    #6
    #States the user entity and it's relative location
    Tools:pushEntity(User:entity())#:isConstrainedTo()
    for(C=1,Tools:count()){Tools[C,entity]:setMass(5000)}
   # for(C=1,Tools:count()){holoCreate(C,Position)}
#    for(C=1,Loc:count()){
#        holoCreate(C,Loc[C,vector])
#        holoColor(C,vec(0,0,64*C))
#    }
    
    
}
Spacing=30
Div=3
Cha=10
Loc[1,vector]=vec(0,0,35) #RT Camera
Loc[2,vector]=vec(cos(Angle:yaw()-90)*Spacing/Div,sin(Angle:yaw()-90)*Spacing/Div,35) #Turret
Loc[3,vector]=vec(cos(Angle:yaw()+90)*-Spacing,sin(Angle:yaw()+90)*-Spacing,0) #stool
#Loc[4,vector]=vec(cos(Angle:yaw()+180)*Cha,sin(Angle:yaw()+180)*Cha,-20) #Chasis
#Loc[5,vector]=vec(cos(Angle:yaw()-90)*Spacing,sin(Angle:yaw()-90)*Spacing,0) #grabber
Loc[4,vector]=vec(cos(Angle:yaw()+90)*Spacing,sin(Angle:yaw()+90)*Spacing,0) #user
#for(C=1,Loc:count()){holoPos(C,Loc[C,vector])}


if(first()){
    #ifdef entity:createWire(entity,string,string)
        print("Autowiring your Stool turret")
        entity():createWire(Stool,"Mode","Mode")
        entity():createWire(Stool,"LeftClick","LeftClick")
        entity():createWire(Stool,"RightClick","RightClick")
        entity():createWire(Stool,"Reload","Reload")
        entity():createWire(Stool,"Config","Config")
        entity():createWire(Stool,"Freeze","Freeze")
        entity():createWire(Stool,"Isolate","Isolate")
    Stool:createWire(entity(),"Isolated","Isolated")
        Stool:createWire(entity(),"Mode","Mode")
        Stool:createWire(entity(),"Config","Config")
        Stool:createWire(entity(),"FireCount","FireCount")
        
    #endif
    Stools=array()
    #constraints
    Stools:pushString("easy_precision")
    Stools:pushString("axis")
    Stools:pushString("ballsocket_adv")
    Stools:pushString("elastic")
    Stools:pushString("hydraulic")
    Stools:pushString("muscle")
    Stools:pushString("superparentmulti")
    Stools:pushString("rope")
    Stools:pushString("smart_constraint")
    Stools:pushString("slider")
    Stools:pushString("weld_ez")
    Stools:pushString("weld")
    Stools:pushString("adv_duplicator")
    Stools:pushString("ignite")
    Stools:pushString("hoverball")
    Stools:pushString("dynamite")
    Stools:pushString("duplicator")
    Stools:pushString("bridgetool")
    Stools:pushString("balloon")
    Stools:pushString("freezer")
    Stools:pushString("remover")
    Stools:pushString("physprop")
    Stools:pushString("no_collide_multi")
    Stools:pushString("light")
    Stools:pushString("keepupright")
    Stools:pushString("ol_stacker")
    Stools:pushString("wheel")
    Stools:pushString("weight")
    Stools:pushString("turret")
    Stools:pushString("thruster")
    Stools:pushString("cratemaker")
    Stools:pushString("camera")
    Stools:pushString("colour")
    Stools:pushString("material")
    Stools:pushString("trails")
    Stools:pushString("rtcamera")
    Stools:pushString("paint")
    Stools:pushString("inflator")
    Stools:pushString("statue")
    Stools:pushString("ol_measuringstick")
    Stools:pushString("freezer")
    Stools:pushString("modelmanipulator")
    Stools:pushString("gravturret")
    Stools:pushString("adv_spawner")
    Stools:pushString("positionswitcher")
    Stools:pushString("fadingdoor")
    Stools:pushString("breakableprops")
    Stools:pushString("wire_expression2")
    Stools:pushString("wire_cam")
    Stools:pushString("wire_adv_pod")
    Stools:pushString("wire_numpad")
    Stools:pushString("wire_winch")
    Stools:pushString("wire_dupeport")
    Stools:pushString("wire_vehicle")
    Stools:pushString("wire_keyboard")
    Stools:pushString("wire_rtcam")
    Stools:pushString("wire_joystick_multi")
    Stools:pushString("wire_button")
    Stools:pushString("wire_explosive")
    Stools:pushString("wire_forcer")
    Stools:pushString("wire_grabber")
    Stools:pushString("wire_hoverball")
    Stools:pushString("wire_hydraulic")
    Stools:pushString("wire_thruster")
    Stools:pushString("wire_turret")
    Stools:pushString("wire_user")
    Stools:pushString("wire_vthruster")
    Stools:pushString("wire_wheel")
    Stools:pushString("multi_wire")
    Stools:pushString("wire_adv")
    Stools:pushString("wire_simulate_data")
}


if(But9){RTOn=1 timer("Camera",100)}
if(clk("Camera")){RTOn=0}

if(Slash&changed(Slash)){
    RTOn=!RTOn
    if(RTOn){print("RT Camera Enabled")}else{print("RT Camera Disabled")}
}


#Hover ranger
FloatHeight=60
rangerFilter(entity():getConstraints())
Ground=rangerOffset(20000,RTCam:entity():pos(),vec(0,0,-1)):position():z()
#TD=T&(T:pos():distance(S:pos())>200)
Height=vec(RTCam:entity():pos():x(),RTCam:entity():pos():y(),Ground+FloatHeight)


#RT Camera control
RTCam["Activate",number]=RTOn
#RTCam["Hide",number]=!RTOn

OE=O:eye()
if(!Joymode){
    Angle=OE:toAngle()
}else{
    Rate=2
    Angle+=angnorm(ang(-Yaxis2*Rate,-Xaxis2*Rate,0))
}
SPEED=6
if(!Rstick){
    Run=SPEED*2
    Sprint=Run*2
}else{
    Run=SPEED/2
    Sprint=Run/2
}

W=N8|(Yaxis>0)
S=N2|(Yaxis<0)
A=N4|(Xaxis<0)
D=N6|(Xaxis>0)
Space=Plus|But8
Alt=Enter|But7
R=Astrix|HatD
Mouse1=O:keyAttack1()
Mouse2=O:keyAttack2()
#Use=O:keyUse()
Shift=Mouse2|Lstick|Rstick

if(On){
    SinY0=sin(Angle:yaw())
    SinP90=sin(Angle:pitch()+90)
    CosP90=cos(Angle:pitch()+90)
    CosY0=cos(Angle:yaw())
    if(Position:isInWorld()){
        if(W) {Y +=SinY0*SinP90*SPEED*((Shift*Run)+1)
               X +=CosY0*SinP90*SPEED*((Shift*Run)+1)
               Z +=CosP90*SPEED*((Shift*Run)+1)}
        if(S) {Y -=SinY0*SPEED*SinP90*((Shift*Run)+1)
               X -=CosY0*SPEED*SinP90*((Shift*Run)+1)
               Z -=CosP90*SPEED*((Shift*Run)+1)}
        if(A) {Y +=CosY0*SPEED*((Shift*Run)+1)
               X -=SinY0*SPEED*((Shift*Run)+1)}
        if(D) {Y -=CosY0*SPEED*((Shift*Run)+1)
               X +=SinY0*SPEED*((Shift*Run)+1)}
        if(Space) {Z +=1*(Shift*Sprint)+1}
        if(Alt) {Z -=1*(Shift*Sprint)+1}
    }
    if(R){Position=entity():pos()+vec(0,0,100)}
    if(vec(X,Y,Z):isInWorld()){Position=vec(X,Y,Z)}
    if(!Joymode){Direction = OE}else{Direction=Angle:forward()}        

}
#if(holoEntity(1)){holoPos(1,Position)}else{holoCreate(1,Position)}

##Input

CamCon:setNumber("Activated",Activated)
#CamCon:setNumber("Zoom",Zoom)
#CamCon:setNumber("X",X)
#CamCon:setNumber("Y",Y)
#CamCon:setNumber("Z",Z)
#CamCon:setNumber("Pitch",Pitch)
#CamCon:setNumber("Yaw",Yaw)
#CamCon:setNumber("Roll",Roll)
#CamCon:setAngle("Angle",Angle)
CamCon:setVector("Position",Position)
CamCon:setVector("Direction",Direction)
#CamCon:setVector("Velocity",Velocity)
#CamCon:setEntity("Parent",Parent)
#rangerHitEntities(0)
rangerFilter(Parts)
Aim=rangerOffset(15000,Position,Direction):pos()
runOnTick(1)





if(On){
    for(C=1,Tools:count()){ 
        #This is move to vector code 
        Speed=100*(Self:mass()/2)
        Self=Tools[C,entity]
        XYZ=Position+Loc[C,vector]
        Dist=XYZ-Self:pos()
        Vel=Dist/Time
        Self:applyForce(Speed*Dist-Self:vel()*Self:mass())
        
        #This aims the arms
        
        #if(C==5){Grab=+Grabber["Grabbed Entity",entity]:vel()}else{Grab=vec()}
        #Dir = G:pos()-(F:pos()+F:vel()/(!CanDo*10))
        Dir = Self:pos()-(Aim)
        #Q = quat(Dir:toAngle())*qRotation(vec(0,0,1),180) #X
        #Q = quat(Dir:toAngle())*qRotation(vec(0,1,0),-90) #Z
        #Q = quat(Dir:toAngle())*qRotation(vec(0,0,1),90) #Y
        if(C<=3){
            Q = quat(Dir:toAngle())*qRotation(vec(0,0,1),180) #X
        #}elseif(C==4){
         #   Q = quat(Dir:toAngle())*qRotation(vec(0,0,1),0) #-X
        }else{
            Q = quat(Dir:toAngle())*qRotation(vec(0,1,0),-90) #Z
        }
        Self:applyTorque((150*Self:toLocal(rotationVector(Q/quat(Self))+Self:pos())-12*Self:angVelVector())*Self:inertia())
    } 
}
