public MissileAI(Projectile owner)
 {
     this.Owner = owner;
     if (MissileAI.universeScreen != null)
     {
         List<GameplayObject> GPO = UniverseScreen.ShipSpatialManager.GetNearby(this.Owner);
         for (int i = 0; i < GPO.Count; i++)
         {
             if (GPO[i] is Ship)
             {
                 Ship target = GPO[i] as Ship;
                 if (target != null && target.loyalty != this.Owner.loyalty && this.Owner.weapon.TargetValid(target.Role))
                     this.TargetList.Add(target);
             }
         }
     }
 }
 protected virtual void CreateProjectiles(Vector2 direction, GameplayObject target, bool playSound)
 {
     if (target != null && (target is ShipModule) && (target as ShipModule).GetParent().Role == "fighter" && this.AltFireMode && this.AltFireTriggerFighter && this.SecondaryFire != null)
     {
         Weapon AltFire = ResourceManager.GetWeapon(this.SecondaryFire);
         Projectile projectile;
         if (this.owner.Projectiles.pendingRemovals.TryPop(out projectile))
         {
             projectile.ProjectileRecreate(this.owner, direction, this.moduleAttachedTo);
             projectile.range = AltFire.Range;
             projectile.weapon = this;
             projectile.explodes = AltFire.explodes;
             projectile.damageAmount = AltFire.DamageAmount;
             projectile.damageRadius = AltFire.DamageRadius;
             projectile.explosionradiusmod = AltFire.ExplosionRadiusVisual;
             projectile.Health = AltFire.HitPoints;
             projectile.speed = AltFire.ProjectileSpeed;
             projectile.WeaponEffectType = AltFire.WeaponEffectType;
             projectile.WeaponType = AltFire.WeaponType;
             projectile.RotationRadsPerSecond = AltFire.RotationRadsPerSecond;
             projectile.ArmorPiercing = (byte)AltFire.ArmourPen;
         }
         else
             projectile = new Projectile(this.owner, direction, this.moduleAttachedTo)
             {
                 range = AltFire.Range,
                 weapon = this,
                 explodes = AltFire.explodes,
                 damageAmount = AltFire.DamageAmount,
                 damageRadius = AltFire.DamageRadius,
                 explosionradiusmod = AltFire.ExplosionRadiusVisual,
                 Health = AltFire.HitPoints,
                 speed = AltFire.ProjectileSpeed,
                 WeaponEffectType = AltFire.WeaponEffectType,
                 WeaponType = AltFire.WeaponType,
                 RotationRadsPerSecond = AltFire.RotationRadsPerSecond,
                 ArmorPiercing = (byte)AltFire.ArmourPen,
             };
         //damage increase by level
         if (this.owner.Level > 0)
         {
             projectile.damageAmount += projectile.damageAmount * (float)this.owner.Level * 0.05f;
         }
         if (AltFire.RangeVariance)
         {
             projectile.range *= RandomMath.RandomBetween(0.9f, 1.1f);
         }
         //Hull bonus damage increase
         if (GlobalStats.ActiveModInfo != null && GlobalStats.ActiveModInfo.useHullBonuses)
         {
             HullBonus mod;
             if (ResourceManager.HullBonuses.TryGetValue(this.owner.shipData.Hull, out mod))
                 projectile.damageAmount += projectile.damageAmount * mod.DamageBonus;
         }
         projectile.LoadContent(AltFire.ProjectileTexturePath, AltFire.ModelPath);
         AltFire.ModifyProjectile(projectile);
         if (AltFire.Tag_Guided)
             projectile.InitializeMissile(projectile.speed, direction, target);
         else
             projectile.Initialize(projectile.speed, direction, this.moduleAttachedTo.Center);
         projectile.Radius = this.ProjectileRadius;
         if (AltFire.Animated == 1)
         {
             string remainder = 0.ToString("00000.##");
             projectile.texturePath = string.Concat(AltFire.AnimationPath, remainder);
         }
         //if(HelperFunctions.GetRandomIndex((int)(Ship.universeScreen.Lag *100)) <2)
         if (Weapon.universeScreen.viewState == UniverseScreen.UnivScreenState.ShipView && this.owner.InFrustum && playSound)
         {
             projectile.DieSound = true;
             if (!string.IsNullOrEmpty(this.ToggleSoundName) && (this.ToggleCue == null || this.ToggleCue != null && !this.ToggleCue.IsPlaying))
             {
                 this.ToggleSoundOn = true;
                 this.ToggleCue = AudioManager.GetCue(AltFire.ToggleSoundName);
                 this.ToggleCue.Apply3D(Weapon.audioListener, this.owner.emitter);
                 this.ToggleCue.Play();
                 if (AltFire.fireCue != null)
                 {
                     //Added by McShooterz: Use sounds from new sound dictionary
                     SoundEffect soundeffect = null;
                     if (ResourceManager.SoundEffectDict.TryGetValue(AltFire.fireCueName,out soundeffect))
                     {
                         AudioManager.PlaySoundEffect(soundeffect, Weapon.audioListener, this.owner.emitter, 0.5f);
                     }
                     else
                     {
                         this.fireCue = AudioManager.GetCue(this.fireCueName);
                         if (!this.owner.isPlayerShip())
                         {
                             this.fireCue.Apply3D(Weapon.audioListener, this.owner.emitter);
                         }
                         this.lastFireSound = 0f;
                         if (this.fireCue != null)
                         {
                             this.fireCue.Play();
                         }
                     }
                 }
             }
             if (!string.IsNullOrEmpty(ResourceManager.WeaponsDict[AltFire.UID].dieCue))
             {
                 projectile.dieCueName = ResourceManager.WeaponsDict[AltFire.UID].dieCue;
             }
             if (!string.IsNullOrEmpty(this.InFlightCue))
             {
                 projectile.InFlightCue = AltFire.InFlightCue;
             }
             if (this.ToggleCue == null && this.owner.ProjectilesFired.Count < 30)
             {
                 this.lastFireSound = 0f;
                 this.owner.ProjectilesFired.Add(new ProjectileTracker());
                 //Added by McShooterz: Use sounds from new sound dictionary
                 if (ResourceManager.SoundEffectDict.ContainsKey(AltFire.fireCueName))
                 {
                     AudioManager.PlaySoundEffect(ResourceManager.SoundEffectDict[fireCueName], Weapon.audioListener, this.owner.emitter, 0.5f);
                 }
                 else
                 {
                     this.fireCue = AudioManager.GetCue(this.fireCueName);
                     if (!this.owner.isPlayerShip())
                     {
                         this.fireCue.Apply3D(Weapon.audioListener, this.owner.emitter);
                     }
                     if (this.fireCue != null)
                     {
                         this.fireCue.Play();
                     }
                 }
             }
         }
         projectile.isSecondary = true;
         this.owner.Projectiles.Add(projectile);
         projectile = null;
     }
     else
     {
         Projectile projectile;
         if (this.owner.Projectiles.pendingRemovals.TryPop(out projectile))
         {
             projectile.ProjectileRecreate(this.owner, direction, this.moduleAttachedTo);
             projectile.range = this.Range;
             projectile.weapon = this;
             projectile.explodes = this.explodes;
             projectile.damageAmount = this.DamageAmount;
             projectile.damageRadius = this.DamageRadius;
             projectile.explosionradiusmod = this.ExplosionRadiusVisual;
             projectile.Health = this.HitPoints;
             projectile.speed = this.ProjectileSpeed;
             projectile.WeaponEffectType = this.WeaponEffectType;
             projectile.WeaponType = this.WeaponType;
             projectile.RotationRadsPerSecond = this.RotationRadsPerSecond;
             projectile.ArmorPiercing = (byte)this.ArmourPen;
         }
         projectile = new Projectile(this.owner, direction, this.moduleAttachedTo)
         {
             range = this.Range,
             weapon = this,
             explodes = this.explodes,
             damageAmount = this.DamageAmount,
             damageRadius = this.DamageRadius,
             explosionradiusmod = this.ExplosionRadiusVisual,
             Health = this.HitPoints,
             speed = this.ProjectileSpeed,
             WeaponEffectType = this.WeaponEffectType,
             WeaponType = this.WeaponType,
             RotationRadsPerSecond = this.RotationRadsPerSecond,
             ArmorPiercing = (byte)this.ArmourPen,
         };
         //damage increase by level
         if (this.owner.Level > 0)
         {
             projectile.damageAmount += projectile.damageAmount * (float)this.owner.Level * 0.05f;
         }
         if (this.RangeVariance)
         {
             projectile.range *= RandomMath.RandomBetween(0.9f, 1.1f);
         }
         //Hull bonus damage increase
         if (GlobalStats.ActiveModInfo != null && GlobalStats.ActiveModInfo.useHullBonuses)
         {
             HullBonus mod;
             if (ResourceManager.HullBonuses.TryGetValue(this.owner.shipData.Hull, out mod))
                 projectile.damageAmount += projectile.damageAmount * mod.DamageBonus;
         }
         projectile.LoadContent(this.ProjectileTexturePath, this.ModelPath);
         this.ModifyProjectile(projectile);
         if (this.Tag_Guided)
             projectile.InitializeMissile(projectile.speed, direction, target);
         else
             projectile.Initialize(projectile.speed, direction, this.moduleAttachedTo.Center);
         projectile.Radius = this.ProjectileRadius;
         if (this.Animated == 1)
         {
             string remainder = 0.ToString("00000.##");
             projectile.texturePath = string.Concat(this.AnimationPath, remainder);
         }
         if (Weapon.universeScreen.viewState == UniverseScreen.UnivScreenState.ShipView && this.owner.InFrustum && playSound)
         {
             projectile.DieSound = true;
             if (!string.IsNullOrEmpty(this.ToggleSoundName) && (this.ToggleCue == null || this.ToggleCue != null && !this.ToggleCue.IsPlaying))
             {
                 this.ToggleSoundOn = true;
                 this.ToggleCue = AudioManager.GetCue(this.ToggleSoundName);
                 this.ToggleCue.Apply3D(Weapon.audioListener, this.owner.emitter);
                 this.ToggleCue.Play();
                 if (this.fireCue != null)
                 {
                     //Added by McShooterz: Use sounds from new sound dictionary
                     if (ResourceManager.SoundEffectDict.ContainsKey(this.fireCueName))
                     {
                         AudioManager.PlaySoundEffect(ResourceManager.SoundEffectDict[fireCueName], Weapon.audioListener, this.owner.emitter, 0.5f);
                     }
                     else
                     {
                         this.fireCue = AudioManager.GetCue(this.fireCueName);
                         if (!this.owner.isPlayerShip())
                         {
                             this.fireCue.Apply3D(Weapon.audioListener, this.owner.emitter);
                         }
                         this.lastFireSound = 0f;
                         if (this.fireCue != null)
                         {
                             this.fireCue.Play();
                         }
                     }
                 }
             }
             if (!string.IsNullOrEmpty(ResourceManager.WeaponsDict[this.UID].dieCue))
             {
                 projectile.dieCueName = ResourceManager.WeaponsDict[this.UID].dieCue;
             }
             if (!string.IsNullOrEmpty(this.InFlightCue))
             {
                 projectile.InFlightCue = this.InFlightCue;
             }
             if (this.ToggleCue == null && this.owner.ProjectilesFired.Count < 30)
             {
                 this.lastFireSound = 0f;
                 this.owner.ProjectilesFired.Add(new ProjectileTracker());
                 //Added by McShooterz: Use sounds from new sound dictionary
                 if (ResourceManager.SoundEffectDict.ContainsKey(this.fireCueName))
                 {
                     AudioManager.PlaySoundEffect(ResourceManager.SoundEffectDict[fireCueName], Weapon.audioListener, this.owner.emitter, 0.5f);
                 }
                 else
                 {
                     this.fireCue = AudioManager.GetCue(this.fireCueName);
                     if (!this.owner.isPlayerShip())
                     {
                         this.fireCue.Apply3D(Weapon.audioListener, this.owner.emitter);
                     }
                     if (this.fireCue != null)
                     {
                         this.fireCue.Play();
                     }
                 }
             }
         }
         this.owner.Projectiles.Add(projectile);
         projectile = null;
     }
 }
 protected virtual void CreateDrone(Vector2 direction)
 {
     Projectile projectile = new Projectile(this.owner, direction, this.moduleAttachedTo)
     {
         range = this.Range,
         weapon = this,
         explodes = this.explodes,
         damageAmount = this.DamageAmount
     };
     projectile.explodes = this.explodes;
     projectile.damageRadius = this.DamageRadius;
     projectile.explosionradiusmod = this.ExplosionRadiusVisual;
     projectile.speed = this.ProjectileSpeed;
     projectile.Health = this.HitPoints;
     projectile.WeaponEffectType = this.WeaponEffectType;
     projectile.WeaponType = this.WeaponType;
     projectile.LoadContent(this.ProjectileTexturePath, this.ModelPath);
     projectile.RotationRadsPerSecond = this.RotationRadsPerSecond;
     this.ModifyProjectile(projectile);
     projectile.InitializeDrone(projectile.speed, direction);
     projectile.Radius = this.ProjectileRadius;
     this.owner.Projectiles.Add(projectile);
     if (this.owner.InFrustum)
     {
         projectile.DieSound = true;
         if (!string.IsNullOrEmpty(this.ToggleSoundName) && !this.ToggleSoundOn)
         {
             this.ToggleSoundOn = true;
             this.ToggleCue = AudioManager.GetCue(this.ToggleSoundName);
             this.ToggleCue.Apply3D(Weapon.audioListener, this.owner.emitter);
             this.ToggleCue.Play();
             this.fireCue = AudioManager.GetCue(this.fireCueName);
             if (!this.owner.isPlayerShip())
             {
                 this.fireCue.Apply3D(Weapon.audioListener, this.owner.emitter);
             }
             this.lastFireSound = 0f;
             if (this.fireCue != null)
             {
                 this.fireCue.Play();
             }
         }
         if (!string.IsNullOrEmpty(ResourceManager.WeaponsDict[this.UID].dieCue))
         {
             projectile.dieCueName = ResourceManager.WeaponsDict[this.UID].dieCue;
         }
         if (!string.IsNullOrEmpty(this.InFlightCue))
         {
             projectile.InFlightCue = this.InFlightCue;
         }
         if (this.ToggleCue == null)
         {
             this.fireCue = AudioManager.GetCue(this.fireCueName);
             if (!this.owner.isPlayerShip())
             {
                 this.fireCue.Apply3D(Weapon.audioListener, this.owner.emitter);
             }
             this.lastFireSound = 0f;
             if (this.fireCue != null)
             {
                 this.fireCue.Play();
             }
         }
     }
 }
 public Projectile LoadProjectiles(Vector2 direction, Ship owner)
 {
     Projectile projectile = new Projectile(owner, direction)
     {
         range = this.Range,
         weapon = this,
         explodes = this.explodes,
         damageAmount = this.DamageAmount
     };
     projectile.explodes = this.explodes;
     projectile.damageRadius = this.DamageRadius;
     projectile.explosionradiusmod = this.ExplosionRadiusVisual;
     projectile.speed = this.ProjectileSpeed;
     projectile.WeaponEffectType = this.WeaponEffectType;
     projectile.WeaponType = this.WeaponType;
     projectile.Initialize(this.ProjectileSpeed, direction, owner.Center);
     projectile.Radius = this.ProjectileRadius;
     projectile.LoadContent(this.ProjectileTexturePath, this.ModelPath);
     if (owner.GetSystem() != null && owner.GetSystem().isVisible || owner.isInDeepSpace)
     {
         int numberSameWeapons = 0;
         //this.toggleTimer = 0f;
         foreach (Weapon w in owner.Weapons)
         {
             if (w == this || !(w.Name == this.Name) || w.timeToNextFire > 0f)
             {
                 continue;
             }
             numberSameWeapons++;
         }
         projectile.DieSound = true;
         if (!string.IsNullOrEmpty(ResourceManager.WeaponsDict[this.UID].dieCue))
         {
             projectile.dieCueName = ResourceManager.WeaponsDict[this.UID].dieCue;
         }
         if (!string.IsNullOrEmpty(this.InFlightCue))
         {
             projectile.InFlightCue = this.InFlightCue;
         }
     }
     return projectile;
 }
 private void ModifyProjectile(Projectile projectile)
 {
     if (this.owner == null)
     {
         return;
     }
     if (this.owner.loyalty.data.Traits.Pack)
     {
         projectile.damageAmount += projectile.damageAmount * this.owner.DamageModifier;
     }
     //Added by McShooterz: Check if mod uses weapon modifiers
     if (GlobalStats.ActiveModInfo != null && !GlobalStats.ActiveModInfo.useWeaponModifiers)
     {
         return;
     }
     if (this.Tag_Missile)
     {
         this.AddModifiers("Missile", projectile);
     }
     if (this.Tag_Energy)
     {
         this.AddModifiers("Energy", projectile);
     }
     if (this.Tag_Torpedo)
     {
         this.AddModifiers("Torpedo", projectile);
     }
     if (this.Tag_Kinetic)
     {
         this.AddModifiers("Kinetic", projectile);
     }
     if (this.Tag_Hybrid)
     {
         this.AddModifiers("Hybrid", projectile);
     }
     if (this.Tag_Railgun)
     {
         this.AddModifiers("Railgun", projectile);
     }
     if (this.Tag_Explosive)
     {
         this.AddModifiers("Explosive", projectile);
     }
     if (this.Tag_Guided)
     {
         this.AddModifiers("Guided", projectile);
     }
     if (this.Tag_Intercept)
     {
         this.AddModifiers("Intercept", projectile);
     }
     if (this.Tag_PD)
     {
         this.AddModifiers("PD", projectile);
     }
     if (this.Tag_SpaceBomb)
     {
         this.AddModifiers("Spacebomb", projectile);
     }
     if (this.Tag_BioWeapon)
     {
         this.AddModifiers("BioWeapon", projectile);
     }
     if (this.Tag_Drone)
     {
         this.AddModifiers("Drone", projectile);
     }
     if (this.Tag_Subspace)
     {
         this.AddModifiers("Subspace", projectile);
     }
     if (this.Tag_Warp)
     {
         this.AddModifiers("Warp", projectile);
     }
     if (this.Tag_Cannon)
     {
         this.AddModifiers("Cannon", projectile);
     }
     if (this.Tag_Beam)
     {
         this.AddModifiers("Beam", projectile);
     }
     if (this.Tag_Bomb)
     {
         this.AddModifiers("Bomb", projectile);
     }
     if (this.Tag_Array)
     {
         this.AddModifiers("Array", projectile);
     }
     if (this.Tag_Flak)
     {
         this.AddModifiers("Flak", projectile);
     }
     if (this.Tag_Tractor)
     {
         this.AddModifiers("Tractor", projectile);
     }
 }
 private void AddModifiers(string Tag, Projectile projectile)
 {
     projectile.damageAmount += this.owner.loyalty.data.WeaponTags[Tag].Damage * projectile.damageAmount;
     projectile.ShieldDamageBonus += this.owner.loyalty.data.WeaponTags[Tag].ShieldDamage;
     projectile.ArmorDamageBonus += this.owner.loyalty.data.WeaponTags[Tag].ArmorDamage;
     //Shield Penetration
     float actualShieldPenChance = this.moduleAttachedTo.GetParent().loyalty.data.ShieldPenBonusChance;
     actualShieldPenChance += this.owner.loyalty.data.WeaponTags[Tag].ShieldPenetration;
     actualShieldPenChance += this.ShieldPenChance;
     if (actualShieldPenChance > 0f && (float)((int)RandomMath2.RandomBetween(0f, 100f)) < actualShieldPenChance)
     {
         projectile.IgnoresShields = true;
     }
     //Projectile specific
     if (!this.isBeam)
     {
         projectile.ArmorPiercing += (byte)this.owner.loyalty.data.WeaponTags[Tag].ArmourPenetration;
         projectile.Health += this.HitPoints * this.owner.loyalty.data.WeaponTags[Tag].HitPoints;
         projectile.RotationRadsPerSecond += this.owner.loyalty.data.WeaponTags[Tag].Turn * this.RotationRadsPerSecond;
         projectile.speed += this.owner.loyalty.data.WeaponTags[Tag].Speed * this.ProjectileSpeed;
         projectile.damageRadius += this.owner.loyalty.data.WeaponTags[Tag].ExplosionRadius * this.DamageRadius;
     }
 }
 protected virtual void CreateProjectilesFromPlanet(Vector2 direction, Planet p, GameplayObject target)
 {
     Projectile projectile = new Projectile(p, direction)
     {
         range = this.Range,
         weapon = this,
         explodes = this.explodes,
         damageAmount = this.DamageAmount
     };
     if (this.RangeVariance)
     {
         projectile.range *= RandomMath.RandomBetween(0.9f, 1.1f);
     }
     projectile.explodes = this.explodes;
     projectile.damageRadius = this.DamageRadius;
     projectile.explosionradiusmod = this.ExplosionRadiusVisual;
     projectile.Health = this.HitPoints;
     projectile.speed = this.ProjectileSpeed;
     projectile.WeaponEffectType = this.WeaponEffectType;
     projectile.WeaponType = this.WeaponType;
     projectile.LoadContent(this.ProjectileTexturePath, this.ModelPath);
     projectile.RotationRadsPerSecond = this.RotationRadsPerSecond;
     projectile.ArmorPiercing = (byte)this.ArmourPen;
     /*
     if (this.ShieldPenChance > 0)
     {
         projectile.IgnoresShields = RandomMath.RandomBetween(0, 100) <= this.ShieldPenChance;
     } */
     this.ModifyProjectile(projectile);
     if(this.Tag_Guided)
         projectile.InitializeMissilePlanet(projectile.speed, direction, target, p);
     else
         projectile.InitializePlanet(projectile.speed, direction, p.Position);
     projectile.Radius = this.ProjectileRadius;
     if (this.Animated == 1)
     {
         string remainder = 0.ToString("00000.##");
         projectile.texturePath = string.Concat(this.AnimationPath, remainder);
     }
     p.Projectiles.Add(projectile);
     this.planetEmitter = new AudioEmitter()
     {
         Position = new Vector3(p.Position, 2500f)
     };
     if (Weapon.universeScreen.viewState <= UniverseScreen.UnivScreenState.SystemView)
     {
         projectile.DieSound = true;
         if (!string.IsNullOrEmpty(this.ToggleSoundName) && !this.ToggleSoundOn)
         {
             this.ToggleSoundOn = true;
             this.ToggleCue = AudioManager.GetCue(this.ToggleSoundName);
             this.ToggleCue.Apply3D(Weapon.audioListener, this.planetEmitter);
             this.ToggleCue.Play();
             this.lastFireSound = 0f;
             //Added by McShooterz: Use sounds from new sound dictionary
             if (ResourceManager.SoundEffectDict.ContainsKey(this.fireCueName))
             {
                 AudioManager.PlaySoundEffect(ResourceManager.SoundEffectDict[fireCueName], Weapon.audioListener, this.planetEmitter, 0.5f);
             }
             else
             {
                 this.fireCue = AudioManager.GetCue(this.fireCueName);
                 if (!this.owner.isPlayerShip())
                 {
                     this.fireCue.Apply3D(Weapon.audioListener, this.planetEmitter);
                 }
                 if (this.fireCue != null)
                 {
                     this.fireCue.Play();
                 }
             }
         }
         if (!string.IsNullOrEmpty(ResourceManager.WeaponsDict[this.UID].dieCue))
         {
             projectile.dieCueName = ResourceManager.WeaponsDict[this.UID].dieCue;
         }
         if (!string.IsNullOrEmpty(this.InFlightCue))
         {
             projectile.InFlightCue = this.InFlightCue;
         }
         try
         {
             if (this.ToggleCue == null)
             {
                 this.planetEmitter.Position = new Vector3(p.Position, -2500f);
                 this.lastFireSound = 0f;
                 //Added by McShooterz: Use sounds from new sound dictionary
                 if (ResourceManager.SoundEffectDict.ContainsKey(this.fireCueName))
                 {
                     AudioManager.PlaySoundEffect(ResourceManager.SoundEffectDict[fireCueName], Weapon.audioListener, this.planetEmitter, 0.5f);
                 }
                 else
                 {
                     this.fireCue = AudioManager.GetCue(this.fireCueName);
                     this.fireCue.Apply3D(Weapon.audioListener, this.planetEmitter);
                     if (this.fireCue != null)
                     {
                         this.fireCue.Play();
                     }
                 }
             }
         }
         catch
         {
         }
     }
 }
        //Added by McShooterz: New way to distribute exploding projectile damage
        public void ProjectileExplode(Projectile source, float damageAmount, float damageRadius)
        {
            if (damageRadius <= 0.0)
                return;

            float modifiedRadius = damageRadius;

            foreach (GameplayObject gameplayObject in this.GetNearby(source).Where(gameplayObject => gameplayObject != null && gameplayObject is Ship && gameplayObject.Active && !(gameplayObject as Ship).dying).OrderBy(gameplayObject => Vector2.Distance(source.Center, gameplayObject.Center)))
            {

                // Doctor: Up until now, the 'Reactive Armour' bonus used in the vanilla tech tree did exactly nothing. Trying to fix - is meant to reduce effective explosion radius.

                // Doctor: Reset the radius on every foreach loop in case ships of different loyalty are to be affected:
                modifiedRadius = damageRadius;

                //Check if valid target
                //added by gremlin check that projectile owner is not null
                if (source.Owner == null || source.Owner != null && source.Owner.loyalty != (gameplayObject as Ship).loyalty)
                {

                    // Doctor: Reduces the effective explosion radius on ships with the 'Reactive Armour' type radius reduction in their empire traits.
                    if ((gameplayObject as Ship).loyalty != null && (gameplayObject as Ship).loyalty.data.ExplosiveRadiusReduction != 0)
                    {
                        modifiedRadius *= (1 - (gameplayObject as Ship).loyalty.data.ExplosiveRadiusReduction);
                    }

                    float DamageTracker = 0;
                    IEnumerable<ModuleSlot> modules = (gameplayObject as Ship).ModuleSlotList.Where(moduleSlot => moduleSlot.module.Health > 0.0 && (moduleSlot.module.shield_power > 0.0 && !source.IgnoresShields) ? Vector2.Distance(source.Center, moduleSlot.module.Center) <= modifiedRadius + moduleSlot.module.shield_radius : Vector2.Distance(source.Center, moduleSlot.module.Center) <= modifiedRadius + 10f).OrderBy(moduleSlot => (moduleSlot.module.shield_power > 0.0 && !source.IgnoresShields) ? Vector2.Distance(source.Center, moduleSlot.module.Center) - moduleSlot.module.shield_radius : Vector2.Distance(source.Center, moduleSlot.module.Center));
                    foreach (ModuleSlot moduleSlot in modules)
                    {
                        moduleSlot.module.Damage(source, damageAmount, ref DamageTracker);
                        if (DamageTracker > 0)
                            damageAmount = DamageTracker;
                        else return;
                    }
                }
            }
        }
 public DroneAI(Projectile owner)
 {
     this.Owner = owner;
     this.w = ResourceManager.GetWeapon("RepairBeam");
 }
        public ShipModule GetRandomInternalModule2(Projectile source)
        {
            int level = 0;
            if (source.Owner != null)
                level = source.Owner.Level;
            if (source.Owner != null && lastAttacker == source.Owner)
            {

                if (this.AttackerTargetting.Count == 0)
                    return null;
                int randomizer = level > 0 ? this.AttackerTargetting.Count() / (level + 1) : this.AttackerTargetting.Count();
                return this.AttackerTargetting[HelperFunctions.GetRandomIndex(randomizer)].module;
            }
            float ourside = Vector2.Distance(this.Center, source.Center);
            //IOrderedEnumerable
            this.AttackerTargetting = this.ModuleSlotList
                .Where(slot => slot != null && slot.module.ModuleType != ShipModuleType.Dummy && slot.module.Active && slot.module.Health > 0.0)
                .OrderByDescending(slot => slot.module.TargetValue + (slot.module.isExternal ? -5 : 0) + (slot.module.Health < slot.module.HealthMax ? 1 : 0))
                .ThenBy(distance => Vector2.Distance(distance.module.Center, source.Center) < ourside)
                .ToList();
            level = 0;
            if (source.Owner != null)
                level = source.Owner.Level;

            if (this.AttackerTargetting.Count == 0)
                return null;
            int randomizer2 = level > 0 ? this.AttackerTargetting.Count() / (level + 1) : this.AttackerTargetting.Count();

            return this.AttackerTargetting[HelperFunctions.GetRandomIndex(randomizer2)].module;

            //List<ShipModule> InternalModules = new List<ShipModule>();
            ////foreach (ModuleSlot slot in this.ModuleSlotList)
            ////foreach (ModuleSlot slot in this.ExternalSlots)
            //ShipModule closest = null;
            //for (int x = 0; x < this.ExternalSlots.Count; x++)
            //{
            //    ModuleSlot slot;
            //    try
            //    {
            //        slot = this.ExternalSlots[x];
            //    }
            //    catch
            //    {
            //        continue;
            //    }
            //    if (slot == null)
            //        continue;
            //    ShipModule slot2;
            //    try
            //    {
            //        slot2 = slot.module;
            //    }
            //    catch
            //    {
            //        continue;
            //    }
            //    if (slot2 == null)
            //        continue;
            //    //if (slot.Restrictions == Restrictions.I && slot.module.ModuleType != ShipModuleType.Dummy && slot.module.Active )
            //    if (slot2.ModuleType != ShipModuleType.Dummy && slot2.Active)
            //        InternalModules.Add(slot.module);

            //    {
            //        if (closest == null)
            //            closest = slot2;
            //        else
            //        {
            //            float distance = Vector2.Distance(source.Center, slot2.Center);//source.GetOwner().Center,slot2.Center);
            //            float distancetoClosest = Vector2.Distance(source.Center, closest.Center);
            //            if (distance < distancetoClosest)
            //                closest = slot2;

            //        }

            //    }
            //}

            //if (InternalModules.Count > 0)
            //{
            //    int level = 0;
            //    if (source.Planet != null)
            //        level = source.Planet.developmentLevel;
            //    else if (source.Owner != null)
            //        level = source.Owner.Level;
            //    else
            //        return InternalModules[HelperFunctions.GetRandomIndex(InternalModules.Count)];
            //    if(level <2)
            //        return InternalModules[HelperFunctions.GetRandomIndex(InternalModules.Count)];

            //        int skill = InternalModules.Count / (level + 2);
            //    int random = HelperFunctions.GetRandomIndex((int)skill);
            //    float healthTarget = 1 / (level + 1);
            //    //if (source.GetOwner().Level >1)

            //    return InternalModules.OrderBy(damage => damage.Health)
            //        .ThenBy(close => Vector2.Distance(close.Center, closest.Center))
            //        .ElementAt(random);

            //    //return InternalModules.OrderBy(close => Vector2.Distance(close.Center, closest.Center)).First(); //[HelperFunctions.GetRandomIndex(InternalModules.Count)];
            //    // return closest;
            //}
            //else
            //    return null;
        }
        public ShipModule GetRandomInternalModule(Projectile source)
        {
            Vector2 center = source.Owner != null ? source.Owner.Center : source.Center;
            float nearest = 0;
            float temp;

            ModuleSlot ClosestES = null;

            foreach (ModuleSlot ES in this.ExternalSlots)
            {
                if (ES.module.ModuleType == ShipModuleType.Dummy || !ES.module.Active ||  ES.module.Health <=0)
                    continue;
                temp = Vector2.Distance(ES.module.Center, center);
                if (nearest == 0 || temp < nearest)
                {
                    nearest = temp;
                    ClosestES = ES;
                }
            }
            if (ClosestES == null)
                return null;
            byte level = 0;
            if (source.Owner != null)
                level = (byte)source.Owner.Level;
            lock (this.AttackerTargetting)
            {
                if (this.AttackerTargetting == null || !this.AttackerTargetting.Contains(ClosestES))
                    if (level > 1)
                    {
                        float Damageradius = Vector2.Distance(ClosestES.module.Center, this.Center); //16 * (7 - level);//
                        this.AttackerTargetting.Clear();
                        foreach (ModuleSlot slot in this.ModuleSlotList)
                        {
                            if (slot != null && slot.module.ModuleType != ShipModuleType.Dummy
                                                       && slot.module.Active && slot.module.Health > 0.0 && (!slot.module.isExternal || slot.module.quadrant == ClosestES.module.quadrant)
                                                       && Vector2.Distance(slot.module.Center, ClosestES.module.Center) < Damageradius)
                            {
                                this.AttackerTargetting.Add(slot);
                            }

                        }
                        this.AttackerTargetting = this.AttackerTargetting.OrderByDescending(slot => slot.module.TargetValue + (slot.module.Health < slot.module.HealthMax ? 1 : 0))

                               .ToList();
                    }
                    else
                    {
                        float Damageradius = Vector2.Distance(ClosestES.module.Center, this.Center);
                        this.AttackerTargetting.Clear();
                        foreach (ModuleSlot slot in this.ModuleSlotList)
                        {
                            if (slot != null && slot.module.ModuleType != ShipModuleType.Dummy
                                                       && slot.module.Active && slot.module.Health > 0.0 && (!slot.module.isExternal || slot.module.quadrant == ClosestES.module.quadrant)
                                                       && Vector2.Distance(slot.module.Center, ClosestES.module.Center) < Damageradius)
                            {
                                this.AttackerTargetting.Add(slot);
                            }

                        }
                    }
            }
            if (this.AttackerTargetting.Count == 0)
            {
                if (this.ExternalSlots.Count == 0)
                    return null;
                else return this.ExternalSlots[0].module;
            }

            {

                if (this.AttackerTargetting.Count == 0)
                    return null;
                int randomizer = this.AttackerTargetting.Count() / (level + 1);
                return this.AttackerTargetting[HelperFunctions.GetRandomIndex(randomizer)].module;
            }
               // if(this.AttackerTargetting != null && this.AttackerTargetting.Contains(ClosestES))
               //// if (source.Owner != null && lastAttacker == source.Owner)
               // {

               //     if (this.AttackerTargetting.Count == 0)
               //         return null;
               //     int randomizer = this.AttackerTargetting.Count() / (level + 1);//level > 0 ? this.AttackerTargetting.Count() / (level + 1) : this.AttackerTargetting.Count();
               //     return this.AttackerTargetting[HelperFunctions.GetRandomIndex(randomizer)].module;
               // }
               // if (level > 1)
               // {
               //     float Damageradius = Vector2.Distance(ClosestES.module.Position, this.Center);
               //     this.AttackerTargetting.Clear();
               //     foreach (ModuleSlot slot in this.ModuleSlotList)
               //     {
               //         if (slot != null && slot.module.ModuleType != ShipModuleType.Dummy
               //                                    && slot.module.Active && slot.module.Health > 0.0 && (!slot.module.isExternal || slot.module.quadrant == ClosestES.module.quadrant)
               //                                    && Vector2.Distance(slot.module.Center, ClosestES.module.Center) < Damageradius)
               //         {
               //             this.AttackerTargetting.Add(slot);
               //         }

               //     }
               //     this.AttackerTargetting = this.AttackerTargetting.OrderByDescending(slot => slot.module.TargetValue + (slot.module.Health < slot.module.HealthMax ? 1 : 0))

               //            .ToList();

               // }
               // else
               // {
               //     float Damageradius = Vector2.Distance(ClosestES.module.Position, this.Center);
               //     this.AttackerTargetting.Clear();
               //     foreach (ModuleSlot slot in this.ModuleSlotList)
               //     {
               //         if (slot != null && slot.module.ModuleType != ShipModuleType.Dummy
               //                                    && slot.module.Active && slot.module.Health > 0.0 && (!slot.module.isExternal || slot.module.quadrant == ClosestES.module.quadrant)
               //                                    && Vector2.Distance(slot.module.Center, ClosestES.module.Center) < Damageradius)
               //         {
               //             this.AttackerTargetting.Add(slot);
               //         }

               //     }
               // }

               // if (this.AttackerTargetting.Count == 0)
               //     return null;
               // int randomizer2 = this.AttackerTargetting.Count() / (level + 1);// level > 0 ? this.AttackerTargetting.Count() / (level + 2) : this.AttackerTargetting.Count();

               // return this.AttackerTargetting[HelperFunctions.GetRandomIndex(randomizer2)].module;
        }