@name constructor_os
@inputs LandingPlate:entity TurretE:entity
@persist RandomSounds:array
 
##NAVIGATION
@inputs  ModeT:string Start Clear
@outputs Gear Shield [Mode WPMODE]:string WayPointIndex
@persist Height Waypoints:array Dis
 
##WEAPONRY
@inputs TargetMode TargetClass:string Fire TargetClear TargetFind
@outputs Target:entity TarPos:vector R:entity Distance
 
if(first()){
    Height = 210
    Mode = "bunker"
    WayPointIndex = 1
    LandingPlate:propNotSolid(0)
   
    RandomSounds[1,string] = "npc/strider/striderx_pain8.wav"
    RandomSounds[2,string] = "npc/strider/striderx_pain2.wav"
    RandomSounds[3,string] = "npc/strider/striderx_alert6.wav"
    RandomSounds[4,string] = "npc/strider/strider_hunt1.wav"
    RandomSounds[5,string] = "npc/strider/striderx_alert4.wav"
}
 
if(dupefinished()){
    reset()
}
 
interval(50)
runOnChat(1)
 
E = entity():isWeldedTo()
 
if(chatClk(owner())){
    LastSaid = owner():lastSaid():explode(" ")
    if(LastSaid[1,string]:lower() == "mode"){
        hideChat(1)
        Mode = LastSaid[2,string]:lower()
    }
    if(LastSaid[1,string]:lower() == "clear"){
        hideChat(1)
        for(I=1, Waypoints:count()){
            holoDelete(I)
        }
        Waypoints = array()
    }
}
 
if(changed(Clear) & Clear){
    for(I=1, Waypoints:count()){
        holoDelete(I)
    }
   
    Waypoints = array()
    WayPointIndex = 1
}
 
if(changed(ModeT)){
    Mode = ModeT
}
 
if(changed(Mode)){
    ActiveFire = 0
     
    if(Mode != "shield"){
        E:soundPlay(1,5,RandomSounds[round(random(1,RandomSounds:count())),string])
        soundPitch(1,145)
       
        E:soundPlay(2,0,"ambient/machines/lab_loop1.wav")
        E:soundPlay(3,0,"ambient/machines/city_ventpump_loop1.wav")
        soundPitch(3,145)
       
        TarPos = vec(0,0,0)
    }
   
    if(Mode == "flight"){
        WPMODE = ""
        Gear = 0
        Shield = 0
        Height = 150
        LandingPlate:propNotSolid(1)
    }
    if(Mode == "bunker"){
        Gear = 1
        LandingPlate:propNotSolid(0)
    }
    if(Mode == "shield"){
        Shield = 1
    }
    if(Mode == "wp"){
        Height = 150
        Gear = 0
        Shield = 0
        LandingPlate:propNotSolid(1)
    }
    if(Mode == "route"|Mode == "patrol"){
        WayPointIndex = 1
        Waypoints = array()
    }
}
 
soundPitch(2, E:vel():length()/10+45)
 
## APPLYTORQUE ##
 
if(Mode == "flight" | Mode == "bunker" | Mode == "wp"){
    RL = 250/rangerOffset(250, E:toWorld(vec(50,50,0)), E:forward() - E:right()):distance()
    RR = 250/rangerOffset(250, E:toWorld(vec(50,-50,0)), E:forward() + E:right()):distance()
   
    Yaw = clamp((RL-RR)*110,-90,90)
   
    if(WPMODE == ""){
        Ta = owner():pos()
        TA = (Ta - E:pos()):toAngle():yaw()
        Dis = vec2(Ta):distance(vec2(E:pos()))
       
        if( Dis > 500){
            if(Mode == "bunker"){ Ang = ang(0,E:angles():yaw() + (-E:angVel():yaw()/15 - Yaw),0) }else{ Ang = ang(0,(-E:angVel():yaw()/15 - Yaw+TA),0) }  
        }
        else{
            Ang = ang(0,E:angles():yaw(),0)
        }
    }
   
    if(WPMODE == "route" | WPMODE == "patrol"){
        Ta = Waypoints[WayPointIndex,vector]
        TA = (Ta - E:pos()):toAngle():yaw()
        Dis = vec2(Ta):distance(vec2(E:pos()))
        if(changed(Dis < 100) & Dis < 100){
            WayPointIndex += 1
            if(WayPointIndex > Waypoints:count()){
                if(WPMODE == "route"){
                    Mode = "bunker"
                    WPMODE = ""
                }
                if(WPMODE == "patrol"){
                    WayPointIndex = 1
                }
            }
        }
        Ang = ang(0,(-E:angVel():yaw()/15 - Yaw) + TA,0)
    }
   
    V = E:toLocal(rotationVector(quat(Ang)/quat(E))+E:pos())
    E:applyTorque((50*V - 15*E:angVelVector())*E:inertia())
}
 
## APPLYFORCE ##
 
rangerHitEntities(0)
rangerHitWater(1)
R1 = rangerOffset(500, E:pos(), vec(0,0,-1))
 
if(Mode == "flight" | Mode == "wp"){
    He = vec(0,0,Height - R1:distance())
    Pa = -E:vel()*0.25
   
    if(WPMODE == ""){
        if(Dis > 500){ Ac = E:forward()*40 }else{ Ac = E:forward()*0 }
    }
    if(WPMODE == "route" | WPMODE == "patrol"){
        if(Dis > 100){ Ac = E:forward()*40 }else{ Ac = E:forward()*0 }
    }
   
    E:applyForce((He + Pa + Ac) * E:mass())
}
 
if(Mode == "bunker"){
    Height = clamp(Height-1,100,150)
    if(Height == 100){
        Mode = "shield"
    }
   
    He = vec(0,0,Height - R1:distance())
    Pa = -E:vel()*0.5
       
    E:applyForce((He + Pa) * E:mass())
}
 
if(Mode == "route" | Mode == "patrol"){
    WayPS = owner():keyAttack2()
    if(changed(WayPS) & WayPS){
        Waypoints[WayPointIndex,vector] = owner():aimPos()
        holoCreate(WayPointIndex, owner():aimPos(), vec(1,1,1), ang(0,0,90))
        holoModel(WayPointIndex, "models/props_lab/labpart.mdl")
        holoEntity(WayPointIndex):soundPlay(10,2,"items/smallmedkit1.wav")
        WayPointIndex += 1
    }
    if(changed(Start)|chatClk(owner())){
        if(Start | lastSaid():lower() == "start"){
            hideChat(1)
           
            if(Waypoints:count() > 0){
                for(I=1, Waypoints:count()){
                    holoDelete(I)
                }
   
                WayPointIndex = 1
                WPMODE = Mode
                Mode = "wp"
            }
            else{
                hint("[ERROR]",5)
            }
        }
    }
}
 
## GUIDED MISSILES ##
 
if(Mode == "shield"){
    RMB = owner():keyAttack2()
    ALT = owner():keyWalk()
   
    if(!R){
        if(TargetFind){
            if(changed(RMB) & RMB){
                if(TargetMode == 1){
                    findInCone(owner():shootPos(),owner():eye(),99999,15)
                    findClipToClass(TargetClass)
                    Target = findClosest(owner():pos())
                   
                    if(Target:isValid()){ owner():soundPlay(10,1,"npc/scanner/combat_scan1.wav") }
                }
                if(TargetMode == 2){
                    findExcludePlayer(owner())
                    findByClass(TargetClass)
                    Target = findClosest(E:pos())
                   
                    if(Target:isValid()){ owner():soundPlay(10,1,"npc/scanner/combat_scan1.wav") }
                }
                if(TargetMode == 3){
                    Target = noentity()
                    TarPos = owner():aimPos()
                    owner():soundPlay(10,1,"npc/scanner/combat_scan1.wav")
                }
            }
        }
    }
   
    if(TargetMode != 3){ TarPos = Target:pos() }
   
    if(!R){
        if(changed(Fire) & Fire){
            if(TargetMode == 1 | TargetMode == 2){
                if(Target:isValid() & TarPos != vec(0,0,0)){
                    R = propSpawn("models/props_phx/torpedo.mdl", TurretE:toWorld(vec(200,0,0)), TurretE:angles(), 0)
                    R:setTrails(10,200,2,"trails/smoke",vec(255,255,255),155)
                    E:soundPlay(10,1,"npc/env_headcrabcanister/launch.wav")
                }
            }
            if(TargetMode == 3){
                if(TarPos != vec(0,0,0)){
                    R = propSpawn("models/props_phx/torpedo.mdl", TurretE:toWorld(vec(200,0,0)), TurretE:angles(), 0)
                    R:setTrails(10,200,2,"trails/smoke",vec(255,255,255),155)
                    E:soundPlay(10,1,"npc/env_headcrabcanister/launch.wav")
                }
            }
        }
    }
   
    if(R:isValid()){
        if(TargetMode == 1 | TargetMode == 2){
            R:applyForce(R:forward()*R:mass()*1300 + vec(0,0,1)*R:mass()*10-R:vel()*R:mass()*0.4)
            Distance = Target:pos():distance(R:pos())
           
            Rate = 3
            Vel = Target:vel():length()
           
            if(Vel > 1){
                Lead = (Target:vel()*Distance/Vel/Rate)
            }
           
            Ang = ((Target:pos()+Lead)-R:pos()):toAngle()
            V = R:toLocal(rotationVector(quat(Ang)/quat(R))+R:pos())
            R:applyTorque((50*V - 15*R:angVelVector())*R:inertia())
       
            if(Distance<500 | TarPos == vec(0,0,0)){R:propBreak()}
        }
        if(TargetMode == 3){
            R:applyForce(R:forward()*R:mass()*1300 + vec(0,0,1)*R:mass()*10-R:vel()*R:mass()*0.4)
            Distance = vec2(TarPos):distance(vec2(R:pos()))
            OFZ = vec(0,0,clamp(Distance/2,0,5000))
           
            Ang = ((TarPos+OFZ)-R:pos()):toAngle()
            V = R:toLocal(rotationVector(quat(Ang)/quat(R))+R:pos())
            R:applyTorque((50*V - 15*R:angVelVector())*R:inertia())
       
            if(R:pos():distance(TarPos) < 200 | TarPos == vec(0,0,0)){R:propBreak()}
        }
    }
}
 
if(changed(TargetClear) & TargetClear){ TarPos = vec(0,0,0), Target = noentity(), E:soundPlay(1,1,"garrysmod/content_downloaded.wav") }
