public override bool Touch(GameplayObject target) { if (this.Miss) { return false; } if (target != null) { if (target == this.owner && !this.weapon.HitsFriendlies) { return false; } Projectile projectile = target as Projectile; if (projectile != null) { if (this.owner != null && projectile.loyalty == this.owner.loyalty) { return false; } if (projectile.WeaponType == "Missile") { float ran = ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(0f, 1f); if (projectile.loyalty != null && ran >= projectile.loyalty.data.MissileDodgeChance) { projectile.DamageMissile(this, this.damageAmount); return true; } } else if (this.weapon.Tag_Intercept || projectile.weapon.Tag_Intercept) { this.DieNextFrame = true; projectile.DieNextFrame = true; } return false; } if (target is Asteroid) { if (!this.explodes) { target.Damage(this, this.damageAmount); } this.Die(null, false); return true; } if (target is ShipModule) { ShipModule module = target as ShipModule; if (module != null && module.GetParent().loyalty == this.loyalty && !this.weapon.HitsFriendlies || module == null) return false; if (this.weapon.TruePD) { this.DieNextFrame = true; return true; } if (module.GetParent().Role == "fighter" && module.GetParent().loyalty.data.Traits.DodgeMod > 0f) { if (((module.GetParent().GetSystem() != null ? module.GetParent().GetSystem().RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(0f, 100f) < module.GetParent().loyalty.data.Traits.DodgeMod * 100f) { this.Miss = true; } } if (this.Miss) { return false; } // Moving this to the Damage function - doesn't seem to be working? Also seems nonsensical. /* if (module.ModuleType == ShipModuleType.Armor || (module.ModuleType == ShipModuleType.Dummy && module.ParentOfDummy.ModuleType == ShipModuleType.Armor)) { this.damageRadius -= module.GetParent().loyalty.data.ExplosiveRadiusReduction * this.damageRadius; this.damageAmount -= module.GetParent().loyalty.data.ExplosiveRadiusReduction * this.damageAmount; this.damageAmount *= this.weapon.EffectVsArmor; this.damageAmount *= this.damageAmount + this.ArmorDamageBonus; } if (module.ModuleType == ShipModuleType.Shield && module.shield_power > 0) { this.damageAmount *= this.weapon.EffectVSShields; this.damageAmount *= this.damageAmount + this.ShieldDamageBonus; //projectiles penetrate weak shields if (this.damageAmount > module.shield_power) { float remainder = 0; module.Damage(this, this.damageAmount, ref remainder); if (remainder > 0) { this.damageAmount = remainder; return false; } else { this.damageAmount = 0; this.explodes = false; this.DieNextFrame = true; return base.Touch(target); } } } */ //Non exploding projectiles should go through multiple modules if it has enough damage if (!this.explodes && module.Active) { float remainder; //Doc: If module has resistance to Armour Piercing effects, deduct that from the projectile's AP before starting AP and damage checks if (module.APResist > 0) { this.ArmorPiercing -= (byte)module.APResist; if (this.ArmorPiercing < 0) this.ArmorPiercing = 0; } if (this.ArmorPiercing == 0 || !(module.ModuleType == ShipModuleType.Armor || (module.ModuleType == ShipModuleType.Dummy && module.ParentOfDummy.ModuleType == ShipModuleType.Armor))) { remainder = 0; module.Damage(this, this.damageAmount, ref remainder); } else { this.ArmorPiercing--; remainder = this.damageAmount; } if (remainder > 0) { this.damageAmount = remainder; bool SlotFound; int depth = 10; Vector2 UnitVector = this.velocity; while (this.damageAmount > 0) { UnitVector.Normalize(); UnitVector *= depth; SlotFound = false; foreach (ModuleSlot slot in module.GetParent().ModuleSlotList) { if (Vector2.Distance(this.Center + UnitVector, slot.module.Center) < 8f) { SlotFound = true; if (slot.module.Active) { if (this.ArmorPiercing > 0 && (slot.module.ModuleType == ShipModuleType.Armor || (slot.module.ModuleType == ShipModuleType.Dummy && slot.module.ParentOfDummy.ModuleType == ShipModuleType.Armor))) break; else { remainder = 0; slot.module.Damage(this, this.damageAmount, ref remainder); if (remainder > 0) this.damageAmount = remainder; else this.damageAmount = 0f; } } break; } } //Slot found means it is still in the ship if (SlotFound) { depth += 8; this.ArmorPiercing--; } else break; } } } base.Health = 0f; } if (this.WeaponEffectType == "Plasma") { Vector3 center = new Vector3(this.Center.X, this.Center.Y, -100f); Vector2 forward = new Vector2((float)Math.Sin((double)base.Rotation), -(float)Math.Cos((double)base.Rotation)); Vector2 right = new Vector2(-forward.Y, forward.X); right = Vector2.Normalize(right); for (int i = 0; i < 20; i++) { Vector3 random = new Vector3(right.X * ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-250f, 250f), right.Y * ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-250f, 250f), ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-250f, 250f)); Projectile.universeScreen.flameParticles.AddParticleThreadA(center, random); random = new Vector3(-forward.X + ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-150f, 150f), -forward.Y + ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-150f, 150f), ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-150f, 150f)); Projectile.universeScreen.flameParticles.AddParticleThreadA(center, random); } } if (this.WeaponEffectType == "MuzzleBlast") // currently unused { Vector3 center = new Vector3(this.Center.X, this.Center.Y, -100f); Vector2 forward = new Vector2((float)Math.Sin((double)base.Rotation), -(float)Math.Cos((double)base.Rotation)); Vector2 right = new Vector2(-forward.Y, forward.X); right = Vector2.Normalize(right); for (int i = 0; i < 20; i++) { Vector3 random = new Vector3(right.X * ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-500f, 500f), right.Y * ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-500f, 500f), ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-250f, 250f)); Projectile.universeScreen.fireTrailParticles.AddParticleThreadA(center, random); random = new Vector3(-forward.X + ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-500f, 500f), -forward.Y + ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-500f, 500f), ((this.system != null ? this.system.RNG : Ship.universeScreen.DeepSpaceRNG)).RandomBetween(-150f, 150f)); Projectile.universeScreen.fireTrailParticles.AddParticleThreadA(center, random); } } else if (this.WeaponType == "Ballistic Cannon") { ShipModule SMtarget = target as ShipModule; if (SMtarget != null && SMtarget.ModuleType != ShipModuleType.Shield) { Cue impact = AudioManager.GetCue("sd_impact_bullet_small_01"); impact.Apply3D(Projectile.universeScreen.listener, this.emitter); impact.Play(); } } } this.DieNextFrame = true; return base.Touch(target); }
private void FireOnTargetNonVisible(Weapon w, GameplayObject fireTarget) { if (this.Owner.Ordinance < w.OrdinanceRequiredToFire || this.Owner.PowerCurrent < w.PowerRequiredToFire) { return; } w.timeToNextFire = w.fireDelay; if (w.IsRepairDrone) { return; } if (TargetShip == null || !TargetShip.Active || TargetShip.dying || !w.TargetValid(TargetShip.Role) || TargetShip.engineState == Ship.MoveState.Warp || !this.Owner.CheckIfInsideFireArc(w, TargetShip)) return; Ship owner = this.Owner; owner.Ordinance = owner.Ordinance - w.OrdinanceRequiredToFire; Ship powerCurrent = this.Owner; powerCurrent.PowerCurrent = powerCurrent.PowerCurrent - w.PowerRequiredToFire; powerCurrent.PowerCurrent -= w.BeamPowerCostPerSecond * w.BeamDuration; this.Owner.InCombatTimer = 15f; if (fireTarget is Projectile) { fireTarget.Damage(w.GetOwner(), w.DamageAmount); return; } if (!(fireTarget is Ship)) { if (fireTarget is ShipModule) { w.timeToNextFire = w.fireDelay; IOrderedEnumerable<ModuleSlot> sortedList = from slot in (fireTarget as ShipModule).GetParent().ExternalSlots orderby Vector2.Distance(slot.module.Center, this.Owner.Center) select slot; float damage = w.DamageAmount; if (w.isBeam) { damage = damage * 90f; } if (w.SalvoCount > 0) { damage = damage * (float)w.SalvoCount; } sortedList.First<ModuleSlot>().module.Damage(this.Owner, damage); } return; } w.timeToNextFire = w.fireDelay; if ((fireTarget as Ship).ExternalSlots.Count == 0) { (fireTarget as Ship).Die(null, true); return; } float nearest = 0; ModuleSlot ClosestES = null; foreach (ModuleSlot ES in (fireTarget as Ship).ExternalSlots) { if (ES.module.ModuleType == ShipModuleType.Dummy || !ES.module.Active || ES.module.Health <= 0) continue; float temp = Vector2.Distance(ES.module.Center, w.GetOwner().Center); if (nearest == 0 || temp < nearest) { nearest = temp; ClosestES = ES; } } if (ClosestES == null) return; // List<ModuleSlot> IEnumerable<ModuleSlot> ExternalSlots = (fireTarget as Ship).ExternalSlots.Where(close => close.module.Active && close.module.quadrant == ClosestES.module.quadrant && close.module.Health > 0);//.ToList(); //.OrderByDescending(shields=> shields.Shield_Power >0);//.ToList(); if ((fireTarget as Ship).shield_power > 0f) { for (int i = 0; i < (fireTarget as Ship).GetShields().Count; i++) { if ((fireTarget as Ship).GetShields()[i].Active && (fireTarget as Ship).GetShields()[i].shield_power > 0f) { float damage = w.DamageAmount; if (w.isBeam) { damage = damage * 90f; } if (w.SalvoCount > 0) { damage = damage * (float)w.SalvoCount; } (fireTarget as Ship).GetShields()[i].Damage(this.Owner, damage); return; } } return; } //this.Owner.GetSystem() != null ? this.Owner.GetSystem().RNG : ArtificialIntelligence.universeScreen.DeepSpaceRNG)).RandomBetween(0f, 100f) <= 50f || if (ExternalSlots.ElementAt(0).module.shield_power > 0f) { for (int i = 0; i < ExternalSlots.Count(); i++) { if (ExternalSlots.ElementAt(i).module.Active && ExternalSlots.ElementAt(i).module.shield_power <= 0f) { float damage = w.DamageAmount; if (w.isBeam) { damage = damage * 90f; } if (w.SalvoCount > 0) { damage = damage * (float)w.SalvoCount; } ExternalSlots.ElementAt(i).module.Damage(this.Owner, damage); return; } } return; } for (int i = 0; i < ExternalSlots.Count(); i++) { if (ExternalSlots.ElementAt(i).module.Active && ExternalSlots.ElementAt(i).module.shield_power <= 0f) { float damage = w.DamageAmount; if (w.isBeam) { damage = damage * 90f; } if (w.SalvoCount > 0) { damage = damage * (float)w.SalvoCount; } ExternalSlots.ElementAt(i).module.Damage(this.Owner, damage); return; } } }