public SupportPowerTimerWidget(World world) { powers = world.ActorsWithTrait<SupportPowerManager>() .Where(p => !p.Actor.IsDead() && !p.Actor.Owner.NonCombatant) .SelectMany(s => s.Trait.Powers.Values) .Where(p => p.Instances.Any() && p.Info.DisplayTimer && !p.Disabled); }
IEnumerable <IFinalizedRenderable> GenerateOverlayRenderables() { var actors = World.ActorsWithTrait <IRenderAboveShroud>() .Where(a => a.Actor.IsInWorld && !a.Actor.Disposed && (!a.Trait.SpatiallyPartitionable || onScreenActors.Contains(a.Actor))) .SelectMany(a => a.Trait.RenderAboveShroud(a.Actor, this)); var selected = World.Selection.Actors.Where(a => a.IsInWorld && !a.Disposed) .SelectMany(a => a.TraitsImplementing <IRenderAboveShroudWhenSelected>() .Where(t => !t.SpatiallyPartitionable || onScreenActors.Contains(a)) .SelectMany(t => t.RenderAboveShroud(a, this))); var effects = World.Effects.Select(e => e as IEffectAboveShroud) .Where(e => e != null) .SelectMany(e => e.RenderAboveShroud(this)); var orderGenerator = SpriteRenderable.None; if (World.OrderGenerator != null) { orderGenerator = World.OrderGenerator.RenderAboveShroud(this, World); } return(actors .Concat(selected) .Concat(effects) .Concat(orderGenerator) .Select(r => r.PrepareRender(this))); }
bool CycleBases() { var bases = world.ActorsWithTrait <BaseBuilding>() .Where(a => a.Actor.Owner == world.LocalPlayer) .Select(b => b.Actor) .ToList(); if (!bases.Any()) { return(true); } var next = bases .SkipWhile(b => !world.Selection.Actors.Contains(b)) .Skip(1) .FirstOrDefault(); if (next == null) { next = bases.First(); } world.Selection.Combine(world, new Actor[] { next }, false, true); return(ToSelection()); }
List <IFinalizedRenderable> GenerateOverlayRenderables() { var aboveShroud = World.ActorsWithTrait <IRenderAboveShroud>() .Where(a => a.Actor.IsInWorld && !a.Actor.Disposed && (!a.Trait.SpatiallyPartitionable || onScreenActors.Contains(a.Actor))) .SelectMany(a => a.Trait.RenderAboveShroud(a.Actor, this)); var aboveShroudSelected = World.Selection.Actors.Where(a => a.IsInWorld && !a.Disposed) .SelectMany(a => a.TraitsImplementing <IRenderAboveShroudWhenSelected>() .Where(t => !t.SpatiallyPartitionable || onScreenActors.Contains(a)) .SelectMany(t => t.RenderAboveShroud(a, this))); var aboveShroudEffects = World.Effects.Select(e => e as IEffectAboveShroud) .Where(e => e != null) .SelectMany(e => e.RenderAboveShroud(this)); var aboveShroudOrderGenerator = SpriteRenderable.None; if (World.OrderGenerator != null) { aboveShroudOrderGenerator = World.OrderGenerator.RenderAboveShroud(this, World); } var overlayRenderables = aboveShroud .Concat(aboveShroudSelected) .Concat(aboveShroudEffects) .Concat(aboveShroudOrderGenerator); Game.Renderer.WorldModelRenderer.BeginFrame(); var finalOverlayRenderables = overlayRenderables.Select(r => r.PrepareRender(this)).ToList(); Game.Renderer.WorldModelRenderer.EndFrame(); return(finalOverlayRenderables); }
void Init() { var visible = world.ActorsWithTrait <StrategicVictoryConditions>().Any() && world.ActorsWithTrait <StrategicPoint>().Any(); IsVisible = () => visible; initialised = true; }
// PERF: Avoid LINQ. void GenerateOverlayRenderables() { foreach (var a in World.ActorsWithTrait <IRenderAboveShroud>()) { if (!a.Actor.IsInWorld || a.Actor.Disposed || (a.Trait.SpatiallyPartitionable && !onScreenActors.Contains(a.Actor))) { continue; } foreach (var renderable in a.Trait.RenderAboveShroud(a.Actor, this)) { preparedOverlayRenderables.Add(renderable.PrepareRender(this)); } } foreach (var a in World.Selection.Actors) { if (!a.IsInWorld || a.Disposed) { continue; } foreach (var t in a.TraitsImplementing <IRenderAboveShroudWhenSelected>()) { if (t.SpatiallyPartitionable && !onScreenActors.Contains(a)) { continue; } foreach (var renderable in t.RenderAboveShroud(a, this)) { preparedOverlayRenderables.Add(renderable.PrepareRender(this)); } } } foreach (var e in World.Effects) { var ea = e as IEffectAboveShroud; if (ea == null) { continue; } foreach (var renderable in ea.RenderAboveShroud(this)) { preparedOverlayRenderables.Add(renderable.PrepareRender(this)); } } if (World.OrderGenerator != null) { foreach (var renderable in World.OrderGenerator.RenderAboveShroud(this, World)) { preparedOverlayRenderables.Add(renderable.PrepareRender(this)); } } }
public void Tick(World world) { lastPos = pos; pos += velocity; velocity += acceleration; if (!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, Util.GetVerticalAngle(lastPos, pos), args.Facing), ImpactPosition = pos, }; args.Weapon.Impact(Target.FromPos(pos), warheadArgs); world.AddFrameEndTask(w => w.Remove(this)); return; } } 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 (!string.IsNullOrEmpty(info.PointDefenseType)) { var shouldExplode = world.ActorsWithTrait <IPointDefense>().Any(x => x.Trait.Destroy(pos, args.SourceActor.Owner, info.PointDefenseType)); if (shouldExplode) { args.Weapon.Impact(Target.FromPos(pos), new WarheadArgs(args)); world.AddFrameEndTask(w => w.Remove(this)); } } anim?.Tick(); }
WVec HomingTick(World world, WVec tarDistVec, int relTarHorDist) { int predClfHgt, predClfDist, lastHtChg, lastHt; InclineLookahead(world, relTarHorDist, out predClfHgt, out predClfDist, out lastHtChg, out lastHt); // Height difference between the incline height and missile height var diffClfMslHgt = predClfHgt - pos.Z; // Get underestimate of distance from target in next tick var nxtRelTarHorDist = (relTarHorDist - speed - info.Acceleration.Length).Clamp(0, relTarHorDist); // Target height relative to the missile var relTarHgt = tarDistVec.Z; // Compute which direction the projectile should be facing var desiredHFacing = OpenRA.Traits.Util.GetFacing(tarDistVec + predVel, hFacing); if (allowPassBy && System.Math.Abs(desiredHFacing - hFacing) >= System.Math.Abs(desiredHFacing + 128 - hFacing)) { desiredHFacing += 128; targetPassedBy = true; } else { targetPassedBy = false; } var desiredVFacing = HomingInnerTick(predClfDist, diffClfMslHgt, relTarHorDist, lastHtChg, lastHt, nxtRelTarHorDist, relTarHgt, vFacing, targetPassedBy); // The target has been passed by if (tarDistVec.HorizontalLength < speed * WAngle.FromFacing(vFacing).Cos() / 1024) { targetPassedBy = true; } // Check whether the homing mechanism is jammed var jammed = info.Jammable && world.ActorsWithTrait <JamsMissiles>().Any(JammedBy); if (jammed) { desiredHFacing = hFacing + world.SharedRandom.Next(-info.JammedDiversionRange, info.JammedDiversionRange + 1); desiredVFacing = vFacing + world.SharedRandom.Next(-info.JammedDiversionRange, info.JammedDiversionRange + 1); } else if (!args.GuidedTarget.IsValidFor(args.SourceActor)) { desiredHFacing = hFacing; } // Compute new direction the projectile will be facing hFacing = OpenRA.Traits.Util.TickFacing(hFacing, desiredHFacing, info.HorizontalRateOfTurn); vFacing = OpenRA.Traits.Util.TickFacing(vFacing, desiredVFacing, info.VerticalRateOfTurn); // Compute the projectile's guided displacement return(new WVec(0, -1024 * speed, 0) .Rotate(new WRot(WAngle.FromFacing(vFacing), WAngle.Zero, WAngle.Zero)) .Rotate(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(hFacing))) / 1024); }
public IngameRadarDisplayLogic(Widget widget, World world) { var radarEnabled = false; var cachedRadarEnabled = false; var blockColor = Color.Transparent; var radar = widget.Get<RadarWidget>("RADAR_MINIMAP"); radar.IsEnabled = () => radarEnabled; var devMode = world.LocalPlayer.PlayerActor.Trait<DeveloperMode>(); var ticker = widget.Get<LogicTickerWidget>("RADAR_TICKER"); ticker.OnTick = () => { radarEnabled = devMode.DisableShroud || world.ActorsWithTrait<ProvidesRadar>() .Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive); if (radarEnabled != cachedRadarEnabled) Game.Sound.PlayNotification(world.Map.Rules, null, "Sounds", radarEnabled ? "RadarUp" : "RadarDown", null); cachedRadarEnabled = radarEnabled; }; var block = widget.GetOrNull<ColorBlockWidget>("RADAR_FADETOBLACK"); if (block != null) { radar.Animating = x => blockColor = Color.FromArgb((int)(255 * x), Color.Black); block.IsVisible = () => blockColor.A != 0; block.GetColor = () => blockColor; } }
public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { var armaments = ai.Traits.WithInterface <ArmamentInfo>(); var range = FallbackRange; if (armaments.Any()) { range = armaments.Select(a => w.Map.Rules.Weapons[a.Weapon.ToLowerInvariant()].Range).Max(); } if (range == WRange.Zero) { return; } wr.DrawRangeCircleWithContrast( centerPosition, range, Color.FromArgb(128, Color.Yellow), Color.FromArgb(96, Color.Black) ); foreach (var a in w.ActorsWithTrait <RenderRangeCircle>()) { if (a.Actor.Owner == a.Actor.World.LocalPlayer) { if (a.Actor.Info.Traits.Get <RenderRangeCircleInfo>().RangeCircleType == RangeCircleType) { a.Trait.RenderAfterWorld(wr); } } } }
public static void Chronoshift(World world, List <Pair <Actor, int2> > units, Actor chronosphere, int duration, bool killCargo) { if (chronosphere != null) { chronosphere.Trait <RenderBuilding>().PlayCustomAnim(chronosphere, "active"); } // Trigger screen desaturate effect foreach (var a in world.ActorsWithTrait <ChronoshiftPaletteEffect>()) { a.Trait.Enable(); } Sound.Play("chrono2.aud", units.First().First.CenterLocation); foreach (var kv in units) { var target = kv.First; var targetCell = kv.Second; var cs = target.Trait <Chronoshiftable>(); if (cs.CanChronoshiftTo(target, targetCell, true)) { cs.Teleport(target, targetCell, duration, killCargo, chronosphere); } } }
public static Bitmap ActorsBitmap(World world) { var map = world.Map; var b = map.Bounds; var size = Exts.NextPowerOf2(Math.Max(b.Width, b.Height)); var bitmap = new Bitmap(size, size); var bitmapData = bitmap.LockBits(bitmap.Bounds(), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); unsafe { var colors = (int*)bitmapData.Scan0; var stride = bitmapData.Stride / 4; foreach (var t in world.ActorsWithTrait<IRadarSignature>()) { if (world.FogObscures(t.Actor)) continue; var color = t.Trait.RadarSignatureColor(t.Actor); foreach (var cell in t.Trait.RadarSignatureCells(t.Actor)) { var uv = Map.CellToMap(map.TileShape, cell); if (b.Contains(uv.X, uv.Y)) colors[(uv.Y - b.Top) * stride + uv.X - b.Left] = color.ToArgb(); } } } bitmap.UnlockBits(bitmapData); return bitmap; }
public static Bitmap ActorsBitmap(World world) { var map = world.Map; var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height)); var bitmap = new Bitmap(size, size); var bitmapData = bitmap.LockBits(bitmap.Bounds(), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); unsafe { int *c = (int *)bitmapData.Scan0; foreach (var t in world.ActorsWithTrait <IRadarSignature>()) { if (world.FogObscures(t.Actor)) { continue; } var color = t.Trait.RadarSignatureColor(t.Actor); foreach (var cell in t.Trait.RadarSignatureCells(t.Actor)) { if (world.Map.IsInMap(cell)) { *(c + ((cell.Y - world.Map.Bounds.Top) * bitmapData.Stride >> 2) + cell.X - world.Map.Bounds.Left) = color.ToArgb(); } } } } bitmap.UnlockBits(bitmapData); return(bitmap); }
public void Tick() { // Only update once per second or so if (--waitTicks > 0) { return; } playerBuildings = world.ActorsWithTrait <Building>() .Where(a => a.Actor.Owner == player) .Select(a => a.Actor) .ToArray(); var active = false; foreach (var queue in ai.FindQueues(category)) { if (TickQueue(queue)) { active = true; } } waitTicks = active ? ai.Info.StructureProductionActiveDelay : ai.Info.StructureProductionInactiveDelay; }
public IngameRadarDisplayLogic(Widget widget, World world) { var radarEnabled = false; var cachedRadarEnabled = false; var blockColor = Color.Transparent; var radar = widget.Get <RadarWidget>("RADAR_MINIMAP"); radar.IsEnabled = () => radarEnabled; var ticker = widget.Get <LogicTickerWidget>("RADAR_TICKER"); ticker.OnTick = () => { radarEnabled = world.ActorsWithTrait <ProvidesRadar>() .Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive); if (radarEnabled != cachedRadarEnabled) { Sound.PlayNotification(world.Map.Rules, null, "Sounds", radarEnabled ? "RadarUp" : "RadarDown", null); } cachedRadarEnabled = radarEnabled; }; var block = widget.GetOrNull <ColorBlockWidget>("RADAR_FADETOBLACK"); if (block != null) { radar.Animating = x => blockColor = Color.FromArgb((int)(255 * x), Color.Black); block.IsVisible = () => blockColor.A != 0; block.GetColor = () => blockColor; } }
public override void Tick() { VisibleQueues.Clear(); var queues = world.ActorsWithTrait <ProductionQueue>() .Where(p => p.Actor.Owner == world.LocalPlayer) .Select(p => p.Trait); if (CurrentQueue != null && CurrentQueue.Actor.Destroyed) { CurrentQueue = null; } foreach (var queue in queues) { if (queue.AllItems().Any()) { VisibleQueues.Add(queue); } else if (CurrentQueue == queue) { CurrentQueue = null; } } if (CurrentQueue == null) { CurrentQueue = VisibleQueues.FirstOrDefault(); } TickPaletteAnimation(world); }
public IEnumerable <IRenderable> Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { var jamsMissiles = ai.TraitInfoOrDefault <JamsMissilesInfo>(); if (jamsMissiles != null) { yield return(new RangeCircleRenderable( centerPosition, jamsMissiles.Range, 0, Color.FromArgb(128, Color.Red), Color.FromArgb(96, Color.Black))); } foreach (var a in w.ActorsWithTrait <RenderJammerCircle>()) { if (a.Actor.Owner.IsAlliedWith(w.RenderPlayer)) { foreach (var r in a.Trait.RenderAboveShroud(a.Actor, wr)) { yield return(r); } } } }
public IEnumerable<IRenderable> Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { var jamsMissiles = ai.TraitInfoOrDefault<JamsMissilesInfo>(); if (jamsMissiles != null) { yield return new RangeCircleRenderable( centerPosition, jamsMissiles.Range, 0, Color.FromArgb(128, Color.Red), Color.FromArgb(96, Color.Black)); } var jamsRadar = ai.TraitInfoOrDefault<JamsRadarInfo>(); if (jamsRadar != null) { yield return new RangeCircleRenderable( centerPosition, jamsRadar.Range, 0, Color.FromArgb(128, Color.Blue), Color.FromArgb(96, Color.Black)); } foreach (var a in w.ActorsWithTrait<RenderJammerCircle>()) if (a.Actor.Owner.IsAlliedWith(w.RenderPlayer)) foreach (var r in a.Trait.RenderAfterWorld(wr)) yield return r; }
public IEnumerable <IRenderable> RenderAnnotations(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { if (EnabledByDefault) { yield return(new RangeCircleAnnotationRenderable( centerPosition, Range, 0, Color, Width, BorderColor, BorderWidth)); foreach (var a in w.ActorsWithTrait <WithRangeCircle>()) { if (a.Trait.Info.Type == Type) { foreach (var r in a.Trait.RenderRangeCircle(a.Actor, wr, RangeCircleVisibility.WhenSelected)) { yield return(r); } } } } }
public IEnumerable <IRenderable> Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { if (range == WDist.Zero) { yield break; } yield return(new RangeCircleRenderable( centerPosition, range, 0, Color.FromArgb(128, Color.Yellow), Color.FromArgb(96, Color.Black))); foreach (var a in w.ActorsWithTrait <RenderRangeCircle>()) { if (a.Actor.Owner.IsAlliedWith(w.RenderPlayer)) { if (a.Actor.Info.TraitInfo <RenderRangeCircleInfo>().RangeCircleType == RangeCircleType) { foreach (var r in a.Trait.RenderAfterWorld(wr)) { yield return(r); } } } } }
public BaseProvider FindBaseProvider(World world, Player p, CPos topLeft) { var center = world.Map.CenterOfCell(topLeft) + CenterOffset(world); var mapBuildRadius = world.WorldActor.TraitOrDefault <MapBuildRadius>(); var allyBuildEnabled = mapBuildRadius != null && mapBuildRadius.AllyBuildRadiusEnabled; if (mapBuildRadius == null || !mapBuildRadius.BuildRadiusEnabled) { return(null); } foreach (var bp in world.ActorsWithTrait <BaseProvider>()) { var validOwner = bp.Actor.Owner == p || (allyBuildEnabled && bp.Actor.Owner.RelationshipWith(p) == PlayerRelationship.Ally); if (!validOwner || !bp.Trait.Ready()) { continue; } // Range is counted from the center of the actor, not from each cell. var target = Target.FromPos(bp.Actor.CenterPosition); if (target.IsInRange(center, bp.Trait.Info.Range)) { return(bp.Trait); } } return(null); }
public IEnumerable <IRenderable> RenderAnnotations(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { var position = centerPosition - new WVec(WDist.Zero, WDist.Zero, RenderOnGround ? w.Map.DistanceAboveTerrain(centerPosition) : WDist.Zero); if (EnabledByDefault) { yield return(new RangeCircleAnnotationRenderable( position, Range, 0, Color, Width, BorderColor, BorderWidth)); foreach (var a in w.ActorsWithTrait <WithRangeCircle>()) { if (a.Trait.Info.Type == Type) { foreach (var r in a.Trait.RenderRangeCircle(a.Actor, wr, RangeCircleVisibility.WhenSelected)) { yield return(r); } } } } }
public Actor FindBaseProvider(World world, Player p, CPos topLeft) { var center = world.Map.CenterOfCell(topLeft) + CenterOffset(world); var mapBuildRadius = world.WorldActor.Trait <MapBuildRadius>(); var allyBuildEnabled = mapBuildRadius.AllyBuildRadiusEnabled; if (!mapBuildRadius.BuildRadiusEnabled) { return(null); } foreach (var bp in world.ActorsWithTrait <BaseProvider>()) { var validOwner = bp.Actor.Owner == p || (allyBuildEnabled && bp.Actor.Owner.Stances[p] == Stance.Ally); if (!validOwner || !bp.Trait.Ready()) { continue; } var target = Target.FromPos(bp.Actor.CenterPosition); if (target.IsInRange(center, bp.Trait.Info.Range)) { return(bp.Actor); } } return(null); }
public static Bitmap ActorsBitmap(World world) { var map = world.Map; var b = map.Bounds; var size = Exts.NextPowerOf2(Math.Max(b.Width, b.Height)); var bitmap = new Bitmap(size, size); var bitmapData = bitmap.LockBits(bitmap.Bounds(), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); unsafe { var colors = (int *)bitmapData.Scan0; var stride = bitmapData.Stride / 4; foreach (var t in world.ActorsWithTrait <IRadarSignature>()) { if (!t.Actor.IsInWorld || world.FogObscures(t.Actor)) { continue; } foreach (var cell in t.Trait.RadarSignatureCells(t.Actor)) { var uv = cell.First.ToMPos(map); if (b.Contains(uv.U, uv.V)) { colors[(uv.V - b.Top) * stride + uv.U - b.Left] = cell.Second.ToArgb(); } } } } bitmap.UnlockBits(bitmapData); return(bitmap); }
public void Tick(Actor self) { // TODO: don't tick all the time. World w = self.World; if (self.Owner == null) { return; } if (previousLocation != self.Location) { previousLocation = self.Location; var actors = w.ActorsWithTrait <Shroud>(); foreach (var s in actors) { s.Actor.Owner.Shroud.RemoveActor(self); } self.UpdateSight(); foreach (var s in actors) { s.Actor.Owner.Shroud.AddActor(self); } } }
public SupportPowerTimerWidget(World world) { powers = world.ActorsWithTrait <SupportPowerManager>() .Where(p => !p.Actor.IsDead() && !p.Actor.Owner.NonCombatant) .SelectMany(s => s.Trait.Powers.Values) .Where(p => p.Instances.Any() && p.Info.DisplayTimer && !p.Disabled); }
public static Bitmap ActorsBitmap(World world) { var map = world.Map; var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height)); var bitmap = new Bitmap(size, size); var bitmapData = bitmap.LockBits(bitmap.Bounds(), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); unsafe { int* c = (int*)bitmapData.Scan0; foreach (var t in world.ActorsWithTrait<IRadarSignature>()) { if (world.FogObscures(t.Actor)) continue; var color = t.Trait.RadarSignatureColor(t.Actor); foreach (var cell in t.Trait.RadarSignatureCells(t.Actor)) if (world.Map.IsInMap(cell)) *(c + ((cell.Y - world.Map.Bounds.Top) * bitmapData.Stride >> 2) + cell.X - world.Map.Bounds.Left) = color.ToArgb(); } } bitmap.UnlockBits(bitmapData); return bitmap; }
public void WorldLoaded(World w, WorldRenderer wr) { bridges = new CellLayer <Bridge>(w.Map); // Build a list of templates that should be overlayed with bridges foreach (var bridge in info.Bridges) { var bi = w.Map.Rules.Actors[bridge].TraitInfo <BridgeInfo>(); foreach (var template in bi.Templates) { bridgeTypes.Add(template.First, Pair.New(bridge, template.Second)); } } // Take all templates to overlay from the map foreach (var cell in w.Map.AllCells.Where(cell => bridgeTypes.ContainsKey(w.Map.Tiles[cell].Type))) { ConvertBridgeToActor(w, cell); } // Link adjacent (long)-bridges so that artwork is updated correctly foreach (var p in w.ActorsWithTrait <Bridge>()) { p.Trait.LinkNeighbouringBridges(w, this); } }
public IEnumerable <IRenderable> RenderAnnotations(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { var jamsMissiles = ai.TraitInfoOrDefault <JamsMissilesInfo>(); if (jamsMissiles != null) { yield return(new RangeCircleAnnotationRenderable( centerPosition, jamsMissiles.Range, 0, Color, Width, BorderColor, BorderWidth)); } foreach (var a in w.ActorsWithTrait <RenderJammerCircle>()) { if (a.Actor.Owner.IsAlliedWith(w.RenderPlayer)) { foreach (var r in a.Trait.RenderAnnotations(a.Actor, wr)) { yield return(r); } } } }
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(); } }
Actor GetRandomSpawnPoint(World world, Support.MersenneTwister random) { var spawnPointActors = world.ActorsWithTrait <ActorSpawner>() .Where(x => !x.Trait.IsTraitDisabled && (info.Types.Overlaps(x.Trait.Types) || !x.Trait.Types.Any())) .ToArray(); return(spawnPointActors.Any() ? spawnPointActors.Random(random).Actor : null); }
public override void Draw() { var player = GetPlayer(); if (player == null) { return; } var queues = world.ActorsWithTrait <ProductionQueue>() .Where(a => a.Actor.Owner == player) .Select((a, i) => new { a.Trait, i }); foreach (var queue in queues) { if (!clocks.ContainsKey(queue.Trait)) { clocks.Add(queue.Trait, new Animation(world, "clock")); } } var iconSize = new float2(IconWidth, IconHeight); foreach (var queue in queues) { var current = queue.Trait.CurrentItem(); if (current == null) { continue; } var race = queue.Trait.Actor.Owner.Country.Race; var actor = queue.Trait.AllItems().FirstOrDefault(a => a.Name == current.Item); if (actor == null) { continue; } var rsi = actor.Traits.Get <RenderSpritesInfo>(); var icon = new Animation(world, rsi.GetImage(actor, world.Map.SequenceProvider, race)); icon.Play(actor.Traits.Get <TooltipInfo>().Icon); var location = new float2(RenderBounds.Location) + new float2(queue.i * (IconWidth + IconSpacing), 0); WidgetUtils.DrawSHPCentered(icon.Image, location + 0.5f * iconSize, worldRenderer, 0.5f); var clock = clocks[queue.Trait]; clock.PlayFetchIndex("idle", () => current.TotalTime == 0 ? 0 : ((current.TotalTime - current.RemainingTime) * (clock.CurrentSequence.Length - 1) / current.TotalTime)); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer, 0.5f); var tiny = Game.Renderer.Fonts["Tiny"]; var text = GetOverlayForItem(current); tiny.DrawTextWithContrast(text, location + new float2(16, 16) - new float2(tiny.Measure(text).X / 2, 0), Color.White, Color.Black, 1); } }
public override void Tick() { var hasRadarNew = world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Undefined || world.ActorsWithTrait <ProvidesRadar>().Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive); if (hasRadarNew != hasRadar) { animating = true; Sound.Play(hasRadarNew ? RadarOnlineSound : RadarOfflineSound); } hasRadar = hasRadarNew; // Build the radar image if (hasRadar) { --updateTicks; if (updateTicks <= 0) { updateTicks = 12; customTerrainSprite.sheet.Texture.SetData(Minimap.CustomTerrainBitmap(world)); } if (updateTicks == 8) { actorSprite.sheet.Texture.SetData(Minimap.ActorsBitmap(world)); } if (updateTicks == 4) { shroudSprite.sheet.Texture.SetData(Minimap.ShroudBitmap(world)); } } if (!animating) { return; } // Increment frame if (hasRadar) { AnimationFrame++; } else { AnimationFrame--; } // Minimap height radarMinimapHeight = float2.Lerp(0, 1, AnimationFrame * 1.0f / AnimationLength); // Animation is complete if (AnimationFrame == (hasRadar ? AnimationLength : 0)) { animating = false; } }
public IEnumerable <IRenderable> RenderAnnotations(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { if (!RequiresBaseProvider) { return(SpriteRenderable.None); } return(w.ActorsWithTrait <BaseProvider>().SelectMany(a => a.Trait.RangeCircleRenderables(wr))); }
protected override void Tick(World world) { this.sellableActors = world.ActorsWithTrait <DeconstructSellable>().Where(e => e.Actor.Owner == world.LocalPlayer && !e.Trait.IsTraitDisabled); if (!this.sellableActors.Any()) { world.CancelInputMode(); } }
void Explode(World world) { world.AddFrameEndTask(w => w.Remove(this)); Combat.DoExplosion(firedBy.PlayerActor, weapon, pos); world.WorldActor.Trait<ScreenShaker>().AddEffect(20, pos, 5); foreach (var a in world.ActorsWithTrait<NukePaletteEffect>()) a.Trait.Enable(); }
public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { wr.DrawRangeCircleWithContrast( Color.FromArgb(128, Color.Cyan), wr.ScreenPxPosition(centerPosition), ai.Traits.Get<CreatesShroudInfo>().Range, Color.FromArgb(96, Color.Black)); foreach (var a in w.ActorsWithTrait<RenderShroudCircle>()) if (a.Actor.Owner == a.Actor.World.LocalPlayer) a.Trait.RenderAfterWorld(wr); }
public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { var jamsMissiles = ai.Traits.GetOrDefault<JamsMissilesInfo>(); if (jamsMissiles != null) RenderJammerCircle.DrawRangeCircle(wr, centerPosition, jamsMissiles.Range, Color.Red); var jamsRadar = ai.Traits.GetOrDefault<JamsRadarInfo>(); if (jamsRadar != null) RenderJammerCircle.DrawRangeCircle(wr, centerPosition, jamsRadar.Range, Color.Blue); foreach (var a in w.ActorsWithTrait<RenderJammerCircle>()) if (a.Actor.Owner == a.Actor.World.LocalPlayer) a.Trait.RenderAfterWorld(wr); }
public IEnumerable<IRenderable> Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { yield return new RangeCircleRenderable( centerPosition, Range, 0, Color, Color.FromArgb(96, Color.Black)); foreach (var a in w.ActorsWithTrait<WithRangeCircle>()) if (a.Actor.Owner.IsAlliedWith(w.RenderPlayer) && a.Trait.Info.Type == Type) foreach (var r in a.Trait.RenderAfterWorld(wr)) yield return r; }
public IEnumerable<IRenderable> Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { yield return new RangeCircleRenderable( centerPosition, ai.TraitInfo<CreatesShroudInfo>().Range, 0, Color.FromArgb(128, Color.Cyan), Color.FromArgb(96, Color.Black)); foreach (var a in w.ActorsWithTrait<RenderShroudCircle>()) if (a.Actor.Owner.IsAlliedWith(w.RenderPlayer)) foreach (var r in a.Trait.RenderAfterWorld(wr)) yield return r; }
public SupportPowerTimerWidget(World world) { powers = world.ActorsWithTrait<SupportPowerManager>() .Where(p => !p.Actor.IsDead && !p.Actor.Owner.NonCombatant) .SelectMany(s => s.Trait.Powers.Values) .Where(p => p.Instances.Any() && p.Info.DisplayTimerStances != Stance.None && !p.Disabled); // Timers in replays should be synced to the effective game time, not the playback time. timestep = world.Timestep; if (world.IsReplay) timestep = world.WorldActor.Trait<MapOptions>().GameSpeed.Timestep; bgDark = ChromeMetrics.Get<Color>("TextContrastColorDark"); bgLight = ChromeMetrics.Get<Color>("TextContrastColorLight"); }
public SupportPowerTimerWidget(World world) { powers = world.ActorsWithTrait<SupportPowerManager>() .Where(p => !p.Actor.IsDead && !p.Actor.Owner.NonCombatant) .SelectMany(s => s.Trait.Powers.Values) .Where(p => p.Instances.Any() && p.Info.DisplayTimer && !p.Disabled); // Timers in replays should be synced to the effective game time, not the playback time. timestep = world.Timestep; if (world.IsReplay) { GameSpeed speed; var gameSpeeds = Game.ModData.Manifest.Get<GameSpeeds>(); if (gameSpeeds.Speeds.TryGetValue(world.LobbyInfo.GlobalSettings.GameSpeedType, out speed)) timestep = speed.Timestep; } }
public static void Chronoshift(World world, List<Pair<Actor, int2>>units, Actor chronosphere, int duration, bool killCargo) { if (chronosphere != null) chronosphere.Trait<RenderBuilding>().PlayCustomAnim(chronosphere, "active"); // Trigger screen desaturate effect foreach (var a in world.ActorsWithTrait<ChronoshiftPaletteEffect>()) a.Trait.Enable(); Sound.Play("chrono2.aud", units.First().First.CenterLocation); foreach (var kv in units) { var target = kv.First; var targetCell = kv.Second; var cs = target.Trait<Chronoshiftable>(); if (cs.CanChronoshiftTo(target, targetCell, true)) cs.Teleport(target, targetCell, duration, killCargo,chronosphere); } }
public void WorldLoaded(World w, WorldRenderer wr) { bridges = new CellLayer<Bridge>(w.Map); // Build a list of templates that should be overlayed with bridges foreach (var bridge in info.Bridges) { var bi = w.Map.Rules.Actors[bridge].TraitInfo<BridgeInfo>(); foreach (var template in bi.Templates) bridgeTypes.Add(template.First, Pair.New(bridge, template.Second)); } // Take all templates to overlay from the map foreach (var cell in w.Map.AllCells.Where(cell => bridgeTypes.ContainsKey(w.Map.MapTiles.Value[cell].Type))) ConvertBridgeToActor(w, cell); // Link adjacent (long)-bridges so that artwork is updated correctly foreach (var p in w.ActorsWithTrait<Bridge>()) p.Trait.LinkNeighbouringBridges(w, this); }
public static IEnumerable<CPos> GetLineBuildCells(World world, CPos location, string name, BuildingInfo bi) { var lbi = world.Map.Rules.Actors[name].Traits.Get<LineBuildInfo>(); var topLeft = location; // 1x1 assumption! if (world.IsCellBuildable(topLeft, bi)) yield return topLeft; // Start at place location, search outwards // TODO: First make it work, then make it nice var vecs = new[] { new CVec(1, 0), new CVec(0, 1), new CVec(-1, 0), new CVec(0, -1) }; int[] dirs = { 0, 0, 0, 0 }; for (int d = 0; d < 4; d++) { for (int i = 1; i < lbi.Range; i++) { if (dirs[d] != 0) continue; var cell = topLeft + i * vecs[d]; if (world.IsCellBuildable(cell, bi)) continue; // Cell is empty; continue search // Cell contains an actor. Is it the type we want? if (world.ActorsWithTrait<LineBuildNode>().Any(a => ( a.Actor.Location == cell && a.Actor.Info.Traits.Get<LineBuildNodeInfo>().Types.Intersect(lbi.NodeTypes).Any() ))) dirs[d] = i; // Cell contains actor of correct type else dirs[d] = -1; // Cell is blocked by another actor type } // Place intermediate-line sections if (dirs[d] > 0) for (int i = 1; i < dirs[d]; i++) yield return topLeft + i * vecs[d]; } }
public void Tick(World world) { anim.Tick(); if (goingUp) { altitude += 10; if (altitude >= world.Map.Bounds.Height*Game.CellSize) StartDescent(world); } else { altitude -= 10; if (altitude <= 0) { // Trigger screen desaturate effect foreach (var a in world.ActorsWithTrait<NukePaletteEffect>()) a.Trait.Enable(); Explode(world); } } }
public static IEnumerable<int2> GetLineBuildCells(World world, int2 location, string name, BuildingInfo bi) { int range = Rules.Info[name].Traits.Get<LineBuildInfo>().Range; var topLeft = location; // 1x1 assumption! if (world.IsCellBuildable(topLeft, bi.WaterBound)) yield return topLeft; // Start at place location, search outwards // TODO: First make it work, then make it nice var vecs = new[] { new int2(1, 0), new int2(0, 1), new int2(-1, 0), new int2(0, -1) }; int[] dirs = { 0, 0, 0, 0 }; for (int d = 0; d < 4; d++) { for (int i = 1; i < range; i++) { if (dirs[d] != 0) continue; int2 cell = topLeft + i * vecs[d]; if (world.IsCellBuildable(cell, bi.WaterBound)) continue; // Cell is empty; continue search // Cell contains an actor. Is it the type we want? if (world.ActorsWithTrait<LineBuild>().Any(a => (a.Actor.Info.Name == name && a.Actor.Location.X == cell.X && a.Actor.Location.Y == cell.Y))) dirs[d] = i; // Cell contains actor of correct type else dirs[d] = -1; // Cell is blocked by another actor type } // Place intermediate-line sections if (dirs[d] > 0) for (int i = 1; i < dirs[d]; i++) yield return topLeft + i * vecs[d]; } }
public static IEnumerable<ProductionQueue> FindQueues(World world, Player player, string category) { return world.ActorsWithTrait<ProductionQueue>() .Where(a => a.Actor.Owner == player && a.Trait.Info.Type == category) .Select(a => a.Trait); }
void HandleBuildPalette(World world, string item, bool isLmb) { var unit = world.Map.Rules.Actors[item]; var producing = CurrentQueue.AllQueued().FirstOrDefault(a => a.Item == item); if (isLmb) { if (producing != null && producing == CurrentQueue.CurrentItem()) { if (producing.Done) { if (unit.Traits.Contains<BuildingInfo>()) world.OrderGenerator = new PlaceBuildingOrderGenerator(CurrentQueue.self, item); else StartProduction(world, item); return; } if (producing.Paused) { world.IssueOrder(Order.PauseProduction(CurrentQueue.self, item, false)); return; } } else { // Check if the item's build-limit has already been reached var queued = CurrentQueue.AllQueued().Count(a => a.Item == unit.Name); var inWorld = world.ActorsWithTrait<Buildable>().Count(a => a.Actor.Info.Name == unit.Name && a.Actor.Owner == world.LocalPlayer); var buildLimit = unit.Traits.Get<BuildableInfo>().BuildLimit; if (!((buildLimit != 0) && (inWorld + queued >= buildLimit))) Sound.PlayNotification(world.Map.Rules, world.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, world.LocalPlayer.Country.Race); else Sound.PlayNotification(world.Map.Rules, world.LocalPlayer, "Speech", CurrentQueue.Info.BlockedAudio, world.LocalPlayer.Country.Race); } StartProduction(world, item); } else { if (producing != null) { // instant cancel of things we havent really started yet, and things that are finished if (producing.Paused || producing.Done || producing.TotalCost == producing.RemainingCost) { Sound.PlayNotification(world.Map.Rules, world.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, world.LocalPlayer.Country.Race); int numberToCancel = Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1; world.IssueOrder(Order.CancelProduction(CurrentQueue.self, item, numberToCancel)); } else { Sound.PlayNotification(world.Map.Rules, world.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, world.LocalPlayer.Country.Race); world.IssueOrder(Order.PauseProduction(CurrentQueue.self, item, true)); } } } }
public static bool PlayerIsAllowedToRepair(World world) { return world.ActorsWithTrait<AllowsBuildingRepair>() .Any(a => a.Actor.Owner == world.LocalPlayer); }
void TriggerDesync(World world) { var trait = world.ActorsWithTrait<ISync>().Random(CosmeticRandom).Trait; var t = trait.GetType(); const BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; var fields = t.GetFields(bf).Where(x => x.HasAttribute<SyncAttribute>()).ToArray(); if (fields.Length > 0) { var f = fields[CosmeticRandom.Next(fields.Length)]; var before = f.GetValue(trait); if (f.FieldType == typeof(Boolean)) f.SetValue(trait, !(Boolean) f.GetValue(trait)); else if (f.FieldType == typeof(Int32)) f.SetValue(trait, CosmeticRandom.Next(Int32.MaxValue)); else Game.AddChatLine(Color.White, "Debug", "Sorry, Field-Type not implemented. Try again!"); var after = f.GetValue(trait); Game.AddChatLine(Color.White, "Debug", "Type: {0}\nField: ({1}) {2}\nBefore: {3}\nAfter: {4}" .F(t.Name, f.FieldType.Name, f.Name, before, after)); } else Game.AddChatLine(Color.White, "Debug", "Bad random choice. This trait has no fields. Try again!"); }
public void InitPlayerWidgets(World world, Widget playerRoot) { // Real player var playerWidgets = Game.LoadWidget(world, "PLAYER_WIDGETS", playerRoot, new WidgetArgs()); playerWidgets.IsVisible = () => true; var sidebarRoot = playerWidgets.Get("SIDEBAR_BACKGROUND"); var powerManager = world.LocalPlayer.PlayerActor.Trait<PowerManager>(); var playerResources = world.LocalPlayer.PlayerActor.Trait<PlayerResources>(); sidebarRoot.Get<LabelWidget>("CASH").GetText = () => "${0}".F(playerResources.DisplayCash + playerResources.DisplayOre); playerWidgets.Get<ButtonWidget>("OPTIONS_BUTTON").OnClick = OptionsClicked; var radarEnabled = false; var cachedRadarEnabled = false; sidebarRoot.Get<RadarWidget>("RADAR_MINIMAP").IsEnabled = () => radarEnabled; var sidebarTicker = playerWidgets.Get<LogicTickerWidget>("SIDEBAR_TICKER"); sidebarTicker.OnTick = () => { // Update radar bin radarEnabled = world.ActorsWithTrait<ProvidesRadar>() .Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive); if (radarEnabled != cachedRadarEnabled) Sound.PlayNotification(world.Map.Rules, null, "Sounds", radarEnabled ? "RadarUp" : "RadarDown", null); cachedRadarEnabled = radarEnabled; // Switch to observer mode after win/loss if (world.LocalPlayer.WinState != WinState.Undefined) Game.RunAfterTick(() => { playerRoot.RemoveChildren(); InitObserverWidgets(world, playerRoot); }); }; var siloBar = playerWidgets.Get<ResourceBarWidget>("SILOBAR"); siloBar.GetProvided = () => playerResources.OreCapacity; siloBar.GetUsed = () => playerResources.Ore; siloBar.TooltipFormat = "Silo Usage: {0}/{1}"; siloBar.GetBarColor = () => { if (playerResources.Ore == playerResources.OreCapacity) return Color.Red; if (playerResources.Ore >= 0.8 * playerResources.OreCapacity) return Color.Orange; return Color.LimeGreen; }; var powerBar = playerWidgets.Get<ResourceBarWidget>("POWERBAR"); powerBar.GetProvided = () => powerManager.PowerProvided; powerBar.GetUsed = () => powerManager.PowerDrained; powerBar.TooltipFormat = "Power Usage: {0}/{1}"; powerBar.GetBarColor = () => { if (powerManager.PowerState == PowerState.Critical) return Color.Red; if (powerManager.PowerState == PowerState.Low) return Color.Orange; return Color.LimeGreen; }; }
void Explode(World world) { world.AddFrameEndTask(w => w.Remove(this)); var weapon = world.Map.Rules.Weapons[this.weapon.ToLowerInvariant()]; weapon.Impact(Target.FromPos(pos), firedBy.PlayerActor, Enumerable.Empty<int>()); world.WorldActor.Trait<ScreenShaker>().AddEffect(20, pos, 5); foreach (var a in world.ActorsWithTrait<NukePaletteEffect>()) a.Trait.Enable(); }
public void Tick(World world) { ticks++; anim.Tick(); // Missile tracks target if (args.GuidedTarget.IsValidFor(args.SourceActor)) targetPosition = args.GuidedTarget.CenterPosition; var dist = targetPosition + offset - pos; var desiredFacing = Traits.Util.GetFacing(dist, facing); var desiredAltitude = targetPosition.Z; var jammed = info.Jammable && world.ActorsWithTrait<JamsMissiles>().Any(j => JammedBy(j)); if (jammed) { desiredFacing = facing + world.SharedRandom.Next(-20, 21); desiredAltitude = world.SharedRandom.Next(-43, 86); } else if (!args.GuidedTarget.IsValidFor(args.SourceActor)) desiredFacing = facing; facing = Traits.Util.TickFacing(facing, desiredFacing, info.ROT); var move = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(facing)) * info.Speed.Range / 1024; if (targetPosition.Z > 0 && info.TurboBoost) move = (move * 3) / 2; if (pos.Z != desiredAltitude) { var delta = move.HorizontalLength * info.MaximumPitch.Tan() / 1024; var dz = (targetPosition.Z - pos.Z).Clamp(-delta, delta); move += new WVec(0, 0, dz); } pos += move; if (info.Trail != null && --ticksToNextSmoke < 0) { world.AddFrameEndTask(w => w.Add(new Smoke(w, pos - 3 * move / 2, info.Trail))); ticksToNextSmoke = info.TrailInterval; } if (info.ContrailLength > 0) trail.Update(pos); var cell = pos.ToCPos(); var shouldExplode = (pos.Z < 0) // Hit the ground || (dist.LengthSquared < MissileCloseEnough.Range * MissileCloseEnough.Range) // Within range || (info.RangeLimit != 0 && ticks > info.RangeLimit) // Ran out of fuel || (!info.High && world.ActorMap.GetUnitsAt(cell) .Any(a => a.HasTrait<IBlocksBullets>())) // Hit a wall || (!string.IsNullOrEmpty(info.BoundToTerrainType) && world.GetTerrainType(cell) != info.BoundToTerrainType); // Hit incompatible terrain if (shouldExplode) Explode(world); }
WVec HomingTick(World world, WVec tarDistVec, int relTarHorDist) { int predClfHgt, predClfDist, lastHtChg, lastHt; InclineLookahead(world, relTarHorDist, out predClfHgt, out predClfDist, out lastHtChg, out lastHt); // Height difference between the incline height and missile height var diffClfMslHgt = predClfHgt - pos.Z; // Get underestimate of distance from target in next tick var nxtRelTarHorDist = (relTarHorDist - speed - info.Acceleration.Length).Clamp(0, relTarHorDist); // Target height relative to the missile var relTarHgt = tarDistVec.Z; // Compute which direction the projectile should be facing var desiredHFacing = OpenRA.Traits.Util.GetFacing(tarDistVec + predVel, hFacing); if (allowPassBy && System.Math.Abs(desiredHFacing - hFacing) >= System.Math.Abs(desiredHFacing + 128 - hFacing)) { desiredHFacing += 128; targetPassedBy = true; } else targetPassedBy = false; var desiredVFacing = HomingInnerTick(predClfDist, diffClfMslHgt, relTarHorDist, lastHtChg, lastHt, nxtRelTarHorDist, relTarHgt, vFacing, targetPassedBy); // The target has been passed by if (tarDistVec.HorizontalLength < speed * WAngle.FromFacing(vFacing).Cos() / 1024) targetPassedBy = true; // Check whether the homing mechanism is jammed var jammed = info.Jammable && world.ActorsWithTrait<JamsMissiles>().Any(JammedBy); if (jammed) { desiredHFacing = hFacing + world.SharedRandom.Next(-info.JammedDiversionRange, info.JammedDiversionRange + 1); desiredVFacing = vFacing + world.SharedRandom.Next(-info.JammedDiversionRange, info.JammedDiversionRange + 1); } else if (!args.GuidedTarget.IsValidFor(args.SourceActor)) desiredHFacing = hFacing; // Compute new direction the projectile will be facing hFacing = OpenRA.Traits.Util.TickFacing(hFacing, desiredHFacing, info.HorizontalRateOfTurn); vFacing = OpenRA.Traits.Util.TickFacing(vFacing, desiredVFacing, info.VerticalRateOfTurn); // Compute the projectile's guided displacement return new WVec(0, -1024 * speed, 0) .Rotate(new WRot(WAngle.FromFacing(vFacing), WAngle.Zero, WAngle.Zero)) .Rotate(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(hFacing))) / 1024; }
public void Tick(World world) { t += 40; // In pixels var dist = Args.target.CenterLocation + offset - PxPosition; var targetAltitude = 0; if (Args.target.IsValid && Args.target.IsActor && Args.target.Actor.HasTrait<IMove>()) targetAltitude = Args.target.Actor.Trait<IMove>().Altitude; var jammed = Info.Jammable && world.ActorsWithTrait<JamsMissiles>().Any(tp => (tp.Actor.CenterLocation - PxPosition).ToCVec().Length <= tp.Trait.Range && (tp.Actor.Owner.Stances[Args.firedBy.Owner] != Stance.Ally || (tp.Actor.Owner.Stances[Args.firedBy.Owner] == Stance.Ally && tp.Trait.AlliedMissiles)) && world.SharedRandom.Next(100 / tp.Trait.Chance) == 0); if (!jammed) { Altitude += Math.Sign(targetAltitude - Altitude); if (Args.target.IsValid) Facing = Traits.Util.TickFacing(Facing, Traits.Util.GetFacing(dist, Facing), Info.ROT); } else { Altitude += world.SharedRandom.Next(-1, 2); Facing = Traits.Util.TickFacing(Facing, Facing + world.SharedRandom.Next(-20, 21), Info.ROT); } anim.Tick(); if (dist.LengthSquared < MissileCloseEnough * MissileCloseEnough && Args.target.IsValid) Explode(world); // TODO: Replace this with a lookup table var dir = (-float2.FromAngle((float)(Facing / 128f * Math.PI))).ToPSubVec(); var move = Info.Speed * dir; if (targetAltitude > 0 && Info.TurboBoost) move = (move * 3) / 2; move = move / 5; SubPxPosition += move; if (Info.Trail != null) { var sp = ((SubPxPosition - (move * 3) / 2)).ToPPos() - new PVecInt(0, Altitude); if (--ticksToNextSmoke < 0) { world.AddFrameEndTask(w => w.Add(new Smoke(w, sp, Info.Trail))); ticksToNextSmoke = Info.TrailInterval; } } if (Info.RangeLimit != 0 && t > Info.RangeLimit * 40) Explode(world); if (!Info.High) // check for hitting a wall { var cell = PxPosition.ToCPos(); if (world.ActorMap.GetUnitsAt(cell).Any(a => a.HasTrait<IBlocksBullets>())) Explode(world); } if (Trail != null) Trail.Tick(PxPosition.ToWPos(Altitude)); }
public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { wr.DrawRangeCircleWithContrast( Color.FromArgb(128, Color.Yellow), wr.ScreenPxPosition(centerPosition), ai.Traits.WithInterface<ArmamentInfo>() .Select(a => Rules.Weapons[a.Weapon.ToLowerInvariant()].Range).Max(), Color.FromArgb(96, Color.Black)); foreach (var a in w.ActorsWithTrait<RenderRangeCircle>()) if (a.Actor.Owner == a.Actor.World.LocalPlayer) if (a.Actor.Info.Traits.Get<RenderRangeCircleInfo>().RangeCircleType == RangeCircleType) a.Trait.RenderAfterWorld(wr); }
public void Tick(World world) { ticks++; if (anim != null) anim.Tick(); // Missile tracks target if (args.GuidedTarget.IsValidFor(args.SourceActor) && lockOn) targetPosition = args.GuidedTarget.CenterPosition; var dist = targetPosition + offset - pos; var desiredFacing = OpenRA.Traits.Util.GetFacing(dist, facing); var desiredAltitude = targetPosition.Z; var jammed = info.Jammable && world.ActorsWithTrait<JamsMissiles>().Any(JammedBy); if (jammed) { desiredFacing = facing + world.SharedRandom.Next(-20, 21); desiredAltitude = world.SharedRandom.Next(-43, 86); } else if (!args.GuidedTarget.IsValidFor(args.SourceActor)) desiredFacing = facing; facing = OpenRA.Traits.Util.TickFacing(facing, desiredFacing, info.RateOfTurn); var move = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(facing)) * info.Speed.Range / 1024; if (pos.Z != desiredAltitude) { var delta = move.HorizontalLength * info.MaximumPitch.Tan() / 1024; var dz = (targetPosition.Z - pos.Z).Clamp(-delta, delta); move += new WVec(0, 0, dz); } pos += move; if (!string.IsNullOrEmpty(info.Trail) && --ticksToNextSmoke < 0) { world.AddFrameEndTask(w => w.Add(new Smoke(w, pos - 3 * move / 2, info.Trail, trailPalette))); ticksToNextSmoke = info.TrailInterval; } if (info.ContrailLength > 0) contrail.Update(pos); var cell = world.Map.CellContaining(pos); var shouldExplode = (pos.Z < 0) // Hit the ground || (dist.LengthSquared < info.CloseEnough.Range * info.CloseEnough.Range) // Within range || (info.RangeLimit != 0 && ticks > info.RangeLimit) // Ran out of fuel || (info.Blockable && world.ActorMap.GetUnitsAt(cell).Any(a => a.HasTrait<IBlocksProjectiles>())) // Hit a wall or other blocking obstacle || !world.Map.Contains(cell) // This also avoids an IndexOutOfRangeException in GetTerrainInfo below. || (!string.IsNullOrEmpty(info.BoundToTerrainType) && world.Map.GetTerrainInfo(cell).Type != info.BoundToTerrainType); // Hit incompatible terrain if (shouldExplode) Explode(world); }
static void SetPlayerStance(World w, Player p, Player target, Stance s) { var oldStance = p.Stances[target]; p.Stances[target] = s; target.Shroud.UpdatePlayerStance(w, p, oldStance, s); p.Shroud.UpdatePlayerStance(w, target, oldStance, s); foreach (var nsc in w.ActorsWithTrait<INotifyStanceChanged>()) nsc.Trait.StanceChanged(nsc.Actor, p, target, oldStance, s); }