Merge branch 'master' of git://github.com/chrisforbes/OpenRA
This commit is contained in:
9
OpenRa.FileFormats/IPaletteRemap.cs
Normal file
9
OpenRa.FileFormats/IPaletteRemap.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
namespace OpenRa.FileFormats
|
||||||
|
{
|
||||||
|
public interface IPaletteRemap
|
||||||
|
{
|
||||||
|
Color GetRemappedColor(Color original, int index);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
<Compile Include="Format80.cs" />
|
<Compile Include="Format80.cs" />
|
||||||
<Compile Include="IniFile.cs" />
|
<Compile Include="IniFile.cs" />
|
||||||
<Compile Include="IniWriter.cs" />
|
<Compile Include="IniWriter.cs" />
|
||||||
|
<Compile Include="IPaletteRemap.cs" />
|
||||||
<Compile Include="Map.cs" />
|
<Compile Include="Map.cs" />
|
||||||
<Compile Include="PackageEntry.cs" />
|
<Compile Include="PackageEntry.cs" />
|
||||||
<Compile Include="Package.cs" />
|
<Compile Include="Package.cs" />
|
||||||
@@ -62,6 +63,7 @@
|
|||||||
<Compile Include="PaletteRemap.cs" />
|
<Compile Include="PaletteRemap.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ShpReader.cs" />
|
<Compile Include="ShpReader.cs" />
|
||||||
|
<Compile Include="ShroudPaletteRemap.cs" />
|
||||||
<Compile Include="Terrain.cs" />
|
<Compile Include="Terrain.cs" />
|
||||||
<Compile Include="TileReference.cs" />
|
<Compile Include="TileReference.cs" />
|
||||||
<Compile Include="TileSet.cs" />
|
<Compile Include="TileSet.cs" />
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace OpenRa.FileFormats
|
|||||||
colors[4] = Color.FromArgb(140, 0, 0, 0);
|
colors[4] = Color.FromArgb(140, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Palette(Palette p, PaletteRemap r)
|
public Palette(Palette p, IPaletteRemap r)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 256; i++)
|
for (int i = 0; i < 256; i++)
|
||||||
colors.Add(r.GetRemappedColor(p.GetColor(i), i));
|
colors.Add(r.GetRemappedColor(p.GetColor(i), i));
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.IO;
|
|||||||
|
|
||||||
namespace OpenRa.FileFormats
|
namespace OpenRa.FileFormats
|
||||||
{
|
{
|
||||||
public class PaletteRemap
|
public class PaletteRemap : IPaletteRemap
|
||||||
{
|
{
|
||||||
int offset;
|
int offset;
|
||||||
List<Color> remapColors = new List<Color>();
|
List<Color> remapColors = new List<Color>();
|
||||||
|
|||||||
32
OpenRa.FileFormats/ShroudPaletteRemap.cs
Normal file
32
OpenRa.FileFormats/ShroudPaletteRemap.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace OpenRa.FileFormats
|
||||||
|
{
|
||||||
|
public class ShroudPaletteRemap : IPaletteRemap
|
||||||
|
{
|
||||||
|
public Color GetRemappedColor(Color original, int index)
|
||||||
|
{
|
||||||
|
// false-color version for debug
|
||||||
|
|
||||||
|
//return new[] {
|
||||||
|
// Color.Orange, Color.Green,
|
||||||
|
// Color.Blue, Color.Yellow,
|
||||||
|
// Color.Black,
|
||||||
|
// Color.Red,
|
||||||
|
// Color.Purple,
|
||||||
|
// Color.Cyan}[index % 8];
|
||||||
|
|
||||||
|
return new[] {
|
||||||
|
Color.Transparent, Color.Green,
|
||||||
|
Color.Blue, Color.Yellow,
|
||||||
|
Color.Black,
|
||||||
|
Color.FromArgb(192,0,0,0),
|
||||||
|
Color.FromArgb(128,0,0,0),
|
||||||
|
Color.FromArgb(64,0,0,0)}[index % 8];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -123,6 +123,7 @@ namespace OpenRa.Game
|
|||||||
}
|
}
|
||||||
|
|
||||||
public bool IsDead { get { return Health <= 0; } }
|
public bool IsDead { get { return Health <= 0; } }
|
||||||
|
public bool IsInWorld { get; set; }
|
||||||
|
|
||||||
public DamageState GetDamageState()
|
public DamageState GetDamageState()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace OpenRa.Game
|
|||||||
typing += c;
|
typing += c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly Color[] paletteColors =
|
public static readonly Color[] paletteColors =
|
||||||
{
|
{
|
||||||
Color.FromArgb(228, 200, 112),
|
Color.FromArgb(228, 200, 112),
|
||||||
Color.FromArgb(56, 72, 125),
|
Color.FromArgb(56, 72, 125),
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
readonly Animation repairButton;
|
readonly Animation repairButton;
|
||||||
readonly Animation sellButton;
|
readonly Animation sellButton;
|
||||||
|
readonly Animation pwrdownButton;
|
||||||
|
|
||||||
readonly SpriteRenderer buildPaletteRenderer;
|
readonly SpriteRenderer buildPaletteRenderer;
|
||||||
readonly Animation cantBuild;
|
readonly Animation cantBuild;
|
||||||
readonly Animation ready;
|
readonly Animation ready;
|
||||||
@@ -40,6 +41,8 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
readonly int paletteColumns;
|
readonly int paletteColumns;
|
||||||
readonly int2 paletteOrigin;
|
readonly int2 paletteOrigin;
|
||||||
|
|
||||||
|
const int MinRows = 4;
|
||||||
|
|
||||||
public Chrome(Renderer r)
|
public Chrome(Renderer r)
|
||||||
{
|
{
|
||||||
@@ -75,6 +78,9 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
sellButton = new Animation("sell");
|
sellButton = new Animation("sell");
|
||||||
sellButton.PlayRepeating("normal");
|
sellButton.PlayRepeating("normal");
|
||||||
|
|
||||||
|
pwrdownButton = new Animation("repair");
|
||||||
|
pwrdownButton.PlayRepeating("normal");
|
||||||
|
|
||||||
blank = SheetBuilder.Add(new Size(64, 48), 16);
|
blank = SheetBuilder.Add(new Size(64, 48), 16);
|
||||||
|
|
||||||
@@ -96,7 +102,7 @@ namespace OpenRa.Game
|
|||||||
cantBuild = new Animation("clock");
|
cantBuild = new Animation("clock");
|
||||||
cantBuild.PlayFetchIndex("idle", () => 0);
|
cantBuild.PlayFetchIndex("idle", () => 0);
|
||||||
|
|
||||||
digitSprites = OpenRa.Game.Graphics.Util.MakeArray(10, a => a)
|
digitSprites = Graphics.Util.MakeArray(10, a => a)
|
||||||
.Select(n => new Sprite(specialBin, new Rectangle(32 + 13 * n, 0, 13, 17), TextureChannel.Alpha)).ToList();
|
.Select(n => new Sprite(specialBin, new Rectangle(32 + 13 * n, 0, 13, 17), TextureChannel.Alpha)).ToList();
|
||||||
|
|
||||||
shimSprites = new[]
|
shimSprites = new[]
|
||||||
@@ -130,6 +136,8 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
PerfHistory.Render(renderer, Game.worldRenderer.lineRenderer);
|
PerfHistory.Render(renderer, Game.worldRenderer.lineRenderer);
|
||||||
|
|
||||||
|
DrawMinimap();
|
||||||
|
|
||||||
chromeRenderer.DrawSprite(specialBinSprite, float2.Zero, PaletteType.Chrome);
|
chromeRenderer.DrawSprite(specialBinSprite, float2.Zero, PaletteType.Chrome);
|
||||||
chromeRenderer.DrawSprite(moneyBinSprite, new float2(Game.viewport.Width - 320, 0), PaletteType.Chrome);
|
chromeRenderer.DrawSprite(moneyBinSprite, new float2(Game.viewport.Width - 320, 0), PaletteType.Chrome);
|
||||||
|
|
||||||
@@ -143,8 +151,18 @@ namespace OpenRa.Game
|
|||||||
DrawChat();
|
DrawChat();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddButton(Rectangle r, Action<bool> b) { buttons.Add(Pair.New(r, b)); }
|
void DrawMinimap()
|
||||||
|
{
|
||||||
|
var hasRadar = Game.world.Actors.Any(a => a.Owner == Game.LocalPlayer
|
||||||
|
&& a.traits.Contains<ProvidesRadar>()
|
||||||
|
&& a.traits.Get<ProvidesRadar>().IsActive());
|
||||||
|
|
||||||
|
if (hasRadar)
|
||||||
|
Game.minimap.Draw(new float2(Game.viewport.Width - 256, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddButton(Rectangle r, Action<bool> b) { buttons.Add(Pair.New(r, b)); }
|
||||||
|
|
||||||
void DrawBuildTabs(int paletteHeight)
|
void DrawBuildTabs(int paletteHeight)
|
||||||
{
|
{
|
||||||
const int tabWidth = 24;
|
const int tabWidth = 24;
|
||||||
@@ -215,6 +233,9 @@ namespace OpenRa.Game
|
|||||||
x -= 14;
|
x -= 14;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float? lastPowerProvidedPos;
|
||||||
|
float? lastPowerDrainedPos;
|
||||||
|
|
||||||
void DrawPower()
|
void DrawPower()
|
||||||
{
|
{
|
||||||
@@ -228,16 +249,32 @@ namespace OpenRa.Game
|
|||||||
float2 bottom = powerOrigin + new float2(0, powerLevelTopSprite.size.Y + powerLevelBottomSprite.size.Y) - new float2(0, 50);
|
float2 bottom = powerOrigin + new float2(0, powerLevelTopSprite.size.Y + powerLevelBottomSprite.size.Y) - new float2(0, 50);
|
||||||
|
|
||||||
var scale = 100;
|
var scale = 100;
|
||||||
while(Game.LocalPlayer.PowerProvided >= scale) scale += 100;
|
while(Math.Max(Game.LocalPlayer.PowerProvided, Game.LocalPlayer.PowerDrained) >= scale) scale *= 2;
|
||||||
//draw bar
|
//draw bar
|
||||||
float2 powerTop = new float2(bottom.X, bottom.Y + (top.Y - bottom.Y) * (Game.LocalPlayer.PowerProvided / (float)scale));
|
|
||||||
|
var powerTopY = bottom.Y + (top.Y - bottom.Y) * (Game.LocalPlayer.PowerProvided / (float)scale) - Game.viewport.Location.Y;
|
||||||
|
lastPowerProvidedPos = float2.Lerp(lastPowerProvidedPos.GetValueOrDefault(powerTopY), powerTopY, .3f);
|
||||||
|
float2 powerTop = new float2(bottom.X, lastPowerProvidedPos.Value + Game.viewport.Location.Y);
|
||||||
|
|
||||||
|
var color = Color.LimeGreen;
|
||||||
|
if (Game.LocalPlayer.GetPowerState() == PowerState.Low)
|
||||||
|
color = Color.Orange;
|
||||||
|
if (Game.LocalPlayer.GetPowerState() == PowerState.Critical)
|
||||||
|
color = Color.Red;
|
||||||
|
|
||||||
|
var color2 = Graphics.Util.Lerp(0.25f, color, Color.Black);
|
||||||
|
|
||||||
|
for(int i = 11; i < 13; i++)
|
||||||
|
lineRenderer.DrawLine(bottom + new float2(i, 0), powerTop + new float2(i, 0), color, color);
|
||||||
|
for (int i = 13; i < 15; i++)
|
||||||
|
lineRenderer.DrawLine(bottom + new float2(i, 0), powerTop + new float2(i, 0), color2, color2);
|
||||||
|
|
||||||
for(int i = 7; i < 11; i++)
|
|
||||||
lineRenderer.DrawLine(bottom + new float2(i, 0), powerTop + new float2(i, 0), Color.LimeGreen, Color.LimeGreen);
|
|
||||||
lineRenderer.Flush();
|
lineRenderer.Flush();
|
||||||
|
|
||||||
|
var drainedPositionY = bottom.Y + (top.Y - bottom.Y)*(Game.LocalPlayer.PowerDrained/(float) scale) - powerIndicatorSprite.size.Y /2 - Game.viewport.Location.Y;
|
||||||
|
lastPowerDrainedPos = float2.Lerp(lastPowerDrainedPos.GetValueOrDefault(drainedPositionY), drainedPositionY, .3f);
|
||||||
//draw indicator
|
//draw indicator
|
||||||
float2 drainedPosition = new float2(bottom.X , bottom.Y + (top.Y - bottom.Y)*(Game.LocalPlayer.PowerDrained/(float) scale));
|
float2 drainedPosition = new float2(bottom.X + 2, lastPowerDrainedPos.Value + Game.viewport.Location.Y);
|
||||||
|
|
||||||
buildPaletteRenderer.DrawSprite(powerIndicatorSprite, drainedPosition, PaletteType.Chrome);
|
buildPaletteRenderer.DrawSprite(powerIndicatorSprite, drainedPosition, PaletteType.Chrome);
|
||||||
buildPaletteRenderer.Flush();
|
buildPaletteRenderer.Flush();
|
||||||
@@ -245,8 +282,24 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
void DrawButtons()
|
void DrawButtons()
|
||||||
{
|
{
|
||||||
|
// Chronoshift
|
||||||
|
Rectangle chronoshiftRect = new Rectangle(6, 14, repairButton.Image.bounds.Width, repairButton.Image.bounds.Height);
|
||||||
|
var chronoshiftDrawPos = Game.viewport.Location + new float2(chronoshiftRect.Location);
|
||||||
|
|
||||||
|
var hasChronosphere = Game.world.Actors.Any(a => a.Owner == Game.LocalPlayer && a.traits.Contains<Chronosphere>());
|
||||||
|
|
||||||
|
if (!hasChronosphere)
|
||||||
|
repairButton.ReplaceAnim("disabled");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//repairButton.ReplaceAnim(Game.controller.orderGenerator is RepairOrderGenerator ? "pressed" : "normal");
|
||||||
|
AddButton(chronoshiftRect, isLmb => HandleChronosphereButton());
|
||||||
|
}
|
||||||
|
buildPaletteRenderer.DrawSprite(repairButton.Image, chronoshiftDrawPos, PaletteType.Chrome);
|
||||||
|
|
||||||
|
|
||||||
// Repair
|
// Repair
|
||||||
Rectangle repairRect = new Rectangle(Game.viewport.Width - 100, 5, repairButton.Image.bounds.Width, repairButton.Image.bounds.Height);
|
Rectangle repairRect = new Rectangle(Game.viewport.Width - 120, 5, repairButton.Image.bounds.Width, repairButton.Image.bounds.Height);
|
||||||
var repairDrawPos = Game.viewport.Location + new float2(repairRect.Location);
|
var repairDrawPos = Game.viewport.Location + new float2(repairRect.Location);
|
||||||
|
|
||||||
var hasFact = Game.world.Actors.Any(a => a.Owner == Game.LocalPlayer && a.traits.Contains<ConstructionYard>());
|
var hasFact = Game.world.Actors.Any(a => a.Owner == Game.LocalPlayer && a.traits.Contains<ConstructionYard>());
|
||||||
@@ -261,7 +314,7 @@ namespace OpenRa.Game
|
|||||||
buildPaletteRenderer.DrawSprite(repairButton.Image, repairDrawPos, PaletteType.Chrome);
|
buildPaletteRenderer.DrawSprite(repairButton.Image, repairDrawPos, PaletteType.Chrome);
|
||||||
|
|
||||||
// Sell
|
// Sell
|
||||||
Rectangle sellRect = new Rectangle(Game.viewport.Width - 60, 5,
|
Rectangle sellRect = new Rectangle(Game.viewport.Width - 80, 5,
|
||||||
sellButton.Image.bounds.Width, sellButton.Image.bounds.Height);
|
sellButton.Image.bounds.Width, sellButton.Image.bounds.Height);
|
||||||
|
|
||||||
var sellDrawPos = Game.viewport.Location + new float2(sellRect.Location);
|
var sellDrawPos = Game.viewport.Location + new float2(sellRect.Location);
|
||||||
@@ -271,6 +324,27 @@ namespace OpenRa.Game
|
|||||||
AddButton(sellRect, isLmb => Game.controller.ToggleInputMode<SellOrderGenerator>());
|
AddButton(sellRect, isLmb => Game.controller.ToggleInputMode<SellOrderGenerator>());
|
||||||
buildPaletteRenderer.DrawSprite(sellButton.Image, sellDrawPos, PaletteType.Chrome);
|
buildPaletteRenderer.DrawSprite(sellButton.Image, sellDrawPos, PaletteType.Chrome);
|
||||||
buildPaletteRenderer.Flush();
|
buildPaletteRenderer.Flush();
|
||||||
|
|
||||||
|
if (Game.Settings.PowerDownBuildings)
|
||||||
|
{
|
||||||
|
// Power Down
|
||||||
|
Rectangle pwrdownRect = new Rectangle(Game.viewport.Width - 40, 5,
|
||||||
|
pwrdownButton.Image.bounds.Width, pwrdownButton.Image.bounds.Height);
|
||||||
|
|
||||||
|
var pwrdownDrawPos = Game.viewport.Location + new float2(pwrdownRect.Location);
|
||||||
|
|
||||||
|
pwrdownButton.ReplaceAnim(Game.controller.orderGenerator is PowerDownOrderGenerator ? "pressed" : "normal");
|
||||||
|
|
||||||
|
AddButton(pwrdownRect, isLmb => Game.controller.ToggleInputMode<PowerDownOrderGenerator>());
|
||||||
|
buildPaletteRenderer.DrawSprite(pwrdownButton.Image, pwrdownDrawPos, PaletteType.Chrome);
|
||||||
|
}
|
||||||
|
buildPaletteRenderer.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleChronosphereButton()
|
||||||
|
{
|
||||||
|
if (Game.controller.ToggleInputMode<ChronosphereSelectOrderGenerator>())
|
||||||
|
Sound.Play("slcttgt1.aud");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawChat()
|
void DrawChat()
|
||||||
@@ -392,7 +466,7 @@ namespace OpenRa.Game
|
|||||||
if (++x == columns) { x = 0; y++; }
|
if (++x == columns) { x = 0; y++; }
|
||||||
}
|
}
|
||||||
|
|
||||||
while (x != 0)
|
while (x != 0 || y < MinRows)
|
||||||
{
|
{
|
||||||
var rect = new Rectangle(origin.X + x * 64, origin.Y + 48 * y, 64, 48);
|
var rect = new Rectangle(origin.X + x * 64, origin.Y + 48 * y, 64, 48);
|
||||||
var drawPos = Game.viewport.Location + new float2(rect.Location);
|
var drawPos = Game.viewport.Location + new float2(rect.Location);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
var maxSpread = GetMaximumSpread(weapon, warhead);
|
var maxSpread = GetMaximumSpread(weapon, warhead);
|
||||||
var hitActors = Game.FindUnitsInCircle(loc, maxSpread);
|
var hitActors = Game.FindUnitsInCircle(loc, maxSpread);
|
||||||
|
|
||||||
foreach (var victim in hitActors)
|
foreach (var victim in hitActors)
|
||||||
victim.InflictDamage(firedBy, (int)GetDamageToInflict(victim, loc, weapon, warhead), warhead);
|
victim.InflictDamage(firedBy, (int)GetDamageToInflict(victim, loc, weapon, warhead), warhead);
|
||||||
}
|
}
|
||||||
@@ -46,11 +46,10 @@ namespace OpenRa.Game
|
|||||||
{
|
{
|
||||||
if (!WeaponValidForTarget(weapon, target))
|
if (!WeaponValidForTarget(weapon, target))
|
||||||
return 0f;
|
return 0f;
|
||||||
|
|
||||||
var distance = (target.CenterLocation - loc).Length;
|
var distance = (target.CenterLocation - loc).Length*1/24f;
|
||||||
var rawDamage = weapon.Damage * (float)Math.Exp(-distance / warhead.Spread);
|
var rawDamage = weapon.Damage * (float)Math.Exp(-distance / warhead.Spread);
|
||||||
var multiplier = warhead.EffectivenessAgainst(target.Info.Armor);
|
var multiplier = warhead.EffectivenessAgainst(target.Info.Armor);
|
||||||
|
|
||||||
return rawDamage * multiplier;
|
return rawDamage * multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,12 +27,18 @@ namespace OpenRa.Game
|
|||||||
orderGenerator = new UnitOrderGenerator(new Actor[] { });
|
orderGenerator = new UnitOrderGenerator(new Actor[] { });
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ToggleInputMode<T>() where T : IOrderGenerator, new()
|
public bool ToggleInputMode<T>() where T : IOrderGenerator, new()
|
||||||
{
|
{
|
||||||
if (orderGenerator is T)
|
if (orderGenerator is T)
|
||||||
|
{
|
||||||
CancelInputMode();
|
CancelInputMode();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
orderGenerator = new T();
|
orderGenerator = new T();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Order> recentOrders = new List<Order>();
|
List<Order> recentOrders = new List<Order>();
|
||||||
|
|||||||
@@ -19,10 +19,12 @@ namespace OpenRa.Game
|
|||||||
public static Cursor Select { get { return new Cursor("select"); } }
|
public static Cursor Select { get { return new Cursor("select"); } }
|
||||||
public static Cursor MoveBlocked { get { return new Cursor("move-blocked"); } }
|
public static Cursor MoveBlocked { get { return new Cursor("move-blocked"); } }
|
||||||
public static Cursor Attack { get { return new Cursor("attack"); } }
|
public static Cursor Attack { get { return new Cursor("attack"); } }
|
||||||
|
public static Cursor AttackMove { get { return new Cursor("attackmove"); } }
|
||||||
public static Cursor Deploy { get { return new Cursor("deploy"); } }
|
public static Cursor Deploy { get { return new Cursor("deploy"); } }
|
||||||
public static Cursor Enter { get { return new Cursor("enter"); } }
|
public static Cursor Enter { get { return new Cursor("enter"); } }
|
||||||
public static Cursor DeployBlocked { get { return new Cursor("deploy-blocked"); } }
|
public static Cursor DeployBlocked { get { return new Cursor("deploy-blocked"); } }
|
||||||
public static Cursor Chronoshift { get { return new Cursor("chrono"); } }
|
public static Cursor Chronoshift { get { return new Cursor("chrono-target"); } }
|
||||||
|
public static Cursor ChronoshiftSelect { get { return new Cursor("chrono-select"); } }
|
||||||
public static Cursor C4 { get { return new Cursor("c4"); } }
|
public static Cursor C4 { get { return new Cursor("c4"); } }
|
||||||
public static Cursor Capture { get { return new Cursor("capture"); } }
|
public static Cursor Capture { get { return new Cursor("capture"); } }
|
||||||
public static Cursor Heal { get { return new Cursor("heal"); } }
|
public static Cursor Heal { get { return new Cursor("heal"); } }
|
||||||
@@ -30,5 +32,6 @@ namespace OpenRa.Game
|
|||||||
public static Cursor SellBlocked { get { return new Cursor("sell-blocked"); } }
|
public static Cursor SellBlocked { get { return new Cursor("sell-blocked"); } }
|
||||||
public static Cursor Repair { get { return new Cursor("repair"); } }
|
public static Cursor Repair { get { return new Cursor("repair"); } }
|
||||||
public static Cursor RepairBlocked { get { return new Cursor("repair-blocked"); } }
|
public static Cursor RepairBlocked { get { return new Cursor("repair-blocked"); } }
|
||||||
|
public static Cursor PowerDown { get { return new Cursor("powerdown"); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ namespace OpenRa.Game
|
|||||||
static bool usingAftermath;
|
static bool usingAftermath;
|
||||||
static int2 clientSize;
|
static int2 clientSize;
|
||||||
static HardwarePalette palette;
|
static HardwarePalette palette;
|
||||||
|
public static Minimap minimap;
|
||||||
|
|
||||||
public static void ChangeMap(string mapName)
|
public static void ChangeMap(string mapName)
|
||||||
{
|
{
|
||||||
@@ -58,6 +59,11 @@ namespace OpenRa.Game
|
|||||||
palette = new HardwarePalette(renderer, Rules.Map);
|
palette = new HardwarePalette(renderer, Rules.Map);
|
||||||
|
|
||||||
world = new World();
|
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++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
@@ -73,10 +79,12 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
var worldActor = new Actor(null, new int2(int.MaxValue, int.MaxValue), null);
|
var worldActor = new Actor(null, new int2(int.MaxValue, int.MaxValue), null);
|
||||||
worldActor.traits.Add(new Traits.WaterPaletteRotation(worldActor));
|
worldActor.traits.Add(new Traits.WaterPaletteRotation(worldActor));
|
||||||
|
worldActor.traits.Add(new Traits.ChronoshiftPaletteEffect(worldActor));
|
||||||
Game.world.Add(worldActor);
|
Game.world.Add(worldActor);
|
||||||
|
|
||||||
Rules.Map.InitOreDensity();
|
Rules.Map.InitOreDensity();
|
||||||
worldRenderer = new WorldRenderer(renderer);
|
worldRenderer = new WorldRenderer(renderer);
|
||||||
|
minimap = new Minimap(renderer);
|
||||||
|
|
||||||
SequenceProvider.Initialize(usingAftermath);
|
SequenceProvider.Initialize(usingAftermath);
|
||||||
viewport = new Viewport(clientSize, Rules.Map.Offset, Rules.Map.Offset + Rules.Map.Size, renderer);
|
viewport = new Viewport(clientSize, Rules.Map.Offset, Rules.Map.Offset + Rules.Map.Size, renderer);
|
||||||
@@ -97,7 +105,7 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
chrome = new Chrome(renderer);
|
chrome = new Chrome(renderer);
|
||||||
|
|
||||||
oreFrequency = (int)(Rules.General.GrowthRate * 60 * 1000);
|
oreFrequency = (int)(Rules.General.GrowthRate * 60 * 25);
|
||||||
oreTicks = oreFrequency;
|
oreTicks = oreFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,6 +176,8 @@ namespace OpenRa.Game
|
|||||||
lastTime += Settings.Timestep;
|
lastTime += Settings.Timestep;
|
||||||
UpdatePalette(world.Actors.SelectMany(
|
UpdatePalette(world.Actors.SelectMany(
|
||||||
a => a.traits.WithInterface<IPaletteModifier>()));
|
a => a.traits.WithInterface<IPaletteModifier>()));
|
||||||
|
minimap.Update();
|
||||||
|
|
||||||
orderManager.TickImmediate();
|
orderManager.TickImmediate();
|
||||||
|
|
||||||
if (orderManager.IsReadyForNextFrame)
|
if (orderManager.IsReadyForNextFrame)
|
||||||
@@ -177,11 +187,12 @@ namespace OpenRa.Game
|
|||||||
controller.orderGenerator.Tick();
|
controller.orderGenerator.Tick();
|
||||||
|
|
||||||
if (--oreTicks == 0)
|
if (--oreTicks == 0)
|
||||||
{
|
|
||||||
using (new PerfSample("ore"))
|
using (new PerfSample("ore"))
|
||||||
|
{
|
||||||
Rules.Map.GrowOre(SharedRandom);
|
Rules.Map.GrowOre(SharedRandom);
|
||||||
oreTicks = oreFrequency;
|
minimap.InvalidateOre();
|
||||||
}
|
oreTicks = oreFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
world.Tick();
|
world.Tick();
|
||||||
UnitInfluence.Tick();
|
UnitInfluence.Tick();
|
||||||
|
|||||||
@@ -55,13 +55,15 @@ namespace OpenRa.Game.GameRules
|
|||||||
public readonly int OrePips = 0;
|
public readonly int OrePips = 0;
|
||||||
public readonly string Icon = null;
|
public readonly string Icon = null;
|
||||||
public readonly int[] SelectionSize = 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 UnitInfo(string name) { Name = name; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MobileInfo : UnitInfo
|
public class MobileInfo : UnitInfo
|
||||||
{
|
{
|
||||||
public readonly int Passengers = 0;
|
|
||||||
public readonly int Speed = 0;
|
public readonly int Speed = 0;
|
||||||
public readonly bool NoMovingFire = false;
|
public readonly bool NoMovingFire = false;
|
||||||
public readonly string Voice = "GenericVoice";
|
public readonly string Voice = "GenericVoice";
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ namespace OpenRa.Game.GameRules
|
|||||||
public readonly string Replay = "";
|
public readonly string Replay = "";
|
||||||
|
|
||||||
// Gameplay options
|
// Gameplay options
|
||||||
public readonly bool RepairRequiresConyard = false;
|
public readonly bool RepairRequiresConyard = true;
|
||||||
|
public readonly bool PowerDownBuildings = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,16 @@ namespace OpenRa.Game.Graphics
|
|||||||
|
|
||||||
static Sprite[] LoadCursors(string filename)
|
static Sprite[] LoadCursors(string filename)
|
||||||
{
|
{
|
||||||
var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts));
|
try
|
||||||
return shp.Select(a => SheetBuilder.Add(a.Image, a.Size)).ToArray();
|
{
|
||||||
|
var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||||
|
return shp.Select(a => SheetBuilder.Add(a.Image, a.Size)).ToArray();
|
||||||
|
}
|
||||||
|
catch (System.IndexOutOfRangeException) // This will occur when loading a custom (RA-format) .shp
|
||||||
|
{
|
||||||
|
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||||
|
return shp.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Sprite[] LoadAllSprites(string filename) { return cursors[filename]; }
|
public static Sprite[] LoadAllSprites(string filename) { return cursors[filename]; }
|
||||||
|
|||||||
@@ -3,7 +3,12 @@ using OpenRa.FileFormats;
|
|||||||
|
|
||||||
namespace OpenRa.Game.Graphics
|
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
|
class HardwarePalette : Sheet
|
||||||
{
|
{
|
||||||
const int maxEntries = 16;
|
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(new Palette(pal, new PaletteRemap(Color.FromArgb(140, 0, 0, 0))));
|
||||||
AddPalette(pal); // iron curtain. todo: remap!
|
AddPalette(pal); // iron curtain. todo: remap!
|
||||||
AddPalette(pal); // chrome (it's like gold, but we're not going to hax it in palettemods)
|
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)
|
int AddPalette(Palette p)
|
||||||
|
|||||||
89
OpenRa.Game/Graphics/Minimap.cs
Normal file
89
OpenRa.Game/Graphics/Minimap.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRa.Game.Traits;
|
||||||
|
using OpenRa.FileFormats;
|
||||||
|
|
||||||
|
namespace OpenRa.Game.Graphics
|
||||||
|
{
|
||||||
|
class Minimap
|
||||||
|
{
|
||||||
|
Sheet sheet;
|
||||||
|
SpriteRenderer spriteRenderer;
|
||||||
|
Sprite sprite;
|
||||||
|
Bitmap terrain, oreLayer;
|
||||||
|
|
||||||
|
public void Tick() { }
|
||||||
|
|
||||||
|
public Minimap(Renderer r)
|
||||||
|
{
|
||||||
|
sheet = new Sheet(r, new Size(128, 128));
|
||||||
|
spriteRenderer = new SpriteRenderer(r, true, r.RgbaSpriteShader);
|
||||||
|
sprite = new Sprite(sheet, new Rectangle(0, 0, 128, 128), TextureChannel.Alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: extract these from the palette
|
||||||
|
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);
|
||||||
|
for (var y = 0; y < 128; y++)
|
||||||
|
for (var x = 0; x < 128; x++)
|
||||||
|
terrain.SetPixel(x, y, Rules.Map.IsInMap(x, y)
|
||||||
|
? terrainTypeColors[Rules.TileSet.GetWalkability(Rules.Map.MapTiles[x, y])]
|
||||||
|
: Color.Black);
|
||||||
|
}
|
||||||
|
|
||||||
|
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] : terrainTypeColors[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var a in Game.world.Actors.Where(a => a.traits.Contains<Unit>()))
|
||||||
|
bitmap.SetPixel(a.Location.X, a.Location.Y, Chat.paletteColors[(int)a.Owner.Palette]);
|
||||||
|
|
||||||
|
sheet.Texture.SetData(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(float2 pos)
|
||||||
|
{
|
||||||
|
spriteRenderer.DrawSprite(sprite, pos, PaletteType.Chrome, new float2(256,256));
|
||||||
|
spriteRenderer.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -57,7 +57,7 @@ namespace OpenRa.Game.Graphics
|
|||||||
public static Sequence GetSequence(string unitName, string sequenceName)
|
public static Sequence GetSequence(string unitName, string sequenceName)
|
||||||
{
|
{
|
||||||
try { return units[unitName][sequenceName]; }
|
try { return units[unitName][sequenceName]; }
|
||||||
catch (KeyNotFoundException e)
|
catch (KeyNotFoundException)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
|
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ namespace OpenRa.Game.Graphics
|
|||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
|
|
||||||
uv = new RectangleF(
|
uv = new RectangleF(
|
||||||
(float)(bounds.Left + 0.5f) / sheet.Size.Width,
|
(float)(bounds.Left + .5f) / sheet.Size.Width,
|
||||||
(float)(bounds.Top + 0.5f) / sheet.Size.Height,
|
(float)(bounds.Top + .5f) / sheet.Size.Height,
|
||||||
(float)(bounds.Width) / sheet.Size.Width,
|
(float)(bounds.Width - .5f) / sheet.Size.Width,
|
||||||
(float)(bounds.Height) / sheet.Size.Height);
|
(float)(bounds.Height - .5f) / sheet.Size.Height);
|
||||||
|
|
||||||
uvhax = new float2[]
|
uvhax = new float2[]
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,12 +55,17 @@ namespace OpenRa.Game.Graphics
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void DrawSprite(Sprite s, float2 location, PaletteType palette)
|
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)
|
if (s.sheet != currentSheet)
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
currentSheet = s.sheet;
|
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;
|
nv += 4; ni += 6;
|
||||||
if (++sprites >= spritesPerBatch)
|
if (++sprites >= spritesPerBatch)
|
||||||
Flush();
|
Flush();
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace OpenRa.Game.Graphics
|
|||||||
for( int i = map.XOffset ; i < map.XOffset + map.Width; i++ )
|
for( int i = map.XOffset ; i < map.XOffset + map.Width; i++ )
|
||||||
{
|
{
|
||||||
Sprite tile = tileMapping[map.MapTiles[i, j]];
|
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;
|
nv += 4;
|
||||||
ni += 6;
|
ni += 6;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,23 +2,12 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
namespace OpenRa.Game.Graphics
|
namespace OpenRa.Game.Graphics
|
||||||
{
|
{
|
||||||
static class Util
|
static class Util
|
||||||
{
|
{
|
||||||
static float2 KLerp(float2 o, float2 d, int k)
|
|
||||||
{
|
|
||||||
switch (k)
|
|
||||||
{
|
|
||||||
case 0: return o;
|
|
||||||
case 1: return new float2(o.X + d.X, o.Y);
|
|
||||||
case 2: return new float2(o.X, o.Y + d.Y);
|
|
||||||
case 3: return new float2(o.X + d.X, o.Y + d.Y);
|
|
||||||
default: throw new InvalidOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string[] ReadAllLines(Stream s)
|
public static string[] ReadAllLines(Stream s)
|
||||||
{
|
{
|
||||||
List<string> result = new List<string>();
|
List<string> result = new List<string>();
|
||||||
@@ -56,14 +45,18 @@ namespace OpenRa.Game.Graphics
|
|||||||
|
|
||||||
static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
|
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]);
|
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] = new Vertex(o,
|
||||||
vertices[nv + 1] = new Vertex(KLerp(o, r.size, 1), r.FastMapTextureCoords(1), attrib);
|
r.FastMapTextureCoords(0), attrib);
|
||||||
vertices[nv + 2] = new Vertex(KLerp(o, r.size, 2), r.FastMapTextureCoords(2), attrib);
|
vertices[nv + 1] = new Vertex(new float2(o.X + size.X, o.Y),
|
||||||
vertices[nv + 3] = new Vertex(KLerp(o, r.size, 3), r.FastMapTextureCoords(3), attrib);
|
r.FastMapTextureCoords(1), attrib);
|
||||||
|
vertices[nv + 2] = new Vertex(new float2(o.X, o.Y + size.Y),
|
||||||
|
r.FastMapTextureCoords(2), attrib);
|
||||||
|
vertices[nv + 3] = new Vertex(new float2(o.X + size.X, o.Y + size.Y),
|
||||||
|
r.FastMapTextureCoords(3), attrib);
|
||||||
|
|
||||||
indices[ni] = (ushort)(nv);
|
indices[ni] = (ushort)(nv);
|
||||||
indices[ni + 1] = indices[ni + 3] = (ushort)(nv + 1);
|
indices[ni + 1] = indices[ni + 3] = (ushort)(nv + 1);
|
||||||
@@ -111,5 +104,19 @@ namespace OpenRa.Game.Graphics
|
|||||||
bitmap.UnlockBits(bits);
|
bitmap.UnlockBits(bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Color Lerp(float t, Color a, Color b)
|
||||||
|
{
|
||||||
|
return Color.FromArgb(
|
||||||
|
LerpChannel(t, a.A, b.A),
|
||||||
|
LerpChannel(t, a.R, b.R),
|
||||||
|
LerpChannel(t, a.G, b.G),
|
||||||
|
LerpChannel(t, a.B, b.B));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int LerpChannel(float t, int a, int b)
|
||||||
|
{
|
||||||
|
return (int)((1 - t) * a + t * b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ namespace OpenRa.Game.Graphics
|
|||||||
if (Game.controller.orderGenerator != null)
|
if (Game.controller.orderGenerator != null)
|
||||||
Game.controller.orderGenerator.Render();
|
Game.controller.orderGenerator.Render();
|
||||||
|
|
||||||
|
Game.LocalPlayer.Shroud.Draw(spriteRenderer);
|
||||||
|
|
||||||
lineRenderer.Flush();
|
lineRenderer.Flush();
|
||||||
spriteRenderer.Flush();
|
spriteRenderer.Flush();
|
||||||
}
|
}
|
||||||
@@ -211,7 +213,7 @@ namespace OpenRa.Game.Graphics
|
|||||||
|
|
||||||
foreach (var pips in selectedUnit.traits.WithInterface<IPips>())
|
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");
|
var pipImages = new Animation("pips");
|
||||||
pipImages.PlayRepeating(pipStrings[(int)pip]);
|
pipImages.PlayRepeating(pipStrings[(int)pip]);
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ using System.IO;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using OpenRa.FileFormats;
|
using OpenRa.FileFormats;
|
||||||
|
using OpenRa.Game.GameRules;
|
||||||
using OpenRa.Game.Graphics;
|
using OpenRa.Game.Graphics;
|
||||||
using OpenRa.Game.Orders;
|
using OpenRa.Game.Orders;
|
||||||
using OpenRa.Game.GameRules;
|
|
||||||
|
|
||||||
|
|
||||||
namespace OpenRa.Game
|
namespace OpenRa.Game
|
||||||
@@ -31,51 +31,33 @@ namespace OpenRa.Game
|
|||||||
[DllImport("user32")]
|
[DllImport("user32")]
|
||||||
static extern int ShowCursor([MarshalAs(UnmanagedType.Bool)] bool visible);
|
static extern int ShowCursor([MarshalAs(UnmanagedType.Bool)] bool visible);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public MainWindow(Settings settings)
|
public MainWindow(Settings settings)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
FormBorderStyle = FormBorderStyle.None;
|
FormBorderStyle = FormBorderStyle.None;
|
||||||
BackColor = Color.Black;
|
BackColor = Color.Black;
|
||||||
StartPosition = FormStartPosition.Manual;
|
StartPosition = FormStartPosition.Manual;
|
||||||
Location = Point.Empty;
|
Location = Point.Empty;
|
||||||
Visible = true;
|
Visible = true;
|
||||||
|
|
||||||
// Load user settings
|
|
||||||
Game.Settings = new UserSettings();
|
|
||||||
|
|
||||||
while (!File.Exists("redalert.mix"))
|
while (!File.Exists("redalert.mix"))
|
||||||
{
|
{
|
||||||
var current = Directory.GetCurrentDirectory();
|
var current = Directory.GetCurrentDirectory();
|
||||||
if (Directory.GetDirectoryRoot(current) == current)
|
if (Directory.GetDirectoryRoot(current) == current)
|
||||||
throw new InvalidOperationException("Unable to load MIX files.");
|
throw new InvalidOperationException("Unable to load MIX files.");
|
||||||
Directory.SetCurrentDirectory("..");
|
Directory.SetCurrentDirectory("..");
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// settings.ini should be located with the mix files
|
|
||||||
FileSystem.MountTemporary(new Folder("./"));
|
|
||||||
IniFile SettingsRules = new IniFile(FileSystem.Open("settings.ini"));
|
|
||||||
FieldLoader.Load(Game.Settings, SettingsRules.GetSection("Settings"));
|
|
||||||
FileSystem.UnmountTemporaryPackages();
|
|
||||||
}
|
|
||||||
catch (FileNotFoundException) { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadUserSettings(settings);
|
||||||
|
|
||||||
UiOverlay.ShowUnitDebug = Game.Settings.UnitDebug;
|
UiOverlay.ShowUnitDebug = Game.Settings.UnitDebug;
|
||||||
UiOverlay.ShowBuildDebug = Game.Settings.BuildingDebug;
|
UiOverlay.ShowBuildDebug = Game.Settings.BuildingDebug;
|
||||||
WorldRenderer.ShowUnitPaths = Game.Settings.PathDebug;
|
WorldRenderer.ShowUnitPaths = Game.Settings.PathDebug;
|
||||||
Renderer.SheetSize = Game.Settings.SheetSize;
|
Renderer.SheetSize = Game.Settings.SheetSize;
|
||||||
|
|
||||||
|
|
||||||
FileSystem.MountDefaultPackages();
|
FileSystem.MountDefaultPackages();
|
||||||
|
|
||||||
if (Game.Settings.UseAftermath)
|
if (Game.Settings.UseAftermath)
|
||||||
{
|
|
||||||
FileSystem.MountAftermathPackages();
|
FileSystem.MountAftermathPackages();
|
||||||
}
|
|
||||||
|
|
||||||
bool windowed = !Game.Settings.Fullscreen;
|
bool windowed = !Game.Settings.Fullscreen;
|
||||||
renderer = new Renderer(this, GetResolution(settings), windowed);
|
renderer = new Renderer(this, GetResolution(settings), windowed);
|
||||||
@@ -89,6 +71,17 @@ namespace OpenRa.Game
|
|||||||
Game.ResetTimer();
|
Game.ResetTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void LoadUserSettings(Settings settings)
|
||||||
|
{
|
||||||
|
Game.Settings = new UserSettings();
|
||||||
|
var settingsFile = settings.GetValue("settings", "settings.ini");
|
||||||
|
FileSystem.MountTemporary(new Folder("./"));
|
||||||
|
if (FileSystem.Exists(settingsFile))
|
||||||
|
FieldLoader.Load(Game.Settings,
|
||||||
|
new IniFile(FileSystem.Open(settingsFile)).GetSection("Settings"));
|
||||||
|
FileSystem.UnmountTemporaryPackages();
|
||||||
|
}
|
||||||
|
|
||||||
internal void Run()
|
internal void Run()
|
||||||
{
|
{
|
||||||
while (Created && Visible)
|
while (Created && Visible)
|
||||||
|
|||||||
@@ -95,19 +95,23 @@
|
|||||||
<Compile Include="GameRules\UserSettings.cs" />
|
<Compile Include="GameRules\UserSettings.cs" />
|
||||||
<Compile Include="GameRules\VoiceInfo.cs" />
|
<Compile Include="GameRules\VoiceInfo.cs" />
|
||||||
<Compile Include="Effects\IEffect.cs" />
|
<Compile Include="Effects\IEffect.cs" />
|
||||||
|
<Compile Include="Graphics\Minimap.cs" />
|
||||||
|
<Compile Include="Orders\ChronosphereSelectOrderGenerator.cs" />
|
||||||
<Compile Include="Orders\IOrderSource.cs" />
|
<Compile Include="Orders\IOrderSource.cs" />
|
||||||
<Compile Include="Orders\LocalOrderSource.cs" />
|
<Compile Include="Orders\LocalOrderSource.cs" />
|
||||||
<Compile Include="Effects\Missile.cs" />
|
<Compile Include="Effects\Missile.cs" />
|
||||||
<Compile Include="Orders\NetworkOrderSource.cs" />
|
<Compile Include="Orders\NetworkOrderSource.cs" />
|
||||||
<Compile Include="Orders\OrderIO.cs" />
|
<Compile Include="Orders\OrderIO.cs" />
|
||||||
<Compile Include="Orders\OrderManager.cs" />
|
<Compile Include="Orders\OrderManager.cs" />
|
||||||
|
<Compile Include="Orders\PowerDownOrderGenerator.cs" />
|
||||||
<Compile Include="Orders\RepairOrderGenerator.cs" />
|
<Compile Include="Orders\RepairOrderGenerator.cs" />
|
||||||
<Compile Include="Orders\SellOrderGenerator.cs" />
|
<Compile Include="Orders\SellOrderGenerator.cs" />
|
||||||
<Compile Include="Orders\TeleportOrderGenerator.cs" />
|
<Compile Include="Orders\ChronoshiftDestinationOrderGenerator.cs" />
|
||||||
<Compile Include="Ore.cs" />
|
<Compile Include="Ore.cs" />
|
||||||
<Compile Include="PathSearch.cs" />
|
<Compile Include="PathSearch.cs" />
|
||||||
<Compile Include="ProductionItem.cs" />
|
<Compile Include="ProductionItem.cs" />
|
||||||
<Compile Include="Orders\ReplayOrderSource.cs" />
|
<Compile Include="Orders\ReplayOrderSource.cs" />
|
||||||
|
<Compile Include="Shroud.cs" />
|
||||||
<Compile Include="Smudge.cs" />
|
<Compile Include="Smudge.cs" />
|
||||||
<Compile Include="Sound.cs" />
|
<Compile Include="Sound.cs" />
|
||||||
<Compile Include="Support\Stopwatch.cs" />
|
<Compile Include="Support\Stopwatch.cs" />
|
||||||
@@ -116,6 +120,7 @@
|
|||||||
<Compile Include="Traits\Activities\Attack.cs" />
|
<Compile Include="Traits\Activities\Attack.cs" />
|
||||||
<Compile Include="Traits\Activities\CaptureBuilding.cs" />
|
<Compile Include="Traits\Activities\CaptureBuilding.cs" />
|
||||||
<Compile Include="Traits\Activities\Demolish.cs" />
|
<Compile Include="Traits\Activities\Demolish.cs" />
|
||||||
|
<Compile Include="Traits\Activities\EnterTransport.cs" />
|
||||||
<Compile Include="Traits\Activities\Fly.cs" />
|
<Compile Include="Traits\Activities\Fly.cs" />
|
||||||
<Compile Include="Traits\Activities\FlyAttack.cs" />
|
<Compile Include="Traits\Activities\FlyAttack.cs" />
|
||||||
<Compile Include="Traits\Activities\FlyTimed.cs" />
|
<Compile Include="Traits\Activities\FlyTimed.cs" />
|
||||||
@@ -183,6 +188,7 @@
|
|||||||
<Compile Include="Traits\Activities\Follow.cs" />
|
<Compile Include="Traits\Activities\Follow.cs" />
|
||||||
<Compile Include="Traits\Activities\Turn.cs" />
|
<Compile Include="Traits\Activities\Turn.cs" />
|
||||||
<Compile Include="Traits\Activities\UndeployMcv.cs" />
|
<Compile Include="Traits\Activities\UndeployMcv.cs" />
|
||||||
|
<Compile Include="Traits\Activities\UnloadCargo.cs" />
|
||||||
<Compile Include="Traits\APMine.cs" />
|
<Compile Include="Traits\APMine.cs" />
|
||||||
<Compile Include="Traits\ATMine.cs" />
|
<Compile Include="Traits\ATMine.cs" />
|
||||||
<Compile Include="Traits\AttackBase.cs" />
|
<Compile Include="Traits\AttackBase.cs" />
|
||||||
@@ -196,6 +202,11 @@
|
|||||||
<Compile Include="Traits\BelowUnits.cs" />
|
<Compile Include="Traits\BelowUnits.cs" />
|
||||||
<Compile Include="Traits\Building.cs" />
|
<Compile Include="Traits\Building.cs" />
|
||||||
<Compile Include="Traits\C4Demolition.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" />
|
||||||
|
<Compile Include="Traits\DemoTruck.cs" />
|
||||||
<Compile Include="Traits\EngineerCapture.cs" />
|
<Compile Include="Traits\EngineerCapture.cs" />
|
||||||
<Compile Include="Traits\Explodes.cs" />
|
<Compile Include="Traits\Explodes.cs" />
|
||||||
<Compile Include="Traits\ChronoshiftDeploy.cs" />
|
<Compile Include="Traits\ChronoshiftDeploy.cs" />
|
||||||
@@ -207,6 +218,8 @@
|
|||||||
<Compile Include="Traits\MineImmune.cs" />
|
<Compile Include="Traits\MineImmune.cs" />
|
||||||
<Compile Include="Traits\Minelayer.cs" />
|
<Compile Include="Traits\Minelayer.cs" />
|
||||||
<Compile Include="Traits\LimitedAmmo.cs" />
|
<Compile Include="Traits\LimitedAmmo.cs" />
|
||||||
|
<Compile Include="Traits\Passenger.cs" />
|
||||||
|
<Compile Include="Traits\ProvidesRadar.cs" />
|
||||||
<Compile Include="Traits\Repairable.cs" />
|
<Compile Include="Traits\Repairable.cs" />
|
||||||
<Compile Include="Traits\Reservable.cs" />
|
<Compile Include="Traits\Reservable.cs" />
|
||||||
<Compile Include="Traits\SquishByTank.cs" />
|
<Compile Include="Traits\SquishByTank.cs" />
|
||||||
@@ -291,4 +304,4 @@
|
|||||||
<Target Name="AfterBuild">
|
<Target Name="AfterBuild">
|
||||||
</Target>
|
</Target>
|
||||||
-->
|
-->
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -3,14 +3,15 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using OpenRa.Game.Traits;
|
||||||
|
|
||||||
namespace OpenRa.Game.Orders
|
namespace OpenRa.Game.Orders
|
||||||
{
|
{
|
||||||
class TeleportOrderGenerator : IOrderGenerator
|
class ChronoshiftDestinationOrderGenerator : IOrderGenerator
|
||||||
{
|
{
|
||||||
public readonly Actor self;
|
public readonly Actor self;
|
||||||
|
|
||||||
public TeleportOrderGenerator(Actor self)
|
public ChronoshiftDestinationOrderGenerator(Actor self)
|
||||||
{
|
{
|
||||||
this.self = self;
|
this.self = self;
|
||||||
}
|
}
|
||||||
@@ -34,7 +35,8 @@ namespace OpenRa.Game.Orders
|
|||||||
|
|
||||||
public Cursor GetCursor(int2 xy, MouseInput mi)
|
public Cursor GetCursor(int2 xy, MouseInput mi)
|
||||||
{
|
{
|
||||||
return Cursor.Chronoshift;
|
var movement = self.traits.WithInterface<IMovement>().FirstOrDefault();
|
||||||
|
return (movement.CanEnterCell(xy)) ? Cursor.Chronoshift : Cursor.MoveBlocked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
57
OpenRa.Game/Orders/ChronosphereSelectOrderGenerator.cs
Normal file
57
OpenRa.Game/Orders/ChronosphereSelectOrderGenerator.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using OpenRa.Game.GameRules;
|
||||||
|
using OpenRa.Game.Traits;
|
||||||
|
|
||||||
|
namespace OpenRa.Game.Orders
|
||||||
|
{
|
||||||
|
class ChronosphereSelectOrderGenerator : IOrderGenerator
|
||||||
|
{
|
||||||
|
public IEnumerable<Order> Order(int2 xy, MouseInput mi)
|
||||||
|
{
|
||||||
|
if (mi.Button == MouseButton.Right)
|
||||||
|
Game.controller.CancelInputMode();
|
||||||
|
|
||||||
|
return OrderInner(xy, mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<Order> OrderInner(int2 xy, MouseInput mi)
|
||||||
|
{
|
||||||
|
if (mi.Button == MouseButton.Left)
|
||||||
|
{
|
||||||
|
var loc = mi.Location + Game.viewport.Location;
|
||||||
|
var underCursor = Game.FindUnits(loc, loc)
|
||||||
|
.Where(a => a.Owner == Game.LocalPlayer
|
||||||
|
&& a.traits.WithInterface<IChronoshiftable>().Any()
|
||||||
|
&& a.Info.Selectable).FirstOrDefault();
|
||||||
|
|
||||||
|
var unit = underCursor != null ? underCursor.Info as UnitInfo : null;
|
||||||
|
|
||||||
|
if (unit != null)
|
||||||
|
{
|
||||||
|
yield return new Order("ChronosphereSelect", underCursor, null, int2.Zero, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick()
|
||||||
|
{
|
||||||
|
var hasChronosphere = Game.world.Actors
|
||||||
|
.Any(a => a.Owner == Game.LocalPlayer && a.traits.Contains<Chronosphere>());
|
||||||
|
|
||||||
|
if (!hasChronosphere)
|
||||||
|
Game.controller.CancelInputMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render() { }
|
||||||
|
|
||||||
|
public Cursor GetCursor(int2 xy, MouseInput mi)
|
||||||
|
{
|
||||||
|
mi.Button = MouseButton.Left;
|
||||||
|
return OrderInner(xy, mi).Any()
|
||||||
|
? Cursor.ChronoshiftSelect : Cursor.MoveBlocked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
OpenRa.Game/Orders/PowerDownOrderGenerator.cs
Normal file
47
OpenRa.Game/Orders/PowerDownOrderGenerator.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using OpenRa.Game.GameRules;
|
||||||
|
using OpenRa.Game.Traits;
|
||||||
|
|
||||||
|
namespace OpenRa.Game.Orders
|
||||||
|
{
|
||||||
|
class PowerDownOrderGenerator : IOrderGenerator
|
||||||
|
{
|
||||||
|
public IEnumerable<Order> Order(int2 xy, MouseInput mi)
|
||||||
|
{
|
||||||
|
if (mi.Button == MouseButton.Right)
|
||||||
|
Game.controller.CancelInputMode();
|
||||||
|
|
||||||
|
return OrderInner(xy, mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<Order> OrderInner(int2 xy, MouseInput mi)
|
||||||
|
{
|
||||||
|
if (mi.Button == MouseButton.Left)
|
||||||
|
{
|
||||||
|
var loc = mi.Location + Game.viewport.Location;
|
||||||
|
var underCursor = Game.FindUnits(loc, loc)
|
||||||
|
.Where(a => a.Owner == Game.LocalPlayer
|
||||||
|
&& a.traits.Contains<Building>()
|
||||||
|
&& a.Info.Selectable).FirstOrDefault();
|
||||||
|
|
||||||
|
var building = underCursor != null ? underCursor.Info as BuildingInfo : null;
|
||||||
|
|
||||||
|
if (building != null)
|
||||||
|
yield return new Order("PowerDown", underCursor, null, int2.Zero, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick() { }
|
||||||
|
public void Render() { }
|
||||||
|
|
||||||
|
public Cursor GetCursor(int2 xy, MouseInput mi)
|
||||||
|
{
|
||||||
|
mi.Button = MouseButton.Left;
|
||||||
|
return OrderInner(xy, mi).Any()
|
||||||
|
? Cursor.PowerDown : Cursor.PowerDown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ namespace OpenRa.Game.Orders
|
|||||||
|
|
||||||
public void Tick()
|
public void Tick()
|
||||||
{
|
{
|
||||||
selection.RemoveAll(a => a.IsDead);
|
selection.RemoveAll(a => !a.IsInWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render()
|
public void Render()
|
||||||
@@ -81,10 +81,11 @@ namespace OpenRa.Game.Orders
|
|||||||
else
|
else
|
||||||
return Cursor.MoveBlocked;
|
return Cursor.MoveBlocked;
|
||||||
case "Enter": return Cursor.Enter;
|
case "Enter": return Cursor.Enter;
|
||||||
|
case "EnterTransport": return Cursor.Enter;
|
||||||
case "Deliver": return Cursor.Enter;
|
case "Deliver": return Cursor.Enter;
|
||||||
case "Infiltrate": return Cursor.Enter;
|
case "Infiltrate": return Cursor.Enter;
|
||||||
case "Capture": return Cursor.Capture;
|
case "Capture": return Cursor.Capture;
|
||||||
case "Harvest": return Cursor.Attack; // TODO: special harvest cursor?
|
case "Harvest": return Cursor.AttackMove;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
using OpenRa.Game.GameRules;
|
using OpenRa.Game.GameRules;
|
||||||
using OpenRa.Game.Graphics;
|
using OpenRa.Game.Graphics;
|
||||||
using OpenRa.Game.Traits;
|
using OpenRa.Game.Traits;
|
||||||
@@ -17,15 +18,17 @@ namespace OpenRa.Game
|
|||||||
public string InternalName;
|
public string InternalName;
|
||||||
public Race Race;
|
public Race Race;
|
||||||
public readonly int Index;
|
public readonly int Index;
|
||||||
public int Cash;
|
public int Cash = 10000;
|
||||||
public int Ore;
|
public int Ore = 0;
|
||||||
public int OreCapacity;
|
public int OreCapacity;
|
||||||
public int DisplayCash;
|
public int DisplayCash = 0;
|
||||||
public int PowerProvided;
|
public int PowerProvided = 0;
|
||||||
public int PowerDrained;
|
public int PowerDrained = 0;
|
||||||
|
|
||||||
public bool IsReady;
|
public bool IsReady;
|
||||||
|
|
||||||
|
public Shroud Shroud = new Shroud();
|
||||||
|
|
||||||
public Player( Actor playerActor, int index, PaletteType palette, string playerName, Race race, string internalName )
|
public Player( Actor playerActor, int index, PaletteType palette, string playerName, Race race, string internalName )
|
||||||
{
|
{
|
||||||
this.PlayerActor = playerActor;
|
this.PlayerActor = playerActor;
|
||||||
@@ -34,10 +37,6 @@ namespace OpenRa.Game
|
|||||||
this.InternalName = internalName;
|
this.InternalName = internalName;
|
||||||
this.PlayerName = playerName;
|
this.PlayerName = playerName;
|
||||||
this.Race = race;
|
this.Race = race;
|
||||||
this.Cash = 10000;
|
|
||||||
this.Ore = 0;
|
|
||||||
this.DisplayCash = 0;
|
|
||||||
this.PowerProvided = this.PowerDrained = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdatePower()
|
void UpdatePower()
|
||||||
@@ -52,11 +51,11 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
foreach (var a in myBuildings)
|
foreach (var a in myBuildings)
|
||||||
{
|
{
|
||||||
var bi = a.Info as BuildingInfo;
|
var p = a.traits.Get<Building>().GetPowerUsage();
|
||||||
if (bi.Power > 0) /* todo: is this how real-ra scales it? */
|
if (p > 0)
|
||||||
PowerProvided += (a.Health * bi.Power) / bi.Strength;
|
PowerProvided += p;
|
||||||
else
|
else
|
||||||
PowerDrained -= bi.Power;
|
PowerDrained -= p;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PowerProvided - PowerDrained < 0)
|
if (PowerProvided - PowerDrained < 0)
|
||||||
|
|||||||
110
OpenRa.Game/Shroud.cs
Normal file
110
OpenRa.Game/Shroud.cs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
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 = 1; j < 127; j++)
|
||||||
|
{
|
||||||
|
var starti = 1;
|
||||||
|
for (var i = 1; i < 127; i++)
|
||||||
|
{
|
||||||
|
if (sprites[i, j] == shadowBits[0x0f])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (starti != i)
|
||||||
|
{
|
||||||
|
r.DrawSprite(sprites[starti,j],
|
||||||
|
Game.CellSize * new float2(starti, j),
|
||||||
|
PaletteType.Shroud,
|
||||||
|
new float2(Game.CellSize * (i - starti), Game.CellSize));
|
||||||
|
starti = i+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.DrawSprite(sprites[i, j],
|
||||||
|
Game.CellSize * new float2(i, j),
|
||||||
|
PaletteType.Shroud);
|
||||||
|
starti = i+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (starti < 127)
|
||||||
|
r.DrawSprite(sprites[starti, j],
|
||||||
|
Game.CellSize * new float2(starti, j),
|
||||||
|
PaletteType.Shroud,
|
||||||
|
new float2(Game.CellSize * (127 - starti), Game.CellSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ using OpenRa.Game.Graphics;
|
|||||||
|
|
||||||
namespace OpenRa.Game
|
namespace OpenRa.Game
|
||||||
{
|
{
|
||||||
enum UnitMovementType : byte
|
public enum UnitMovementType : byte
|
||||||
{
|
{
|
||||||
Foot = 0,
|
Foot = 0,
|
||||||
Track = 1,
|
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 IActivity NextActivity { get; set; }
|
||||||
|
|
||||||
public int desiredFacing;
|
int desiredFacing;
|
||||||
|
|
||||||
public Turn( 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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,12 +26,9 @@ namespace OpenRa.Game.Traits
|
|||||||
|
|
||||||
protected override void QueueAttack( Actor self, Order order )
|
protected override void QueueAttack( Actor self, Order order )
|
||||||
{
|
{
|
||||||
var bi = self.Info as BuildingInfo;
|
var b = self.traits.Get<Building>();
|
||||||
if (bi != null && bi.Powered && self.Owner.GetPowerState() != PowerState.Normal)
|
if (b != null && b.InsuffientPower())
|
||||||
{
|
|
||||||
if (self.Owner == Game.LocalPlayer) Sound.Play("nopowr1.aud");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */
|
const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */
|
||||||
/* todo: choose the appropriate weapon, when only one works against this target */
|
/* todo: choose the appropriate weapon, when only one works against this target */
|
||||||
|
|||||||
@@ -5,20 +5,66 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using OpenRa.Game.Effects;
|
using OpenRa.Game.Effects;
|
||||||
|
using OpenRa.Game.Graphics;
|
||||||
|
|
||||||
namespace OpenRa.Game.Traits
|
namespace OpenRa.Game.Traits
|
||||||
{
|
{
|
||||||
class Building : INotifyDamage, IOrder, ITick
|
class Building : INotifyDamage, IOrder, ITick, IRenderModifier
|
||||||
{
|
{
|
||||||
|
readonly Actor self;
|
||||||
public readonly BuildingInfo unitInfo;
|
public readonly BuildingInfo unitInfo;
|
||||||
bool isRepairing = false;
|
bool isRepairing = false;
|
||||||
|
bool isPoweredDown = false;
|
||||||
|
|
||||||
public Building(Actor self)
|
public Building(Actor self)
|
||||||
{
|
{
|
||||||
|
this.self = self;
|
||||||
unitInfo = (BuildingInfo)self.Info;
|
unitInfo = (BuildingInfo)self.Info;
|
||||||
self.CenterLocation = Game.CellSize
|
self.CenterLocation = Game.CellSize
|
||||||
* ((float2)self.Location + .5f * (float2)unitInfo.Dimensions);
|
* ((float2)self.Location + .5f * (float2)unitInfo.Dimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool InsuffientPower()
|
||||||
|
{
|
||||||
|
return (isPoweredDown || (unitInfo.Powered && self.Owner.GetPowerState() != PowerState.Normal));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetPowerUsage()
|
||||||
|
{
|
||||||
|
if (isPoweredDown)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (unitInfo.Power > 0) /* todo: is this how real-ra scales it? */
|
||||||
|
return (self.Health * unitInfo.Power) / unitInfo.Strength;
|
||||||
|
else
|
||||||
|
return unitInfo.Power;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Animation iconAnim;
|
||||||
|
public IEnumerable<Renderable>
|
||||||
|
ModifyRender(Actor self, IEnumerable<Renderable> rs)
|
||||||
|
{
|
||||||
|
if (!InsuffientPower())
|
||||||
|
return rs;
|
||||||
|
|
||||||
|
List<Renderable> nrs = new List<Renderable>(rs);
|
||||||
|
foreach(var r in rs)
|
||||||
|
{
|
||||||
|
// Need 2 shadows to make it dark enough
|
||||||
|
nrs.Add(r.WithPalette(PaletteType.Shadow));
|
||||||
|
nrs.Add(r.WithPalette(PaletteType.Shadow));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPoweredDown)
|
||||||
|
{
|
||||||
|
iconAnim = new Animation("powerdown");
|
||||||
|
iconAnim.PlayRepeating("disabled");
|
||||||
|
nrs.Add(new Renderable(iconAnim.Image, self.CenterLocation - 0.5f*iconAnim.Image.size, PaletteType.Chrome));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return nrs;
|
||||||
|
}
|
||||||
|
|
||||||
public void Damaged(Actor self, AttackInfo e)
|
public void Damaged(Actor self, AttackInfo e)
|
||||||
{
|
{
|
||||||
@@ -43,6 +89,12 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
isRepairing = !isRepairing;
|
isRepairing = !isRepairing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (order.OrderString == "PowerDown")
|
||||||
|
{
|
||||||
|
isPoweredDown = !isPoweredDown;
|
||||||
|
Sound.Play((isPoweredDown) ? "bleep12.aud" : "bleep11.aud");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int remainingTicks;
|
int remainingTicks;
|
||||||
|
|||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,20 +6,22 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
class ChronoshiftDeploy : IOrder, ISpeedModifier, ITick, IPips
|
class ChronoshiftDeploy : IOrder, ISpeedModifier, ITick, IPips
|
||||||
{
|
{
|
||||||
public ChronoshiftDeploy(Actor self) { }
|
// Recharge logic
|
||||||
int remainingChargeTime = 0; // How long until we can chronoshift again?
|
int chargeTick = 0; // How long until we can chronoshift again?
|
||||||
int chargeTime = (int)(Rules.Aftermath.ChronoTankDuration * 60 * 25); // How long between shifts?
|
int chargeLength = (int)(Rules.Aftermath.ChronoTankDuration * 60 * 25); // How long between shifts?
|
||||||
|
|
||||||
|
public ChronoshiftDeploy(Actor self) { }
|
||||||
|
|
||||||
public void Tick(Actor self)
|
public void Tick(Actor self)
|
||||||
{
|
{
|
||||||
if (remainingChargeTime > 0)
|
if (chargeTick > 0)
|
||||||
remainingChargeTime--;
|
chargeTick--;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||||
{
|
{
|
||||||
if( mi.Button == MouseButton.Right && xy == self.Location && remainingChargeTime <= 0 )
|
if (mi.Button == MouseButton.Right && xy == self.Location && chargeTick <= 0)
|
||||||
return new Order( "Deploy", self, null, int2.Zero, null );
|
return new Order("Deploy", self, null, int2.Zero, null);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -28,7 +30,7 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
if (order.OrderString == "Deploy")
|
if (order.OrderString == "Deploy")
|
||||||
{
|
{
|
||||||
Game.controller.orderGenerator = new TeleportOrderGenerator(self);
|
Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,23 +41,26 @@ namespace OpenRa.Game.Traits
|
|||||||
self.CancelActivity();
|
self.CancelActivity();
|
||||||
self.QueueActivity(new Activities.Teleport(order.TargetLocation));
|
self.QueueActivity(new Activities.Teleport(order.TargetLocation));
|
||||||
Sound.Play("chrotnk1.aud");
|
Sound.Play("chrotnk1.aud");
|
||||||
remainingChargeTime = chargeTime;
|
chargeTick = chargeLength;
|
||||||
|
|
||||||
|
foreach (var a in Game.world.Actors.Where(a => a.traits.Contains<ChronoshiftPaletteEffect>()))
|
||||||
|
a.traits.Get<ChronoshiftPaletteEffect>().DoChronoshift();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetSpeedModifier()
|
public float GetSpeedModifier()
|
||||||
{
|
{
|
||||||
// ARGH! You must not do this, it will desync!
|
// ARGH! You must not do this, it will desync!
|
||||||
return (Game.controller.orderGenerator is TeleportOrderGenerator) ? 0f : 1f;
|
return (Game.controller.orderGenerator is ChronoshiftDestinationOrderGenerator) ? 0f : 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display 5 pips indicating the current charge status
|
// Display 5 pips indicating the current charge status
|
||||||
public IEnumerable<PipType> GetPips()
|
public IEnumerable<PipType> GetPips(Actor self)
|
||||||
{
|
{
|
||||||
const int numPips = 5;
|
const int numPips = 5;
|
||||||
for (int i = 0; i < numPips; i++)
|
for (int i = 0; i < numPips; i++)
|
||||||
{
|
{
|
||||||
if ((1 - remainingChargeTime * 1.0f / chargeTime) * numPips < i + 1)
|
if ((1 - chargeTick * 1.0f / chargeLength) * numPips < i + 1)
|
||||||
{
|
{
|
||||||
yield return PipType.Transparent;
|
yield return PipType.Transparent;
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
40
OpenRa.Game/Traits/ChronoshiftPaletteEffect.cs
Normal file
40
OpenRa.Game/Traits/ChronoshiftPaletteEffect.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using OpenRa.Game.Graphics;
|
||||||
|
|
||||||
|
namespace OpenRa.Game.Traits
|
||||||
|
{
|
||||||
|
class ChronoshiftPaletteEffect : IPaletteModifier, ITick
|
||||||
|
{
|
||||||
|
const int chronoEffectLength = 20;
|
||||||
|
int remainingFrames;
|
||||||
|
|
||||||
|
public ChronoshiftPaletteEffect(Actor self) { }
|
||||||
|
|
||||||
|
public void DoChronoshift()
|
||||||
|
{
|
||||||
|
remainingFrames = chronoEffectLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick(Actor self)
|
||||||
|
{
|
||||||
|
if (remainingFrames > 0)
|
||||||
|
remainingFrames--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AdjustPalette(Bitmap b)
|
||||||
|
{
|
||||||
|
if (remainingFrames == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var frac = (float)remainingFrames / chronoEffectLength;
|
||||||
|
for( var y = 0; y < (int)PaletteType.Chrome; y++ )
|
||||||
|
for (var x = 0; x < 256; x++)
|
||||||
|
{
|
||||||
|
var orig = b.GetPixel(x, y);
|
||||||
|
var lum = (int)(255 * orig.GetBrightness());
|
||||||
|
var desat = Color.FromArgb(orig.A, lum, lum, lum);
|
||||||
|
b.SetPixel(x, y, Graphics.Util.Lerp(frac, orig, desat));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
78
OpenRa.Game/Traits/Chronoshiftable.cs
Normal file
78
OpenRa.Game/Traits/Chronoshiftable.cs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
using OpenRa.Game.Traits;
|
||||||
|
using OpenRa.Game.Orders;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace OpenRa.Game.Traits
|
||||||
|
{
|
||||||
|
class Chronoshiftable : IOrder, ISpeedModifier, ITick, IChronoshiftable
|
||||||
|
{
|
||||||
|
// Return-to-sender logic
|
||||||
|
int2 chronoshiftOrigin;
|
||||||
|
int chronoshiftReturnTicks = 0;
|
||||||
|
|
||||||
|
public Chronoshiftable(Actor self) { }
|
||||||
|
|
||||||
|
public void Tick(Actor self)
|
||||||
|
{
|
||||||
|
if (chronoshiftReturnTicks <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (chronoshiftReturnTicks > 0)
|
||||||
|
chronoshiftReturnTicks--;
|
||||||
|
|
||||||
|
// Return to original location
|
||||||
|
if (chronoshiftReturnTicks == 0)
|
||||||
|
{
|
||||||
|
self.CancelActivity();
|
||||||
|
// Todo: need a new Teleport method that will move to the closest available cell
|
||||||
|
self.QueueActivity(new Activities.Teleport(chronoshiftOrigin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||||
|
{
|
||||||
|
return null; // Chronoshift order is issued through Chrome.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResolveOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
if (order.OrderString == "ChronosphereSelect")
|
||||||
|
{
|
||||||
|
Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
var movement = self.traits.WithInterface<IMovement>().FirstOrDefault();
|
||||||
|
if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation))
|
||||||
|
{
|
||||||
|
|
||||||
|
// Set up return-to-sender info
|
||||||
|
chronoshiftOrigin = self.Location;
|
||||||
|
chronoshiftReturnTicks = (int)(Rules.General.ChronoDuration * 60 * 25);
|
||||||
|
|
||||||
|
// TODO: Kill cargo if Rules.General.ChronoKillCargo says so
|
||||||
|
|
||||||
|
// Set up the teleport
|
||||||
|
Game.controller.CancelInputMode();
|
||||||
|
self.CancelActivity();
|
||||||
|
self.QueueActivity(new Activities.Teleport(order.TargetLocation));
|
||||||
|
Sound.Play("chrono2.aud");
|
||||||
|
|
||||||
|
foreach (var a in Game.world.Actors.Where(a => a.traits.Contains<ChronoshiftPaletteEffect>()))
|
||||||
|
a.traits.Get<ChronoshiftPaletteEffect>().DoChronoshift();
|
||||||
|
|
||||||
|
// Play chronosphere active anim
|
||||||
|
var chronosphere = Game.world.Actors.Where(a => a.Owner == order.Subject.Owner && a.traits.Contains<Chronosphere>()).FirstOrDefault();
|
||||||
|
if (chronosphere != null)
|
||||||
|
chronosphere.traits.Get<RenderBuilding>().PlayCustomAnim(chronosphere, "active");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetSpeedModifier()
|
||||||
|
{
|
||||||
|
// ARGH! You must not do this, it will desync!
|
||||||
|
return (Game.controller.orderGenerator is ChronoshiftDestinationOrderGenerator) ? 0f : 1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
OpenRa.Game/Traits/Chronosphere.cs
Normal file
12
OpenRa.Game/Traits/Chronosphere.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OpenRa.Game.Traits
|
||||||
|
{
|
||||||
|
class Chronosphere
|
||||||
|
{
|
||||||
|
public Chronosphere(Actor self) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
59
OpenRa.Game/Traits/DemoTruck.cs
Normal file
59
OpenRa.Game/Traits/DemoTruck.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using OpenRa.Game.Effects;
|
||||||
|
using OpenRa.Game.Traits;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRa.Game.Orders;
|
||||||
|
|
||||||
|
namespace OpenRa.Game.Traits
|
||||||
|
{
|
||||||
|
class DemoTruck : IOrder, ISpeedModifier, INotifyDamage, IChronoshiftable
|
||||||
|
{
|
||||||
|
readonly Actor self;
|
||||||
|
public DemoTruck(Actor self)
|
||||||
|
{
|
||||||
|
this.self = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire primary on Chronoshift
|
||||||
|
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||||
|
{
|
||||||
|
return null; // Chronoshift order is issued through Chrome.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResolveOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
if (order.OrderString == "ChronosphereSelect")
|
||||||
|
Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(self);
|
||||||
|
|
||||||
|
var movement = self.traits.WithInterface<IMovement>().FirstOrDefault();
|
||||||
|
var chronosphere = Game.world.Actors.Where(a => a.Owner == order.Subject.Owner && a.traits.Contains<Chronosphere>()).FirstOrDefault();
|
||||||
|
if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation))
|
||||||
|
self.InflictDamage(chronosphere, self.Health, Rules.WarheadInfo["Super"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire primary on death
|
||||||
|
public void Damaged(Actor self, AttackInfo e)
|
||||||
|
{
|
||||||
|
if (e.DamageState == DamageState.Dead)
|
||||||
|
Detonate(self, e.Attacker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Detonate(Actor self, Actor detonatedBy)
|
||||||
|
{
|
||||||
|
self.InflictDamage(detonatedBy, self.Health, Rules.WarheadInfo["Super"]);
|
||||||
|
var unit = self.traits.GetOrDefault<Unit>();
|
||||||
|
var altitude = unit != null ? unit.Altitude : 0;
|
||||||
|
int2 detonateLocation = self.CenterLocation.ToInt2();
|
||||||
|
|
||||||
|
Game.world.AddFrameEndTask(
|
||||||
|
w => w.Add(new Bullet(self.Info.Primary, detonatedBy.Owner, detonatedBy,
|
||||||
|
detonateLocation, detonateLocation, altitude, altitude)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetSpeedModifier()
|
||||||
|
{
|
||||||
|
// ARGH! You must not do this, it will desync!
|
||||||
|
return (Game.controller.orderGenerator is ChronoshiftDestinationOrderGenerator) ? 0f : 1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -57,7 +57,7 @@ namespace OpenRa.Game.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<PipType> GetPips()
|
public IEnumerable<PipType> GetPips(Actor self)
|
||||||
{
|
{
|
||||||
const int numPips = 7;
|
const int numPips = 7;
|
||||||
for (int i = 0; i < numPips; i++)
|
for (int i = 0; i < numPips; i++)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace OpenRa.Game.Traits
|
|||||||
|
|
||||||
public void Attacking(Actor self) { --ammo; }
|
public void Attacking(Actor self) { --ammo; }
|
||||||
|
|
||||||
public IEnumerable<PipType> GetPips()
|
public IEnumerable<PipType> GetPips(Actor self)
|
||||||
{
|
{
|
||||||
return Graphics.Util.MakeArray(self.Info.Ammo,
|
return Graphics.Util.MakeArray(self.Info.Ammo,
|
||||||
i => ammo > i ? PipType.Green : PipType.Transparent);
|
i => ammo > i ? PipType.Green : PipType.Transparent);
|
||||||
|
|||||||
@@ -18,7 +18,16 @@ namespace OpenRa.Game.Traits
|
|||||||
public int2 toCell
|
public int2 toCell
|
||||||
{
|
{
|
||||||
get { return self.Location; }
|
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)
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
OpenRa.Game/Traits/ProvidesRadar.cs
Normal file
28
OpenRa.Game/Traits/ProvidesRadar.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OpenRa.Game.Traits
|
||||||
|
{
|
||||||
|
class ProvidesRadar
|
||||||
|
{
|
||||||
|
Actor self;
|
||||||
|
public ProvidesRadar(Actor self)
|
||||||
|
{
|
||||||
|
this.self = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsActive()
|
||||||
|
{
|
||||||
|
// TODO: Check for nearby MRJ
|
||||||
|
|
||||||
|
// Check if powered
|
||||||
|
var b = self.traits.Get<Building>();
|
||||||
|
if (b != null && b.InsuffientPower())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ namespace OpenRa.Game.Traits
|
|||||||
this.self = self;
|
this.self = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<PipType> GetPips()
|
public IEnumerable<PipType> GetPips(Actor self)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < self.Info.OrePips; i++)
|
for (int i = 0; i < self.Info.OrePips; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace OpenRa.Game.Traits
|
|||||||
interface IDamageModifier { float GetDamageModifier(); }
|
interface IDamageModifier { float GetDamageModifier(); }
|
||||||
interface ISpeedModifier { float GetSpeedModifier(); }
|
interface ISpeedModifier { float GetSpeedModifier(); }
|
||||||
interface IPaletteModifier { void AdjustPalette(Bitmap b); }
|
interface IPaletteModifier { void AdjustPalette(Bitmap b); }
|
||||||
interface IPips { IEnumerable<PipType> GetPips(); }
|
interface IPips { IEnumerable<PipType> GetPips(Actor self); }
|
||||||
interface ITags { IEnumerable<TagType> GetTags(); }
|
interface ITags { IEnumerable<TagType> GetTags(); }
|
||||||
interface IMovement
|
interface IMovement
|
||||||
{
|
{
|
||||||
@@ -43,7 +43,7 @@ namespace OpenRa.Game.Traits
|
|||||||
bool IsCrushableBy(UnitMovementType umt, Player player);
|
bool IsCrushableBy(UnitMovementType umt, Player player);
|
||||||
bool IsPathableCrush(UnitMovementType umt, Player player);
|
bool IsPathableCrush(UnitMovementType umt, Player player);
|
||||||
}
|
}
|
||||||
|
interface IChronoshiftable{}
|
||||||
struct Renderable
|
struct Renderable
|
||||||
{
|
{
|
||||||
public readonly Sprite Sprite;
|
public readonly Sprite Sprite;
|
||||||
|
|||||||
@@ -10,8 +10,19 @@ namespace OpenRa.Game
|
|||||||
List<IEffect> effects = new List<IEffect>();
|
List<IEffect> effects = new List<IEffect>();
|
||||||
List<Action<World>> frameEndActions = new List<Action<World>>();
|
List<Action<World>> frameEndActions = new List<Action<World>>();
|
||||||
|
|
||||||
public void Add(Actor a) { actors.Add(a); ActorAdded(a); }
|
public void Add(Actor a)
|
||||||
public void Remove(Actor a) { actors.Remove(a); ActorRemoved(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 Add(IEffect b) { effects.Add(b); }
|
||||||
public void Remove(IEffect b) { effects.Remove(b); }
|
public void Remove(IEffect b) { effects.Remove(b); }
|
||||||
|
|||||||
@@ -83,7 +83,8 @@ namespace SequenceEditor
|
|||||||
Doc = new XmlDocument();
|
Doc = new XmlDocument();
|
||||||
Doc.Load(XmlFilename);
|
Doc.Load(XmlFilename);
|
||||||
|
|
||||||
Pal = new Palette(FileSystem.Open("temperat.pal"));
|
var tempPal = new Palette(FileSystem.Open("temperat.pal"));
|
||||||
|
Pal = tempPal; //new Palette(tempPal, new ShroudPaletteRemap());
|
||||||
|
|
||||||
UnitName = args.FirstOrDefault( x => !x.EndsWith(".xml") );
|
UnitName = args.FirstOrDefault( x => !x.EndsWith(".xml") );
|
||||||
if (UnitName == null)
|
if (UnitName == null)
|
||||||
|
|||||||
@@ -7,28 +7,28 @@ QTNK
|
|||||||
|
|
||||||
[STNK]
|
[STNK]
|
||||||
Description=Stealth Tank
|
Description=Stealth Tank
|
||||||
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, Cloak
|
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, Cloak, Chronoshiftable
|
||||||
Recoil=2
|
Recoil=2
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
|
|
||||||
[TTNK]
|
[TTNK]
|
||||||
Description=Tesla Tank
|
Description=Tesla Tank
|
||||||
Traits=Unit, Mobile, AttackBase, RenderUnitSpinner
|
Traits=Unit, Mobile, AttackBase, RenderUnitSpinner, Chronoshiftable
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
|
|
||||||
[CTNK]
|
[CTNK]
|
||||||
Description=Chrono Tank
|
Description=Chrono Tank
|
||||||
Traits=Unit, Mobile, AttackBase, RenderUnit, ChronoshiftDeploy
|
Traits=Unit, Mobile, AttackBase, RenderUnit, ChronoshiftDeploy, Chronoshiftable
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
|
|
||||||
[DTRK]
|
[DTRK]
|
||||||
Description=Demo Truck
|
Description=Demo Truck
|
||||||
Traits=Unit, Mobile, AttackBase, RenderUnit
|
Traits=Unit, Mobile, AttackBase, RenderUnit, DemoTruck
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
|
|
||||||
[QTNK]
|
[QTNK]
|
||||||
Description=M.A.D. Tank
|
Description=M.A.D. Tank
|
||||||
Traits=Unit, Mobile, RenderUnit
|
Traits=Unit, Mobile, RenderUnit, Chronoshiftable
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
|
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ MSUB
|
|||||||
Description=Missile Submarine
|
Description=Missile Submarine
|
||||||
WaterBound=yes
|
WaterBound=yes
|
||||||
BuiltAt=spen
|
BuiltAt=spen
|
||||||
Traits=Unit, Mobile, AttackBase, RenderUnit, Submarine
|
Traits=Unit, Mobile, AttackBase, RenderUnit, Submarine, Chronoshiftable
|
||||||
FireDelay=2
|
FireDelay=2
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ All tracked vehicles
|
|||||||
|
|
||||||
Light vehicles
|
Light vehicles
|
||||||
V2RL Works
|
V2RL Works
|
||||||
APC Cargo doesn't work
|
APC Works
|
||||||
MNLY Works
|
MNLY Works
|
||||||
MGG No gap
|
MGG No gap
|
||||||
MRJ No radar
|
MRJ No radar
|
||||||
@@ -31,8 +31,7 @@ HARV Works
|
|||||||
ARTY Works
|
ARTY Works
|
||||||
|
|
||||||
Helicopters
|
Helicopters
|
||||||
- Return to base after attack doesnt work
|
TRAN Works
|
||||||
TRAN Cargo doesn't work
|
|
||||||
HELI Works
|
HELI Works
|
||||||
HIND Works
|
HIND Works
|
||||||
|
|
||||||
@@ -47,5 +46,5 @@ CA Works
|
|||||||
SS Works
|
SS Works
|
||||||
DD depth charges don't work
|
DD depth charges don't work
|
||||||
PT depth charges don't work
|
PT depth charges don't work
|
||||||
LST Cargo doesn't work
|
LST Works
|
||||||
|
|
||||||
|
|||||||
@@ -283,6 +283,8 @@
|
|||||||
<unit name="apc">
|
<unit name="apc">
|
||||||
<sequence name="idle" start="0" length="32" />
|
<sequence name="idle" start="0" length="32" />
|
||||||
<sequence name="muzzle" start="0" length="48" src="minigun" />
|
<sequence name="muzzle" start="0" length="48" src="minigun" />
|
||||||
|
<sequence name="close" start="32" length="3" />
|
||||||
|
<sequence name="unload" start="32" length="1" />
|
||||||
</unit>
|
</unit>
|
||||||
<!-- mine layer -->
|
<!-- mine layer -->
|
||||||
<unit name="mnly">
|
<unit name="mnly">
|
||||||
@@ -368,7 +370,7 @@
|
|||||||
<sequence name="move" start="10" length="4" x="12" y="12" />
|
<sequence name="move" start="10" length="4" x="12" y="12" />
|
||||||
<sequence name="move-blocked" start="14" x="12" y="12" />
|
<sequence name="move-blocked" start="14" x="12" y="12" />
|
||||||
<sequence name="select" start="15" length="6" x="12" y="12" />
|
<sequence name="select" start="15" length="6" x="12" y="12" />
|
||||||
<sequence name="attack" start="21" length="8" x="12" y="12" />
|
<sequence name="attackmove" start="21" length="8" x="12" y="12" />
|
||||||
<sequence name="move-minimap" start="29" length="6" />
|
<sequence name="move-minimap" start="29" length="6" />
|
||||||
<sequence name="repair" start="35" length="24" />
|
<sequence name="repair" start="35" length="24" />
|
||||||
<sequence name="deploy" start="59" length="9" x="12" y="12" />
|
<sequence name="deploy" start="59" length="9" x="12" y="12" />
|
||||||
@@ -376,14 +378,15 @@
|
|||||||
<sequence name="default-minimap" start="80" length="1" />
|
<sequence name="default-minimap" start="80" length="1" />
|
||||||
<sequence name="ability" start="82" length="8" />
|
<sequence name="ability" start="82" length="8" />
|
||||||
<sequence name="nuke" start="90" length="7" x="12" y="12" />
|
<sequence name="nuke" start="90" length="7" x="12" y="12" />
|
||||||
<sequence name="chrono" start="105" length="8" x="12" y="12" />
|
<sequence name="chrono-select" start="97" length="8" x="12" y="12" />
|
||||||
|
<sequence name="chrono-target" start="105" length="8" x="12" y="12" />
|
||||||
<sequence name="enter" start="113" length="3" x="12" y="12" />
|
<sequence name="enter" start="113" length="3" x="12" y="12" />
|
||||||
<sequence name="c4" start="116" length="3" x="12" y="12" />
|
<sequence name="c4" start="116" length="3" x="12" y="12" />
|
||||||
<sequence name="sell-blocked" start="119" length="1" x="12" y="12" />
|
<sequence name="sell-blocked" start="119" length="1" x="12" y="12" />
|
||||||
<sequence name="repair-blocked" start="120" length="1" />
|
<sequence name="repair-blocked" start="120" length="1" />
|
||||||
<sequence name="c4-minimap" start="121" length="3" />
|
<sequence name="c4-minimap" start="121" length="3" />
|
||||||
<sequence name="scroll-blocked" start="124" length="8" />
|
<sequence name="scroll-blocked" start="124" length="8" />
|
||||||
<sequence name="attack-minimap" start="134" length="8" />
|
<sequence name="attackmove-minimap" start="134" length="8" />
|
||||||
<sequence name="enter-minimap" start="142" length="3" />
|
<sequence name="enter-minimap" start="142" length="3" />
|
||||||
<sequence name="guard-minimap" start="146" length="1" />
|
<sequence name="guard-minimap" start="146" length="1" />
|
||||||
<sequence name="guard" start="147" length="1" x="12" y="12" />
|
<sequence name="guard" start="147" length="1" x="12" y="12" />
|
||||||
@@ -393,13 +396,19 @@
|
|||||||
<sequence name="capture-minimap" start="167" length="3" />
|
<sequence name="capture-minimap" start="167" length="3" />
|
||||||
<sequence name="repair2" start="170" length="24" />
|
<sequence name="repair2" start="170" length="24" />
|
||||||
<sequence name="heal-minimap" start="194" length="1" />
|
<sequence name="heal-minimap" start="194" length="1" />
|
||||||
<sequence name="attack2" start="195" length="8" x="12" y="12" />
|
<sequence name="attack" start="195" length="8" x="12" y="12" />
|
||||||
<sequence name="attack2-minimap" start="203" length="8" />
|
<sequence name="attack-minimap" start="203" length="8" />
|
||||||
<sequence name="deploy-blocked" start="211" length="1" x="12" y="12" />
|
<sequence name="deploy-blocked" start="211" length="1" x="12" y="12" />
|
||||||
<sequence name="enter-blocked" start="212" length="1" />
|
<sequence name="enter-blocked" start="212" length="1" />
|
||||||
<sequence name="repair2-blocked" start="213" length="1" />
|
<sequence name="repair2-blocked" start="213" length="1" />
|
||||||
<sequence name="ability-minimap" start="214" length="8" />
|
<sequence name="ability-minimap" start="214" length="8" />
|
||||||
</cursor>
|
</cursor>
|
||||||
|
<cursor src="speed">
|
||||||
|
<sequence name="powerdown" start="3" length="12" />
|
||||||
|
</cursor>
|
||||||
|
<unit name="powerdown">
|
||||||
|
<sequence name="disabled" start="3" length="1" src="speed" />
|
||||||
|
</unit>
|
||||||
<unit name="120mm">
|
<unit name="120mm">
|
||||||
<sequence name="idle" start="0" length="1" />
|
<sequence name="idle" start="0" length="1" />
|
||||||
</unit>
|
</unit>
|
||||||
@@ -535,6 +544,8 @@
|
|||||||
</unit>
|
</unit>
|
||||||
<unit name="lst">
|
<unit name="lst">
|
||||||
<sequence name="idle" start="0" length="1" />
|
<sequence name="idle" start="0" length="1" />
|
||||||
|
<sequence name="open" start="1" length="4" />
|
||||||
|
<sequence name="unload" start="4" length="1" />
|
||||||
</unit>
|
</unit>
|
||||||
<unit name="pips">
|
<unit name="pips">
|
||||||
<sequence name="groups" start="8" length="10" />
|
<sequence name="groups" start="8" length="10" />
|
||||||
@@ -571,6 +582,8 @@
|
|||||||
<sequence name="rotor2" start="0" length="4" src="rrotor" />
|
<sequence name="rotor2" start="0" length="4" src="rrotor" />
|
||||||
<sequence name="slow-rotor" start="4" length="8" src="lrotor" />
|
<sequence name="slow-rotor" start="4" length="8" src="lrotor" />
|
||||||
<sequence name="slow-rotor2" start="4" length="8" src="rrotor" />
|
<sequence name="slow-rotor2" start="4" length="8" src="rrotor" />
|
||||||
|
<sequence name="open" start="32" length="4" />
|
||||||
|
<sequence name="unload" start="35" length="1" />
|
||||||
</unit>
|
</unit>
|
||||||
<unit name="v2">
|
<unit name="v2">
|
||||||
<sequence name="idle" start="0" length="32" />
|
<sequence name="idle" start="0" length="32" />
|
||||||
@@ -1007,8 +1020,8 @@
|
|||||||
<sequence name="disabled" start="2" length="1" />
|
<sequence name="disabled" start="2" length="1" />
|
||||||
</unit>
|
</unit>
|
||||||
<unit name="sell">
|
<unit name="sell">
|
||||||
<sequence name="normal" start="0" length="1" />
|
<sequence name="normal" start="0" length="1" />
|
||||||
<sequence name="pressed" start="1" length="1" />
|
<sequence name="pressed" start="1" length="1" />
|
||||||
<sequence name="disabled" start="2" length="1" />
|
<sequence name="disabled" start="2" length="1" />
|
||||||
</unit>
|
</unit>
|
||||||
</sequences>
|
</sequences>
|
||||||
@@ -8,4 +8,6 @@ s0=Multi0,mcv,600,2841,0,Guard,None
|
|||||||
s1=Multi2,mcv,600,12445,0,Guard,None
|
s1=Multi2,mcv,600,12445,0,Guard,None
|
||||||
s2=Multi1,mcv,600,12505,0,Guard,None
|
s2=Multi1,mcv,600,12505,0,Guard,None
|
||||||
;s2=Multi1,e3,600,12505,0,Guard,None
|
;s2=Multi1,e3,600,12505,0,Guard,None
|
||||||
s3=Multi3,mcv,600,2910,0,Guard,None
|
s3=Multi3,mcv,600,2910,0,Guard,None
|
||||||
|
;s4=Multi1,ctnk,600,12506,Gaurd,None
|
||||||
|
s5=Multi1,apc,600,12510,Gaurd,None
|
||||||
4
settings-netplay-local-aftermath.ini
Normal file
4
settings-netplay-local-aftermath.ini
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[Settings]
|
||||||
|
NetworkHost=localhost
|
||||||
|
NetworkPort=1234
|
||||||
|
UseAftermath=yes
|
||||||
3
settings-netplay-local.ini
Normal file
3
settings-netplay-local.ini
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[Settings]
|
||||||
|
NetworkHost=localhost
|
||||||
|
NetworkPort=1234
|
||||||
68
units.ini
68
units.ini
@@ -16,89 +16,91 @@ MNLY.AT
|
|||||||
|
|
||||||
[V2RL]
|
[V2RL]
|
||||||
Description=V2 Rocket
|
Description=V2 Rocket
|
||||||
Traits=Unit, Mobile, AttackBase, RenderUnitReload, AutoTarget, Repairable
|
Traits=Unit, Mobile, AttackBase, RenderUnitReload, AutoTarget, Repairable, Chronoshiftable, Passenger
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Long-range rocket artillery.\n Strong vs Infantry, Buildings\n Weak vs Tanks, Aircraft
|
LongDesc=Long-range rocket artillery.\n Strong vs Infantry, Buildings\n Weak vs Tanks, Aircraft
|
||||||
[1TNK]
|
[1TNK]
|
||||||
Description=Light Tank
|
Description=Light Tank
|
||||||
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable
|
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable, Passenger
|
||||||
Recoil=2
|
Recoil=2
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Light Tank, good for scouting.\n Strong vs Light Vehicles\n Weak vs Tanks, Aircraft
|
LongDesc=Light Tank, good for scouting.\n Strong vs Light Vehicles\n Weak vs Tanks, Aircraft
|
||||||
[2TNK]
|
[2TNK]
|
||||||
Description=Medium Tank
|
Description=Medium Tank
|
||||||
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable
|
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable, Passenger
|
||||||
Recoil=3
|
Recoil=3
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Allied Main Battle Tank.\n Strong vs Tanks, Light Vehicles\n Weak vs Infantry, Aircraft
|
LongDesc=Allied Main Battle Tank.\n Strong vs Tanks, Light Vehicles\n Weak vs Infantry, Aircraft
|
||||||
[3TNK]
|
[3TNK]
|
||||||
Description=Heavy Tank
|
Description=Heavy Tank
|
||||||
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable
|
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable, Passenger
|
||||||
Recoil=3
|
Recoil=3
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Soviet Main Battle Tank, with dual cannons\n Strong vs Tanks, Light Vehicles\n Weak vs Infantry, Aircraft
|
LongDesc=Soviet Main Battle Tank, with dual cannons\n Strong vs Tanks, Light Vehicles\n Weak vs Infantry, Aircraft
|
||||||
[4TNK]
|
[4TNK]
|
||||||
Description=Mammoth Tank
|
Description=Mammoth Tank
|
||||||
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable
|
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable, Passenger
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Big and slow tank, with anti-air capability.\n Strong vs Tanks, Aircraft\n Weak vs Infantry
|
LongDesc=Big and slow tank, with anti-air capability.\n Strong vs Tanks, Aircraft\n Weak vs Infantry
|
||||||
[ARTY]
|
[ARTY]
|
||||||
Description=Artillery
|
Description=Artillery
|
||||||
Traits=Unit, Mobile, AttackBase, RenderUnit, Explodes, AutoTarget, Repairable
|
Traits=Unit, Mobile, AttackBase, RenderUnit, Explodes, AutoTarget, Repairable, Chronoshiftable, Passenger
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Long-range artillery.\n Strong vs Infantry, Buildings\n Weak vs Tanks, Aircraft
|
LongDesc=Long-range artillery.\n Strong vs Infantry, Buildings\n Weak vs Tanks, Aircraft
|
||||||
[JEEP]
|
[JEEP]
|
||||||
Description=Ranger
|
Description=Ranger
|
||||||
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable
|
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable, Passenger
|
||||||
PrimaryOffset=0,0,0,-2
|
PrimaryOffset=0,0,0,-2
|
||||||
MuzzleFlash=yes
|
MuzzleFlash=yes
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Fast scout & anti-infantry vehicle.\n Strong vs Infantry\n Weak vs Tanks, Aircraft
|
LongDesc=Fast scout & anti-infantry vehicle.\n Strong vs Infantry\n Weak vs Tanks, Aircraft
|
||||||
[APC]
|
[APC]
|
||||||
Description=Armored Personnel Carrier
|
Description=Armored Personnel Carrier
|
||||||
Traits=Unit, Mobile, AttackBase, RenderUnitMuzzleFlash, AutoTarget, Repairable
|
Traits=Unit, Mobile, AttackBase, RenderUnitMuzzleFlash, AutoTarget, Repairable, Chronoshiftable, Cargo, Passenger
|
||||||
PrimaryOffset=0,0,0,-4
|
PrimaryOffset=0,0,0,-4
|
||||||
MuzzleFlash=yes
|
MuzzleFlash=yes
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Tough infantry transport.\n Strong vs Infantry, Light Vehicles\n Weak vs Tanks, Aircraft
|
LongDesc=Tough infantry transport.\n Strong vs Infantry, Light Vehicles\n Weak vs Tanks, Aircraft
|
||||||
|
UnloadFacing=220
|
||||||
|
PassengerTypes=Foot
|
||||||
|
|
||||||
;; non-combat vehicles
|
;; non-combat vehicles
|
||||||
[MRJ]
|
[MRJ]
|
||||||
Description=Radar Jammer
|
Description=Radar Jammer
|
||||||
Traits=Unit, Mobile, RenderUnitSpinner, Repairable
|
Traits=Unit, Mobile, RenderUnitSpinner, Repairable, Chronoshiftable, Passenger
|
||||||
PrimaryOffset=0,4,0,-6
|
PrimaryOffset=0,4,0,-6
|
||||||
SelectionPriority=3
|
SelectionPriority=3
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Hides nearby units on the enemy's minimap.\n Unarmed
|
LongDesc=Hides nearby units on the enemy's minimap.\n Unarmed
|
||||||
[MGG]
|
[MGG]
|
||||||
Description=Mobile Gap Generator
|
Description=Mobile Gap Generator
|
||||||
Traits=Unit, Mobile, RenderUnitSpinner, Repairable
|
Traits=Unit, Mobile, RenderUnitSpinner, Repairable, Chronoshiftable, Passenger
|
||||||
PrimaryOffset=0,6,0,-3
|
PrimaryOffset=0,6,0,-3
|
||||||
SelectionPriority=3
|
SelectionPriority=3
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Regenerates Fog of War in a small area \naround the unit.\n Unarmed
|
LongDesc=Regenerates Fog of War in a small area \naround the unit.\n Unarmed
|
||||||
[HARV]
|
[HARV]
|
||||||
Description=Ore Truck
|
Description=Ore Truck
|
||||||
Traits=Harvester, Unit, Mobile, RenderUnit, Repairable
|
Traits=Harvester, Unit, Mobile, RenderUnit, Repairable, Chronoshiftable, Passenger
|
||||||
SelectionPriority=7
|
SelectionPriority=7
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Collects Ore and Gems for processing.\n Unarmed
|
LongDesc=Collects Ore and Gems for processing.\n Unarmed
|
||||||
[MCV]
|
[MCV]
|
||||||
Description=Mobile Construction Vehicle
|
Description=Mobile Construction Vehicle
|
||||||
Traits=Unit, Mobile, McvDeploy, RenderUnit, Repairable
|
Traits=Unit, Mobile, McvDeploy, RenderUnit, Repairable, Chronoshiftable, Passenger
|
||||||
SelectionPriority=3
|
SelectionPriority=3
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Deploys into another Construction Yard.\n Unarmed
|
LongDesc=Deploys into another Construction Yard.\n Unarmed
|
||||||
|
|
||||||
[MNLY.AP]
|
[MNLY.AP]
|
||||||
Description=Minelayer (Anti-Personnel)
|
Description=Minelayer (Anti-Personnel)
|
||||||
Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune, Repairable, LimitedAmmo
|
Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune, Repairable, LimitedAmmo, Chronoshiftable, Passenger
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Lays mines to destroy unwary enemy units.\n Unarmed
|
LongDesc=Lays mines to destroy unwary enemy units.\n Unarmed
|
||||||
Primary=MINP ;; temporary hack
|
Primary=MINP ;; temporary hack
|
||||||
[MNLY.AT]
|
[MNLY.AT]
|
||||||
Description=Minelayer (Anti-Tank)
|
Description=Minelayer (Anti-Tank)
|
||||||
Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune, Repairable, LimitedAmmo
|
Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune, Repairable, LimitedAmmo, Chronoshiftable, Passenger
|
||||||
Voice=VehicleVoice
|
Voice=VehicleVoice
|
||||||
LongDesc=Lays mines to destroy unwary enemy units.\n Unarmed
|
LongDesc=Lays mines to destroy unwary enemy units.\n Unarmed
|
||||||
Primary=MINV ;; temporary hack
|
Primary=MINV ;; temporary hack
|
||||||
@@ -116,21 +118,21 @@ PT
|
|||||||
Description=Submarine
|
Description=Submarine
|
||||||
WaterBound=yes
|
WaterBound=yes
|
||||||
BuiltAt=spen
|
BuiltAt=spen
|
||||||
Traits=Unit, Mobile, RenderUnit, Submarine, AttackBase
|
Traits=Unit, Mobile, RenderUnit, Submarine, AttackBase, Chronoshiftable
|
||||||
FireDelay=2
|
FireDelay=2
|
||||||
LongDesc=Submerged anti-ship unit armed with \ntorpedoes.\n Strong vs Ships\n Weak vs Everything\n Special Ability: Submerge
|
LongDesc=Submerged anti-ship unit armed with \ntorpedoes.\n Strong vs Ships\n Weak vs Everything\n Special Ability: Submerge
|
||||||
[DD]
|
[DD]
|
||||||
Description=Destroyer
|
Description=Destroyer
|
||||||
WaterBound=yes
|
WaterBound=yes
|
||||||
BuiltAt=syrd
|
BuiltAt=syrd
|
||||||
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget
|
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Chronoshiftable
|
||||||
PrimaryOffset=0,-8,0,-3
|
PrimaryOffset=0,-8,0,-3
|
||||||
LongDesc=Fast multi-role ship. \n Strong vs Submarines, Aircraft\n Weak vs Infantry, Tanks
|
LongDesc=Fast multi-role ship. \n Strong vs Submarines, Aircraft\n Weak vs Infantry, Tanks
|
||||||
[CA]
|
[CA]
|
||||||
Description=Cruiser
|
Description=Cruiser
|
||||||
WaterBound=yes
|
WaterBound=yes
|
||||||
BuiltAt=syrd
|
BuiltAt=syrd
|
||||||
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget
|
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Chronoshiftable
|
||||||
PrimaryOffset=0,17,0,-2
|
PrimaryOffset=0,17,0,-2
|
||||||
SecondaryOffset=0,-17,0,-2
|
SecondaryOffset=0,-17,0,-2
|
||||||
LongDesc=Very slow long-range ship. \n Strong vs Buildings\n Weak vs Ships, Submarines
|
LongDesc=Very slow long-range ship. \n Strong vs Buildings\n Weak vs Ships, Submarines
|
||||||
@@ -138,13 +140,14 @@ Recoil=3
|
|||||||
[LST]
|
[LST]
|
||||||
Description=Transport
|
Description=Transport
|
||||||
WaterBound=yes
|
WaterBound=yes
|
||||||
Traits=Unit, Mobile, RenderUnit
|
Traits=Unit, Mobile, RenderUnit, Cargo
|
||||||
LongDesc=General-purpose naval transport.\nCan carry infantry and tanks.\n Unarmed
|
LongDesc=General-purpose naval transport.\nCan carry infantry and tanks.\n Unarmed
|
||||||
|
PassengerTypes=Foot,Wheel,Track
|
||||||
[PT]
|
[PT]
|
||||||
Description=Gunboat
|
Description=Gunboat
|
||||||
WaterBound=yes
|
WaterBound=yes
|
||||||
BuiltAt=syrd
|
BuiltAt=syrd
|
||||||
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget
|
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Chronoshiftable
|
||||||
PrimaryOffset=0,-6,0,-1
|
PrimaryOffset=0,-6,0,-1
|
||||||
LongDesc=Light scout & support ship. \n Strong vs Ships, Submarines\n Weak vs Aircraft
|
LongDesc=Light scout & support ship. \n Strong vs Ships, Submarines\n Weak vs Aircraft
|
||||||
|
|
||||||
@@ -179,9 +182,10 @@ Description=Transport Helicopter
|
|||||||
RotorOffset=0,14,0,-4
|
RotorOffset=0,14,0,-4
|
||||||
RotorOffset2=0,-14,0,-2
|
RotorOffset2=0,-14,0,-2
|
||||||
BuiltAt=hpad
|
BuiltAt=hpad
|
||||||
Traits=Unit, Helicopter, RenderUnitRotor, WithShadow
|
Traits=Unit, Helicopter, RenderUnitRotor, WithShadow, Cargo
|
||||||
InitialFacing=20
|
InitialFacing=20
|
||||||
LongDesc=Fast Infantry Transport Helicopter.\n Unarmed
|
LongDesc=Fast Infantry Transport Helicopter.\n Unarmed
|
||||||
|
PassengerTypes=Foot
|
||||||
[HELI]
|
[HELI]
|
||||||
Description=Longbow
|
Description=Longbow
|
||||||
BuiltAt=hpad
|
BuiltAt=hpad
|
||||||
@@ -289,7 +293,7 @@ SelectionPriority=3
|
|||||||
LongDesc=Makes a group of units invulnerable for a \nshort time.\n Special Ability: Invulnerability
|
LongDesc=Makes a group of units invulnerable for a \nshort time.\n Special Ability: Invulnerability
|
||||||
[PDOX]
|
[PDOX]
|
||||||
Description=Chronosphere
|
Description=Chronosphere
|
||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding, Chronosphere
|
||||||
Dimensions=2,2
|
Dimensions=2,2
|
||||||
Footprint=xx xx
|
Footprint=xx xx
|
||||||
SelectionPriority=3
|
SelectionPriority=3
|
||||||
@@ -407,7 +411,7 @@ SpawnOffset=0,-4
|
|||||||
LongDesc=Produces and reloads helicopters
|
LongDesc=Produces and reloads helicopters
|
||||||
[DOME]
|
[DOME]
|
||||||
Description=Radar Dome
|
Description=Radar Dome
|
||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding, ProvidesRadar
|
||||||
Dimensions=2,2
|
Dimensions=2,2
|
||||||
Footprint=xx xx
|
Footprint=xx xx
|
||||||
SelectionPriority=3
|
SelectionPriority=3
|
||||||
@@ -544,62 +548,62 @@ MEDI
|
|||||||
Description=Attack Dog
|
Description=Attack Dog
|
||||||
BuiltAt=KENN
|
BuiltAt=KENN
|
||||||
Voice=DogVoice
|
Voice=DogVoice
|
||||||
Traits=Unit, Mobile, RenderInfantry ;; AttackBase, SquishByTank, AutoTarget, dog??
|
Traits=Unit, Mobile, RenderInfantry, Passenger ;; AttackBase, SquishByTank, AutoTarget, dog??
|
||||||
LongDesc=Anti-infantry unit. Not fooled by the \nSpy's disguise.\n Strong vs Infantry\n Weak vs Vehicles
|
LongDesc=Anti-infantry unit. Not fooled by the \nSpy's disguise.\n Strong vs Infantry\n Weak vs Vehicles
|
||||||
SelectionSize=12,17,-1,-4
|
SelectionSize=12,17,-1,-4
|
||||||
[E1]
|
[E1]
|
||||||
Description=Rifle Infantry
|
Description=Rifle Infantry
|
||||||
Traits=Unit, Mobile, RenderInfantry, AttackBase, TakeCover, SquishByTank, AutoTarget
|
Traits=Unit, Mobile, RenderInfantry, AttackBase, TakeCover, SquishByTank, AutoTarget, Passenger
|
||||||
LongDesc=General-purpose infantry. Strong vs Infantry\n Weak vs Vehicles
|
LongDesc=General-purpose infantry. Strong vs Infantry\n Weak vs Vehicles
|
||||||
SelectionSize=12,17,0,-9
|
SelectionSize=12,17,0,-9
|
||||||
[E2]
|
[E2]
|
||||||
Description=Grenadier
|
Description=Grenadier
|
||||||
Traits=Unit, Mobile, RenderInfantry, AttackBase, TakeCover, SquishByTank, AutoTarget
|
Traits=Unit, Mobile, RenderInfantry, AttackBase, TakeCover, SquishByTank, AutoTarget, Passenger
|
||||||
FireDelay=15
|
FireDelay=15
|
||||||
PrimaryOffset=0,0,0,-13
|
PrimaryOffset=0,0,0,-13
|
||||||
LongDesc=Infantry armed with grenades. \n Strong vs Buildings, Infantry\n Weak vs Vehicles
|
LongDesc=Infantry armed with grenades. \n Strong vs Buildings, Infantry\n Weak vs Vehicles
|
||||||
SelectionSize=12,17,0,-9
|
SelectionSize=12,17,0,-9
|
||||||
[E3]
|
[E3]
|
||||||
Description=Rocket Soldier
|
Description=Rocket Soldier
|
||||||
Traits=Unit, Mobile, RenderInfantry, AttackBase, TakeCover, SquishByTank, AutoTarget
|
Traits=Unit, Mobile, RenderInfantry, AttackBase, TakeCover, SquishByTank, AutoTarget, Passenger
|
||||||
PrimaryOffset=0,0,0,-13
|
PrimaryOffset=0,0,0,-13
|
||||||
LongDesc=Anti-tank/Anti-aircraft infantry.\n Strong vs Tanks, Aircraft\n Weak vs Infantry
|
LongDesc=Anti-tank/Anti-aircraft infantry.\n Strong vs Tanks, Aircraft\n Weak vs Infantry
|
||||||
SelectionSize=12,17,0,-9
|
SelectionSize=12,17,0,-9
|
||||||
[E4]
|
[E4]
|
||||||
Description=Flamethrower
|
Description=Flamethrower
|
||||||
Traits=Unit, Mobile, RenderInfantry, AttackBase, TakeCover, SquishByTank, AutoTarget
|
Traits=Unit, Mobile, RenderInfantry, AttackBase, TakeCover, SquishByTank, AutoTarget, Passenger
|
||||||
FireDelay=8
|
FireDelay=8
|
||||||
PrimaryOffset=0,0,0,-7
|
PrimaryOffset=0,0,0,-7
|
||||||
LongDesc=Advanced Anti-infantry unit.\n Strong vs Infantry, Buildings\n Weak vs Vehicles
|
LongDesc=Advanced Anti-infantry unit.\n Strong vs Infantry, Buildings\n Weak vs Vehicles
|
||||||
SelectionSize=12,17,0,-9
|
SelectionSize=12,17,0,-9
|
||||||
[E6]
|
[E6]
|
||||||
Description=Engineer
|
Description=Engineer
|
||||||
Traits=Unit, Mobile, EngineerCapture, RenderInfantry, TakeCover, SquishByTank
|
Traits=Unit, Mobile, EngineerCapture, RenderInfantry, TakeCover, SquishByTank, Passenger
|
||||||
Voice=EngineerVoice
|
Voice=EngineerVoice
|
||||||
LongDesc=Infiltrates and captures enemy structures.\n Strong vs Nothing\n Weak vs Everything
|
LongDesc=Infiltrates and captures enemy structures.\n Strong vs Nothing\n Weak vs Everything
|
||||||
SelectionSize=12,17,0,-9
|
SelectionSize=12,17,0,-9
|
||||||
[SPY]
|
[SPY]
|
||||||
Description=Spy
|
Description=Spy
|
||||||
Voice=SpyVoice
|
Voice=SpyVoice
|
||||||
Traits=Unit, Mobile, RenderInfantry, TakeCover, SquishByTank
|
Traits=Unit, Mobile, RenderInfantry, TakeCover, SquishByTank, Passenger
|
||||||
LongDesc=Infiltrates enemy structures to gather \nintelligence. Exact effect depends on the \nbuilding infiltrated.\n Strong vs Nothing\n Weak vs Everything\n Special Ability: Disguised
|
LongDesc=Infiltrates enemy structures to gather \nintelligence. Exact effect depends on the \nbuilding infiltrated.\n Strong vs Nothing\n Weak vs Everything\n Special Ability: Disguised
|
||||||
SelectionSize=12,17,0,-9
|
SelectionSize=12,17,0,-9
|
||||||
[THF]
|
[THF]
|
||||||
Description=Thief
|
Description=Thief
|
||||||
Voice=ThiefVoice
|
Voice=ThiefVoice
|
||||||
Traits=Unit, Mobile, RenderInfantry, TakeCover, SquishByTank
|
Traits=Unit, Mobile, RenderInfantry, TakeCover, SquishByTank, Passenger
|
||||||
LongDesc=Infiltrates enemy refineries & \nsilos, and steals money stored there.\n Unarmed
|
LongDesc=Infiltrates enemy refineries & \nsilos, and steals money stored there.\n Unarmed
|
||||||
SelectionSize=12,17,0,-9
|
SelectionSize=12,17,0,-9
|
||||||
[E7]
|
[E7]
|
||||||
Description=Tanya
|
Description=Tanya
|
||||||
Voice=TanyaVoice
|
Voice=TanyaVoice
|
||||||
Traits=Unit, Mobile, RenderInfantry, C4Demolition, AttackBase, TakeCover, SquishByTank, AutoTarget
|
Traits=Unit, Mobile, RenderInfantry, C4Demolition, AttackBase, TakeCover, SquishByTank, AutoTarget, Passenger
|
||||||
LongDesc=Elite commando infantry, armed with \ndual pistols and C4.\n Strong vs Infantry, Buildings\n Weak vs Vehicles\n Special Ability: Destroy Building with C4
|
LongDesc=Elite commando infantry, armed with \ndual pistols and C4.\n Strong vs Infantry, Buildings\n Weak vs Vehicles\n Special Ability: Destroy Building with C4
|
||||||
SelectionSize=12,17,0,-9
|
SelectionSize=12,17,0,-9
|
||||||
[MEDI]
|
[MEDI]
|
||||||
Description=Medic
|
Description=Medic
|
||||||
Voice=MedicVoice
|
Voice=MedicVoice
|
||||||
Traits=Unit, Mobile, RenderInfantry, AutoHeal, AttackBase, TakeCover, SquishByTank
|
Traits=Unit, Mobile, RenderInfantry, AutoHeal, AttackBase, TakeCover, SquishByTank, Passenger
|
||||||
LongDesc=Heals nearby infantry.\n Strong vs Nothing\n Weak vs Everything
|
LongDesc=Heals nearby infantry.\n Strong vs Nothing\n Weak vs Everything
|
||||||
SelectionSize=12,17,0,-9
|
SelectionSize=12,17,0,-9
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user