public static float2 GetTurretPosition(Actor self, Unit unit, int[] offset, float recoil) { if( unit == null ) return int2.Zero; /* things that don't have a rotating base don't need the turrets repositioned */ var ru = self.traits.GetOrDefault<RenderUnit>(); var numDirs = (ru != null) ? ru.anim.CurrentSequence.Facings : 8; var bodyFacing = unit.Facing; var quantizedFacing = QuantizeFacing(bodyFacing, numDirs) * (256 / numDirs); return (RotateVectorByFacing(offset.RelOffset(), quantizedFacing, .7f) + GetRecoil(self, recoil)) + offset.AbsOffset(); }
bool CheckFire(Actor self, Unit unit, string weaponName, ref int fireDelay, int[] offset, ref int burst, int[] localOffset) { if (fireDelay > 0) return false; var limitedAmmo = self.traits.GetOrDefault<LimitedAmmo>(); if (limitedAmmo != null && !limitedAmmo.HasAmmo()) return false; var weapon = Rules.Weapons[weaponName.ToLowerInvariant()]; if (weapon.Range * weapon.Range < (target.Location - self.Location).LengthSquared) return false; if (!Combat.WeaponValidForTarget(weapon, target)) return false; var numOffsets = (localOffset.Length + 2) / 3; if (numOffsets == 0) numOffsets = 1; var localOffsetForShot = burst % numOffsets; var thisLocalOffset = localOffset.Skip(3 * localOffsetForShot).Take(3).ToArray(); var fireOffset = new[] { offset.ElementAtOrDefault(0) + thisLocalOffset.ElementAtOrDefault(0), offset.ElementAtOrDefault(1) + thisLocalOffset.ElementAtOrDefault(1), offset.ElementAtOrDefault(2), offset.ElementAtOrDefault(3) }; if (--burst > 0) fireDelay = 5; else { fireDelay = weapon.ROF; burst = weapon.Burst; } var destUnit = target.traits.GetOrDefault<Unit>(); var args = new ProjectileArgs { weapon = Rules.Weapons[weaponName.ToLowerInvariant()], firedBy = self, target = target, src = self.CenterLocation.ToInt2() + Util.GetTurretPosition(self, unit, fireOffset, 0f).ToInt2(), srcAltitude = unit != null ? unit.Altitude : 0, dest = target.CenterLocation.ToInt2(), destAltitude = destUnit != null ? destUnit.Altitude : 0, facing = thisLocalOffset.ElementAtOrDefault(2) + (self.traits.Contains<Turreted>() ? self.traits.Get<Turreted>().turretFacing : unit != null ? unit.Facing : Util.GetFacing(target.CenterLocation - self.CenterLocation, 0)), }; ScheduleDelayedAction( FireDelay( self, self.Info.Traits.Get<AttackBaseInfo>() ), () => { var projectile = args.weapon.Projectile.Create(args); if (projectile != null) self.World.Add(projectile); if (!string.IsNullOrEmpty(args.weapon.Report)) Sound.Play(args.weapon.Report + ".aud"); }); foreach (var na in self.traits.WithInterface<INotifyAttack>()) na.Attacking(self); return true; }