@name Flying Robotic Eradicator Drone (F.R.E.D.)
@inputs 
#Fred's core
@outputs [XYZ Height]:vector Fire [Target Tar]:array Laser:entity T:entity Master Self Ground
#Networking 
@persist Master Self T:entity
@trigger 
@model models/props_combine/combine_binocular01.mdl
runOnTick(1)
#T=owner() #target
E=entity() #the chip
EC=E:isConstrainedTo()
S=entity() #the thing you want to move
FloatHeight=80 #how high does it hover
Hostile=0 #Looking at dormant drones causes them to attack

timer("Pathfind",5000)  #How often Do we search for the target?
if(clk("Pathfind")){Search=1}


if(EC){EC:setMass(1)}
Com="FRED"
Get="get"
Brk="<"
Menu="menu"
PK="PK"
NK="NK"

#Hostility Mode
if(Hostile&!T){
    Pl=players()
    for(C=1,Pl:count()){
        AimE=Pl[C,entity]:aimEntity()
        if(!(EC:isFrozen()|E:isFrozen())|(AimE==E)|(AimE==EC)){
            T=Pl[C,entity]
            
        }
    }
}
#End of Hostility Mode

gSetGroup("Network") #give your unit network a unique name.
if(duped()){reset()}
runOnLast(1)
Diag=0 #this prints network reports to chat
NetMax=20 #this is the maximum number of networked units, surplus units are removed automatically.
ID="ID"
Erase=0 #set this to 1 to erase the entire unit network, (diagnostic only)
MasterInterval=500 #frequency units check for updates on who is the master unit.
HiveMind=1 #1 enables a client/server AKA master/slave mode (used for hiveminds.) 0 limits use to simple network ID generation.
Brk="<" #separation or "break" character, used to create a unique string to help mass search the network table with.
if(!Self){
    EID=entity():id()
    EIDS=toString(EID)
    ScanN=gGetStr(ID) 
    NetT=glonDecodeTable(ScanN) 
    
    for(C=1,NetMax){if(!ScanN:find(Brk+C)){Self=C break}} #locate a hole and take that slot
    if(HiveMind){
        for(C=1,NetMax){if(ScanN:find(Brk+C)){Master=C break}} #locate first unit and mark that unit
        if(!Master){Master=Self}
    }
    if(!Self){
        if(Diag){print("Self Destructing Excess Clones!")} 
        selfDestructAll()
    }
    NetT[Brk+Self,number]=EID
    if(Self==Master&HiveMind){gSetNum("master",Self)}
    gSetStr(ID,glonEncode(NetT))
    if(Diag){print("Self="+Self)} #you can remove this if you want it's diagnostic
}
if(last()){
    NetT=glonDecodeTable(gGetStr(ID))
    NetT:remove(Brk+Self)
    if(Self==Master&HiveMind){ #passing the torch
        for(C=1,NetMax){
            if(NetT[Brk+C,number]){
                gSetNum("master",C)
                Master=0
                if(Diag){print("Unit "+Self+" is passing leadership to "+C)}
                break
            }
        }
        if(Master){ #if there is no unit to pass the torch to
            gSetNum("master",0) 
            if(Diag){print("Unit "+Self+" was unable to pass leadership.")}
        }
    }
    gSetStr(ID,glonEncode(NetT))
    if(Diag){print("Unit "+Self+" Deleted")} #diagnostic non critical
}
if(Erase){gSetStr(ID,"")}
#periodically checks to see if the master has passed the torch
if(HiveMind){
    timer("master",MasterInterval)
    if(clk("master")){Master=gGetNum("master")}
    
    #Add your own targeting code below
    if(findCanQuery()){
        #This collpases the unit spread and organizes their orders.        
        NetT=glonDecodeTable(gGetStr(ID))
        Units=array() 
        Orders=table()
        for(C=1,NetMax){if(NetT[Brk+C,number]){Units:pushNumber(C)}} #collapse the spread of units on the network 
        Orders=invert(Units) #we want the collapsed units indexed by self ID
        
        if(Master==Self){ #actions for the network master
############your find functions here################

            findInSphere(entity():pos(),50000) #demo only
            findSortByDistance(entity():pos())
            findIncludeClass("player")
            #findExcludeEntity(owner())
            Target=findToArray()
            #Target=array(noentity())
#############then let this command the hive#########
            #Target=players()
            
            gSetStr("Target",glonEncode(Target)) #issues orders to slaves
            
        }else{Target=glonDecode(gGetStr("Target"))} #all slaves take orders
        #if(!T){ 
        
            T=Target[Orders[toString(Self),number],entity] #if there are more units than targets the surplus units are idle.
        #}
    
    }
}
#End of D-Link Network Code

#Hover ranger
rangerFilter(E)
Ground=rangerOffset(20000,E:pos(),vec(0,0,-1)):position():z()

TD=T&(T:pos():distance(S:pos())>200)
Height=vec(E:pos():x()*!TD,E:pos():y()*!TD,!TD*Ground+FloatHeight)

#set height to 
XYZ=Height+(T:pos())*TD

Pos = E:toWorld(vec(0,0,0))
Dir = S:pos()-(T:shootPos()+T:vel()/(10))
AltAng = E:angles()
Q = quat(Dir:toAngle())*qRotation(vec(0,0,1),180)
S:applyTorque((150*S:toLocal(rotationVector(Q/quat(S))+S:pos()) - 12*S:angVelVector())*S:inertia())
Speed=3*(S:mass()/4)
S:applyForce(Speed*(XYZ-S:pos())-(S:vel()/2)*S:mass())

#Laser Sight
Laser=rangerOffset(4000,E:pos(),E:forward()):entity()
Fire=T&((Laser==T)|((T:aimEntity()==E)|(T:aimEntity()==EC)))&!(EC:isFrozen()|E:isFrozen())&!(E:isPlayerHolding()|EC:isPlayerHolding())



#ifdef entity:shootTo(vector,number,number,number)
    if(Fire){E:shootTo(E:forward(),0,100,1)}
#endif
