public FrozenActor(Actor self, PPos[] footprint, Shroud shroud, bool startsRevealed) { actor = self; this.shroud = shroud; NeedRenderables = startsRevealed; // Consider all cells inside the map area (ignoring the current map bounds) Footprint = footprint .Where(m => shroud.Contains(m)) .ToArray(); if (Footprint.Length == 0) { throw new ArgumentException(("This frozen actor has no footprint.\n" + "Actor Name: {0}\n" + "Actor Location: {1}\n" + "Input footprint: [{2}]\n" + "Input footprint (after shroud.Contains): [{3}]") .F(actor.Info.Name, actor.Location.ToString(), footprint.Select(p => p.ToString()).JoinWith("|"), footprint.Select(p => shroud.Contains(p).ToString()).JoinWith("|"))); } CenterPosition = self.CenterPosition; Bounds = self.Bounds; TargetTypes = self.GetEnabledTargetTypes().ToHashSet(); tooltip = self.TraitsImplementing <ITooltip>().FirstOrDefault(); health = self.TraitOrDefault <IHealth>(); UpdateVisibility(); }
public FrozenActor(Actor actor, ICreatesFrozenActors frozenTrait, PPos[] footprint, Player viewer, bool startsRevealed) { this.actor = actor; this.frozenTrait = frozenTrait; this.viewer = viewer; shroud = viewer.Shroud; NeedRenderables = startsRevealed; // Consider all cells inside the map area (ignoring the current map bounds) Footprint = footprint .Where(m => shroud.Contains(m)) .ToArray(); if (Footprint.Length == 0) { throw new ArgumentException(("This frozen actor has no footprint.\n" + "Actor Name: {0}\n" + "Actor Location: {1}\n" + "Input footprint: [{2}]\n" + "Input footprint (after shroud.Contains): [{3}]") .F(actor.Info.Name, actor.Location.ToString(), footprint.Select(p => p.ToString()).JoinWith("|"), footprint.Select(p => shroud.Contains(p).ToString()).JoinWith("|"))); } CenterPosition = actor.CenterPosition; tooltips = actor.TraitsImplementing <ITooltip>().ToArray(); health = actor.TraitOrDefault <IHealth>(); UpdateVisibility(); }
public void Tick(World world, Shroud shroud) { Visible = !Footprint.Any(shroud.IsVisibleTest(FootprintRegion)); if (flashTicks > 0) { flashTicks--; } }
public void Tick(World world, Shroud shroud) { Visible = !Footprint.Any(c => shroud.IsVisible(c)); if (flashTicks > 0) { flashTicks--; } }
public ShroudRenderer(Player owner, Map map) { this.shroud = owner.World.WorldActor.Trait<Traits.Shroud>(); this.map = map; sprites = new Sprite[map.MapSize.X, map.MapSize.Y]; fogSprites = new Sprite[map.MapSize.X, map.MapSize.Y]; shroud.Dirty += () => dirty = true; }
public FrozenActor(Actor self, MPos[] footprint, CellRegion footprintRegion, Shroud shroud) { actor = self; isVisibleTest = shroud.IsVisibleTest(footprintRegion); Footprint = footprint; CenterPosition = self.CenterPosition; Bounds = self.Bounds; UpdateVisibility(); }
public void Explore(Shroud s) { foreach (var cell in map.Cells) { if (s.explored[cell]) { explored[cell] = true; } } Invalidate(); }
public void Tick(Actor self) { if (lobbyShroudFogDisabled) { return; } if (cachedLocation != self.Location) { cachedLocation = self.Location; Shroud.UpdateVisibility(self.World.Players.Select(p => p.Shroud), self); } }
public FrozenActor(Actor self, MPos[] footprint, Shroud shroud) { actor = self; this.shroud = shroud; // Consider all cells inside the map area (ignoring the current map bounds) Footprint = footprint .Where(m => shroud.Contains(m)) .ToArray(); CenterPosition = self.CenterPosition; Bounds = self.Bounds; UpdateVisibility(); }
public void Tick(World world, Shroud shroud) { Visible = true; foreach (var pos in Footprint) { if (shroud.IsVisible(pos)) { Visible = false; break; } } if (flashTicks > 0) flashTicks--; }
public void Explore(Shroud s) { for (var i = map.Bounds.Left; i < map.Bounds.Right; i++) { for (var j = map.Bounds.Top; j < map.Bounds.Bottom; j++) { if (s.explored[i, j] == true) { explored[i, j] = true; } } } ExploredBounds = Rectangle.Union(ExploredBounds, s.ExploredBounds); }
public void Tick(Actor self) { if (lobbyShroudFogDisabled) { return; } var disabled = self.IsDisabled(); if (cachedLocation != self.Location || cachedDisabled != disabled) { cachedLocation = self.Location; cachedDisabled = disabled; Shroud.UpdateShroudGeneration(self.World.Players.Select(p => p.Shroud), self); } }
public void Tick(Actor self) { if (lobbyShroudFogDisabled) { return; } var disabled = self.TraitsImplementing <IDisable>().Any(d => d.Disabled); if (cachedLocation != self.Location || cachedDisabled != disabled) { cachedLocation = self.Location; cachedDisabled = disabled; Shroud.UpdateShroudGeneration(self.World.Players.Select(p => p.Shroud), self); } }
public void Explore(Shroud s) { if (map.Bounds != s.map.Bounds) { throw new ArgumentException("The map bounds of these shrouds do not match.", "s"); } foreach (var puv in map.ProjectedCells) { if (!explored[puv] && s.explored[puv]) { touched[puv] = true; explored[puv] = true; } } }
public void Tick(World world, Shroud shroud) { Visible = true; foreach (var pos in Footprint) { if (shroud.IsVisible(pos)) { Visible = false; break; } } if (flashTicks > 0) { flashTicks--; } }
public void Explore(Shroud s) { if (map.Bounds != s.map.Bounds) { throw new ArgumentException("The map bounds of these shrouds do not match.", "s"); } foreach (var cell in map.Cells) { if (s.explored[cell]) { explored[cell] = true; } } Invalidate(); }
public void Explore(Shroud s) { if (map.Bounds != s.map.Bounds) { throw new ArgumentException("The map bounds of these shrouds do not match.", "s"); } foreach (var puv in map.ProjectedCells) { var index = touched.Index(puv); if (!explored[index] && s.explored[index]) { touched[index] = true; anyCellTouched = true; explored[index] = true; } } }
public FrozenActor(Actor self, PPos[] footprint, Shroud shroud, bool startsRevealed) { actor = self; this.shroud = shroud; NeedRenderables = startsRevealed; removeFrozenActors = self.TraitsImplementing<IRemoveFrozenActor>().ToArray(); // Consider all cells inside the map area (ignoring the current map bounds) Footprint = footprint .Where(m => shroud.Contains(m)) .ToArray(); CenterPosition = self.CenterPosition; Bounds = self.Bounds; TargetTypes = self.TraitsImplementing<ITargetable>().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes).ToHashSet(); UpdateVisibility(); }
public void MergeShroud(Shroud s) { for (int i = map.Bounds.Left; i < map.Bounds.Right; i++) { for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++) { if (s.exploredCells[i, j] == true) { exploredCells[i, j] = true; } if (s.foggedCells[i, j] == true) { foggedCells[i, j] = true; } } ExploredBounds = Rectangle.Union(ExploredBounds, s.ExploredBounds); } }
public FrozenActor(Actor self, PPos[] footprint, Shroud shroud, bool startsRevealed) { actor = self; this.shroud = shroud; NeedRenderables = startsRevealed; removeFrozenActors = self.TraitsImplementing <IRemoveFrozenActor>().ToArray(); // Consider all cells inside the map area (ignoring the current map bounds) Footprint = footprint .Where(m => shroud.Contains(m)) .ToArray(); CenterPosition = self.CenterPosition; Bounds = self.Bounds; TargetTypes = self.TraitsImplementing <ITargetable>().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes).ToHashSet(); UpdateVisibility(); }
public bool IsVisible(Shroud s, Actor self) { if (self.World.LocalPlayer != null) { if (s == null) { if (!Cloaked || self.Owner == self.World.LocalPlayer || self.Owner.Stances[self.World.LocalPlayer] == Stance.Ally) return true; } else { if (!Cloaked || self.Owner == s.Owner || self.Owner.Stances[s.Owner] == Stance.Ally) return true; } } return self.World.ActorsWithTrait<DetectCloaked>().Any(a => a.Actor.Owner.Stances[self.Owner] != Stance.Ally && (self.Location - a.Actor.Location).Length < a.Actor.Info.Traits.Get<DetectCloakedInfo>().Range); }
internal void Draw(WorldRenderer wr, Shroud shroud) { if (initializePalettes) { if (shroudInfo.Fog) fogPalette = wr.Palette("fog"); shroudPalette = wr.Palette("shroud"); initializePalettes = false; } GenerateSprites(shroud); var clipRect = Game.viewport.WorldBounds(wr.world); // We draw the shroud when disabled to hide the sharp map edges DrawShroud(wr, clipRect, sprites, shroudPalette); if (shroudInfo.Fog) DrawShroud(wr, clipRect, fogSprites, fogPalette); }
public void Explore(Shroud s) { if (map.Bounds != s.map.Bounds) { throw new ArgumentException("The map bounds of these shrouds do not match.", "s"); } var changed = new List <CPos>(); foreach (var uv in map.Cells.MapCoords) { if (!explored[uv] && s.explored[uv]) { explored[uv] = true; changed.Add(uv.ToCPos(map)); } } Invalidate(changed); }
public Player(World world, Session.Client client, Session.Slot slot, PlayerReference pr) { World = world; InternalName = pr.Name; PlayerReference = pr; string botType = null; // Real player or host-created bot if (client != null) { ClientIndex = client.Index; Color = client.Color; PlayerName = client.Name; botType = client.Bot; Country = ChooseCountry(world, client.Country); } else { // Map player ClientIndex = 0; // Owned by the host (TODO: fix this) Color = pr.Color; PlayerName = pr.Name; NonCombatant = pr.NonCombatant; botType = pr.Bot; Country = ChooseCountry(world, pr.Race); } PlayerActor = world.CreateActor("Player", new TypeDictionary { new OwnerInit(this) }); Shroud = PlayerActor.Trait<Shroud>(); // Enable the bot logic on the host IsBot = botType != null; if (IsBot && Game.IsHost) { var logic = PlayerActor.TraitsImplementing<IBot>() .FirstOrDefault(b => b.Info.Name == botType); if (logic == null) Log.Write("debug", "Invalid bot type: {0}", botType); else logic.Activate(this); } }
public void Explore(Shroud s) { if (map.Bounds != s.map.Bounds) { throw new ArgumentException("The map bounds of these shrouds do not match.", "s"); } var changed = new List <PPos>(); foreach (var puv in map.ProjectedCellBounds) { var uv = (MPos)puv; if (!explored[uv] && s.explored[uv]) { explored[uv] = true; changed.Add(puv); } } Invalidate(changed); }
public void Tick(Actor self) { // TODO: don't tick all the time. if (self.Owner == null) { return; } var shrouds = self.World.ActorsWithTrait <Shroud>().Select(s => s.Actor.Owner.Shroud); if (previousLocation != self.Location && v != null) { previousLocation = self.Location; foreach (var shroud in shrouds) { shroud.UnhideActor(self, v, Info.Range); } } if (!self.TraitsImplementing <IDisable>().Any(d => d.Disabled)) { foreach (var shroud in shrouds) { shroud.HideActor(self, Info.Range); } } else { foreach (var shroud in shrouds) { shroud.UnhideActor(self, v, Info.Range); } } v = new Shroud.ActorVisibility { vis = Shroud.GetVisOrigins(self).ToArray() }; }
public Mobile(ActorInitializer init, MobileInfo info) { this.self = init.self; this.Info = info; shroud = self.World.WorldActor.Trait<Shroud>(); uim = self.World.WorldActor.Trait<UnitInfluence>(); bim = self.World.WorldActor.Trait<BuildingInfluence>(); canShareCell = self.HasTrait<SharesCell>(); if (init.Contains<LocationInit>()) { this.__fromCell = this.__toCell = init.Get<LocationInit,int2>(); AddInfluence(); } this.Facing = init.Contains<FacingInit>() ? init.Get<FacingInit,int>() : info.InitialFacing; this.Altitude = init.Contains<AltitudeInit>() ? init.Get<AltitudeInit,int>() : 0; TerrainCost = new Dictionary<string, float>(); TerrainSpeed = new Dictionary<string, float>(); if (info.TerrainTypes.Count() != info.TerrainSpeeds.Count()) throw new InvalidOperationException("Mobile TerrainType/TerrainSpeed length mismatch"); if (info.TerrainCostOverrides != null) for (int i = 0; i < info.TerrainCostOverrides.Count(); i++) { TerrainCost.Add(info.TerrainCostOverrides[i], info.TerrainCosts[i]); } for (int i = 0; i < info.TerrainTypes.Count(); i++) { if (!TerrainCost.ContainsKey(info.TerrainTypes[i])) TerrainCost.Add(info.TerrainTypes[i], 1f/info.TerrainSpeeds[i]); TerrainSpeed.Add(info.TerrainTypes[i], info.TerrainSpeeds[i]); } }
public void MergeShroud(Shroud s) { for (int i = map.Bounds.Left; i < map.Bounds.Right; i++) { for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++) { if (s.exploredCells[i,j] == true) exploredCells[i, j] = true; } exploredBounds = Rectangle.Union(exploredBounds.Value, s.exploredBounds.Value); } }
public Player(World world, Session.Client client, PlayerReference pr) { string botType; World = world; InternalName = pr.Name; PlayerReference = pr; // Real player or host-created bot if (client != null) { ClientIndex = client.Index; Color = client.Color; PlayerName = client.Name; botType = client.Bot; Faction = ChooseFaction(world, client.Faction, !pr.LockFaction); DisplayFaction = ChooseDisplayFaction(world, client.Faction); } else { // Map player ClientIndex = 0; // Owned by the host (TODO: fix this) Color = pr.Color; PlayerName = pr.Name; NonCombatant = pr.NonCombatant; Playable = pr.Playable; Spectating = pr.Spectating; botType = pr.Bot; Faction = ChooseFaction(world, pr.Faction, false); DisplayFaction = ChooseDisplayFaction(world, pr.Faction); } PlayerActor = world.CreateActor("Player", new TypeDictionary { new OwnerInit(this) }); Shroud = PlayerActor.Trait<Shroud>(); fogVisibilities = PlayerActor.TraitsImplementing<IFogVisibilityModifier>().ToArray(); // Enable the bot logic on the host IsBot = botType != null; if (IsBot && Game.IsHost) { var logic = PlayerActor.TraitsImplementing<IBot>().FirstOrDefault(b => b.Info.Name == botType); if (logic == null) Log.Write("debug", "Invalid bot type: {0}", botType); else logic.Activate(this); } }
public void Explore(Shroud s) { if (map.Bounds != s.map.Bounds) throw new ArgumentException("The map bounds of these shrouds do not match.", "s"); var changed = new List<PPos>(); foreach (var puv in map.ProjectedCellBounds) { var uv = (MPos)puv; if (!explored[uv] && s.explored[uv]) { explored[uv] = true; changed.Add(puv); } } Invalidate(changed); }
Sprite ChooseFog(Shroud s, int i, int j) { if (!s.IsVisible(i, j)) return shadowBits[0xf]; if (!s.IsExplored(i, j)) return shadowBits[0xf]; // bits are for unexploredness: up, right, down, left var v = 0; // bits are for unexploredness: TL, TR, BR, BL var u = 0; if (!s.IsVisible(i, j - 1)) { v |= 1; u |= 3; } if (!s.IsVisible(i + 1, j)) { v |= 2; u |= 6; } if (!s.IsVisible(i, j + 1)) { v |= 4; u |= 12; } if (!s.IsVisible(i - 1, j)) { v |= 8; u |= 9; } var uSides = u; if (!s.IsVisible(i - 1, j - 1)) u |= 1; if (!s.IsVisible(i + 1, j - 1)) u |= 2; if (!s.IsVisible(i + 1, j + 1)) u |= 4; if (!s.IsVisible(i - 1, j + 1)) u |= 8; return shadowBits[SpecialShroudTiles[u ^ uSides][v]]; }
public FrozenUnderFog(Actor self) { shroud = self.World.WorldActor.Trait<Shroud>(); }
public void Explore(Shroud s) { if (map.Bounds != s.map.Bounds) throw new ArgumentException("The map bounds of these shrouds do not match.", "s"); foreach (var cell in map.Cells) if (s.explored[cell]) explored[cell] = true; Invalidate(); }
public void Explore(Shroud s) { foreach (var cell in map.Cells) if (s.explored[cell]) explored[cell] = true; Invalidate(); }
public void RenderShroud(WorldRenderer wr, Shroud shroud) { Update(shroud); var clip = wr.Viewport.CellBounds; var width = clip.Width; for (var j = clip.Top; j < clip.Bottom; j++) { var start = j * tileStride + clip.Left; for (var k = 0; k < width; k++) { var s = tiles[start + k].Shroud; var f = tiles[start + k].Fog; if (s != null) { var pos = tiles[start + k].ScreenPosition - 0.5f * s.size; Game.Renderer.WorldSpriteRenderer.DrawSprite(s, pos, shroudPalette); } if (f != null) { var pos = tiles[start + k].ScreenPosition - 0.5f * f.size; Game.Renderer.WorldSpriteRenderer.DrawSprite(f, pos, fogPalette); } } } }
void Update(Shroud shroud) { var hash = shroud != null ? shroud.Hash : 0; if (shroudHash == hash) return; shroudHash = hash; if (shroud == null) { // Players with no shroud see the whole map so we only need to set the edges for (var k = 0; k < tiles.Length; k++) { var shrouded = ObserverShroudedEdges(tiles[k].Position, bounds, useExtendedIndex); tiles[k].Shroud = GetTile(shrouded, tiles[k].Variant); tiles[k].Fog = GetTile(shrouded, tiles[k].Variant); } } else { for (var k = 0; k < tiles.Length; k++) { var shrouded = ShroudedEdges(shroud, tiles[k].Position, useExtendedIndex); var fogged = FoggedEdges(shroud, tiles[k].Position, useExtendedIndex); tiles[k].Shroud = GetTile(shrouded, tiles[k].Variant); tiles[k].Fog = GetTile(fogged, tiles[k].Variant); } } }
void GenerateSprites(Shroud shroud) { var hash = shroud != null ? shroud.Hash : 0; if (shroudHash == hash) return; shroudHash = hash; if (shroud == null) { // Players with no shroud see the whole map so we only need to set the edges var b = map.Bounds; for (int i = b.Left; i < b.Right; i++) for (int j = b.Top; j < b.Bottom; j++) { var v = 0; var u = 0; if (j == b.Top) { v |= 1; u |= 3; } if (i == b.Right - 1) { v |= 2; u |= 6; } if (j == b.Bottom - 1) { v |= 4; u |= 12; } if (i == b.Left) { v |= 8; u |= 9; } var uSides = u; if (i == b.Left && j == b.Top) u |= 1; if (i == b.Right - 1 && j == b.Top) u |= 2; if (i == b.Right - 1 && j == b.Bottom - 1) u |= 4; if (i == b.Left && j == b.Bottom - 1) u |= 8; sprites[i, j] = fogSprites[i, j] = shadowBits[SpecialShroudTiles[u ^ uSides][v]]; } } else { for (int i = map.Bounds.Left; i < map.Bounds.Right; i++) for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++) sprites[i, j] = ChooseShroud(shroud, i, j); for (int i = map.Bounds.Left; i < map.Bounds.Right; i++) for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++) fogSprites[i, j] = ChooseFog(shroud, i, j); } }
void Update(Shroud newShroud) { if (currentShroud != newShroud) { if (currentShroud != null) currentShroud.CellsChanged -= MarkCellsDirty; if (newShroud != null) { shroudDirty.Clear(true); newShroud.CellsChanged += MarkCellsDirty; } cellsDirty.Clear(); cellsAndNeighborsDirty.Clear(); currentShroud = newShroud; } if (currentShroud != null) { mapBorderShroudIsCached = false; // We need to mark newly dirtied areas of the shroud. // Expand the dirty area to cover the neighboring cells, since shroud is affected by neighboring cells. foreach (var cell in cellsDirty) { cellsAndNeighborsDirty.Add(cell); foreach (var direction in CVec.Directions) cellsAndNeighborsDirty.Add(cell + direction); } foreach (var cell in cellsAndNeighborsDirty) shroudDirty[cell] = true; cellsDirty.Clear(); cellsAndNeighborsDirty.Clear(); } else if (!mapBorderShroudIsCached) { mapBorderShroudIsCached = true; CacheMapBorderShroud(); } }
public void Explore(Shroud s) { if (map.Bounds != s.map.Bounds) throw new ArgumentException("The map bounds of these shrouds do not match.", "s"); var changed = new List<CPos>(); foreach (var uv in map.CellsInsideBounds.MapCoords) { if (!explored[uv] && s.explored[uv]) { explored[uv] = true; changed.Add(uv.ToCPos(map)); } } Invalidate(changed); }
void Update(Shroud shroud) { var hash = shroud != null ? shroud.Hash : 0; if (shroudHash == hash) return; shroudHash = hash; if (shroud == null) { // Players with no shroud see the whole map so we only need to set the edges foreach (var cell in map.Cells) { var t = tiles[cell]; var shrouded = ObserverShroudedEdges(map, t.Position, info.UseExtendedIndex); t.Shroud = shrouded != 0 ? shroudSprites[t.Variant * variantStride + spriteMap[shrouded]] : null; t.Fog = shrouded != 0 ? fogSprites[t.Variant * variantStride + spriteMap[shrouded]] : null; } } else { foreach (var cell in map.Cells) { var t = tiles[cell]; var shrouded = ShroudedEdges(shroud, t.Position, info.UseExtendedIndex); var fogged = FoggedEdges(shroud, t.Position, info.UseExtendedIndex); t.Shroud = shrouded != 0 ? shroudSprites[t.Variant * variantStride + spriteMap[shrouded]] : null; t.Fog = fogged != 0 ? fogSprites[t.Variant * variantStride + spriteMap[fogged]] : null; } } }
public void Explore(Shroud s) { for (var i = map.Bounds.Left; i < map.Bounds.Right; i++) for (var j = map.Bounds.Top; j < map.Bounds.Bottom; j++) if (s.explored[i,j] == true) explored[i, j] = true; ExploredBounds = Rectangle.Union(ExploredBounds, s.ExploredBounds); }
public void Tick(World world, Shroud shroud) { Visible = !Footprint.Any(c => shroud.IsVisible(c)); if (flashTicks > 0) flashTicks--; }
void IRenderShroud.RenderShroud(Shroud shroud, WorldRenderer wr) { if (currentShroud != shroud) { if (currentShroud != null) currentShroud.CellsChanged -= DirtyCells; if (shroud != null) shroud.CellsChanged += DirtyCells; // Needs the anonymous function to ensure the correct overload is chosen if (shroud != null) visibleUnderShroud = puv => currentShroud.IsExplored(puv); else visibleUnderShroud = puv => map.Contains(puv); if (shroud != null) visibleUnderFog = puv => currentShroud.IsVisible(puv); else visibleUnderFog = puv => map.Contains(puv); currentShroud = shroud; DirtyCells(map.ProjectedCellBounds); } // We need to update newly dirtied areas of the shroud. // Expand the dirty area to cover the neighboring cells, since shroud is affected by neighboring cells. foreach (var uv in cellsDirty) { cellsAndNeighborsDirty.Add(uv); var cell = ((MPos)uv).ToCPos(map); foreach (var direction in CVec.Directions) cellsAndNeighborsDirty.Add((PPos)(cell + direction).ToMPos(map)); } foreach (var puv in cellsAndNeighborsDirty) { var uv = (MPos)puv; if (!tileInfos.Contains(uv)) continue; var tileInfo = tileInfos[uv]; var shroudSprite = GetSprite(shroudSprites, GetEdges(puv, visibleUnderShroud), tileInfo.Variant); var shroudPos = tileInfo.ScreenPosition; if (shroudSprite != null) shroudPos += shroudSprite.Offset - 0.5f * shroudSprite.Size; var fogSprite = GetSprite(fogSprites, GetEdges(puv, visibleUnderFog), tileInfo.Variant); var fogPos = tileInfo.ScreenPosition; if (fogSprite != null) fogPos += fogSprite.Offset - 0.5f * fogSprite.Size; shroudLayer.Update(uv, shroudSprite, shroudPos); fogLayer.Update(uv, fogSprite, fogPos); } cellsDirty.Clear(); cellsAndNeighborsDirty.Clear(); fogLayer.Draw(wr.Viewport); shroudLayer.Draw(wr.Viewport); }
static int ShroudedEdges(Shroud s, CPos p, bool useExtendedIndex) { if (!s.IsExplored(p.X, p.Y)) return 15; // If a side is shrouded then we also count the corners var u = 0; if (!s.IsExplored(p.X, p.Y - 1)) u |= 0x13; if (!s.IsExplored(p.X + 1, p.Y)) u |= 0x26; if (!s.IsExplored(p.X, p.Y + 1)) u |= 0x4C; if (!s.IsExplored(p.X - 1, p.Y)) u |= 0x89; var uside = u & 0x0F; if (!s.IsExplored(p.X - 1, p.Y - 1)) u |= 0x01; if (!s.IsExplored(p.X + 1, p.Y - 1)) u |= 0x02; if (!s.IsExplored(p.X + 1, p.Y + 1)) u |= 0x04; if (!s.IsExplored(p.X - 1, p.Y + 1)) u |= 0x08; // RA provides a set of frames for tiles with shrouded // corners but unshrouded edges. We want to detect this // situation without breaking the edge -> corner enabling // in other combinations. The XOR turns off the corner // bits that are enabled twice, which gives the behavior // we want here. return useExtendedIndex ? u ^ uside : u & 0x0F; }
public void RenderShroud(WorldRenderer wr, Shroud shroud) { Update(shroud); foreach (var cell in CellRegion.Expand(wr.Viewport.VisibleCells, 1)) { var t = tiles[cell]; if (t.Shroud != null) { var pos = t.ScreenPosition - 0.5f * t.Shroud.size; Game.Renderer.WorldSpriteRenderer.DrawSprite(t.Shroud, pos, shroudPalette); } if (t.Fog != null) { var pos = t.ScreenPosition - 0.5f * t.Fog.size; Game.Renderer.WorldSpriteRenderer.DrawSprite(t.Fog, pos, fogPalette); } } }
public override void Tick() { // Enable/Disable the radar var enabled = IsEnabled(); if (enabled != cachedEnabled) Game.Sound.Play(enabled ? RadarOnlineSound : RadarOfflineSound); cachedEnabled = enabled; if (enabled) { var rp = world.RenderPlayer; var newRenderShroud = rp != null ? rp.Shroud : null; if (newRenderShroud != renderShroud) { if (renderShroud != null) renderShroud.CellsChanged -= MarkShroudDirty; if (newRenderShroud != null) { // Redraw the full shroud sprite MarkShroudDirty(world.Map.AllCells.MapCoords.Select(uv => (PPos)uv)); // Update the notification binding newRenderShroud.CellsChanged += MarkShroudDirty; } renderShroud = newRenderShroud; } // The actor layer is updated every tick var stride = radarSheet.Size.Width; Array.Clear(radarData, 4 * actorSprite.Bounds.Top * stride, 4 * actorSprite.Bounds.Height * stride); unsafe { fixed (byte* colorBytes = &radarData[0]) { var colors = (int*)colorBytes; 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)) { if (!world.Map.Contains(cell.First)) continue; var uv = cell.First.ToMPos(world.Map.Grid.Type); var color = cell.Second.ToArgb(); if (isRectangularIsometric) { // Odd rows are shifted right by 1px var dx = uv.V & 1; if (uv.U + dx > 0) colors[(uv.V + previewHeight) * stride + 2 * uv.U + dx - 1] = color; if (2 * uv.U + dx < stride) colors[(uv.V + previewHeight) * stride + 2 * uv.U + dx] = color; } else colors[(uv.V + previewHeight) * stride + uv.U] = color; } } } } } var targetFrame = enabled ? AnimationLength : 0; hasRadar = enabled && frame == AnimationLength; if (frame == targetFrame) return; frame += enabled ? 1 : -1; radarMinimapHeight = float2.Lerp(0, 1, (float)frame / AnimationLength); Animating(frame * 1f / AnimationLength); // Update map rectangle for event handling var ro = RenderOrigin; mapRect = new Rectangle(previewOrigin.X + ro.X, previewOrigin.Y + ro.Y, mapRect.Width, mapRect.Height); // Animation is complete if (frame == targetFrame) { if (enabled) AfterOpen(); else AfterClose(); } }
void UpdateShroud(Shroud shroud) { var visibleUnderShroud = shroud.IsExploredTest(updatedRegion); var visibleUnderFog = shroud.IsVisibleTest(updatedRegion); foreach (var cell in updatedRegion) { var shrouded = GetEdges(cell, visibleUnderShroud); var fogged = GetEdges(cell, visibleUnderFog); var shroudTile = tiles[cell]; var variant = shroudTile.Variant; shroudTile.Shroud = GetTile(shroudSprites, shrouded, variant); shroudTile.Fog = GetTile(fogSprites, fogged, variant); tiles[cell] = shroudTile; } }
public void RenderShroud(WorldRenderer wr, Shroud shroud) { Update(shroud); Render(wr.Viewport.VisibleCells); }