@name Swarm Machine
@inputs In:entity
@outputs Props E:entity
@persist Enabled Swarming R:array V1:vector V2:vector V3:vector V4:vector V5:vector V6:vector V7:vector V8:vector V9:vector V10:vector V11:vector V12:vector V13:vector V14:vector V15:vector V16:vector V17:vector V18:vector V19:vector V20:vector T A
@trigger all

interval(10)
runOnChat(1)
if (first() | duped())
{
    concmd("say")
}

# If the bees are enabled, we want people to know they can swarm other players
if (clk("Enabled"))
{
    concmd("say")
}

# We got a chat command from someone
if (chatClk() == 1)
{
    # Seperate the string into Explode
    Explode = lastSaid():explode(" ")

    # If the first word is swarm, then the second word must be the player
    # we want to own. If the target isn't the owner, and a target is found,
    # swarm the target
    if (Explode:string(1):lower() == "swarm")
    {
        E = findPlayerByName(Explode:string(2))
        if (E != entity():owner())
        {
            if (E:name() == "")
            {
                concmd("say")
                Swarming = 0
                E = entity()
            }
            else
            {
                concmd("say Here comes the bees " + E:name() + "!")
                Swarming = 1
            }
        }
        else
        {
            Swarming = 1
            concmd("say")
            E = lastSpoke()
        }
    }
    
    # If the first word bees and the owner said it, enable or disable the bees
    if (Explode:string(1):lower() == "bees" & chatClk(entity():owner()))
    {
        # Check to make sure the owner says 'bees' and nothing else
        if (Explode:string(2) == "")
        {
            # Basic logic: If it's disabled, enable it, else disable it
            if (Enabled == 0)
            {
                Enabled = 1
                print("Bees enabled")
                timer("Enabled", 2000)
            }
            else
            {
                Enabled = 0
                print("Bees disabled")
            }
        }
        # Check if the owner wants to reset the bees back to the hive
        if (Explode:string(2) == "reset")
        {
            E = entity()
            Swarming = 0
            print("Bees reset")
        }
    }
}

# If the bees are flying, do the fun stuff
if (Enabled == 1)
{   
    # If the expression doesn't have any bees, then get some
    if (Props < 1)
    {
        # Pop cans are the bees. Look for any popcans
        findByModel("models/props_phx/misc/potato.mdl")
        
        # Filter the results to the owner's popcans only
        findIncludePlayerProps(owner())
        
        # Toss the find results into an array
        R = findToArray()
        
        # Count how many bees we got and tell the user
        Props = R:count()
        print(toString(Props) + " Bees found.")
        
        E = entity()
    }
    
    # There's an issue with the dupe thinking there's 40 bees instead of 20, this fixes the issue
    # By removing the first non-existant bees in the list, until the list count reaches 20. Sometimes
    # removes good bees, but not often. If this is an issue, respawn the dupe and it'll work
    if (Props > 20)
    {
        R:remove(1)
        Props = Props - 1
        print("Too many Bees. Bee removed. At " + toString(Props))
    }

    # Calculate the object to player positions
    Pos1 = E:pos() - R:entity(1):massCenter()
    Pos2 = E:pos() - R:entity(2):massCenter()
    Pos3 = E:pos() - R:entity(3):massCenter()
    Pos4 = E:pos() - R:entity(4):massCenter()
    Pos5 = E:pos() - R:entity(5):massCenter()
    Pos6 = E:pos() - R:entity(6):massCenter()
    Pos7 = E:pos() - R:entity(7):massCenter()
    Pos8 = E:pos() - R:entity(8):massCenter()
    Pos9 = E:pos() - R:entity(9):massCenter()
    Pos10 = E:pos() - R:entity(10):massCenter()
    Pos11 = E:pos() - R:entity(11):massCenter()
    Pos12 = E:pos() - R:entity(12):massCenter()
    Pos13 = E:pos() - R:entity(13):massCenter()
    Pos14 = E:pos() - R:entity(14):massCenter()
    Pos15 = E:pos() - R:entity(15):massCenter()
    Pos16 = E:pos() - R:entity(16):massCenter()
    Pos17 = E:pos() - R:entity(17):massCenter()
    Pos18 = E:pos() - R:entity(18):massCenter()
    Pos19 = E:pos() - R:entity(19):massCenter()
    Pos20 = E:pos() - R:entity(20):massCenter()

    # Create the swarm logic by using the targets position and adding a random
    # vector
    V1 = Pos1 + vec(random(-125,125),random(-125,125),random(15,125))
    V2 = Pos2 + vec(random(-125,125),random(-125,125),random(15,125))
    V3 = Pos3 + vec(random(-125,125),random(-125,125),random(15,125))
    V4 = Pos4 + vec(random(-125,125),random(-125,125),random(15,125))
    V5 = Pos5 + vec(random(-125,125),random(-125,125),random(15,125))
    V6 = Pos6 + vec(random(-125,125),random(-125,125),random(15,125))
    V7 = Pos7 + vec(random(-125,125),random(-125,125),random(15,125))
    V8 = Pos8 + vec(random(-125,125),random(-125,125),random(15,125))
    V9 = Pos9 + vec(random(-125,125),random(-125,125),random(15,125))
    V10 = Pos10 + vec(random(-125,125),random(-125,125),random(15,125))
    V11 = Pos11 + vec(random(-125,125),random(-125,125),random(15,125))
    V12 = Pos12 + vec(random(-125,125),random(-125,125),random(15,125))
    V13 = Pos13 + vec(random(-125,125),random(-125,125),random(15,125))
    V14 = Pos14 + vec(random(-125,125),random(-125,125),random(15,125))
    V15 = Pos15 + vec(random(-125,125),random(-125,125),random(15,125))
    V16 = Pos16 + vec(random(-125,125),random(-125,125),random(15,125))
    V17 = Pos17 + vec(random(-125,125),random(-125,125),random(15,125))
    V18 = Pos18 + vec(random(-125,125),random(-125,125),random(15,125))
    V19 = Pos19 + vec(random(-125,125),random(-125,125),random(15,125))
    V20 = Pos20 + vec(random(-125,125),random(-125,125),random(15,125))
    
    # If there's a target to swarm, we want them to go full speed, or they won't hurt.
    # While the bees are waiting, we want it to look like they're moping around. This is
    # accomplished by reducing the calculated mass of the object, which in turn reduces the thrust
    if (Swarming == 1)
    {
        M = R:entity(1):mass() / 6
    }
    else
    {
        M = R:entity(1):mass() / 60
    }

    # Move the object to the player
    R:entity(1):applyForce(V1*M*10 + $V1*M*20)
    R:entity(2):applyForce(V2*M*10 + $V2*M*20)
    R:entity(3):applyForce(V3*M*10 + $V3*M*20)
    R:entity(4):applyForce(V4*M*10 + $V4*M*20)
    R:entity(5):applyForce(V5*M*10 + $V5*M*20)
    R:entity(6):applyForce(V6*M*10 + $V6*M*20)
    R:entity(7):applyForce(V7*M*10 + $V7*M*20)
    R:entity(8):applyForce(V8*M*10 + $V8*M*20)
    R:entity(9):applyForce(V9*M*10 + $V9*M*20)
    R:entity(10):applyForce(V10*M*10 + $V10*M*20)
    R:entity(11):applyForce(V11*M*10 + $V11*M*20)
    R:entity(12):applyForce(V12*M*10 + $V12*M*20)
    R:entity(13):applyForce(V13*M*10 + $V13*M*20)
    R:entity(14):applyForce(V14*M*10 + $V14*M*20)
    R:entity(15):applyForce(V15*M*10 + $V15*M*20)
    R:entity(16):applyForce(V16*M*10 + $V16*M*20)
    R:entity(17):applyForce(V17*M*10 + $V17*M*20)
    R:entity(18):applyForce(V18*M*10 + $V18*M*20)
    R:entity(19):applyForce(V19*M*10 + $V19*M*20)
    R:entity(20):applyForce(V20*M*10 + $V20*M*20)
    
    # When the target dies, we want to put the swam back to passive and change the entity to the chip
    if (Swarming == 1 & E:name() != "" & E:health() <= 0)
    {
        Swarming = 0
        E = entity()
    }
    # When the target dies, we want to put the swam back to passive and change the entity to the chip
    if (Swarming == 1 & E:name() != "" & E:isUnderWater() == 1)
    {
        Swarming = 0
        E = entity()
    }
}
