protected override void DoImpact(WPos pos, Actor firedBy, WarheadArgs args) { var world = firedBy.World; if (world.LocalPlayer != null) { var devMode = world.LocalPlayer.PlayerActor.TraitOrDefault <DebugVisualizations>(); if (devMode != null && devMode.CombatGeometry) { WDist[] rng = Exts.MakeArray(Range.Length, i => WDist.FromCells(Range[i].Length)); world.WorldActor.Trait <WarheadDebugOverlay>().AddImpact(pos, rng, DebugOverlayColor); } } var targetTile = world.Map.CellContaining(pos); for (var i = 0; i < Range.Length; i++) { var affectedCells = world.Map.FindTilesInCircle(targetTile, (int)Math.Ceiling((decimal)Range[i].Length / 1024)); var raLayer = world.WorldActor.TraitsImplementing <TintedCellsLayer>() .First(l => l.Info.Name == LayerName); foreach (var cell in affectedCells) { int mul = GetIntensityFalloff((pos - world.Map.CenterOfCell(cell)).Length); IncreaseTintedCellLevel(cell, mul, Falloff[i], raLayer); } } }
public override void DoImpact(Target target, WarheadArgs args) { var firedBy = args.SourceActor; var actors = target.Type == TargetType.Actor ? new[] { target.Actor } : firedBy.World.FindActorsInCircle(target.CenterPosition, Range); foreach (var a in actors) { // Don't do anything on friendly fire if (a.Owner == firedBy.Owner) { continue; } if (Duration == 0) { a.ChangeOwner(firedBy.Owner); // Permanent } else { var tempOwnerManager = a.TraitOrDefault <TemporaryOwnerManager>(); if (tempOwnerManager == null) { continue; } tempOwnerManager.ChangeOwner(a, firedBy.Owner, Duration); } // Stop shooting, you have new enemies a.CancelActivity(); } }
// TODO: Allow maximum resource removal to be defined. (Per tile, and in total). public override void DoImpact(Target target, WarheadArgs args) { if (target.Type == TargetType.Invalid) { return; } var firedBy = args.SourceActor; var pos = target.CenterPosition; var world = firedBy.World; var dat = world.Map.DistanceAboveTerrain(pos); if (dat > AirThreshold) { return; } var targetTile = world.Map.CellContaining(pos); var resLayer = world.WorldActor.Trait <ResourceLayer>(); var minRange = (Size.Length > 1 && Size[1] > 0) ? Size[1] : 0; var allCells = world.Map.FindTilesInAnnulus(targetTile, minRange, Size[0]); // Destroy all resources in the selected tiles foreach (var cell in allCells) { resLayer.Destroy(cell); } }
void Explode(World world, bool removeProjectile) { if (removeProjectile) { world.AddFrameEndTask(w => { w.Remove(this); w.ScreenMap.Remove(this); }); } if (detonated) { return; } var target = Target.FromPos(pos); var warheadArgs = new WarheadArgs { Weapon = weapon, Source = target.CenterPosition, SourceActor = firedBy.PlayerActor, WeaponTarget = target }; weapon.Impact(target, warheadArgs); detonated = true; }
public void Tick(World world) { lastPos = pos; pos += velocity; velocity += acceleration; if (pos.Z <= args.PassiveTarget.Z) { pos += new WVec(0, 0, args.PassiveTarget.Z - pos.Z); world.AddFrameEndTask(w => w.Remove(this)); var warheadArgs = new WarheadArgs(args) { ImpactOrientation = new WRot(WAngle.Zero, Util.GetVerticalAngle(lastPos, pos), args.Facing), ImpactPosition = pos, }; args.Weapon.Impact(Target.FromPos(pos), warheadArgs); } if (anim != null) { anim.Tick(); } }
void Explode(World world, bool removeProjectile) { if (removeProjectile) { world.AddFrameEndTask(w => { w.Remove(this); w.ScreenMap.Remove(this); }); } if (detonated) { return; } var target = Target.FromPos(pos); var warheadArgs = new WarheadArgs { Weapon = weapon, Source = target.CenterPosition, SourceActor = firedBy.PlayerActor, WeaponTarget = target }; weapon.Impact(target, warheadArgs); foreach (var flash in world.WorldActor.TraitsImplementing <FlashPaletteEffect>()) { if (flash.Info.Type == flashType) { flash.Enable(-1); } } detonated = true; }
public override void DoImpact(Target target, WarheadArgs args) { var firedBy = args.SourceActor; // Used by traits or warheads that damage a single actor, rather than a position if (target.Type == TargetType.Actor) { var victim = target.Actor; if (!IsValidAgainst(victim, firedBy)) { return; } var closestActiveShape = victim.TraitsImplementing <HitShape>().Where(Exts.IsTraitEnabled) .MinByOrDefault(t => t.DistanceFromEdge(victim, victim.CenterPosition)); // Cannot be damaged without an active HitShape if (closestActiveShape == null) { return; } InflictDamage(victim, firedBy, closestActiveShape.Info, args.DamageModifiers); } else if (target.Type != TargetType.Invalid) { DoImpact(target.CenterPosition, firedBy, args.DamageModifiers); } }
public override void DoImpact(Target target, WarheadArgs args) { var firedBy = args.SourceActor; var actors = target.Type == TargetType.Actor ? new[] { target.Actor } : firedBy.World.FindActorsInCircle(target.CenterPosition, Range); foreach (var a in actors) { // Don't do anything on friendly fire if (a.Owner == firedBy.Owner) { continue; } if (!target.IsValidFor(firedBy)) { return; } if (!IsValidAgainst(a, firedBy)) { continue; } a.ChangeOwner(a.World.Players.First(p => p.InternalName == Owner)); // Permanent // Stop shooting, you have new enemies a.CancelActivity(); } }
public DelayedImpact(int delay, IWarhead wh, Target target, WarheadArgs args) { this.wh = wh; this.delay = delay; this.target = target; this.args = args; }
public void Tick(World world) { // Check for blocking actors WPos blockedPos; if (info.Blockable) { // If GuidedTarget has become invalid due to getting killed the same tick, // we need to set target to args.PassiveTarget to prevent target.CenterPosition below from crashing. // The warheads have target validity checks themselves so they don't need this, but AnyBlockingActorsBetween does. if (target.Type == TargetType.Invalid) { target = Target.FromPos(args.PassiveTarget); } if (BlocksProjectiles.AnyBlockingActorsBetween(world, args.Source, target.CenterPosition, info.Width, out blockedPos)) { target = Target.FromPos(blockedPos); } } var warheadArgs = new WarheadArgs(args) { ImpactOrientation = new WRot(WAngle.Zero, Util.GetVerticalAngle(args.Source, target.CenterPosition), args.Facing), ImpactPosition = target.CenterPosition, }; args.Weapon.Impact(target, warheadArgs); world.AddFrameEndTask(w => w.Remove(this)); }
void ITick.Tick(Actor self) { if (IsTraitDisabled) { return; } var density = info.Density.Length == 2 ? world.SharedRandom.Next(info.Density[0], info.Density[1]) : info.Density[0]; var weapons = mapsize * density / 1000; var firer = info.Enemy ? world.Players.First(x => x.PlayerName == info.Owner).PlayerActor : world.WorldActor; for (var i = 0; i < weapons; i++) { var tpos = world.Map.CenterOfCell(world.Map.ChooseRandomCell(world.SharedRandom)) + new WVec(WDist.Zero, WDist.Zero, info.Altitude); var args = new WarheadArgs { Weapon = info.WeaponInfo, Source = tpos, SourceActor = firer, WeaponTarget = Target.FromPos(tpos) }; info.WeaponInfo.Impact(Target.FromPos(tpos), args); } }
public override void DoImpact(Target target, WarheadArgs args) { if (target.Type == TargetType.Invalid) { return; } var firedBy = args.SourceActor; var map = firedBy.World.Map; var targetCell = map.CellContaining(target.CenterPosition); var targetCells = CellsMatching(targetCell, false); foreach (var c in targetCells) { FireProjectileAtCell(map, firedBy, target, c, args); } if (RandomClusterCount != 0) { var randomTargetCells = CellsMatching(targetCell, true); var clusterCount = RandomClusterCount < 0 ? randomTargetCells.Count() : RandomClusterCount; if (randomTargetCells.Any()) { for (var i = 0; i < clusterCount; i++) { FireProjectileAtCell(map, firedBy, target, randomTargetCells.Random(firedBy.World.SharedRandom), args); } } } }
public void Tick(World world) { if (--delay < 0) { WPos target; if (args.GuidedTarget.IsValidFor(args.SourceActor)) { target = args.GuidedTarget.CenterPosition + new WVec(WDist.Zero, WDist.Zero, altitude); } else { target = args.PassiveTarget + new WVec(WDist.Zero, WDist.Zero, altitude); } world.AddFrameEndTask(w => w.Remove(this)); var warheadArgs = new WarheadArgs(args) { ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(args.Source, target), args.CurrentMuzzleFacing()), ImpactPosition = target, }; args.Weapon.Impact(Target.FromPos(target), warheadArgs); } }
public void Tick(World world) { if (!exploded) { lastPos = pos; pos += velocity; velocity += acceleration; if (pos.Z <= args.PassiveTarget.Z) { pos += new WVec(0, 0, args.PassiveTarget.Z - pos.Z); var warheadArgs = new WarheadArgs(args) { ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(lastPos, pos), args.Facing), ImpactPosition = pos, }; args.Weapon.Impact(Target.FromPos(pos), warheadArgs); exploded = true; if (!string.IsNullOrEmpty(info.ParachuteClosingSequence)) { parachute.PlayThen(info.ParachuteClosingSequence, () => world.AddFrameEndTask(w => w.Remove(this))); } else { parachute.PlayBackwardsThen(info.ParachuteOpeningSequence, () => world.AddFrameEndTask(w => w.Remove(this))); } } if (!exploded && !string.IsNullOrEmpty(info.PointDefenseType)) { var shouldExplode = world.ActorsWithTrait <IPointDefense>().Any(x => x.Trait.Destroy(pos, args.SourceActor.Owner, info.PointDefenseType)); if (shouldExplode) { var warheadArgs = new WarheadArgs(args) { ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(lastPos, pos), args.Facing), ImpactPosition = pos, }; args.Weapon.Impact(Target.FromPos(pos), warheadArgs); exploded = true; world.AddFrameEndTask(w => w.Remove(this)); } } if (anim != null) { anim.Tick(); } } if (parachute != null) { parachute.Tick(); } }
public override void DoImpact(Target target, WarheadArgs args) { var firedBy = args.SourceActor; if (!target.IsValidFor(firedBy)) { return; } var map = firedBy.World.Map; var targetCell = map.CellContaining(target.CenterPosition); var targetCells = map.FindTilesInCircle(targetCell, Range); var cell = targetCells.GetEnumerator(); foreach (var a in Actors) { var td = new TypeDictionary(); var ai = map.Rules.Actors[a.ToLowerInvariant()]; td.Add(new OwnerInit(firedBy.World.Players.First(p => p.InternalName == InternalOwner))); while (cell.MoveNext()) { if (!firedBy.World.ActorMap.GetActorsAt(cell.Current).Any() && TerrainTypes.Contains(firedBy.World.Map.GetTerrainInfo(cell.Current).Type)) { td.Add(new LocationInit(cell.Current)); var unit = firedBy.World.CreateActor(false, a.ToLowerInvariant(), td); firedBy.World.AddFrameEndTask(w => { w.Add(unit); var palette = Palette; if (UsePlayerPalette) { palette += unit.Owner.InternalName; } var spawn = firedBy.World.Map.CenterOfCell(cell.Current); if (Image != null) { w.Add(new SpriteEffect(spawn, w, Image, Sequence, palette)); } var sound = Sounds.RandomOrDefault(firedBy.World.LocalRandom); if (sound != null) { Game.Sound.Play(SoundType.World, sound, spawn); } }); break; } } } }
protected override void DoImpact(WPos pos, Actor firedBy, WarheadArgs args) { var debugVis = firedBy.World.WorldActor.TraitOrDefault <DebugVisualizations>(); if (debugVis != null && debugVis.CombatGeometry) { firedBy.World.WorldActor.Trait <WarheadDebugOverlay>().AddImpact(pos, Range, DebugOverlayColor); } foreach (var victim in firedBy.World.FindActorsOnCircle(pos, Range[Range.Length - 1])) { if (!IsValidAgainst(victim, firedBy)) { continue; } var closestActiveShape = victim.TraitsImplementing <HitShape>() .Where(Exts.IsTraitEnabled) .Select(s => Pair.New(s, s.DistanceFromEdge(victim, pos))) .MinByOrDefault(s => s.Second); // Cannot be damaged without an active HitShape. if (closestActiveShape.First == null) { continue; } var falloffDistance = 0; switch (DamageCalculationType) { case DamageCalculationType.HitShape: falloffDistance = closestActiveShape.Second.Length; break; case DamageCalculationType.ClosestTargetablePosition: falloffDistance = victim.GetTargetablePositions().Select(x => (x - pos).Length).Min(); break; case DamageCalculationType.CenterPosition: falloffDistance = (victim.CenterPosition - pos).Length; break; } // The range to target is more than the range the warhead covers, so GetDamageFalloff() is going to give us 0 and we're going to do 0 damage anyway, so bail early. if (falloffDistance > Range[Range.Length - 1].Length) { continue; } var localModifiers = args.DamageModifiers.Append(GetDamageFalloff(falloffDistance)); var updatedWarheadArgs = new WarheadArgs(args) { DamageModifiers = localModifiers.ToArray(), }; InflictDamage(victim, firedBy, closestActiveShape.First, updatedWarheadArgs); } }
protected override void DoImpact(WPos pos, Actor firedBy, WarheadArgs args) { if (Spread == WDist.Zero) { return; } var debugVis = firedBy.World.WorldActor.TraitOrDefault <DebugVisualizations>(); if (debugVis != null && debugVis.CombatGeometry) { firedBy.World.WorldActor.Trait <WarheadDebugOverlay>().AddImpact(pos, new[] { WDist.Zero, Spread }, DebugOverlayColor); } foreach (var victim in firedBy.World.FindActorsOnCircle(pos, Spread)) { if (!IsValidAgainst(victim, firedBy)) { continue; } var closestActiveShape = victim.TraitsImplementing <HitShape>() .Where(Exts.IsTraitEnabled) .Select(s => Pair.New(s, s.DistanceFromEdge(victim, pos))) .MinByOrDefault(s => s.Second); // Cannot be damaged without an active HitShape or if HitShape is outside Spread if (closestActiveShape.First == null || closestActiveShape.Second > Spread) { continue; } var building = victim.TraitOrDefault <Building>(); var adjustedDamageModifiers = args.DamageModifiers.Append(DamageVersus(victim, closestActiveShape.First, args)); if (MaxAffect > 0 && building != null) { var affectedcells = building.OccupiedCells().Select(x => (pos - firedBy.World.Map.CenterOfCell(x.First)).Length) .Where(x => x > Spread.Length).OrderBy(x => x).Take(MaxAffect); var delivereddamage = 0; foreach (var c in affectedcells) { delivereddamage += Util.ApplyPercentageModifiers(Damage, adjustedDamageModifiers.Append(int2.Lerp(PercentAtMax, 100, c, Spread.Length))); } victim.InflictDamage(firedBy, new Damage(delivereddamage, DamageTypes)); } else { var damage = Util.ApplyPercentageModifiers(Damage, adjustedDamageModifiers.Append(int2.Lerp(PercentAtMax, 100, closestActiveShape.Second.Length, Spread.Length))); victim.InflictDamage(firedBy, new Damage(damage, DamageTypes)); } } }
public override void DoImpact(Target target, WarheadArgs args) { var firedBy = args.SourceActor; if (!target.IsValidFor(firedBy)) { return; } var map = firedBy.World.Map; var targetCell = map.CellContaining(target.CenterPosition); if (!IsValidImpact(target.CenterPosition, firedBy)) { return; } var targetCells = map.FindTilesInCircle(targetCell, Range); var cell = targetCells.GetEnumerator(); foreach (var passenger in args.SourceActor.TraitOrDefault <Cargo>().Passengers) { var a = passenger.Info.Name; //var placed = false; var td = new TypeDictionary(); var ai = map.Rules.Actors[a.ToLowerInvariant()]; if (OwnerType == ASOwnerType.Attacker) { td.Add(new OwnerInit(firedBy.Owner)); } else { td.Add(new OwnerInit(firedBy.World.Players.First(p => p.InternalName == InternalOwner))); } firedBy.World.AddFrameEndTask(w => { firedBy.TraitOrDefault <ProductionCA>().Produce(firedBy, passenger.Info, firedBy.TraitOrDefault <ProductionCA>().Info.Produces[0], td, unit => { //Game.Debug(String.Join("; ", firedBy.TraitOrDefault<Production>() )); if (passenger.TraitOrDefault <Cargo>() != null) { foreach (var p in passenger.TraitOrDefault <Cargo>().Passengers) { //Game.Debug(String.Join("; ", passenger.TraitOrDefault<Cargo>().Passengers)); //Game.Debug(p.Info.Name); var newPassenger = firedBy.World.CreateActor(false, p.Info.Name, td); unit.TraitOrDefault <Cargo>().Load(unit, newPassenger); } } }); }); } }
public override void DoImpact(Target target, WarheadArgs args) { foreach (var flash in args.SourceActor.World.WorldActor.TraitsImplementing <FlashPaletteEffect>()) { if (flash.Info.Type == FlashType) { flash.Enable(Duration); } } }
public DelayedWeaponTrigger(AttachDelayedWeaponWarhead warhead, WarheadArgs args) { this.args = args; TriggerTime = warhead.TriggerTime; RemainingTime = TriggerTime; DeathTypes = warhead.DeathTypes; weaponInfo = warhead.WeaponInfo; AttachedBy = args.SourceActor; IsValid = true; }
public void Impact() { var pos = forceToGround ? projectilepos - new WVec(0, 0, world.Map.DistanceAboveTerrain(projectilepos).Length) : projectilepos; var warheadArgs = new WarheadArgs(args) { ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(lastPos, projectilepos), args.Facing), ImpactPosition = pos, }; args.Weapon.Impact(Target.FromPos(pos), warheadArgs); }
public override void DoImpact(Target target, WarheadArgs args) { if (target.Type == TargetType.Invalid) { return; } var firedBy = args.SourceActor; var world = firedBy.World; if (Chance < world.LocalRandom.Next(100)) { return; } var pos = target.CenterPosition; var dat = world.Map.DistanceAboveTerrain(pos); if (dat > AirThreshold) { return; } var targetTile = world.Map.CellContaining(pos); var smudgeLayers = world.WorldActor.TraitsImplementing <SmudgeLayer>().ToDictionary(x => x.Info.Type); var minRange = (Size.Length > 1 && Size[1] > 0) ? Size[1] : 0; var allCells = world.Map.FindTilesInAnnulus(targetTile, minRange, Size[0]); // Draw the smudges: foreach (var sc in allCells) { var smudgeType = world.Map.GetTerrainInfo(sc).AcceptsSmudgeType.FirstOrDefault(SmudgeType.Contains); if (smudgeType == null) { continue; } var cellActors = world.ActorMap.GetActorsAt(sc); if (cellActors.Any(a => !IsValidAgainst(a, firedBy))) { continue; } SmudgeLayer smudgeLayer; if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer)) { throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType)); } smudgeLayer.AddSmudge(sc); } }
public void Tick(World world) { if (ticks == 0) { if (hitanim != null) { hitanim.PlayThen(info.HitAnimSequence, () => animationComplete = true); } else { animationComplete = true; } if (info.LineWidth.Length > 0) { var actors = world.FindActorsOnLine(args.Source, target, info.LineWidth); foreach (var a in actors) { var warheadArgs = new WarheadArgs(args) { ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(args.Source, target), args.Facing), // Calculating an impact position is bogus for line damage. // FindActorsOnLine guarantees that the beam touches the target's HitShape, // so we just assume a center hit to avoid bogus warhead recalculations. ImpactPosition = a.CenterPosition, }; args.Weapon.Impact(Target.FromActor(a), warheadArgs); } } else { var warheadArgs = new WarheadArgs(args) { ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(args.Source, target), args.Facing), ImpactPosition = target, }; args.Weapon.Impact(Target.FromPos(target), warheadArgs); } } if (hitanim != null) { hitanim.Tick(); } if (ticks++ > info.Duration && animationComplete) { world.AddFrameEndTask(w => w.Remove(this)); } }
public override void DoImpact(Target target, WarheadArgs args) { args.SourceActor.World.AddFrameEndTask(world => { world.CreateActor(BitActors.Random(world.SharedRandom), new TypeDictionary { new LocationInit(world.Map.CellContaining(target.CenterPosition)), new ColonyBitInit(args.SourceActor), new OwnerInit(world.Players.First(player => player.InternalName == "Neutral")) }); }); }
public void Tick(World world) { lastPos = pos; if (--lifetime < 0) { world.AddFrameEndTask(w => { w.Remove(this); w.ScreenMap.Remove(this); }); return; } if (--randomRate < 0) { var forward = speed.Length == 2 ? world.SharedRandom.Next(speed[0].Length, speed[1].Length) : speed[0].Length; var height = gravity.Length == 2 ? world.SharedRandom.Next(gravity[0].Length, gravity[1].Length) : gravity[0].Length; offset = new WVec(forward, 0, height); if (turnRate > 0) { facing = (facing + world.SharedRandom.Next(-turnRate, turnRate)) & 0xFF; } offset = offset.Rotate(WRot.FromFacing(facing)); randomRate = smoke.RandomRate; } anim.Tick(); pos += offset; world.ScreenMap.Update(this, pos, anim.Image); if (canDamage && --explosionInterval < 0) { var args = new WarheadArgs { Weapon = smoke.Weapon, Source = pos, SourceActor = invoker, WeaponTarget = Target.FromPos(pos), ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(lastPos, pos), WAngle.FromFacing(facing)), ImpactPosition = pos }; smoke.Weapon.Impact(Target.FromPos(pos), args); explosionInterval = smoke.Weapon.ReloadDelay; } }
public void Tick(World world) { world.AddFrameEndTask(w => w.Remove(this)); var warheadArgs = new WarheadArgs(args) { ImpactOrientation = new WRot(WAngle.Zero, WAngle.Zero, args.CurrentMuzzleFacing()), ImpactPosition = args.Source, }; args.Weapon.Impact(Target.FromPos(args.Source), warheadArgs); }
public void Tick(World world) { source = args.CurrentSource(); if (hasLaunchEffect && ticks == 0) { world.AddFrameEndTask(w => w.Add(new SpriteEffect(args.CurrentSource, args.CurrentMuzzleFacing, world, info.LaunchEffectImage, info.LaunchEffectSequence, info.LaunchEffectPalette))); } // Beam tracks target if (info.TrackTarget && args.GuidedTarget.IsValidFor(args.SourceActor)) { target = args.Weapon.TargetActorCenter ? args.GuidedTarget.CenterPosition : args.GuidedTarget.Positions.PositionClosestTo(source); } // Check for blocking actors WPos blockedPos; if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, source, target, info.Width, out blockedPos)) { target = blockedPos; } if (ticks < info.DamageDuration && --interval <= 0) { var warheadArgs = new WarheadArgs(args) { ImpactOrientation = new WRot(WAngle.Zero, Util.GetVerticalAngle(source, target), args.CurrentMuzzleFacing()), ImpactPosition = target, }; args.Weapon.Impact(Target.FromPos(target), warheadArgs); interval = info.DamageInterval; } if (showHitAnim) { if (ticks == 0) { hitanim.PlayThen(info.HitAnimSequence, () => showHitAnim = false); } hitanim.Tick(); } if (++ticks >= info.Duration && !showHitAnim) { world.AddFrameEndTask(w => w.Remove(this)); } }
public override void DoImpact(Target target, WarheadArgs args) { if (target.Type == TargetType.Invalid) { return; } var firedBy = args.SourceActor; var pos = target.CenterPosition; var world = firedBy.World; var actorAtImpact = ImpactActors ? ActorTypeAtImpact(world, pos, firedBy) : ImpactActorType.None; // Ignore the impact if there are only invalid actors within range if (actorAtImpact == ImpactActorType.Invalid) { return; } // Ignore the impact if there are no valid actors and no valid terrain // (impacts are allowed on valid actors sitting on invalid terrain!) if (actorAtImpact == ImpactActorType.None && !IsValidAgainstTerrain(world, pos)) { return; } var explosion = Explosions.RandomOrDefault(world.LocalRandom); if (Image != null && explosion != null) { if (ForceDisplayAtGroundLevel) { var dat = world.Map.DistanceAboveTerrain(pos); pos -= new WVec(0, 0, dat.Length); } var palette = ExplosionPalette; if (UsePlayerPalette) { palette += firedBy.Owner.InternalName; } world.AddFrameEndTask(w => w.Add(new SpriteEffect(pos, w, Image, explosion, palette))); } var impactSound = ImpactSounds.RandomOrDefault(world.LocalRandom); if (impactSound != null && world.LocalRandom.Next(0, 100) < ImpactSoundChance) { Game.Sound.Play(SoundType.World, impactSound, pos); } }
public override void DoImpact(Target target, WarheadArgs args) { if (target.Type == TargetType.Invalid) { return; } var firedBy = args.SourceActor; var world = firedBy.World; var layer = world.WorldActor.Trait <BuildableTerrainLayer>(); var cell = world.Map.CellContaining(target.CenterPosition); layer.HitTile(cell, Damage); }
public override void DoImpact(Target target, WarheadArgs args) { var firedBy = args.SourceActor; if (!target.IsValidFor(firedBy)) { return; } var pos = target.CenterPosition; if (!IsValidImpact(pos, firedBy)) { return; } var availableActors = firedBy.World.FindActorsOnCircle(pos, Range); foreach (var actor in availableActors) { if (!IsValidAgainst(actor, firedBy)) { continue; } if (actor.IsDead) { continue; } var activeShapes = actor.TraitsImplementing <HitShape>().Where(Exts.IsTraitEnabled); if (!activeShapes.Any()) { continue; } var distance = activeShapes.Min(t => t.DistanceFromEdge(actor, pos)); if (distance > Range) { continue; } var attachable = actor.TraitsImplementing <DelayedWeaponAttachable>().FirstOrDefault(a => a.CanAttach(Type)); if (attachable != null) { attachable.Attach(new DelayedWeaponTrigger(this, args)); } } }