@name Bounding Mine Deployer (Press H)
@inputs Drop
#@outputs Pct MinesC PropModel:string Config Hold CnfgChk [Bubs Blinded Ranges]:array
@persist [Mines Targets Blinded Bubs Ranges]:array Minelmt CnfgChk Config PropModel:string Hold DropI                         #Main variables
@persist VehicleR FlashR InfantryR Range Force Mass Max Opslmt Wrnlmt HoldIntval ScanIntval UnblindUndo VehicMode             #Settings variables
@persist [Mode InfantryPM VehiclePM FlashPM InfantryBM VehicleBM FlashBM Key]:string [P E]:entity FlashDur FlashRng           #More settings variables
#By thewhitish

#Hold key for 1 second to display info. Hold for 2 and release to enter config mode. Hold for 3 to delete last mine placed. Hold for 4 to delete all mines and unblind players.
#Hard limit of 44 mines per chip.
#If over a certain ops usage (default 90%), will only scan for new targets when a mine is laid.
if (first())                                                 
{
runOnTick(1)
runOnLast(1)
#-------------------------------------------------------------------------------------------------------------------------------------Options                                                        
Key = "H"    #The key on your keyboard that will control this chip. Comment out this line to disable. http://wiki.garrysmod.com/page/Enums/KEY. Case insensitive, exclude 'KEY_'"

VehicleR = 500 #Range from target to leap. The larger the largest value, the more ops. Try to keep these numbers close together for better performance
FlashR = 325
InfantryR = 350

Force = 250   #Force to launch mine (multiplied by prop mass) default 200
Mass = 2000   #Mass of mine props, lower mass will cause a field of them to scatter if one is tripped. default 2000

Max = 44      #Max number of mines. Keeps us within ops max most of the time
Opslmt = 106  #Fail-safe ops *percentage*. Will purge lots of mines when usage percentage max is reached to maintain control of chip
Wrnlmt = 90   #Ops percentage threshold that the chip will stop automatically scanning at, and start to notify of ops usage instead 

HoldIntval = 1000 #Duration to hold button before skipping to next function. In milliseconds
ScanIntval = 5000 #How often to automatically rescan for targets in milliseconds

Mode = "Flash-Bang" #Default mine mode. Options are "Anti-Infantry", "Anti-Vehicle", and "Flash-Bang"

VehicMode = 0 #If set to 1, mine will shoot out of the top of the chip, instead of appearing where you aim

FlashDur = 8000 #How long flash effect lasts
UnblindUndo = 0 #If set to 1, undo a mine will also unblind all players. Use if players are getting stuck blinded a lot

InfantryPM = "models/props_phx2/garbage_metalcan001a.mdl"
VehiclePM = "models/props_combine/combine_mine01.mdl"      
FlashPM = "models/jaanus/thruster_flat.mdl"
#"models/props_combine/combine_mine01.mdl"
#"models/props_phx2/garbage_metalcan001a.mdl"
#"models/items/combine_rifle_ammo01.mdl"

InfantryBM = "models/props_phx/amraam.mdl"                    
VehicleBM = "models/props_phx/torpedo.mdl"                      
FlashBM = "models/props_phx/misc/potato_launcher_explosive.mdl"
#"models/props_c17/oildrum001_explosive.mdl"                     Range 200, gibbs
#"models/props_phx/ww2bomb.mdl"                                  Range 125
#"models/props_phx/torpedo.mdl"                                  Range 500-700
#"models/props_phx/misc/potato_launcher_explosive.mdl"           Range very small, rarely lethal
#"models/props_phx/misc/flakshell_big.mdl"                       Range 300-500, shrapnel, may cause lag
#"models/props_phx/amraam.mdl"                                   Range 325
P = owner()
#findExcludePlayer(P)                                           #Uncomment this if you want mines to ignore you (the player who owns the chip)
#--------------------------------------------------------------------------------------------------------------------------------------Misc

E = entity()
findIncludeClass("player")
findIncludeClass("npc")
findIncludeClass("vehicle")
findExcludeClass("prop_physics")
Ranges = array(VehicleR,FlashR,InfantryR)
Range = Ranges:max()

if (Mode == "Anti-Infantry")                                #default mine type stuff
    {PropModel = InfantryPM}
if (Mode == "Anti-Vehicle")
    {PropModel = VehiclePM}
if (Mode == "Flash-Bang")
    {PropModel = FlashPM}

timer("tar-scan",ScanIntval)                                #Start auto-scanning
}

if (duped())                                                #Work around for a duping bug.                             
    {reset()}
#--------------------------------------------------------------------------------------------------------------------------------------Ops fail safe
Pct = int((ops()/hardQuota()) * 1000)                        #rounded percent ops usage

if (Pct >= Opslmt)                                         #Start deleting lots of mines if limit is reached
{
    print("Ops limit reached, deleting many mines.")
    for(I=1,(Pct - (Opslmt - 8)))
        {Mines[I,entity]:propDelete()}
}

if (Pct < Opslmt) {                                              #If we're above the ops limit, don't do any of this
#--------------------------------------------------------------------------------------------------------------------------------------Input
DropI = P:keyPressed(Key)

if (DropI | Drop) #Held down
    {Input = 1}

if ((DropI & $DropI) | (~Drop & Drop)) #If pressed this tick
    {Input = 2}
    elseif (($DropI == (-1)) | (~Drop & !Drop)) #If released this tick
        {Input = 3}
#--------------------------------------------------------------------------------------------------------------------------------------Main function
if (Input == 2)                                                #Button pressed
{
    if (!Config)                            
    {
        timer("mode",2*HoldIntval)                                       #Switch mine type mode
        timer("undo",3*HoldIntval)                                       #Delete last countdown
        timer("purge",4*HoldIntval)                                      #Total purge countdown
    }
    timer("info",1*HoldIntval)                                           #Show info countdown

    findInSphere(E:pos(),50000)                                  #Scan for new targets
    Targets = findToArray()
}

if (Input == 3)                                               #Button released
{
    stoptimer("info")
    stoptimer("mode")
    stoptimer("undo")
    stoptimer("purge")
    timer("tar-scan",ScanIntval)                                 #Restart target scan timer
    if (CnfgChk)
        {print("Config mode enabled. Press to cycle through mine types. Hold to save."), Config = 1, CnfgChk = 0}
    if ((Pct < Opslmt) & !Config & !Hold)                        #Drop if we have the ops for it
    {
        if (Minelmt)                                             #Start deleting mines from the beginning if limit reached
        {
            print("Mine limit reached, replacing mines. Slow deployment rate!")
            Mines[1,entity]:propDelete()
        }
        if (!VehicMode)
        {Temp = propSpawn(PropModel,(P:aimPos() + vec(0,0,2)),0)}
            else
            {Temp = propSpawn(PropModel,E:pos(),0)}
        Temp:setMass(Mass)
        Mines:pushEntity(Temp)
        P:soundPlay(1,2,"hl1/fvox/blip.wav")
    }
    if (Config & !Hold)                                          #Cycle through mine types if in config mode
    {
        if (Mode == "Anti-Infantry")
            {Mode = "Anti-Vehicle", PropModel = VehiclePM}
            elseif (Mode == "Flash-Bang")
                {Mode = "Anti-Infantry", PropModel = InfantryPM}
            elseif (Mode == "Anti-Vehicle")
                {Mode = "Flash-Bang", PropModel = FlashPM}
        print(Mode)
    }
    if ((Pct >= Wrnlmt) & !Config)                            #Start notifying of ops usage
        {print("Ops usage at",Pct,"%.")}
    Hold = 0
}

if ((Pct < Wrnlmt) & clk("tar-scan"))                            #Automatically rescan for new targets, if we have the ops for it
{
    findInSphere(E:pos(),50000)                              
    Targets = findToArray()
    timer("tar-scan",ScanIntval)
}

MinesC = Mines:count()

if (MinesC >= Max)
    {Minelmt = 1}
    else {Minelmt = 0}
#--------------------------------------------------------------------------------------------------------------------------------------mine loop
if (MinesC) {
    for(I=1,MinesC)                                             #Main function, cycles through list of mines, compares distance to list of targets.
    {
        Mine = Mines[I,entity]
        if (!Mine)                                                # if the prop doesn't exist at this tick's index, remove from Mines array
        {
            Mines:remove(I)
            continue
        }
        if ((clk("purge") & Input) | last())                                  # Delete all mines
        {
            Mine:propDelete()
            continue
        }
        MineP = Mine:pos()
        T = Targets[(int(random(1,Targets:count()+1))),entity]
        Dist = (MineP:distance(T:pos()))
        if (Dist < Range)                                               # if target in range, leap
        {
            if ((Mine:model() == InfantryPM) & (Dist > InfantryR))      #if this shit aint true don't bounce
                {continue}
            if ((Mine:model() == FlashPM) & ((Dist > FlashR) | !T:isPlayer()))
                {continue}
            if ((Mine:model() == VehiclePM) & ((Dist > VehicleR) | !T:isVehicle()))
                {continue}
            Mine:applyForce(vec(0,0,(Force*Mine:mass())))
            Mine:soundPlay(2,5,"doors/vent_open1.wav")
        }
            else {continue}
        if ( ((MineP:z()) >= (T:pos():z() + 50)) & (Mine:vel():length() > 10) & ((MineP:distance(T:pos())) < (Range))) #Spawn real bomb and detonate 25
        {
            if (Mine:model() == InfantryPM)
            {
                Bomb = propSpawn(InfantryBM,MineP,1)                   #for cheaty face mode, exchange MineP with T:pos()
                Bomb:propBreak()
            }
            if (Mine:model() == FlashPM)
            {
                if (T:isPlayer())                                      #If target is a player, add to list of players to be blinded
                {
                    Blinded:pushEntity(T)
                }
                Bomb = propSpawn(FlashBM,MineP,1)                   
                Bomb:propBreak()
            }
            if (Mine:model() == VehiclePM)
            {
                Bomb = propSpawn(VehicleBM,MineP,1)                    #for cheaty face mode, exchange MineP with T:pos()
                Bomb:propBreak()
            }
            Mine:propDelete()
            continue
        }
    }
}

#--------------------------------------------------------------------------------------------------------------------------------------Blinding function

BlindedC = Blinded:count()

if (BlindedC) {
    for(O=1,BlindedC)                                           #Spawn opaque sphere around every player in blinded array
    {
        stoptimer(O:toString())
        TarB = Blinded[O,entity]
        if (!TarB | !(TarB:isPlayer()))
            {
                Blinded:remove(O)
                continue
            }
        TarB:soundPlay(O+3,0,"synth/sine_1760.wav")
        soundVolume(O+3,0.25)
        holoCreate(O)
        holoPos(O, TarB:shootPos())
        holoScale(O, vec(-8,8,8))
        holoColor(O, vec(255,255,255))
        holoMaterial(O,"models/debug/debugwhite")
        holoParent(O,TarB)
        holoModel(O,"hq_sphere")
        holoShadow(O,0)
        Bubs:pushEntity(holoEntity(O))
        timer(O:toString(),FlashDur)
        Blinded:remove(O)
    }
}

BubsC = Bubs:count()

if (BubsC) {
    for (U=1,BubsC)
    {
        Bub = Bubs[U,entity]
        if (!Bub)                                                
        {
            Bubs:remove(U)
            continue
        }
        if (clk(U:toString()) | !(Bub:parent():isAlive()))                                     #If the player has been flashed for long enough, delete holo sphere and stop ringing sound
        {
            holoDelete(U)
            soundStop(U+3)
        }
    }
}
if (last())                                                        #If chip was removed before a player was done being flashed, remove anyway
{
    holoDeleteAll()
    soundPurge()
}
#--------------------------------------------------------------------------------------------------------------------------------------Hold functions
if (clk("info") & Input)                                 #Show info
{
    Hold = 1
    if (!Config)
        {print(MinesC:toString(),"mines laid,",(Max-MinesC),"remaining.",Pct,"% op usage. Type is ",Mode)}
    if (Config)
    {
        Config = 0
        print("Configuration saved as",Mode)
    }
}

if (clk("mode") & Input)
{
    print("Release to enter config mode.")
    CnfgChk = 1
}

if (clk("undo") & Input)                                  #Delete last mine (and delete the mine you just laid in order to invoke this function)
{
    Mines[Mines:count(),entity]:propDelete()
    CnfgChk = 0
    if (UnblindUndo)
    {
        holoDeleteAll()
        soundPurge()
        print("Last mine deleted, players unblinded.")
    }
    else {print("Last mine deleted.")}
}

if (clk("purge") & Input)                                 #Delete all mines
{
    print(MinesC:toString(),"mines purged, players unblinded.")
    holoDeleteAll()
    soundPurge()
}

}
