@name Chaqua Mach Attempt 3
@inputs CE:entity
@persist Ntpl [E P]:entity Aim:vector [OA AA A1 A2]:angle [H]:table PWrk CWrk Gs GsX GsY Ht C:wirelink N
@persist FI
@persist [F1O F1C F1N F1A F1V]:vector F1P F1W
@persist [F2O F2C F2N F2A F2V]:vector F2P F2W
@model models/hunter/blocks/cube1x1x05.mdl

interval(70)

if(first())
{
    function vector bezierC(Src:vector,End:vector,CurvePoint:vector,Progress:number)
    {
        return mix(mix(Src,CurvePoint,Progress),mix(CurvePoint,End,Progress),Progress)
    }
    
    function number cosine(A, B, C)
    {
        return acos((A^2 + B^2 - C^2) / (2*A*B))
    }
    
    function ik(L1,L2,Hip:entity,Foot:entity,Chassis:entity,I1,I2)
    {    
        local Axis = Chassis:toLocalAxis(Foot:pos() - Hip:pos())
        local Angle = Axis:toAngle():setRoll(-bearing(Hip:pos(), Chassis:angles(), Foot:pos()))
        local Dist = min(Axis:length(), L1 + L2)
        local Quat = quat(Angle) * qRotation(vec(0,90 + cosine(Dist, L1, L2),0))
        
        holoAng(I1, Chassis:toWorld(Quat:toAngle()))
        holoAng(I2, Hip:toWorld(ang(cosine(L2, L1, Dist) + 180, 0, 0)))
    }
    
    Ntpl = 70 / (500 / 33)
    
    E = entity()
    E:setMass(50000)
    E:propFreeze(0)
    E:setColor(0,0,0,0)
    
    AA = E:angles()
    
    holoCreate(100, E:toWorld(vec(0, 32, 0)), vec(1), E:toWorld(ang()))
    holoParent(100, E)
    
    holoCreate(101, E:toWorld(vec(0, -32, 0)), vec(1), E:toWorld(ang()))
    holoParent(101, E)
    
    holoCreate(1000)
    holoAlpha(1000, 0)
    holoCreate(1001)
    holoAlpha(1001, 0)
    
    holoCreate(1, holoEntity(100):toWorld(vec(0, 0, 70)), vec(), holoEntity(100):toWorld(ang()))
    holoParent(1, 100)
    holoCreate(2, holoEntity(1):toWorld(vec(0, 0, 70)), vec(1), holoEntity(100):toWorld(ang()))
    holoParent(2, 1)
    
    holoCreate(3, holoEntity(100):toWorld(vec(0, 0, 35)), vec(1, 1, 35/6), holoEntity(100):toWorld(ang()))
    holoParent(3, 100)
    holoCreate(4, holoEntity(1):toWorld(vec(0, 0, 35)), vec(1, 1, 35/6), holoEntity(100):toWorld(ang()))
    holoParent(4, 1)
    
    holoCreate(5, holoEntity(101):toWorld(vec(0, 0, 70)), vec(), holoEntity(101):toWorld(ang()))
    holoParent(5, 101)
    holoCreate(6, holoEntity(5):toWorld(vec(0, 0, 70)), vec(1), holoEntity(1001):toWorld(ang()))
    holoParent(6, 5)
    
    holoCreate(7, holoEntity(101):toWorld(vec(0, 0, 35)), vec(1, 1, 35/6), holoEntity(101):toWorld(ang()))
    holoParent(7, 101)
    holoCreate(8, holoEntity(5):toWorld(vec(0, 0, 35)), vec(1, 1, 35/6), holoEntity(101):toWorld(ang()))
    holoParent(8, 5)
    
    holoCreate(500, E:toWorld(vec(0, 0, 8)), vec(5), E:toWorld(ang(180, 0, 0)))
    holoModel(500, "hq_dome")
    holoParent(500, E)
    
    rangerPersist(1)
    
    local Vel = clamp(E:vel() / 3, -vec(75, 75, 0), vec(75, 75, 0))
    F1O = rangerOffset(135, holoEntity(100):pos() + Vel, vec(0, 0, -1)):pos()
    F2O = rangerOffset(135, holoEntity(101):pos() + Vel, vec(0, 0, -1)):pos()
    F1C = F1O
    F2C = F2O
    F1N = F1O
    F2N = F2O
}

if(PWrk)
{
    Dri = P:driver()
    Act = P:driver():isValid()
    
    W = Dri:keyForward()
    A = Dri:keyLeft()
    S = Dri:keyBack()
    D = Dri:keyRight()
    Shi = Dri:keySprint()
    Spc = Dri:keyJump()
    R = Dri:keyReload()
    Alt = Dri:keyWalk()
    M1 = Dri:keyAttack1()
    M2 = Dri:keyAttack2()
    
    if(CWrk)
    {
        if(Act)
        {
            Aim = P:toLocalAxis(Dri:eye())
            
            if(W|A|S|D)
            {
                local OA = vec(W - S, A - D, 0):toAngle()*(W|A|S|D)
                A1 = P:toLocal(Dri:eyeAngles())
                A2 = P:angles()
                if(abs($A2:forward():length() - $A1:forward():length()) < 5)
                {
                    AA = (P:toLocal(Dri:eyeAngles()) + OA) * ang(0, 1, 0)
                }
            }
        }
        
        Ht = clamp(Ht + (Act ? 0.05 : -0.05), 0, 1)
        
        if(changed(Act))
        {
            C["Activated", number] = Act
            C["Position", vector] = Dri:shootPos()
            C["Angle", angle] = Dri:eyeAngles()
            C["Parent", entity] = P
        }
        
        Gs += ((W|A|S|D)/(1+Shi) - Gs) / 4
    }else
    {
        if((owner():aimEntity() ?: CE):type() == "gmod_wire_cameracontroller")
        {
            C = (owner():aimEntity() ?: CE):wirelink()
            CWrk = 1
        }
    }
}else
{
    if(P:isValid())
    {
        if(changed(P:isValid()))
        {
            P:propFreeze(1)
            P:setPos(E:toWorld(vec(0, 0, 4)))
            P:setAng(E:toWorld(ang(0, -90, 0)))
            
            timer("pwrk", 70)
        }
        
        if(clk("pwrk"))
        {
            stoptimer("pwrk")
            P:parentTo(E)
            PWrk = 1
        }
    }else
    {
        if(findCanQuery())
        {
            findByClass("prop_vehicle_prisoner_pod")
            findSortByDistance(E:pos())
            findIncludePlayerProps(owner())
            findByModel("models/nova/airboat_seat.mdl")
            
            if(find():pos():distance(E:pos()) < 150)
            {
                P = find()
            }
        }
    }
}

Vel = clamp(E:vel() / 2.5, -vec(100, 100, 0), vec(100, 100, 0))
local Dst = (43 + Ht*50 + sin((F1P + F2P)*90)*4) / (1+Shi)
GR = rangerOffset(Dst + 30, E:pos(), vec(0, 0, -1))
F1R = rangerOffset(137.5, holoEntity(100):pos(), vec(0, 0, -1))
F2R = rangerOffset(137.5, holoEntity(101):pos(), vec(0, 0, -1))

F1A = holoEntity(1000):pos()
F2A = holoEntity(1001):pos()

Hit = GR:hit() & F1R:hit() & F2R:hit()
if(Hit)
{
    if(changed(Hit))
    {
        F1O = F1R:pos()
        F1N = F1R:pos()
        F1C = F1R:pos()
        F1W = 0
        F1P = 0
        
        F2O = F2R:pos()
        F2N = F2R:pos()
        F2C = F2R:pos()
        F2W = 0
        F2P = 0
    }
    
    applyForce(((E:forward() * Gs*6 + vec(0, 0, (GR:pos() + vec(0, 0, Dst) - E:pos()):z())) * vec(6, 6, 3) - E:vel() / vec(4, 4, 1.25)) * E:mass())
}else
{
    F1V += $F1A / 1.25
    F1V *= 0.4
    
    F2V += $F2A / 1.25
    F2V *= 0.4
}
applyAngForce((angnorm(AA + OA - E:angles())*ang(4, 1, 4)*Hit - E:angVel()) * E:mass() * Ntpl)

if(changed(Gs))
{
    DstN = 5 + (Gs*35)/6
}
if(FI)
{
    if(F1W)
    {
        if(F1P < 1)
        {
            F1P += 0.2 * (1 + Gs/3)
            
            F1C = bezierC(F1N, F1O, mix(F1N, F1O, 0.5) + vec(0, 0, 45), F1P)
        }else
        {
            F1O = F1N
            F1C = F1N
            F1P = 0
            F1W = 0
            FI = !FI
        }
    }else
    {
        if(F1O:distance(F1R:pos()) > DstN)
        {
            local Vel = clamp(E:vel() * 0.8,  -vec(100, 100, 0), vec(100, 100, 0))
            F1N = rangerOffset(135, holoEntity(100):pos() + Vel:setZ(0), vec(0, 0, -1)):pos()
            F1W = 1
        }else
        {
            FI = !FI
        }
    }
    
}else
{
    if(F2W)
    {
        if(F2P < 1)
        {
            F2P += 0.2 * (1 + Gs/3)
            
            F2C = bezierC(F2N, F2O, mix(F2N, F2O, 0.5) + vec(0, 0, 45), F2P)
        }else
        {
            F2O = F2N
            F2C = F2N
            F2P = 0
            F2W = 0
            FI = !FI
        }
    }else
    {
        if(F2O:distance(F2R:pos()) > DstN)
        {
            local Vel = clamp(E:vel() * 0.8,  -vec(100, 100, 0), vec(100, 100, 0))
            F2N = rangerOffset(135, holoEntity(101):pos() + Vel:setZ(0), vec(0, 0, -1)):pos()
            F2W = 1
        }else
        {
            FI = !FI
        }
    }
}

holoPos(1000, mix(Hit ? F1C : (holoEntity(100):pos() + E:toWorldAxis(vec(0, 8, -64)) + F1V), holoEntity(1000):pos(), (2)/3))
holoPos(1001, mix(Hit ? F2C : (holoEntity(101):pos() + E:toWorldAxis(vec(0, -8, -64)) + F2V), holoEntity(1001):pos(), (2)/3))
ik(70, 70, holoEntity(100), holoEntity(1000), E, 100, 1)
ik(70, 70, holoEntity(101), holoEntity(1001), E, 101, 5)

N++
if(!(N % 3))
{
    if(changed(numPlayers()))
    {
        rangerFilter(array(E, P):merge(players()))
    }
}
