merged pchote/master attack-omni bridge-setup-as-trait

This commit is contained in:
Chris Forbes
2010-02-09 13:31:26 +13:00
35 changed files with 361 additions and 588 deletions

View File

@@ -356,10 +356,8 @@ namespace OpenRa
while (!PaletteAvailable(newIndex) && newIndex != (int)Game.world.LocalPlayer.PaletteIndex)
newIndex = (newIndex + d) % Player.PlayerColors.Count();
Game.world.Minimap.InvalidateSpawnPoints();
Game.IssueOrder(
Order.Chat("/pal " + newIndex));
}
void CycleRace(bool left)
@@ -1193,5 +1191,13 @@ namespace OpenRa
renderer.DrawText(sp.Info.LongDesc.Replace("\\n", "\n"), pos, Color.White);
}
}
public void SetCurrentTab(string produces)
{
if (!paletteOpen)
paletteAnimating = true;
paletteOpen = true;
currentTab = produces;
}
}
}

View File

@@ -13,6 +13,7 @@ namespace OpenRa
public class Controller : IHandleInput
{
public IOrderGenerator orderGenerator;
public Selection selection = new Selection();
readonly Func<Modifiers> GetModifierKeys;
@@ -22,10 +23,7 @@ namespace OpenRa
CancelInputMode();
}
public void CancelInputMode()
{
orderGenerator = new UnitOrderGenerator(new Actor[] { });
}
public void CancelInputMode() { orderGenerator = new UnitOrderGenerator(); }
public bool ToggleInputMode<T>() where T : IOrderGenerator, new()
{
@@ -83,7 +81,7 @@ namespace OpenRa
if (orderGenerator is UnitOrderGenerator)
{
var newSelection = world.SelectActorsInBox(Game.CellSize * dragStart, Game.CellSize * xy);
CombineSelection(world, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
selection.Combine(world, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
}
dragStart = dragEnd = xy;
@@ -98,29 +96,6 @@ namespace OpenRa
return true;
}
void CombineSelection(World world, IEnumerable<Actor> newSelection, bool isCombine, bool isClick)
{
var oldSelection = (orderGenerator is UnitOrderGenerator)
? (orderGenerator as UnitOrderGenerator).selection : new Actor[] { }.AsEnumerable();
if (isClick)
{
var adjNewSelection = newSelection.Take(1); /* todo: select BEST, not FIRST */
orderGenerator = new UnitOrderGenerator(isCombine
? oldSelection.SymmetricDifference(adjNewSelection) : adjNewSelection);
}
else
orderGenerator = new UnitOrderGenerator(isCombine
? oldSelection.Union(newSelection) : newSelection);
var voicedUnit = ((UnitOrderGenerator)orderGenerator).selection
.Where(a => a.traits.Contains<Unit>()
&& a.Owner == world.LocalPlayer)
.FirstOrDefault();
Sound.PlayVoice("Select", voicedUnit);
}
public Pair<float2, float2>? SelectionBox
{
get
@@ -153,42 +128,5 @@ namespace OpenRa
throw new InvalidOperationException( "Desync in Controller.ChooseCursor" );
}
}
Cache<int, List<Actor>> controlGroups = new Cache<int, List<Actor>>(_ => new List<Actor>());
public void DoControlGroup(World world, int group, Modifiers mods)
{
var uog = orderGenerator as UnitOrderGenerator;
if (uog == null) return;
if (mods.HasModifier(Modifiers.Ctrl))
{
if (!uog.selection.Any())
return;
controlGroups[group].Clear();
for (var i = 0; i < 10; i++) /* all control groups */
controlGroups[i].RemoveAll(a => uog.selection.Contains(a));
controlGroups[group].AddRange(uog.selection);
return;
}
if (mods.HasModifier(Modifiers.Alt))
{
Game.viewport.Center(controlGroups[group]);
return;
}
CombineSelection(world, controlGroups[group], mods.HasModifier(Modifiers.Shift), false);
}
public int? GetControlGroupForActor(Actor a)
{
return controlGroups.Where(g => g.Value.Contains(a))
.Select(g => (int?)g.Key)
.FirstOrDefault();
}
}
}

View File

@@ -37,19 +37,12 @@ namespace OpenRa
public static void LoadModPackages(Manifest manifest)
{
FileSystem.UnmountTemporaryPackages();
FileSystem.UnmountAll();
Timer.Time("reset: {0}");
foreach (var dir in manifest.Folders)
FileSystem.MountTemporary(new Folder(dir));
foreach (var pkg in manifest.Packages)
if (pkg.StartsWith( "~")) // this package is optional.
try { FileSystem.MountTemporary(new Package(pkg.Substring(1))); }
catch { }
else
FileSystem.MountTemporary(new Package(pkg));
foreach (var dir in manifest.Folders) FileSystem.Mount(dir);
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
Timer.Time("mount temporary packages: {0}");
}
@@ -87,7 +80,6 @@ namespace OpenRa
viewport = new Viewport(clientSize, Game.world.Map.Offset, Game.world.Map.Offset + Game.world.Map.Size, renderer);
Timer.Time( "ChromeProv, SeqProv, viewport: {0}" );
skipMakeAnims = true;
foreach (var treeReference in Game.world.Map.Trees)
world.CreateActor(treeReference.Image, new int2(treeReference.Location), null);
@@ -161,9 +153,9 @@ namespace OpenRa
if (orderManager.IsReadyForNextFrame)
{
orderManager.Tick( world );
if (controller.orderGenerator != null)
controller.orderGenerator.Tick( world );
orderManager.Tick(world);
controller.orderGenerator.Tick(world);
controller.selection.Tick(world);
world.Tick();
}
@@ -300,7 +292,8 @@ namespace OpenRa
if( !Game.chat.isChatting )
if( e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9 )
Game.controller.DoControlGroup( world, (int)e.KeyCode - (int)Keys.D0, (Modifiers)(int)e.Modifiers );
Game.controller.selection.DoControlGroup( world,
(int)e.KeyCode - (int)Keys.D0, (Modifiers)(int)e.Modifiers );
if( sync != Game.world.SyncHash() )
throw new InvalidOperationException( "Desync in OnKeyDown" );

View File

@@ -46,9 +46,6 @@ namespace OpenRa.GameRules
public readonly float BuildupTime = 0;
public readonly int GemValue = 0;
public readonly int GoldValue = 0;
public readonly float GrowthRate = 0;
public readonly bool OreGrows = true;
public readonly bool OreSpreads = true;
public readonly float OreTruckRate = 0;
public readonly bool SeparateAircraft = true;
public readonly float SurvivorRate = 0;
@@ -90,7 +87,6 @@ namespace OpenRa.GameRules
public readonly bool FineDiffControl = false;
/* OpenRA-specific */
public readonly float OreChance = 0; /* chance of spreading to a particular eligible cell */
public readonly int LowPowerSlowdown = 3; /* build time multiplier */
}
}

View File

@@ -17,7 +17,7 @@ namespace OpenRa.Graphics
SpriteRenderer rgbaRenderer;
LineRenderer lineRenderer;
Sprite sprite, mapOnlySprite, mapSpawnPointSprite;
Bitmap terrain, oreLayer, spawnPointsLayer;
Bitmap terrain, oreLayer;
Rectangle bounds;
Sprite ownedSpawnPoint;
@@ -74,7 +74,6 @@ namespace OpenRa.Graphics
static Color shroudColor;
public void InvalidateOre() { oreLayer = null; }
public void InvalidateSpawnPoints() { spawnPointsLayer = null; }
public static Bitmap RenderTerrainBitmap(Map map, TileSet tileset)
{

View File

@@ -234,7 +234,7 @@ namespace OpenRa.Graphics
void DrawControlGroup(Actor selectedUnit, float2 basePosition)
{
var group = Game.controller.GetControlGroupForActor(selectedUnit);
var group = Game.controller.selection.GetControlGroupForActor(selectedUnit);
if (group == null) return;
var pipImages = new Animation("pips");

View File

@@ -74,11 +74,11 @@ namespace OpenRa
{
Game.Settings = new UserSettings();
var settingsFile = settings.GetValue("settings", "settings.ini");
FileSystem.MountTemporary(new Folder("./"));
FileSystem.Mount("./");
if (FileSystem.Exists(settingsFile))
FieldLoader.Load(Game.Settings,
new IniFile(FileSystem.Open(settingsFile)).GetSection("Settings"));
FileSystem.UnmountTemporaryPackages();
FileSystem.UnmountAll();
}
internal void Run()

View File

@@ -73,7 +73,6 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Bridges.cs" />
<Compile Include="Chat.cs" />
<Compile Include="Chrome.cs" />
<Compile Include="Combat.cs" />
@@ -111,13 +110,18 @@
<Compile Include="Ore.cs" />
<Compile Include="PackageDownloader.cs" />
<Compile Include="PathSearch.cs" />
<Compile Include="Selection.cs" />
<Compile Include="Shroud.cs" />
<Compile Include="Smudge.cs" />
<Compile Include="Sound.cs" />
<Compile Include="Support\OpenAlInterop.cs" />
<Compile Include="Support\PerfHistory.cs" />
<Compile Include="Sync.cs" />
<Compile Include="Traits\AttackOmni.cs" />
<Compile Include="Traits\BridgeLoadHook.cs" />
<Compile Include="Traits\ChoosePaletteOnSelect.cs" />
<Compile Include="Traits\CrateSpawner.cs" />
<Compile Include="Traits\OreGrowth.cs" />
<Compile Include="Traits\OreRefinery.cs" />
<Compile Include="Traits\Activities\Attack.cs" />
<Compile Include="Traits\Activities\CallFunc.cs" />
@@ -313,4 +317,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@@ -8,16 +8,9 @@ namespace OpenRa.Orders
{
class UnitOrderGenerator : IOrderGenerator
{
public readonly List<Actor> selection;
public UnitOrderGenerator( IEnumerable<Actor> selected )
{
selection = selected.ToList();
}
public IEnumerable<Order> Order( World world, int2 xy, MouseInput mi )
{
foreach( var unit in selection )
foreach( var unit in Game.controller.selection.Actors )
{
var ret = unit.Order( xy, mi );
if( ret != null )
@@ -25,14 +18,11 @@ namespace OpenRa.Orders
}
}
public void Tick( World world )
{
selection.RemoveAll(a => !a.IsInWorld);
}
public void Tick( World world ) {}
public void Render( World world )
{
foreach( var a in selection )
foreach( var a in Game.controller.selection.Actors )
world.WorldRenderer.DrawSelectionBox( a, Color.White, true );
}

View File

@@ -8,14 +8,13 @@ namespace OpenRa
{
public static void AddOre(this Map map, int i, int j)
{
if (Rules.General.OreSpreads)
if (map.ContainsOre(i, j) && map.MapTiles[i, j].density < 12)
map.MapTiles[i, j].density++;
else if (map.MapTiles[i, j].overlay == 0xff)
{
map.MapTiles[i, j].overlay = ChooseOre();
map.MapTiles[i, j].density = 1;
}
if (map.ContainsOre(i, j) && map.MapTiles[i, j].density < 12)
map.MapTiles[i, j].density++;
else if (map.MapTiles[i, j].overlay == 0xff)
{
map.MapTiles[i, j].overlay = ChooseOre();
map.MapTiles[i, j].density = 1;
}
}
public static void DestroyOre(this Map map, int i, int j)
@@ -37,48 +36,49 @@ namespace OpenRa
< double.PositiveInfinity;
}
public static void SpreadOre(this World world, Random r, float chance)
{
var map = world.Map;
var mini = map.XOffset; var maxi = map.XOffset + map.Width;
var minj = map.YOffset; var maxj = map.YOffset + map.Height;
/* phase 1: grow into neighboring regions */
var newOverlay = new byte[128, 128];
for (int j = minj; j < maxj; j++)
for (int i = mini; i < maxi; i++)
{
newOverlay[i, j] = 0xff;
if (!map.HasOverlay(i, j)
&& r.NextDouble() < chance
&& map.GetOreDensity(i, j) > 0
&& world.OreCanSpreadInto(i, j))
newOverlay[i, j] = ChooseOre();
}
for (int j = minj; j < maxj; j++)
for (int i = mini; i < maxi; i++)
if (newOverlay[i, j] != 0xff)
map.MapTiles[i, j].overlay = newOverlay[i, j];
}
public static void GrowOre(this World world, Random r)
{
var map = world.Map;
var mini = map.XOffset; var maxi = map.XOffset + map.Width;
var minj = map.YOffset; var maxj = map.YOffset + map.Height;
var chance = Rules.General.OreChance;
/* phase 1: grow into neighboring regions */
if (Rules.General.OreSpreads)
{
var newOverlay = new byte[128, 128];
for (int j = minj; j < maxj; j++)
for (int i = mini; i < maxi; i++)
{
newOverlay[i, j] = 0xff;
if (!map.HasOverlay(i, j)
&& r.NextDouble() < chance
&& map.GetOreDensity(i, j) > 0
&& world.OreCanSpreadInto(i,j))
newOverlay[i, j] = ChooseOre();
}
for (int j = minj; j < maxj; j++)
for (int i = mini; i < maxi; i++)
if (newOverlay[i, j] != 0xff)
map.MapTiles[i, j].overlay = newOverlay[i, j];
}
/* phase 2: increase density of existing areas */
if (Rules.General.OreGrows)
{
var newDensity = new byte[128, 128];
for (int j = minj; j < maxj; j++)
for (int i = mini; i < maxi; i++)
if (map.ContainsOre(i, j)) newDensity[i, j] = map.GetOreDensity(i, j);
var newDensity = new byte[128, 128];
for (int j = minj; j < maxj; j++)
for (int i = mini; i < maxi; i++)
if (map.ContainsOre(i, j)) newDensity[i, j] = map.GetOreDensity(i, j);
for (int j = minj; j < maxj; j++)
for (int i = mini; i < maxi; i++)
if (map.MapTiles[i, j].density < newDensity[i, j])
++map.MapTiles[i, j].density;
}
for (int j = minj; j < maxj; j++)
for (int i = mini; i < maxi; i++)
if (map.MapTiles[i, j].density < newDensity[i, j])
++map.MapTiles[i, j].density;
}
public static void InitOreDensity( this Map map )

76
OpenRa.Game/Selection.cs Normal file
View File

@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRa.Traits;
using IjwFramework.Collections;
namespace OpenRa
{
public class Selection
{
List<Actor> actors = new List<Actor>();
public void Combine(World world, IEnumerable<Actor> newSelection, bool isCombine, bool isClick)
{
var oldSelection = actors.AsEnumerable();
if (isClick)
{
var adjNewSelection = newSelection.Take(1); /* todo: select BEST, not FIRST */
actors = (isCombine ? oldSelection.SymmetricDifference(adjNewSelection) : adjNewSelection).ToList();
}
else
actors = (isCombine ? oldSelection.Union(newSelection) : newSelection).ToList();
var voicedUnit = actors.FirstOrDefault(a => a.traits.Contains<Unit>() && a.Owner == world.LocalPlayer);
Sound.PlayVoice("Select", voicedUnit);
foreach (var ns in world.WorldActor.traits.WithInterface<INotifySelection>())
ns.SelectionChanged();
}
public IEnumerable<Actor> Actors { get { return actors; } }
public void Clear() { actors = new List<Actor>(); }
public void Tick(World world)
{
actors.RemoveAll(a => !a.IsInWorld);
}
Cache<int, List<Actor>> controlGroups = new Cache<int, List<Actor>>(_ => new List<Actor>());
public void DoControlGroup(World world, int group, Modifiers mods)
{
if (mods.HasModifier(Modifiers.Ctrl))
{
if (actors.Count == 0)
return;
controlGroups[group].Clear();
for (var i = 0; i < 10; i++) /* all control groups */
controlGroups[i].RemoveAll(a => actors.Contains(a));
controlGroups[group].AddRange(actors);
return;
}
if (mods.HasModifier(Modifiers.Alt))
{
Game.viewport.Center(controlGroups[group]);
return;
}
Combine(world, controlGroups[group],
mods.HasModifier(Modifiers.Shift), false);
}
public int? GetControlGroupForActor(Actor a)
{
return controlGroups.Where(g => g.Value.Contains(a))
.Select(g => (int?)g.Key)
.FirstOrDefault();
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Traits
{
class AttackOmniInfo : AttackBaseInfo
{
public override object Create(Actor self) { return new AttackOmni(self); }
}
class AttackOmni : AttackBase, INotifyBuildComplete
{
bool buildComplete = false;
public void BuildingComplete(Actor self) { buildComplete = true; }
public AttackOmni(Actor self) : base(self) { }
public override void Tick(Actor self)
{
base.Tick(self);
if (!CanAttack(self)) return;
if (self.traits.Contains<Building>() && !buildComplete) return;
DoAttack(self);
}
protected override void QueueAttack(Actor self, Order order)
{
target = order.TargetActor;
}
}
}

View File

@@ -2,13 +2,14 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRa.Traits;
namespace OpenRa
namespace OpenRa.Traits
{
static class Bridges
class BridgeLoadHookInfo : StatelessTraitInfo<BridgeLoadHook> { }
class BridgeLoadHook : ILoadWorldHook
{
public static void MakeBridges(World w)
static void MakeBridges(World w)
{
var mini = w.Map.XOffset; var maxi = w.Map.XOffset + w.Map.Width;
var minj = w.Map.YOffset; var maxj = w.Map.YOffset + w.Map.Height;
@@ -40,8 +41,8 @@ namespace OpenRa
if (!template.TerrainType.ContainsKey(n)) continue;
if (w.Map.IsInMap(x, y))
if (w.Map.MapTiles[x, y].tile == tile
&& w.Map.MapTiles[x,y].image == n)
if (w.Map.MapTiles[x, y].tile == tile
&& w.Map.MapTiles[x, y].image == n)
{
// stash it
replacedTiles[new int2(x, y)] = w.Map.MapTiles[x, y].image;
@@ -63,5 +64,7 @@ namespace OpenRa
{
return w.TileSet.walk[t].Bridge != null;
}
public void WorldLoaded(World w) { MakeBridges(w); }
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Traits
{
class ChoosePaletteOnSelectInfo : StatelessTraitInfo<ChoosePaletteOnSelect> { }
class ChoosePaletteOnSelect : INotifySelection
{
public void SelectionChanged()
{
var firstItem = Game.controller.selection.Actors.FirstOrDefault(
a => a.World.LocalPlayer == a.Owner && a.traits.Contains<Production>());
if (firstItem == null)
return;
var produces = firstItem.Info.Traits.Get<ProductionInfo>().Produces.FirstOrDefault();
if (produces == null)
return;
Game.chrome.SetCurrentTab(produces);
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRa.Graphics;
namespace OpenRa.Traits
{
class OreGrowthInfo : ITraitInfo
{
public readonly float Interval = 1f;
public readonly float Chance = .02f;
public readonly bool Spreads = true;
public readonly bool Grows = true;
public object Create(Actor self) { return new OreGrowth(); }
}
class OreGrowth : ITick, ILoadWorldHook
{
int remainingTicks;
public void Tick(Actor self)
{
if (--remainingTicks <= 0)
{
var info = self.Info.Traits.Get<OreGrowthInfo>();
if (info.Spreads)
Ore.SpreadOre(self.World,
Game.SharedRandom,
info.Chance);
if (info.Grows)
Ore.GrowOre(self.World, Game.SharedRandom);
self.World.Minimap.InvalidateOre();
remainingTicks = (int)(info.Interval * 60 * 25);
}
}
public void WorldLoaded(World w)
{
Ore.InitOreDensity(w.Map);
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using OpenRa.Graphics;
using OpenRa.Orders;
@@ -27,8 +28,7 @@ namespace OpenRa.Traits
public IEnumerable<Renderable> Render(Actor self)
{
var uog = Game.controller.orderGenerator as UnitOrderGenerator;
if (uog != null && self.Owner == self.World.LocalPlayer && uog.selection.Contains(self))
if (self.Owner == self.World.LocalPlayer && Game.controller.selection.Actors.Contains(self))
yield return Util.Centered(self,
anim.Image, Util.CenterOfCell(rallyPoint));
}

View File

@@ -99,5 +99,8 @@ namespace OpenRa.Traits
public object Create(Actor self) { return Instance.Value; }
}
interface ITraitPrerequisite<T> { }
public interface ITraitPrerequisite<T> { }
public interface INotifySelection { void SelectionChanged(); }
public interface ILoadWorldHook { void WorldLoaded(World w); }
}

View File

@@ -34,7 +34,6 @@ namespace OpenRa
}
if (!string.IsNullOrEmpty(Game.Settings.PlayerName) && LocalPlayer.PlayerName != Game.Settings.PlayerName)
Game.IssueOrder(Order.Chat("/name " + Game.Settings.PlayerName));
}
public readonly Actor WorldActor;
@@ -50,9 +49,6 @@ namespace OpenRa
public readonly WorldRenderer WorldRenderer;
internal readonly Minimap Minimap;
readonly int oreFrequency;
int oreTicks;
public World()
{
Timer.Time( "----World.ctor" );
@@ -66,26 +62,21 @@ namespace OpenRa
WorldRenderer = new WorldRenderer(this, Game.renderer);
Timer.Time("renderer: {0}");
oreFrequency = (int)(Rules.General.GrowthRate * 60 * 25);
oreTicks = oreFrequency;
Map.InitOreDensity();
Timer.Time( "Ore: {0}" );
WorldActor = CreateActor("World", new int2(int.MaxValue, int.MaxValue), null);
for (int i = 0; i < 8; i++)
{
players[i] = new Player(this, i, Game.LobbyInfo.Clients.FirstOrDefault(a => a.Index == i));
}
Timer.Time( "worldActor, players: {0}" );
Queries = new AllQueries( this );
Timer.Time( "queries: {0}" );
Bridges.MakeBridges(this);
foreach (var wlh in WorldActor.traits.WithInterface<ILoadWorldHook>())
wlh.WorldLoaded(this);
PathFinder = new PathFinder(this);
Timer.Time( "bridge, pathing: {0}" );
Timer.Time( "hooks, pathing: {0}" );
Minimap = new Minimap(this, Game.renderer);
Timer.Time( "minimap: {0}" );
@@ -124,14 +115,6 @@ namespace OpenRa
public void Tick()
{
if (--oreTicks == 0)
using( new PerfSample( "ore" ) )
{
this.GrowOre( Game.SharedRandom );
Minimap.InvalidateOre();
oreTicks = oreFrequency;
}
foreach (var a in actors) a.Tick();
Queries.WithTraitMultiple<ITick>().Do( x => x.Trait.Tick( x.Actor ) );