Merge branches 'bugfixes', 'shroud', 'cargo' and 'minimap'
This commit is contained in:
@@ -123,6 +123,7 @@ namespace OpenRa.Game
|
||||
}
|
||||
|
||||
public bool IsDead { get { return Health <= 0; } }
|
||||
public bool IsInWorld { get; set; }
|
||||
|
||||
public DamageState GetDamageState()
|
||||
{
|
||||
|
||||
@@ -132,6 +132,8 @@ namespace OpenRa.Game
|
||||
|
||||
PerfHistory.Render(renderer, Game.worldRenderer.lineRenderer);
|
||||
|
||||
Game.minimap.Draw(new float2(Game.viewport.Width - 256, 8));
|
||||
|
||||
chromeRenderer.DrawSprite(specialBinSprite, float2.Zero, PaletteType.Chrome);
|
||||
chromeRenderer.DrawSprite(moneyBinSprite, new float2(Game.viewport.Width - 320, 0), PaletteType.Chrome);
|
||||
|
||||
@@ -143,8 +145,6 @@ namespace OpenRa.Game
|
||||
int paletteHeight = DrawBuildPalette(currentTab);
|
||||
DrawBuildTabs(paletteHeight);
|
||||
DrawChat();
|
||||
|
||||
Game.minimap.Draw(new float2(Game.viewport.Width - 128,30));
|
||||
}
|
||||
|
||||
void AddButton(Rectangle r, Action<bool> b) { buttons.Add(Pair.New(r, b)); }
|
||||
|
||||
@@ -59,6 +59,11 @@ namespace OpenRa.Game
|
||||
palette = new HardwarePalette(renderer, Rules.Map);
|
||||
|
||||
world = new World();
|
||||
Game.world.ActorAdded += a =>
|
||||
{
|
||||
if (a.Owner != null && a.Info != null)
|
||||
a.Owner.Shroud.Explore(a);
|
||||
};
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
@@ -100,7 +105,7 @@ namespace OpenRa.Game
|
||||
|
||||
chrome = new Chrome(renderer);
|
||||
|
||||
oreFrequency = (int)(Rules.General.GrowthRate * 60 * 1000);
|
||||
oreFrequency = (int)(Rules.General.GrowthRate * 60 * 25);
|
||||
oreTicks = oreFrequency;
|
||||
}
|
||||
|
||||
@@ -182,11 +187,12 @@ namespace OpenRa.Game
|
||||
controller.orderGenerator.Tick();
|
||||
|
||||
if (--oreTicks == 0)
|
||||
{
|
||||
using (new PerfSample("ore"))
|
||||
{
|
||||
Rules.Map.GrowOre(SharedRandom);
|
||||
oreTicks = oreFrequency;
|
||||
}
|
||||
minimap.InvalidateOre();
|
||||
oreTicks = oreFrequency;
|
||||
}
|
||||
|
||||
world.Tick();
|
||||
UnitInfluence.Tick();
|
||||
|
||||
@@ -55,13 +55,15 @@ namespace OpenRa.Game.GameRules
|
||||
public readonly int OrePips = 0;
|
||||
public readonly string Icon = null;
|
||||
public readonly int[] SelectionSize = null;
|
||||
public readonly int Passengers = 0;
|
||||
public readonly int UnloadFacing = 0;
|
||||
public readonly UnitMovementType[] PassengerTypes = null;
|
||||
|
||||
public UnitInfo(string name) { Name = name; }
|
||||
}
|
||||
|
||||
public class MobileInfo : UnitInfo
|
||||
{
|
||||
public readonly int Passengers = 0;
|
||||
public readonly int Speed = 0;
|
||||
public readonly bool NoMovingFire = false;
|
||||
public readonly string Voice = "GenericVoice";
|
||||
|
||||
@@ -3,7 +3,12 @@ using OpenRa.FileFormats;
|
||||
|
||||
namespace OpenRa.Game.Graphics
|
||||
{
|
||||
public enum PaletteType { Gold, Blue, Red, Orange, Teal, Salmon, Green, Gray, Shadow, Invuln, Chrome };
|
||||
public enum PaletteType
|
||||
{
|
||||
Gold, Blue, Red, Orange, Teal, Salmon, Green, Gray,
|
||||
Shadow, Invuln, Chrome, Shroud,
|
||||
};
|
||||
|
||||
class HardwarePalette : Sheet
|
||||
{
|
||||
const int maxEntries = 16;
|
||||
@@ -21,6 +26,7 @@ namespace OpenRa.Game.Graphics
|
||||
AddPalette(new Palette(pal, new PaletteRemap(Color.FromArgb(140, 0, 0, 0))));
|
||||
AddPalette(pal); // iron curtain. todo: remap!
|
||||
AddPalette(pal); // chrome (it's like gold, but we're not going to hax it in palettemods)
|
||||
AddPalette(new Palette(pal, new ShroudPaletteRemap()));
|
||||
}
|
||||
|
||||
int AddPalette(Palette p)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRa.Game.Traits;
|
||||
using OpenRa.FileFormats;
|
||||
|
||||
namespace OpenRa.Game.Graphics
|
||||
{
|
||||
@@ -9,7 +10,7 @@ namespace OpenRa.Game.Graphics
|
||||
Sheet sheet;
|
||||
SpriteRenderer spriteRenderer;
|
||||
Sprite sprite;
|
||||
Bitmap terrain;
|
||||
Bitmap terrain, oreLayer;
|
||||
|
||||
public void Tick() { }
|
||||
|
||||
@@ -21,20 +22,29 @@ namespace OpenRa.Game.Graphics
|
||||
}
|
||||
|
||||
// todo: extract these from the palette
|
||||
static readonly Color[] terrainTypeColors = {
|
||||
Color.Green,
|
||||
Color.Red,
|
||||
Color.Blue,
|
||||
Color.Yellow,
|
||||
Color.Purple,
|
||||
Color.Turquoise,
|
||||
Color.Violet,
|
||||
Color.Tomato,
|
||||
Color.Teal,
|
||||
};
|
||||
Color[] terrainTypeColors;
|
||||
|
||||
public void InvalidateOre() { oreLayer = null; }
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (terrainTypeColors == null)
|
||||
{
|
||||
var pal = new Palette(FileSystem.Open(Rules.Map.Theater + ".pal"));
|
||||
terrainTypeColors = new[] {
|
||||
pal.GetColor(0x1a),
|
||||
pal.GetColor(0x63),
|
||||
pal.GetColor(0x2f),
|
||||
pal.GetColor(0x1f),
|
||||
pal.GetColor(0x14),
|
||||
pal.GetColor(0x64),
|
||||
pal.GetColor(0x1f),
|
||||
pal.GetColor(0x68),
|
||||
pal.GetColor(0x6b),
|
||||
pal.GetColor(0x6d),
|
||||
};
|
||||
}
|
||||
|
||||
if (terrain == null)
|
||||
{
|
||||
terrain = new Bitmap(128, 128);
|
||||
@@ -45,14 +55,23 @@ namespace OpenRa.Game.Graphics
|
||||
: Color.Black);
|
||||
}
|
||||
|
||||
var bitmap = new Bitmap(terrain);
|
||||
if (oreLayer == null)
|
||||
{
|
||||
oreLayer = new Bitmap(terrain);
|
||||
for (var y = 0; y < 128; y++)
|
||||
for (var x = 0; x < 128; x++)
|
||||
if (Rules.Map.ContainsResource(new int2(x, y)))
|
||||
oreLayer.SetPixel(x, y, terrainTypeColors[(int)TerrainMovementType.Ore]);
|
||||
}
|
||||
|
||||
var bitmap = new Bitmap(oreLayer);
|
||||
|
||||
for( var y = 0; y < 128; y++ )
|
||||
for (var x = 0; x < 128; x++)
|
||||
{
|
||||
var b = Game.BuildingInfluence.GetBuildingAt(new int2(x, y));
|
||||
if (b != null)
|
||||
bitmap.SetPixel(x, y, b.Owner != null ? Chat.paletteColors[(int)b.Owner.Palette] : Color.Gray);
|
||||
bitmap.SetPixel(x, y, b.Owner != null ? Chat.paletteColors[(int)b.Owner.Palette] : terrainTypeColors[4]);
|
||||
}
|
||||
|
||||
foreach (var a in Game.world.Actors.Where(a => a.traits.Contains<Unit>()))
|
||||
@@ -63,7 +82,7 @@ namespace OpenRa.Game.Graphics
|
||||
|
||||
public void Draw(float2 pos)
|
||||
{
|
||||
spriteRenderer.DrawSprite(sprite, pos, PaletteType.Chrome);
|
||||
spriteRenderer.DrawSprite(sprite, pos, PaletteType.Chrome, new float2(256,256));
|
||||
spriteRenderer.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +55,17 @@ namespace OpenRa.Game.Graphics
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, PaletteType palette)
|
||||
{
|
||||
DrawSprite(s, location, palette, s.size);
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, PaletteType palette, float2 size)
|
||||
{
|
||||
if (s.sheet != currentSheet)
|
||||
Flush();
|
||||
|
||||
currentSheet = s.sheet;
|
||||
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, (int) palette, nv, ni);
|
||||
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, (int)palette, nv, ni, size);
|
||||
nv += 4; ni += 6;
|
||||
if (++sprites >= spritesPerBatch)
|
||||
Flush();
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace OpenRa.Game.Graphics
|
||||
for( int i = map.XOffset ; i < map.XOffset + map.Width; i++ )
|
||||
{
|
||||
Sprite tile = tileMapping[map.MapTiles[i, j]];
|
||||
Util.FastCreateQuad(vertices, indices, Game.CellSize * new float2(i, j), tile, 0, nv, ni);
|
||||
Util.FastCreateQuad(vertices, indices, Game.CellSize * new float2(i, j), tile, 0, nv, ni, tile.size);
|
||||
nv += 4;
|
||||
ni += 6;
|
||||
}
|
||||
|
||||
@@ -57,14 +57,14 @@ namespace OpenRa.Game.Graphics
|
||||
|
||||
static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
|
||||
|
||||
public static void FastCreateQuad(Vertex[] vertices, ushort[] indices, float2 o, Sprite r, int palette, int nv, int ni)
|
||||
public static void FastCreateQuad(Vertex[] vertices, ushort[] indices, float2 o, Sprite r, int palette, int nv, int ni, float2 size)
|
||||
{
|
||||
float2 attrib = new float2(palette / 16.0f, channelSelect[(int)r.channel]);
|
||||
|
||||
vertices[nv] = new Vertex(KLerp(o, r.size, 0), r.FastMapTextureCoords(0), attrib);
|
||||
vertices[nv + 1] = new Vertex(KLerp(o, r.size, 1), r.FastMapTextureCoords(1), attrib);
|
||||
vertices[nv + 2] = new Vertex(KLerp(o, r.size, 2), r.FastMapTextureCoords(2), attrib);
|
||||
vertices[nv + 3] = new Vertex(KLerp(o, r.size, 3), r.FastMapTextureCoords(3), attrib);
|
||||
vertices[nv] = new Vertex(KLerp(o, size, 0), r.FastMapTextureCoords(0), attrib);
|
||||
vertices[nv + 1] = new Vertex(KLerp(o, size, 1), r.FastMapTextureCoords(1), attrib);
|
||||
vertices[nv + 2] = new Vertex(KLerp(o, size, 2), r.FastMapTextureCoords(2), attrib);
|
||||
vertices[nv + 3] = new Vertex(KLerp(o, size, 3), r.FastMapTextureCoords(3), attrib);
|
||||
|
||||
indices[ni] = (ushort)(nv);
|
||||
indices[ni + 1] = indices[ni + 3] = (ushort)(nv + 1);
|
||||
|
||||
@@ -87,6 +87,8 @@ namespace OpenRa.Game.Graphics
|
||||
if (Game.controller.orderGenerator != null)
|
||||
Game.controller.orderGenerator.Render();
|
||||
|
||||
Game.LocalPlayer.Shroud.Draw(spriteRenderer);
|
||||
|
||||
lineRenderer.Flush();
|
||||
spriteRenderer.Flush();
|
||||
}
|
||||
@@ -211,7 +213,7 @@ namespace OpenRa.Game.Graphics
|
||||
|
||||
foreach (var pips in selectedUnit.traits.WithInterface<IPips>())
|
||||
{
|
||||
foreach (var pip in pips.GetPips())
|
||||
foreach (var pip in pips.GetPips(selectedUnit))
|
||||
{
|
||||
var pipImages = new Animation("pips");
|
||||
pipImages.PlayRepeating(pipStrings[(int)pip]);
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
<Compile Include="PathSearch.cs" />
|
||||
<Compile Include="ProductionItem.cs" />
|
||||
<Compile Include="Orders\ReplayOrderSource.cs" />
|
||||
<Compile Include="Shroud.cs" />
|
||||
<Compile Include="Smudge.cs" />
|
||||
<Compile Include="Sound.cs" />
|
||||
<Compile Include="Support\Stopwatch.cs" />
|
||||
@@ -118,6 +119,7 @@
|
||||
<Compile Include="Traits\Activities\Attack.cs" />
|
||||
<Compile Include="Traits\Activities\CaptureBuilding.cs" />
|
||||
<Compile Include="Traits\Activities\Demolish.cs" />
|
||||
<Compile Include="Traits\Activities\EnterTransport.cs" />
|
||||
<Compile Include="Traits\Activities\Fly.cs" />
|
||||
<Compile Include="Traits\Activities\FlyAttack.cs" />
|
||||
<Compile Include="Traits\Activities\FlyTimed.cs" />
|
||||
@@ -185,6 +187,7 @@
|
||||
<Compile Include="Traits\Activities\Follow.cs" />
|
||||
<Compile Include="Traits\Activities\Turn.cs" />
|
||||
<Compile Include="Traits\Activities\UndeployMcv.cs" />
|
||||
<Compile Include="Traits\Activities\UnloadCargo.cs" />
|
||||
<Compile Include="Traits\APMine.cs" />
|
||||
<Compile Include="Traits\ATMine.cs" />
|
||||
<Compile Include="Traits\AttackBase.cs" />
|
||||
@@ -198,6 +201,7 @@
|
||||
<Compile Include="Traits\BelowUnits.cs" />
|
||||
<Compile Include="Traits\Building.cs" />
|
||||
<Compile Include="Traits\C4Demolition.cs" />
|
||||
<Compile Include="Traits\Cargo.cs" />
|
||||
<Compile Include="Traits\Chronoshiftable.cs" />
|
||||
<Compile Include="Traits\ChronoshiftPaletteEffect.cs" />
|
||||
<Compile Include="Traits\Chronosphere.cs" />
|
||||
@@ -213,6 +217,7 @@
|
||||
<Compile Include="Traits\MineImmune.cs" />
|
||||
<Compile Include="Traits\Minelayer.cs" />
|
||||
<Compile Include="Traits\LimitedAmmo.cs" />
|
||||
<Compile Include="Traits\Passenger.cs" />
|
||||
<Compile Include="Traits\Repairable.cs" />
|
||||
<Compile Include="Traits\Reservable.cs" />
|
||||
<Compile Include="Traits\SquishByTank.cs" />
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRa.Game.Orders
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
selection.RemoveAll(a => a.IsDead);
|
||||
selection.RemoveAll(a => !a.IsInWorld);
|
||||
}
|
||||
|
||||
public void Render()
|
||||
@@ -81,6 +81,7 @@ namespace OpenRa.Game.Orders
|
||||
else
|
||||
return Cursor.MoveBlocked;
|
||||
case "Enter": return Cursor.Enter;
|
||||
case "EnterTransport": return Cursor.Enter;
|
||||
case "Deliver": return Cursor.Enter;
|
||||
case "Infiltrate": return Cursor.Enter;
|
||||
case "Capture": return Cursor.Capture;
|
||||
|
||||
@@ -17,15 +17,17 @@ namespace OpenRa.Game
|
||||
public string InternalName;
|
||||
public Race Race;
|
||||
public readonly int Index;
|
||||
public int Cash;
|
||||
public int Ore;
|
||||
public int Cash = 10000;
|
||||
public int Ore = 0;
|
||||
public int OreCapacity;
|
||||
public int DisplayCash;
|
||||
public int PowerProvided;
|
||||
public int PowerDrained;
|
||||
public int DisplayCash = 0;
|
||||
public int PowerProvided = 0;
|
||||
public int PowerDrained = 0;
|
||||
|
||||
public bool IsReady;
|
||||
|
||||
public Shroud Shroud = new Shroud();
|
||||
|
||||
public Player( Actor playerActor, int index, PaletteType palette, string playerName, Race race, string internalName )
|
||||
{
|
||||
this.PlayerActor = playerActor;
|
||||
@@ -34,10 +36,6 @@ namespace OpenRa.Game
|
||||
this.InternalName = internalName;
|
||||
this.PlayerName = playerName;
|
||||
this.Race = race;
|
||||
this.Cash = 10000;
|
||||
this.Ore = 0;
|
||||
this.DisplayCash = 0;
|
||||
this.PowerProvided = this.PowerDrained = 0;
|
||||
}
|
||||
|
||||
void UpdatePower()
|
||||
|
||||
87
OpenRa.Game/Shroud.cs
Normal file
87
OpenRa.Game/Shroud.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using IjwFramework.Types;
|
||||
using OpenRa.Game.Graphics;
|
||||
|
||||
namespace OpenRa.Game
|
||||
{
|
||||
class Shroud
|
||||
{
|
||||
bool[,] explored = new bool[128, 128];
|
||||
Sprite[] shadowBits = SpriteSheetBuilder.LoadAllSprites("shadow");
|
||||
Sprite[,] sprites = new Sprite[128, 128];
|
||||
bool dirty;
|
||||
|
||||
public void Explore(Actor a)
|
||||
{
|
||||
foreach (var t in Game.FindTilesInCircle((1f/Game.CellSize * a.CenterLocation).ToInt2(), a.Info.Sight))
|
||||
explored[t.X, t.Y] = true;
|
||||
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
Sprite ChooseShroud(int i, int j)
|
||||
{
|
||||
// bits are for exploredness: left, right, up, down, self
|
||||
var n = new[] {
|
||||
0xf,0xf,0xf,0xf,
|
||||
0xf,0x0f,0x0f,0xf,
|
||||
0xf,0x0f,0x0f,0xf,
|
||||
0xf,0xf,0xf,0xf,
|
||||
0,7,13,0,
|
||||
14,6,12,4,
|
||||
11,3,9,1,
|
||||
0,2,8,0,
|
||||
};
|
||||
|
||||
var v = 0;
|
||||
if (explored[i-1,j]) v |= 1;
|
||||
if (explored[i+1,j]) v |= 2;
|
||||
if (explored[i,j-1]) v |= 4;
|
||||
if (explored[i,j+1]) v |= 8;
|
||||
if (explored[i, j]) v |= 16;
|
||||
|
||||
var x = n[v];
|
||||
|
||||
if (x == 0)
|
||||
{
|
||||
// bits are for exploredness: TL, TR, BR, BL
|
||||
var m = new[] {
|
||||
46, 41, 42, 38,
|
||||
43, 45, 39, 35,
|
||||
40, 37, 44, 34,
|
||||
36, 33, 32, 47,
|
||||
};
|
||||
|
||||
var u = 0;
|
||||
if (explored[i - 1, j - 1]) u |= 1;
|
||||
if (explored[i + 1, j - 1]) u |= 2;
|
||||
if (explored[i + 1, j + 1]) u |= 4;
|
||||
if (explored[i - 1, j + 1]) u |= 8;
|
||||
return shadowBits[m[u]];
|
||||
}
|
||||
|
||||
return shadowBits[x];
|
||||
}
|
||||
|
||||
public void Draw(SpriteRenderer r)
|
||||
{
|
||||
if (dirty)
|
||||
{
|
||||
dirty = false;
|
||||
for (int j = 1; j < 127; j++)
|
||||
for (int i = 1; i < 127; i++)
|
||||
sprites[i, j] = ChooseShroud(i, j);
|
||||
}
|
||||
|
||||
for (var j = 0; j < 128; j++)
|
||||
for (var i = 0; i < 128; i++)
|
||||
if (sprites[i,j] != null)
|
||||
r.DrawSprite(sprites[i, j],
|
||||
Game.CellSize * new float2(i, j),
|
||||
PaletteType.Shroud);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ using OpenRa.Game.Graphics;
|
||||
|
||||
namespace OpenRa.Game
|
||||
{
|
||||
enum UnitMovementType : byte
|
||||
public enum UnitMovementType : byte
|
||||
{
|
||||
Foot = 0,
|
||||
Track = 1,
|
||||
|
||||
36
OpenRa.Game/Traits/Activities/EnterTransport.cs
Normal file
36
OpenRa.Game/Traits/Activities/EnterTransport.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenRa.Game.Traits.Activities
|
||||
{
|
||||
class EnterTransport : IActivity
|
||||
{
|
||||
public IActivity NextActivity { get; set; }
|
||||
bool isCanceled;
|
||||
public Actor transport;
|
||||
|
||||
public EnterTransport(Actor self, Actor transport)
|
||||
{
|
||||
this.transport = transport;
|
||||
}
|
||||
|
||||
public IActivity Tick(Actor self)
|
||||
{
|
||||
if (isCanceled) return NextActivity;
|
||||
if (transport == null || !transport.IsInWorld) return NextActivity;
|
||||
|
||||
var cargo = transport.traits.Get<Cargo>();
|
||||
if (cargo.IsFull(transport))
|
||||
return NextActivity;
|
||||
|
||||
cargo.Load(transport, self);
|
||||
Game.world.AddFrameEndTask(w => w.Remove(self));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Cancel(Actor self) { isCanceled = true; NextActivity = null; }
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace OpenRa.Game.Traits.Activities
|
||||
{
|
||||
public IActivity NextActivity { get; set; }
|
||||
|
||||
public int desiredFacing;
|
||||
int desiredFacing;
|
||||
|
||||
public Turn( int desiredFacing )
|
||||
{
|
||||
|
||||
69
OpenRa.Game/Traits/Activities/UnloadCargo.cs
Normal file
69
OpenRa.Game/Traits/Activities/UnloadCargo.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenRa.Game.Traits.Activities
|
||||
{
|
||||
class UnloadCargo : IActivity
|
||||
{
|
||||
public IActivity NextActivity { get; set; }
|
||||
bool isCanceled;
|
||||
|
||||
int2? ChooseExitTile(Actor self)
|
||||
{
|
||||
// is anyone still hogging this tile?
|
||||
if (Game.UnitInfluence.GetUnitsAt(self.Location).Count() > 1)
|
||||
return null;
|
||||
|
||||
for (var i = -1; i < 2; i++)
|
||||
for (var j = -1; j < 2; j++)
|
||||
if ((i != 0 || j != 0) &&
|
||||
Game.IsCellBuildable(self.Location + new int2(i, j),
|
||||
UnitMovementType.Foot))
|
||||
return self.Location + new int2(i, j);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IActivity Tick(Actor self)
|
||||
{
|
||||
if (isCanceled) return NextActivity;
|
||||
|
||||
// if we're a thing that can turn, turn to the
|
||||
// right facing for the unload animation
|
||||
var unit = self.traits.GetOrDefault<Unit>();
|
||||
if (unit != null && unit.Facing != self.Info.UnloadFacing)
|
||||
return new Turn(self.Info.UnloadFacing) { NextActivity = this };
|
||||
|
||||
// todo: handle the BS of open/close sequences, which are inconsistent,
|
||||
// for reasons that probably make good sense to the westwood guys.
|
||||
|
||||
var cargo = self.traits.Get<Cargo>();
|
||||
if (cargo.IsEmpty(self))
|
||||
return NextActivity;
|
||||
|
||||
var ru = self.traits.WithInterface<RenderUnit>().FirstOrDefault();
|
||||
if (ru != null)
|
||||
ru.PlayCustomAnimation(self, "unload", null);
|
||||
|
||||
var exitTile = ChooseExitTile(self);
|
||||
if (exitTile == null)
|
||||
return this;
|
||||
|
||||
var actor = cargo.Unload(self);
|
||||
|
||||
Game.world.AddFrameEndTask(w =>
|
||||
{
|
||||
w.Add(actor);
|
||||
actor.traits.Get<Mobile>().TeleportTo(actor, self.Location);
|
||||
actor.CancelActivity();
|
||||
actor.QueueActivity(new Move(exitTile.Value, 0));
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Cancel(Actor self) { NextActivity = null; isCanceled = true; }
|
||||
}
|
||||
}
|
||||
85
OpenRa.Game/Traits/Cargo.cs
Normal file
85
OpenRa.Game/Traits/Cargo.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using OpenRa.Game.GameRules;
|
||||
using OpenRa.Game.Traits.Activities;
|
||||
|
||||
namespace OpenRa.Game.Traits
|
||||
{
|
||||
class Cargo : IPips, IOrder
|
||||
{
|
||||
List<Actor> cargo = new List<Actor>();
|
||||
|
||||
public Cargo(Actor self) {}
|
||||
|
||||
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||
{
|
||||
// todo: check if there is an unoccupied `land` tile adjacent
|
||||
if (mi.Button == MouseButton.Right && underCursor == self && cargo.Count > 0)
|
||||
{
|
||||
var unit = underCursor.traits.GetOrDefault<Unit>();
|
||||
if (unit != null && unit.Altitude > 0) return null;
|
||||
|
||||
return new Order("Deploy", self, null, int2.Zero, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "Deploy")
|
||||
{
|
||||
// todo: eject the units
|
||||
self.CancelActivity();
|
||||
self.QueueActivity(new UnloadCargo());
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFull(Actor self)
|
||||
{
|
||||
return cargo.Count == self.Info.Passengers;
|
||||
}
|
||||
|
||||
public bool IsEmpty(Actor self)
|
||||
{
|
||||
return cargo.Count == 0;
|
||||
}
|
||||
|
||||
public Actor Unload(Actor self)
|
||||
{
|
||||
var a = cargo[0];
|
||||
cargo.RemoveAt(0);
|
||||
return a;
|
||||
}
|
||||
|
||||
public IEnumerable<PipType> GetPips( Actor self )
|
||||
{
|
||||
for (var i = 0; i < self.Info.Passengers; i++)
|
||||
if (i >= cargo.Count)
|
||||
yield return PipType.Transparent;
|
||||
else
|
||||
yield return GetPipForPassenger(cargo[i]);
|
||||
}
|
||||
|
||||
static PipType GetPipForPassenger(Actor a)
|
||||
{
|
||||
// probably not actually right yet; fix to match real-ra
|
||||
|
||||
if (a.traits.Contains<AutoHeal>())
|
||||
return PipType.Yellow;
|
||||
if (!a.traits.WithInterface<AttackBase>().Any())
|
||||
return PipType.Yellow; // noncombat [E6,SPY,THF]
|
||||
if (a.traits.Contains<C4Demolition>())
|
||||
return PipType.Red; // E7
|
||||
|
||||
return PipType.Green;
|
||||
}
|
||||
|
||||
public void Load(Actor self, Actor a)
|
||||
{
|
||||
cargo.Add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ namespace OpenRa.Game.Traits
|
||||
}
|
||||
|
||||
// Display 5 pips indicating the current charge status
|
||||
public IEnumerable<PipType> GetPips()
|
||||
public IEnumerable<PipType> GetPips(Actor self)
|
||||
{
|
||||
const int numPips = 5;
|
||||
for (int i = 0; i < numPips; i++)
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace OpenRa.Game.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<PipType> GetPips()
|
||||
public IEnumerable<PipType> GetPips(Actor self)
|
||||
{
|
||||
const int numPips = 7;
|
||||
for (int i = 0; i < numPips; i++)
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace OpenRa.Game.Traits
|
||||
|
||||
public void Attacking(Actor self) { --ammo; }
|
||||
|
||||
public IEnumerable<PipType> GetPips()
|
||||
public IEnumerable<PipType> GetPips(Actor self)
|
||||
{
|
||||
return Graphics.Util.MakeArray(self.Info.Ammo,
|
||||
i => ammo > i ? PipType.Green : PipType.Transparent);
|
||||
|
||||
@@ -18,7 +18,16 @@ namespace OpenRa.Game.Traits
|
||||
public int2 toCell
|
||||
{
|
||||
get { return self.Location; }
|
||||
set { Game.UnitInfluence.Remove(self, this); self.Location = value; Game.UnitInfluence.Add(self, this); }
|
||||
set
|
||||
{
|
||||
if (self.Location != value)
|
||||
{
|
||||
Game.UnitInfluence.Remove(self, this);
|
||||
self.Location = value;
|
||||
self.Owner.Shroud.Explore(self);
|
||||
}
|
||||
Game.UnitInfluence.Add(self, this);
|
||||
}
|
||||
}
|
||||
|
||||
public Mobile(Actor self)
|
||||
|
||||
42
OpenRa.Game/Traits/Passenger.cs
Normal file
42
OpenRa.Game/Traits/Passenger.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using OpenRa.Game.Traits.Activities;
|
||||
|
||||
namespace OpenRa.Game.Traits
|
||||
{
|
||||
class Passenger : IOrder
|
||||
{
|
||||
public Passenger(Actor self) { }
|
||||
|
||||
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||
{
|
||||
if (mi.Button != MouseButton.Right)
|
||||
return null;
|
||||
|
||||
if (underCursor == null || underCursor.Owner != self.Owner)
|
||||
return null;
|
||||
|
||||
var cargo = underCursor.traits.GetOrDefault<Cargo>();
|
||||
if (cargo == null || cargo.IsFull(underCursor))
|
||||
return null;
|
||||
|
||||
var umt = self.traits.WithInterface<IMovement>().First().GetMovementType();
|
||||
if (!underCursor.Info.PassengerTypes.Contains(umt))
|
||||
return null;
|
||||
|
||||
return new Order("EnterTransport", self, underCursor, int2.Zero, null);
|
||||
}
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "EnterTransport")
|
||||
{
|
||||
self.CancelActivity();
|
||||
self.QueueActivity(new Move(order.TargetActor.Location, 1));
|
||||
self.QueueActivity(new EnterTransport(self, order.TargetActor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace OpenRa.Game.Traits
|
||||
this.self = self;
|
||||
}
|
||||
|
||||
public IEnumerable<PipType> GetPips()
|
||||
public IEnumerable<PipType> GetPips(Actor self)
|
||||
{
|
||||
for (int i = 0; i < self.Info.OrePips; i++)
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenRa.Game.Traits
|
||||
interface IDamageModifier { float GetDamageModifier(); }
|
||||
interface ISpeedModifier { float GetSpeedModifier(); }
|
||||
interface IPaletteModifier { void AdjustPalette(Bitmap b); }
|
||||
interface IPips { IEnumerable<PipType> GetPips(); }
|
||||
interface IPips { IEnumerable<PipType> GetPips(Actor self); }
|
||||
interface ITags { IEnumerable<TagType> GetTags(); }
|
||||
interface IMovement
|
||||
{
|
||||
|
||||
@@ -10,8 +10,19 @@ namespace OpenRa.Game
|
||||
List<IEffect> effects = new List<IEffect>();
|
||||
List<Action<World>> frameEndActions = new List<Action<World>>();
|
||||
|
||||
public void Add(Actor a) { actors.Add(a); ActorAdded(a); }
|
||||
public void Remove(Actor a) { actors.Remove(a); ActorRemoved(a); }
|
||||
public void Add(Actor a)
|
||||
{
|
||||
a.IsInWorld = true;
|
||||
actors.Add(a);
|
||||
ActorAdded(a);
|
||||
}
|
||||
|
||||
public void Remove(Actor a)
|
||||
{
|
||||
a.IsInWorld = false;
|
||||
actors.Remove(a);
|
||||
ActorRemoved(a);
|
||||
}
|
||||
|
||||
public void Add(IEffect b) { effects.Add(b); }
|
||||
public void Remove(IEffect b) { effects.Remove(b); }
|
||||
|
||||
Reference in New Issue
Block a user