@name Reds Tracks
@inputs [La Ra]:wirelink
@outputs Off
@persist [L R]:array Sprmod RSprmod Width Thickness Color:vector Roadwheelmod Stretch Selected Roadwheelnumber M TUV:vector Roadwheelsize Interval Secondtrack Debug Rm Slacktrack Timer Scm
@persist [Points Pointsr]:array Vel:vector Rend Int
#v6.1 update - Mr. White foudn a way to save some computational effort, so I redirected it into increasing update speed, he should be proud.  Let's all be proud of Mr. White.

#This chip is provided courtesy of Fast Red Snail (FRS) and Redreaper.
##################################################  ##################################################  ###################################
#USING THIS SHOULD BE FUCKSIMPLE
#Make sure your wheels on each side are in a line, not staggered
#Use an adv e marker to select one side, from the FRONT to the BACK, all the wheels that are tracked.  That includes idlers and sprockets.
#If you are making a snowmobile, or need individual tracks, use only the LEFT array--it will AUTO DETECT TO IGNORE RIGHT
#Minor adjustments can be made below as shown, read the annotations!
##################################################  ##################################################  ###################################

#ignore this segment
Vel = entity():pos()
if($Vel:length() ==0) {} else {runOnChat(1)}
if(dupefinished()) {reset()}
if(first()) {
#Ok, now work on what's below.


##################################################  ##################################################  ###################################
############ALTER THESE#############################################  ##################################################  ########################################
        Slacktrack = 0 #Does it have the tracks droop along the top?
        Sprmod = 1 #Fine-tune the size of the front sprocket - 0 is perfect for Sprops
        RSprmod = 1 #Fine-tune the size of the rear sprocket - 0 is perfect for sprops
        Width = 1.25 #How wide the tracks are.  1 is default.  0.75 would be a teeny tankette, 1.25 a bulldozer.
        Thickness = 0.15 #The thickness of the actual track, lower values appear more fragile.  Keep it between 0.1 and 0.3, usually 0.15 is enough. 
        Color = vec(125) #Color the treads
        Roadwheelmod = -1.75 #Fine-tune the size of roadwheels - 0 is perfect for sprops.
##################################################  ##################################################  ###################################
##################################################  ##################################################  ###################################
        #nochange ANYTHING below this line.
        Sprmod = Sprmod -1 #Added to sync with sprops sizes, remove this line to revert to old functionality.
        RSprmod = RSprmod -1 #No bitches it's not "legacy" or "classic", it's just HOW IT FUCKING WAS.  I HATE when it's "legacy" or "retro".  FUck you all.
        Roadwheelmod = Roadwheelmod-0.5 #More shit I modded so it's in sync with sprops.  Srsly sprops tank wheels are monstrously good.
        Skin = entity():getMaterial()
        L = La:array("Entities") #Note: if you want to just use arrays, and not an adv e marker, just add L and R as array inputs and remove these lines.
        R = Ra:array("Entities")
        M = 0.084 #should be able to ignore, scaling for track connection, 0.084 seems to be precise
        Uhm = Thickness*12 #trackrun above ground
        TUV = vec(0,0,(Thickness*1.5)) #Thickness up multiplier.
        Fore = entity():forward()
        Up = entity():up()
        #Detect connected tracks
        if(R:entity(1):isValid()) {Secondtrack = 1}
        #Detect roadwheel count
        Roadwheelnumber = 1
        Roadwheelsize = (L:entity(2):boxSize():x() /2) + Roadwheelmod 
        while(L:entity(Roadwheelnumber+1):isValid()) {Roadwheelnumber = Roadwheelnumber+1}
        Rm = Roadwheelnumber#Kept as a backup as a seprate variable
        Int = clamp(150 + (((Roadwheelnumber-5)*(Roadwheelnumber>5))*(10+(Slacktrack*5))),150,300) #Increasing variable here, it slows the chip's repeat speed slightly with more roadwheels and such.
        #Size for sprockets
        Sprsize = (L:entity(1):boxSize():x()/2) + Sprmod 
        RSprsize = (L:entity(Roadwheelnumber):boxSize():x()/2) + RSprmod 
        Points:setVector(1,entity():toLocal(L:entity(1):massCenter() + (Fore * (Sprsize*0)) + (Up*(Sprsize*1))))
        Points:setVector(2,entity():toLocal(L:entity(1):massCenter() + (Fore * (Sprsize*0.9)) + (Up*(Sprsize*0.5))))
        Points:setVector(3,entity():toLocal(L:entity(1):massCenter() + (Fore * (Sprsize*0.9)) + (Up*-(Sprsize*0.5))))
        Points:setVector(4,entity():toLocal(L:entity(1):massCenter() + (Fore * (Sprsize*0)) + (Up*-(Sprsize*1)) - (Up*Thickness*10)
))
        Points:setVector(Roadwheelnumber+1,entity():toLocal(L:entity(Roadwheelnumber):massCenter() + (Fore * (-RSprsize*0)) + (Up*(RSprsize*1))))
        Points:setVector(Roadwheelnumber+2,entity():toLocal(L:entity(Roadwheelnumber):massCenter() + (Fore * (-RSprsize*0.9)) + (Up*(RSprsize*0.5))))
        Points:setVector(Roadwheelnumber+3,entity():toLocal(L:entity(Roadwheelnumber):massCenter() + (Fore * (-RSprsize*0.9)) + (Up*-(RSprsize*0.5))))
        Points:setVector(Roadwheelnumber+4,entity():toLocal(L:entity(Roadwheelnumber):massCenter() + (Fore * (-RSprsize*0)) + (Up*-(RSprsize*1)) - (Up*Thickness*10)))
        if(Secondtrack) {Pointsr:setVector(1,entity():toLocal(R:entity(1):massCenter() + (Fore * (Sprsize*0)) + (Up*(Sprsize*1))))
        Pointsr:setVector(2,entity():toLocal(R:entity(1):massCenter() + (Fore * (Sprsize*0.9)) + (Up*(Sprsize*0.5))))
        Pointsr:setVector(3,entity():toLocal(R:entity(1):massCenter() + (Fore * (Sprsize*0.9)) + (Up*-(Sprsize*0.5))))
        Pointsr:setVector(4,entity():toLocal(R:entity(1):massCenter() + (Fore * (Sprsize*0)) + (Up*-(Sprsize*1)) - (Up*Thickness*10)))
        Pointsr:setVector(Roadwheelnumber+1,entity():toLocal(R:entity(Roadwheelnumber):massCenter() + (Fore * (-RSprsize*0)) + (Up*(RSprsize*1))))
        Pointsr:setVector(Roadwheelnumber+2,entity():toLocal(R:entity(Roadwheelnumber):massCenter() + (Fore * (-RSprsize*0.9)) + (Up*(RSprsize*0.5))))
        Pointsr:setVector(Roadwheelnumber+3,entity():toLocal(R:entity(Roadwheelnumber):massCenter() + (Fore * (-RSprsize*0.9)) + (Up*-(RSprsize*0.5))))
        Pointsr:setVector(Roadwheelnumber+4,entity():toLocal(R:entity(Roadwheelnumber):massCenter() + (Fore * (-RSprsize*0)) + (Up*-(RSprsize*1)) - (Up*Thickness*10)))
        }
        Scm = (Thickness*-10)+(Roadwheelsize)
        Rend = Roadwheelnumber+50
        #This has to be run wit heach change
        Upscaler = (Up*((Thickness*-10)+(Roadwheelsize)))
        X = 21#Front sprocket construction
        while(X<24) {
            P1 = entity():toWorld(Points:vector(X-19))
            P2 = entity():toWorld(Points:vector(X-20))
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(X)
            holoMaterial(X,Skin)
            holoColor(X,Color)
            holoPos(X,(P1+P2)/2)
            holoAng(X,entity():toWorld(ang(Atan,0,0)))
            holoScale(X,vec(((P1-P2):length())*M,Width,Thickness))
            X = X+1}
        
        X = 31#Rear sprocket construction
        while(X<34) {
            P1 = entity():toWorld(Points:vector((X-29)+Roadwheelnumber))
            P2 = entity():toWorld(Points:vector((X-30)+Roadwheelnumber))
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(X)
            holoMaterial(X,Skin)
            holoColor(X,Color)
            holoPos(X,(P1+P2)/2)
            holoAng(X,entity():toWorld(ang(Atan,0,0)))
            holoScale(X,vec(((P1-P2):length())*M,Width,Thickness))
            X = X+1}
            
            #Second track, runs holo + 50
            if(Secondtrack) {
        X = 71#Front sprocket construction
        while(X<74) {
            P1 = entity():toWorld(Pointsr:vector(X-69))
            P2 = entity():toWorld(Pointsr:vector(X-70))
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(X)
            holoMaterial(X,Skin)
            holoColor(X,Color)
            holoPos(X,(P1+P2)/2)
            holoAng(X,entity():toWorld(ang(Atan,0,0)))
            holoScale(X,vec(((P1-P2):length())*M,Width,Thickness))
            X = X+1}
            
        X = 81#Rear sprocket construction
        while(X<84) {
            P1 = entity():toWorld(Pointsr:vector((X-79)+Roadwheelnumber))
            P2 = entity():toWorld(Pointsr:vector((X-80)+Roadwheelnumber))
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(X)
            holoMaterial(X,Skin)
            holoColor(X,Color)
            holoPos(X,(P1+P2)/2)
            holoAng(X,entity():toWorld(ang(Atan,0,0)))
            holoScale(X,vec(((P1-P2):length())*M,Width,Thickness))
            X = X+1}
        }
            
        ###########
        if(Slacktrack ==0) {
            P1 = entity():toWorld(Points:vector(1))
            P2 = entity():toWorld(Points:vector(Roadwheelnumber+1))
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(99)
            holoMaterial(99,Skin)
            holoColor(X,Color)
            holoPos(99,(P1+P2)/2)
            holoAng(99,entity():toWorld(ang(Atan,0,0)))
            holoScale(99,vec((P1-P2):length()*0.084,Width,Thickness))
            if(Secondtrack) {
                P1 = entity():toWorld(Pointsr:vector(1))
            P2 = entity():toWorld(Pointsr:vector(Roadwheelnumber+1)  )
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(98)
            holoMaterial(98,Skin)
            holoColor(X,Color)
            holoPos(98,(P1+P2)/2)
            holoAng(98,entity():toWorld(ang(Atan,0,0)))
            holoScale(98,vec((P1-P2):length()*0.084,Width,Thickness))
            }
        }
        #Adding slack track
        else{
   X = 3
#First wheel with stretch and adjustments
P1 = entity():toWorld(Points:vector(1))
            P2 = L:entity(2):pos()+Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(102)
            holoPos(102,(P1+P2+TUV)/2)
            holoAng(102,entity():toWorld(ang(Atan,0,0)))
            holoScale(102,vec(((P1-P2):length())*M,Width,Thickness))
            
        while(X<(Rm)) {
            P1 = L:entity(X-1):pos()+Upscaler
            P2 = L:entity(X):pos()+Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(X+100)
            holoPos(X+100,(P1+P2+TUV)/2)
            holoAng(X+100,entity():toWorld(ang(Atan,0,0)))
            holoScale(X+100,vec(((P1-P2):length())*M,Width,Thickness))
            X = X+1
        }
        if(X==Rm) {
        P1 = entity():toWorld(Points:vector(Roadwheelnumber+1))
            P2 = L:entity(Roadwheelnumber-1):pos()+Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(Roadwheelnumber+100)
            holoPos(Roadwheelnumber+100,(P1+P2+TUV)/2)
            holoAng(Roadwheelnumber+100,entity():toWorld(ang(Atan,0,0)))
            holoScale(Roadwheelnumber+100,vec(((P1-P2):length())*M,Width,Thickness))
        }
if(Secondtrack) {
     X = 3
#First wheel with stretch and adjustments
P1 = entity():toWorld(Pointsr:vector(1))
            P2 = R:entity(2):pos()+Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(152)
            holoPos(152,(P1+P2+TUV)/2)
            holoAng(152,entity():toWorld(ang(Atan,0,0)))
            holoScale(152,vec(((P1-P2):length())*M,Width,Thickness))
            
        while(X<(Rm)) {
            P1 = R:entity(X-1):pos()+Upscaler
            P2 = R:entity(X):pos()+Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(X+150)
            holoPos(X+150,(P1+P2+TUV)/2)
            holoAng(X+150,entity():toWorld(ang(Atan,0,0)))
            holoScale(X+150,vec(((P1-P2):length())*M,Width,Thickness))
            X = X+1
        }
        if(X==Rm) {
        P1 = entity():toWorld(Pointsr:vector(Roadwheelnumber+1)  )
            P2 = R:entity(Roadwheelnumber-1):pos()+Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoCreate(Roadwheelnumber+150)
            holoPos(Roadwheelnumber+150,(P1+P2+TUV)/2)
            holoAng(Roadwheelnumber+150,entity():toWorld(ang(Atan,0,0)))
            holoScale(Roadwheelnumber+150,vec(((P1-P2):length())*M,Width,Thickness))
        } 
    
}
         
           
        }    
    #This is th stuff that'll do main tracks
        X = 1
        while(X<(Roadwheelnumber+1)) {
            P1 = (L:entity(X-1):pos()-Upscaler)
            P2 = L:entity(X):pos()-Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            #New line
            holoCreate(X)
            holoMaterial(X,Skin)
            holoColor(X,Color)
            #End new lines
            holoPos(X,(P1+P2+TUV)/2)
            holoAng(X,entity():toWorld(ang(Atan,0,0)))
            holoScale(X,vec(((P1-P2):length())*M,Width,Thickness))
            X = X+1
        }
    if(Secondtrack) {
      X = 1
        while(X<(Roadwheelnumber+1)) {D = (X+50)
            P1 = (R:entity(X-1):pos()-Upscaler)
            P2 = R:entity(X):pos()-Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            #New line
            holoCreate(D)
            holoMaterial(D,Skin)
            holoColor(D,Color)
            #End new lines
            holoPos(D,(P1+P2+TUV)/2)
            holoAng(D,entity():toWorld(ang(Atan,0,0)))
            holoScale(D,vec(((P1-P2):length())*M,Width,Thickness))
            X = X+1
        }   
    }    
    holoDelete(1)
    holoDelete(51)
    
        Debug = 1 #Hurr
        
#[##pet code kept in its cage, lookin' all cute as reference material
AxisA1 = Master:toLocalAxis(A0-A1)
AtanA2 = atan(-AxisA2:z(), AxisA2:x())
holoPos(1,(A0+A1+TUV)/2))
holoAng(1,Master:toWorld((ang(AtanA1,0,180)+AMod))  )
holoScale(11,vec(((B0-B1):length())*M,Width,Thickness))
]##
X = 0
while(X<250) {holoParent(X,entity()) 
    holoColor(X,Color)
    holoMaterial(X,Skin)
X = X+1}
} ###END all of the if-first spawning

if (chatClk(owner())) {
    Chat = owner():lastSaid():lower()
    if(Chat == "tracks off") {Off = 1
        Slackmod = 333}
    if(Debug) {Split  = Chat:sub(1,Chat:length()):explode(" ")
    Key = Split:string(1):lower()
    if(Key == "link") {
    holoColor(Selected,Color)
    Selected = Split:string(2):toNumber()
    hideChat(1)
    holoColor(Selected,vec(255,0,0))
    hint("Link "+Selected+" Valid "+holoEntity(Selected):isValid(),3)}
    elseif(Key == "wheels") {hint("Wheels: "+Roadwheelnumber,3)}
    }
    elseif(Chat == "tracks on") {X = 0
        hint("Resetting...",3)
        while(X<300) {holoDelete(X)
        X = X+1}
    reset()}
}

if(!Off) {
Upscaler = (entity():up()*(Scm))
   X = 3
#First wheel with stretch and adjustments
P1 = entity():toWorld(Points:vector(4))
            P2 = L:entity(2):pos()-Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoPos(2,(P1+P2+TUV)/2)
            A = entity():toWorld(ang(Atan,0,0))
            S = vec(((P1-P2):length())*M,Width,Thickness)
            holoAng(2,A)
            holoScale(2,S)
            if(Slacktrack) {P1 = entity():toWorld(Points:vector(1))
            P2 = L:entity(2):pos()+Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoPos(102,(P1+P2+TUV)/2)
            holoAng(102,entity():toWorld(ang(Atan,0,0)))
            holoScale(102,vec(((P1-P2):length())*M,Width,Thickness))}
            
        while(X<(Rm)) {
            P1 = L:entity(X-1):pos()-Upscaler
            P2 = L:entity(X):pos()-Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoPos(X,(P1+P2+TUV)/2)
            holoAng(X,entity():toWorld(ang(Atan,0,0)))
            holoScale(X,vec(((P1-P2):length())*M,Width,Thickness))
            if(Slacktrack) {
            holoPos(X+100,(P1+P2+(Upscaler*4)+TUV)/2)
            holoAng(X+100,entity():toWorld(ang(Atan,0,0)))
            holoScale(X+100,vec(((P1-P2):length())*M,Width,Thickness))}
            X = X+1
        }
        if(X==Rm) {
        P1 = entity():toWorld(Points:vector(Roadwheelnumber+4))
            P2 = L:entity(Roadwheelnumber-1):pos()-Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoPos(Roadwheelnumber,(P1+P2+TUV)/2)
            holoAng(Roadwheelnumber,entity():toWorld(ang(Atan,  0,0)))
            holoScale(Roadwheelnumber,vec(((P1-P2):length())*M,Width,Thickness))
            if(Slacktrack) {P1 = entity():toWorld(Points:vector(Roadwheelnumber+1))
            P2 = L:entity(Roadwheelnumber-1):pos()+Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoPos(Roadwheelnumber+100,(P1+P2+TUV)/2)
            holoAng(Roadwheelnumber+100,entity():toWorld(ang(Atan,0,0)))
        holoScale(Roadwheelnumber+100,vec(((P1-P2):length())*M,Width,Thickness))}
        }
        
if(Secondtrack) {   X = 3
#First wheel with stretch and adjustments
P1 = entity():toWorld(Pointsr:vector(4))
            P2 = R:entity(2):pos()-Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoPos(52,(P1+P2+TUV)/2)
            holoAng(52,entity():toWorld(ang(Atan,0,0)))
            holoScale(52,vec(((P1-P2):length())*M,Width,Thickness))
            if(Slacktrack) {P1 = entity():toWorld(Pointsr:vector(1))
            P2 = R:entity(2):pos()+Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoPos(152,(P1+P2+TUV)/2)
            holoAng(152,entity():toWorld(ang(Atan,0,0)))
            holoScale(152,vec(((P1-P2):length())*M,Width,Thickness))}
            
        while(X<(Rm)) {
            P1 = R:entity(X-1):pos()-Upscaler
            P2 = R:entity(X):pos()-Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoPos(X+50,(P1+P2+TUV)/2)
            holoAng(X+50,entity():toWorld(ang(Atan,0,0)))
            holoScale(X+50,vec(((P1-P2):length())*M,Width,Thickness))
            if(Slacktrack) {
            holoPos(X+150,(P1+P2+(Upscaler*4)+TUV)/2)
            holoAng(X+150,entity():toWorld(ang(Atan,0,0)))
            holoScale(X+150,vec(((P1-P2):length())*M,Width,Thickness))}
            X = X+1
        }
        if(X==Rm) {
        P1 = entity():toWorld(Pointsr:vector(Roadwheelnumber+4)  )
            P2 = R:entity(Roadwheelnumber-1):pos()-Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoPos(Rend,(P1+P2+TUV)/2)
            holoAng(Rend,entity():toWorld(ang(Atan,0,0)))
            holoScale(Rend,vec(((P1-P2):length())*M,Width,Thickness))
            if(Slacktrack) {P1 = entity():toWorld(Pointsr:vector(Roadwheelnumber+1)  )
            P2 = R:entity(Roadwheelnumber-1):pos()+Upscaler
            Axis = entity():toLocalAxis(P1-P2)
            Atan = atan(-Axis:z(),Axis:x())
            holoPos(Roadwheelnumber+150,(P1+P2+TUV)/2)
            holoAng(Roadwheelnumber+150,entity():toWorld(ang(Atan,0,0)))
            holoScale(Roadwheelnumber+150,vec(((P1-P2):length())*M,Width,Thickness))}
            }
    }
}          
