Move ShroudPalette, ShroudRenderer and StartGameNotification to Common
Move World into Traits folder
This commit is contained in:
@@ -1,97 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
{
|
||||
[Desc("Attach this to the world actor.")]
|
||||
public class CreateMPPlayersInfo : TraitInfo<CreateMPPlayers> { }
|
||||
|
||||
public class CreateMPPlayers : ICreatePlayers
|
||||
{
|
||||
public void CreatePlayers(World w)
|
||||
{
|
||||
// create the unplayable map players -- neutral, shellmap, scripted, etc.
|
||||
foreach (var kv in w.Map.Players.Where(p => !p.Value.Playable))
|
||||
{
|
||||
var player = new Player(w, null, null, kv.Value);
|
||||
w.AddPlayer(player);
|
||||
if (kv.Value.OwnsWorld)
|
||||
w.WorldActor.Owner = player;
|
||||
}
|
||||
|
||||
// create the players which are bound through slots.
|
||||
foreach (var kv in w.LobbyInfo.Slots)
|
||||
{
|
||||
var client = w.LobbyInfo.ClientInSlot(kv.Key);
|
||||
if (client == null)
|
||||
continue;
|
||||
|
||||
var player = new Player(w, client, kv.Value, w.Map.Players[kv.Value.PlayerReference]);
|
||||
w.AddPlayer(player);
|
||||
|
||||
if (client.Index == Game.LocalClientId)
|
||||
w.SetLocalPlayer(player.InternalName);
|
||||
}
|
||||
|
||||
// create a player that is allied with everyone for shared observer shroud
|
||||
w.AddPlayer(new Player(w, null, null, new PlayerReference
|
||||
{
|
||||
Name = "Everyone",
|
||||
NonCombatant = true,
|
||||
Spectating = true,
|
||||
Allies = w.Players.Where(p => !p.NonCombatant && p.Playable).Select(p => p.InternalName).ToArray()
|
||||
}));
|
||||
|
||||
foreach (var p in w.Players)
|
||||
foreach (var q in w.Players)
|
||||
if (!p.Stances.ContainsKey(q))
|
||||
p.Stances[q] = ChooseInitialStance(p, q);
|
||||
}
|
||||
|
||||
static Stance ChooseInitialStance(Player p, Player q)
|
||||
{
|
||||
if (p == q)
|
||||
return Stance.Ally;
|
||||
|
||||
if (q.Spectating && !p.NonCombatant && p.Playable)
|
||||
return Stance.Ally;
|
||||
|
||||
// Stances set via PlayerReference
|
||||
if (p.PlayerReference.Allies.Contains(q.InternalName))
|
||||
return Stance.Ally;
|
||||
if (p.PlayerReference.Enemies.Contains(q.InternalName))
|
||||
return Stance.Enemy;
|
||||
|
||||
// HACK: Map players share a ClientID with the host, so would
|
||||
// otherwise take the host's team stance instead of being neutral
|
||||
if (p.PlayerReference.Playable && q.PlayerReference.Playable)
|
||||
{
|
||||
// Stances set via lobby teams
|
||||
var pc = GetClientForPlayer(p);
|
||||
var qc = GetClientForPlayer(q);
|
||||
if (pc != null && qc != null)
|
||||
return pc.Team != 0 && pc.Team == qc.Team
|
||||
? Stance.Ally : Stance.Enemy;
|
||||
}
|
||||
|
||||
// Otherwise, default to neutral
|
||||
return Stance.Neutral;
|
||||
}
|
||||
|
||||
static Session.Client GetClientForPlayer(Player p)
|
||||
{
|
||||
return p.World.LobbyInfo.ClientWithIndex(p.ClientIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
{
|
||||
public class MPStartLocationsInfo : TraitInfo<MPStartLocations>
|
||||
{
|
||||
public readonly WRange InitialExploreRange = WRange.FromCells(5);
|
||||
}
|
||||
|
||||
public class MPStartLocations : IWorldLoaded
|
||||
{
|
||||
public Dictionary<Player, CPos> Start = new Dictionary<Player, CPos>();
|
||||
|
||||
public void WorldLoaded(World world, WorldRenderer wr)
|
||||
{
|
||||
var spawns = world.Map.GetSpawnPoints().ToList();
|
||||
var taken = world.LobbyInfo.Clients.Where(c => c.SpawnPoint != 0 && c.Slot != null)
|
||||
.Select(c => spawns[c.SpawnPoint-1]).ToList();
|
||||
var available = spawns.Except(taken).ToList();
|
||||
|
||||
// Set spawn
|
||||
foreach (var kv in world.LobbyInfo.Slots)
|
||||
{
|
||||
var player = FindPlayerInSlot(world, kv.Key);
|
||||
if (player == null) continue;
|
||||
|
||||
var client = world.LobbyInfo.ClientInSlot(kv.Key);
|
||||
var spid = (client == null || client.SpawnPoint == 0)
|
||||
? ChooseSpawnPoint(world, available, taken)
|
||||
: spawns[client.SpawnPoint-1];
|
||||
|
||||
Start.Add(player, spid);
|
||||
|
||||
player.SpawnPoint = (client == null || client.SpawnPoint == 0)
|
||||
? spawns.IndexOf(spid) + 1
|
||||
: client.SpawnPoint;
|
||||
}
|
||||
|
||||
// Explore allied shroud
|
||||
var explore = world.WorldActor.Info.Traits.Get<MPStartLocationsInfo>().InitialExploreRange;
|
||||
foreach (var p in Start.Keys)
|
||||
foreach (var q in world.Players)
|
||||
if (p.IsAlliedWith(q))
|
||||
q.Shroud.Explore(world, Start[p], explore);
|
||||
|
||||
// Set viewport
|
||||
if (world.LocalPlayer != null && Start.ContainsKey(world.LocalPlayer))
|
||||
wr.Viewport.Center(world.Map.CenterOfCell(Start[world.LocalPlayer]));
|
||||
}
|
||||
|
||||
static Player FindPlayerInSlot(World world, string pr)
|
||||
{
|
||||
return world.Players.FirstOrDefault(p => p.PlayerReference.Name == pr);
|
||||
}
|
||||
|
||||
static CPos ChooseSpawnPoint(World world, List<CPos> available, List<CPos> taken)
|
||||
{
|
||||
if (available.Count == 0)
|
||||
throw new InvalidOperationException("No free spawnpoint.");
|
||||
|
||||
var n = taken.Count == 0
|
||||
? world.SharedRandom.Next(available.Count)
|
||||
: available // pick the most distant spawnpoint from everyone else
|
||||
.Select((k, i) => Pair.New(k, i))
|
||||
.MaxBy(a => taken.Sum(t => (t - a.First).LengthSquared)).Second;
|
||||
|
||||
var sp = available[n];
|
||||
available.RemoveAt(n);
|
||||
taken.Add(sp);
|
||||
return sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
{
|
||||
[Desc("Used by SpawnMPUnits. Attach these to the world actor. You can have multiple variants by adding @suffixes.")]
|
||||
public class MPStartUnitsInfo : TraitInfo<MPStartUnits>
|
||||
{
|
||||
[Desc("Internal class ID.")]
|
||||
public readonly string Class = "none";
|
||||
|
||||
[Desc("Exposed via the UI to the player.")]
|
||||
public readonly string ClassName = "Unlabeled";
|
||||
|
||||
[Desc("Only available when selecting this faction.", "Leave empty for no restrictions.")]
|
||||
public readonly string[] Races = { };
|
||||
|
||||
[Desc("The mobile construction vehicle.")]
|
||||
public readonly string BaseActor = null;
|
||||
|
||||
[Desc("A group of units ready to defend or scout.")]
|
||||
public readonly string[] SupportActors = { };
|
||||
|
||||
[Desc("Inner radius for spawning support actors")]
|
||||
public readonly int InnerSupportRadius = 2;
|
||||
|
||||
[Desc("Outer radius for spawning support actors")]
|
||||
public readonly int OuterSupportRadius = 4;
|
||||
}
|
||||
|
||||
public class MPStartUnits { }
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
{
|
||||
class PlayMusicOnMapLoadInfo : ITraitInfo
|
||||
{
|
||||
public readonly string Music = null;
|
||||
public readonly bool Loop = false;
|
||||
|
||||
public object Create(ActorInitializer init) { return new PlayMusicOnMapLoad(init.world, this); }
|
||||
}
|
||||
|
||||
class PlayMusicOnMapLoad : IWorldLoaded
|
||||
{
|
||||
readonly PlayMusicOnMapLoadInfo info;
|
||||
readonly World world;
|
||||
|
||||
public PlayMusicOnMapLoad(World world, PlayMusicOnMapLoadInfo info)
|
||||
{
|
||||
this.world = world;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public void WorldLoaded(World world, WorldRenderer wr)
|
||||
{
|
||||
PlayMusic();
|
||||
}
|
||||
|
||||
void PlayMusic()
|
||||
{
|
||||
var onComplete = info.Loop ? (Action)PlayMusic : () => {};
|
||||
|
||||
if (Game.Settings.Sound.MapMusic &&
|
||||
world.Map.Rules.Music.ContainsKey(info.Music))
|
||||
Sound.PlayMusicThen(world.Map.Rules.Music[info.Music], onComplete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
{
|
||||
public class RadarPingsInfo : ITraitInfo
|
||||
{
|
||||
public readonly int FromRadius = 200;
|
||||
public readonly int ToRadius = 15;
|
||||
public readonly int ShrinkSpeed = 4;
|
||||
public readonly float RotationSpeed = 0.12f;
|
||||
|
||||
public object Create(ActorInitializer init) { return new RadarPings(this); }
|
||||
}
|
||||
|
||||
public class RadarPings : ITick
|
||||
{
|
||||
public readonly List<RadarPing> Pings = new List<RadarPing>();
|
||||
readonly RadarPingsInfo info;
|
||||
|
||||
public WPos? LastPingPosition;
|
||||
|
||||
public RadarPings(RadarPingsInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
foreach (var ping in Pings.ToArray())
|
||||
if (!ping.Tick())
|
||||
Pings.Remove(ping);
|
||||
}
|
||||
|
||||
public RadarPing Add(Func<bool> isVisible, WPos position, Color color, int duration)
|
||||
{
|
||||
var ping = new RadarPing(isVisible, position, color, duration,
|
||||
info.FromRadius, info.ToRadius, info.ShrinkSpeed, info.RotationSpeed);
|
||||
|
||||
if (ping.IsVisible())
|
||||
LastPingPosition = ping.Position;
|
||||
|
||||
Pings.Add(ping);
|
||||
|
||||
return ping;
|
||||
}
|
||||
|
||||
public void Remove(RadarPing ping)
|
||||
{
|
||||
Pings.Remove(ping);
|
||||
}
|
||||
}
|
||||
|
||||
public class RadarPing
|
||||
{
|
||||
public Func<bool> IsVisible;
|
||||
public WPos Position;
|
||||
public Color Color;
|
||||
public int Duration;
|
||||
public int FromRadius;
|
||||
public int ToRadius;
|
||||
public int ShrinkSpeed;
|
||||
public float RotationSpeed;
|
||||
|
||||
int radius;
|
||||
float angle;
|
||||
int tick;
|
||||
|
||||
public RadarPing(Func<bool> isVisible, WPos position, Color color, int duration,
|
||||
int fromRadius, int toRadius, int shrinkSpeed, float rotationSpeed)
|
||||
{
|
||||
IsVisible = isVisible;
|
||||
Position = position;
|
||||
Color = color;
|
||||
Duration = duration;
|
||||
FromRadius = fromRadius;
|
||||
ToRadius = toRadius;
|
||||
ShrinkSpeed = shrinkSpeed;
|
||||
RotationSpeed = rotationSpeed;
|
||||
|
||||
radius = fromRadius;
|
||||
}
|
||||
|
||||
public bool Tick()
|
||||
{
|
||||
if (++tick == Duration)
|
||||
return false;
|
||||
|
||||
radius = Math.Max(radius - ShrinkSpeed, ToRadius);
|
||||
angle -= RotationSpeed;
|
||||
return true;
|
||||
}
|
||||
|
||||
public IEnumerable<float2> Points(float2 center)
|
||||
{
|
||||
yield return center + radius * float2.FromAngle(angle);
|
||||
yield return center + radius * float2.FromAngle((float)(angle + 2 * Math.PI / 3));
|
||||
yield return center + radius * float2.FromAngle((float)(angle + 4 * Math.PI / 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
{
|
||||
public sealed class ResourceClaim
|
||||
{
|
||||
public readonly Actor Claimer;
|
||||
public CPos Cell;
|
||||
|
||||
public ResourceClaim(Actor claimer, CPos cell) { Claimer = claimer; Cell = cell; }
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
{
|
||||
[Desc("Allows harvesters to coordinate their operations. Attach this to the world actor.")]
|
||||
public sealed class ResourceClaimLayerInfo : TraitInfo<ResourceClaimLayer> { }
|
||||
|
||||
public sealed class ResourceClaimLayer : IWorldLoaded
|
||||
{
|
||||
Dictionary<CPos, ResourceClaim> claimByCell;
|
||||
Dictionary<Actor, ResourceClaim> claimByActor;
|
||||
|
||||
private void MakeClaim(Actor claimer, CPos cell)
|
||||
{
|
||||
UnclaimByActor(claimer);
|
||||
UnclaimByCell(cell, claimer);
|
||||
claimByActor[claimer] = claimByCell[cell] = new ResourceClaim(claimer, cell);
|
||||
}
|
||||
|
||||
private void Unclaim(ResourceClaim claim, Actor claimer)
|
||||
{
|
||||
if (claimByActor.Remove(claim.Claimer) & claimByCell.Remove(claim.Cell))
|
||||
{
|
||||
if (claim.Claimer.Destroyed) return;
|
||||
if (!claim.Claimer.IsInWorld) return;
|
||||
if (claim.Claimer.IsDead()) return;
|
||||
|
||||
claim.Claimer.Trait<INotifyResourceClaimLost>().OnNotifyResourceClaimLost(claim.Claimer, claim, claimer);
|
||||
}
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
// NOTE(jsd): 32 seems a sane default initial capacity for the total # of harvesters in a game. Purely a guesstimate.
|
||||
claimByCell = new Dictionary<CPos, ResourceClaim>(32);
|
||||
claimByActor = new Dictionary<Actor, ResourceClaim>(32);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to claim the resource at the cell for the given actor.
|
||||
/// </summary>
|
||||
/// <param name="claimer"></param>
|
||||
/// <param name="cell"></param>
|
||||
/// <returns></returns>
|
||||
public bool ClaimResource(Actor claimer, CPos cell)
|
||||
{
|
||||
// Has anyone else claimed this point?
|
||||
ResourceClaim claim;
|
||||
if (claimByCell.TryGetValue(cell, out claim))
|
||||
{
|
||||
// Same claimer:
|
||||
if (claim.Claimer == claimer) return true;
|
||||
|
||||
// This is to prevent in-fighting amongst friendly harvesters:
|
||||
if (claimer.Owner == claim.Claimer.Owner) return false;
|
||||
if (claimer.Owner.Stances[claim.Claimer.Owner] == Stance.Ally) return false;
|
||||
|
||||
// If an enemy/neutral claimed this, don't respect that claim:
|
||||
}
|
||||
|
||||
// Either nobody else claims this point or an enemy/neutral claims it:
|
||||
MakeClaim(claimer, cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release the last resource claim made on this cell.
|
||||
/// </summary>
|
||||
/// <param name="cell"></param>
|
||||
public void UnclaimByCell(CPos cell, Actor claimer)
|
||||
{
|
||||
ResourceClaim claim;
|
||||
if (claimByCell.TryGetValue(cell, out claim))
|
||||
Unclaim(claim, claimer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release the last resource claim made by this actor.
|
||||
/// </summary>
|
||||
/// <param name="claimer"></param>
|
||||
public void UnclaimByActor(Actor claimer)
|
||||
{
|
||||
ResourceClaim claim;
|
||||
if (claimByActor.TryGetValue(claimer, out claim))
|
||||
Unclaim(claim, claimer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the cell location <paramref name="cell"/> claimed for harvesting by any other actor?
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="cell"></param>
|
||||
/// <returns>true if already claimed by an ally that isn't <paramref name="self"/>; false otherwise.</returns>
|
||||
public bool IsClaimedByAnyoneElse(Actor self, CPos cell, out ResourceClaim claim)
|
||||
{
|
||||
if (claimByCell.TryGetValue(cell, out claim))
|
||||
{
|
||||
// Same claimer:
|
||||
if (claim.Claimer == self) return false;
|
||||
|
||||
// This is to prevent in-fighting amongst friendly harvesters:
|
||||
if (self.Owner == claim.Claimer.Owner) return true;
|
||||
if (self.Owner.Stances[claim.Claimer.Owner] == Stance.Ally) return true;
|
||||
|
||||
// If an enemy/neutral claimed this, don't respect that claim and fall through:
|
||||
}
|
||||
else
|
||||
{
|
||||
// No claim.
|
||||
claim = null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Effects;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
{
|
||||
[Desc("Attach this to the world actor.", "Order of the layers defines the Z sorting.")]
|
||||
public class SmudgeLayerInfo : ITraitInfo
|
||||
{
|
||||
public readonly string Type = "Scorch";
|
||||
|
||||
[Desc("Sprite sequence name")]
|
||||
public readonly string Sequence = "scorch";
|
||||
|
||||
public readonly int SmokePercentage = 25;
|
||||
|
||||
[Desc("Sprite sequence name")]
|
||||
public readonly string SmokeType = "smoke_m";
|
||||
|
||||
public readonly string Palette = "terrain";
|
||||
|
||||
public object Create(ActorInitializer init) { return new SmudgeLayer(this); }
|
||||
}
|
||||
|
||||
public class SmudgeLayer : IRenderOverlay, IWorldLoaded, ITickRender
|
||||
{
|
||||
struct Smudge
|
||||
{
|
||||
public string Type;
|
||||
public int Depth;
|
||||
public Sprite Sprite;
|
||||
}
|
||||
|
||||
public SmudgeLayerInfo Info;
|
||||
Dictionary<CPos, Smudge> tiles;
|
||||
Dictionary<CPos, Smudge> dirty;
|
||||
Dictionary<string, Sprite[]> smudges;
|
||||
World world;
|
||||
|
||||
public SmudgeLayer(SmudgeLayerInfo info)
|
||||
{
|
||||
this.Info = info;
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
tiles = new Dictionary<CPos, Smudge>();
|
||||
dirty = new Dictionary<CPos, Smudge>();
|
||||
smudges = new Dictionary<string, Sprite[]>();
|
||||
|
||||
var types = world.Map.SequenceProvider.Sequences(Info.Sequence);
|
||||
foreach (var t in types)
|
||||
{
|
||||
var seq = world.Map.SequenceProvider.GetSequence(Info.Sequence, t);
|
||||
var sprites = Exts.MakeArray(seq.Length, x => seq.GetSprite(x));
|
||||
smudges.Add(t, sprites);
|
||||
}
|
||||
|
||||
// Add map smudges
|
||||
foreach (var s in w.Map.Smudges.Value.Where(s => smudges.Keys.Contains(s.Type)))
|
||||
{
|
||||
var smudge = new Smudge
|
||||
{
|
||||
Type = s.Type,
|
||||
Depth = s.Depth,
|
||||
Sprite = smudges[s.Type][s.Depth]
|
||||
};
|
||||
|
||||
tiles.Add((CPos)s.Location, smudge);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSmudge(CPos loc)
|
||||
{
|
||||
if (Game.CosmeticRandom.Next(0, 100) <= Info.SmokePercentage)
|
||||
world.AddFrameEndTask(w => w.Add(new Smoke(w, world.Map.CenterOfCell(loc), Info.SmokeType)));
|
||||
|
||||
if (!dirty.ContainsKey(loc) && !tiles.ContainsKey(loc))
|
||||
{
|
||||
// No smudge; create a new one
|
||||
var st = smudges.Keys.Random(world.SharedRandom);
|
||||
dirty[loc] = new Smudge { Type = st, Depth = 0, Sprite = smudges[st][0] };
|
||||
}
|
||||
else
|
||||
{
|
||||
// Existing smudge; make it deeper
|
||||
var tile = dirty.ContainsKey(loc) ? dirty[loc] : tiles[loc];
|
||||
var maxDepth = smudges[tile.Type].Length;
|
||||
if (tile.Depth < maxDepth - 1)
|
||||
{
|
||||
tile.Depth++;
|
||||
tile.Sprite = smudges[tile.Type][tile.Depth];
|
||||
}
|
||||
|
||||
dirty[loc] = tile;
|
||||
}
|
||||
}
|
||||
|
||||
public void TickRender(WorldRenderer wr, Actor self)
|
||||
{
|
||||
var remove = new List<CPos>();
|
||||
foreach (var kv in dirty)
|
||||
{
|
||||
if (!self.World.FogObscures(kv.Key))
|
||||
{
|
||||
tiles[kv.Key] = kv.Value;
|
||||
remove.Add(kv.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var r in remove)
|
||||
dirty.Remove(r);
|
||||
}
|
||||
|
||||
public void Render(WorldRenderer wr)
|
||||
{
|
||||
var pal = wr.Palette(Info.Palette);
|
||||
|
||||
foreach (var kv in tiles)
|
||||
{
|
||||
if (!wr.Viewport.VisibleCells.Contains(kv.Key))
|
||||
continue;
|
||||
|
||||
if (world.ShroudObscures(kv.Key))
|
||||
continue;
|
||||
|
||||
new SpriteRenderable(kv.Value.Sprite, world.Map.CenterOfCell(kv.Key),
|
||||
WVec.Zero, -511, pal, 1f, true).Render(wr); // TODO ZOffset is ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
{
|
||||
public class SpawnMapActorsInfo : TraitInfo<SpawnMapActors> { }
|
||||
|
||||
public class SpawnMapActors : IWorldLoaded
|
||||
{
|
||||
public Dictionary<string, Actor> Actors = new Dictionary<string, Actor>();
|
||||
public uint LastMapActorID { get; private set; }
|
||||
|
||||
public void WorldLoaded(World world, WorldRenderer wr)
|
||||
{
|
||||
foreach (var actorReference in world.Map.Actors.Value)
|
||||
{
|
||||
// if there is no real player associated, dont spawn it.
|
||||
var ownerName = actorReference.Value.InitDict.Get<OwnerInit>().PlayerName;
|
||||
if (!world.Players.Any(p => p.InternalName == ownerName))
|
||||
continue;
|
||||
|
||||
var initDict = actorReference.Value.InitDict;
|
||||
initDict.Add(new SkipMakeAnimsInit());
|
||||
var actor = world.CreateActor(actorReference.Value.Type, initDict);
|
||||
Actors[actorReference.Key] = actor;
|
||||
LastMapActorID = actor.ActorID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SkipMakeAnimsInit : IActorInit {}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
{
|
||||
[Desc("Renders a debug overlay showing the terrain cells. Attach this to the world actor.")]
|
||||
public class TerrainGeometryOverlayInfo : ITraitInfo
|
||||
{
|
||||
public object Create(ActorInitializer init) { return new TerrainGeometryOverlay(init.self); }
|
||||
}
|
||||
|
||||
public class TerrainGeometryOverlay : IRenderOverlay
|
||||
{
|
||||
readonly int[][] vertices = new int[][]
|
||||
{
|
||||
// Flat
|
||||
new[] { 0, 0, 0, 0 },
|
||||
|
||||
// Slopes (two corners high)
|
||||
new[] { 0, 0, 1, 1 },
|
||||
new[] { 1, 0, 0, 1 },
|
||||
new[] { 1, 1, 0, 0 },
|
||||
new[] { 0, 1, 1, 0 },
|
||||
|
||||
// Slopes (one corner high)
|
||||
new[] { 0, 0, 0, 1 },
|
||||
new[] { 1, 0, 0, 0 },
|
||||
new[] { 0, 1, 0, 0 },
|
||||
new[] { 0, 0, 1, 0 },
|
||||
|
||||
// Slopes (three corners high)
|
||||
new[] { 1, 0, 1, 1 },
|
||||
new[] { 1, 1, 0, 1 },
|
||||
new[] { 1, 1, 1, 0 },
|
||||
new[] { 0, 1, 1, 1 },
|
||||
|
||||
// Slopes (two corners high, one corner double high)
|
||||
new[] { 1, 0, 1, 2 },
|
||||
new[] { 2, 1, 0, 1 },
|
||||
new[] { 1, 2, 1, 0 },
|
||||
new[] { 0, 1, 2, 1 },
|
||||
|
||||
// Slopes (two corners high, alternating)
|
||||
new[] { 1, 0, 1, 0 },
|
||||
new[] { 0, 1, 0, 1 },
|
||||
new[] { 1, 0, 1, 0 },
|
||||
new[] { 0, 1, 0, 1 }
|
||||
};
|
||||
|
||||
readonly Lazy<DeveloperMode> devMode;
|
||||
|
||||
public TerrainGeometryOverlay(Actor self)
|
||||
{
|
||||
devMode = Exts.Lazy(() => self.World.LocalPlayer != null ? self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>() : null);
|
||||
}
|
||||
|
||||
public void Render(WorldRenderer wr)
|
||||
{
|
||||
if (devMode.Value == null || !devMode.Value.ShowTerrainGeometry)
|
||||
return;
|
||||
|
||||
var ts = wr.world.Map.TileShape;
|
||||
var colors = wr.world.TileSet.HeightDebugColors;
|
||||
|
||||
var leftDelta = ts == TileShape.Diamond ? new WVec(-512, 0, 0) : new WVec(-512, -512, 0);
|
||||
var topDelta = ts == TileShape.Diamond ? new WVec(0, -512, 0) : new WVec(512, -512, 0);
|
||||
var rightDelta = ts == TileShape.Diamond ? new WVec(512, 0, 0) : new WVec(512, 512, 0);
|
||||
var bottomDelta = ts == TileShape.Diamond ? new WVec(0, 512, 0) : new WVec(-512, 512, 0);
|
||||
|
||||
foreach (var cell in wr.Viewport.VisibleCells)
|
||||
{
|
||||
var lr = Game.Renderer.WorldLineRenderer;
|
||||
var pos = wr.world.Map.CenterOfCell(cell);
|
||||
|
||||
var height = (int)wr.world.Map.MapHeight.Value[cell];
|
||||
var tile = wr.world.Map.MapTiles.Value[cell];
|
||||
|
||||
TerrainTileInfo tileInfo = null;
|
||||
|
||||
// TODO: This is a temporary workaround for our sloppy tileset definitions
|
||||
// (ra/td templates omit Clear tiles from templates)
|
||||
try
|
||||
{
|
||||
tileInfo = wr.world.TileSet.Templates[tile.Type][tile.Index];
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
if (tileInfo == null)
|
||||
continue;
|
||||
|
||||
var leftHeight = vertices[tileInfo.RampType][0];
|
||||
var topHeight = vertices[tileInfo.RampType][1];
|
||||
var rightHeight = vertices[tileInfo.RampType][2];
|
||||
var bottomHeight = vertices[tileInfo.RampType][3];
|
||||
|
||||
var leftColor = colors[height + leftHeight];
|
||||
var topColor = colors[height + topHeight];
|
||||
var rightColor = colors[height + rightHeight];
|
||||
var bottomColor = colors[height + bottomHeight];
|
||||
|
||||
var left = wr.ScreenPxPosition(pos + leftDelta + new WVec(0, 0, 512 * leftHeight)).ToFloat2();
|
||||
var top = wr.ScreenPxPosition(pos + topDelta + new WVec(0, 0, 512 * topHeight)).ToFloat2();
|
||||
var right = wr.ScreenPxPosition(pos + rightDelta + new WVec(0, 0, 512 * rightHeight)).ToFloat2();
|
||||
var bottom = wr.ScreenPxPosition(pos + bottomDelta + new WVec(0, 0, 512 * bottomHeight)).ToFloat2();
|
||||
|
||||
lr.DrawLine(left, top, leftColor, topColor);
|
||||
lr.DrawLine(top, right, topColor, rightColor);
|
||||
lr.DrawLine(right, bottom, rightColor, bottomColor);
|
||||
lr.DrawLine(bottom, left, bottomColor, leftColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user