Merge branch 'master' of git://github.com/chrisforbes/OpenRA

Conflicts:
	sequences.xml
This commit is contained in:
Paul Chote
2010-01-08 20:52:18 +13:00
17 changed files with 272 additions and 189 deletions

View File

@@ -29,6 +29,16 @@ namespace OpenRa.Game
readonly Animation pwrdownButton; readonly Animation pwrdownButton;
readonly Animation optionsButton; readonly Animation optionsButton;
readonly Sprite optionsTop;
readonly Sprite optionsBottom;
readonly Sprite optionsLeft;
readonly Sprite optionsRight;
readonly Sprite optionsTopLeft;
readonly Sprite optionsTopRight;
readonly Sprite optionsBottomLeft;
readonly Sprite optionsBottomRight;
readonly Sprite optionsBackground;
readonly SpriteRenderer buildPaletteRenderer; readonly SpriteRenderer buildPaletteRenderer;
readonly Animation cantBuild; readonly Animation cantBuild;
readonly Animation ready; readonly Animation ready;
@@ -87,6 +97,16 @@ namespace OpenRa.Game
optionsButton = new Animation("tabs"); optionsButton = new Animation("tabs");
optionsButton.PlayRepeating("left-normal"); optionsButton.PlayRepeating("left-normal");
optionsLeft = SpriteSheetBuilder.LoadAllSprites("dd-left")[0];
optionsRight = SpriteSheetBuilder.LoadAllSprites("dd-right")[0];
optionsTop = SpriteSheetBuilder.LoadAllSprites("dd-top")[0];
optionsBottom = SpriteSheetBuilder.LoadAllSprites("dd-botm")[0];
optionsTopLeft = SpriteSheetBuilder.LoadAllSprites("dd-crnr")[0];
optionsTopRight = SpriteSheetBuilder.LoadAllSprites("dd-crnr")[1];
optionsBottomLeft = SpriteSheetBuilder.LoadAllSprites("dd-crnr")[2];
optionsBottomRight = SpriteSheetBuilder.LoadAllSprites("dd-crnr")[3];
optionsBackground = SpriteSheetBuilder.LoadAllSprites("dd-bkgnd")[Game.CosmeticRandom.Next(4)];
blank = SheetBuilder.Add(new Size(64, 48), 16); blank = SheetBuilder.Add(new Size(64, 48), 16);
sprites = groups sprites = groups
@@ -154,6 +174,7 @@ namespace OpenRa.Game
int paletteHeight = DrawBuildPalette(currentTab); int paletteHeight = DrawBuildPalette(currentTab);
DrawBuildTabs(paletteHeight); DrawBuildTabs(paletteHeight);
DrawChat(); DrawChat();
DrawOptionsMenu();
} }
void DrawMinimap() void DrawMinimap()
@@ -372,17 +393,43 @@ namespace OpenRa.Game
optionsButton.ReplaceAnim(optionsPressed ? "left-pressed" : "left-normal"); optionsButton.ReplaceAnim(optionsPressed ? "left-pressed" : "left-normal");
AddButton(optionsRect, isLmb => DrawOptionsMenu()); AddButton(optionsRect, isLmb => optionsPressed = !optionsPressed);
buildPaletteRenderer.DrawSprite(optionsButton.Image, optionsDrawPos, PaletteType.Chrome); buildPaletteRenderer.DrawSprite(optionsButton.Image, optionsDrawPos, PaletteType.Chrome);
buildPaletteRenderer.Flush(); buildPaletteRenderer.Flush();
renderer.DrawText("Exit", new int2(80, -2) , Color.White); renderer.DrawText("Options", new int2(80, -2) , Color.White);
} }
void DrawOptionsMenu() void DrawOptionsMenu()
{ {
Environment.Exit(0); if (optionsPressed){
var menuDrawPos = Game.viewport.Location + new float2(Game.viewport.Width/2, Game.viewport.Height/2);
var width = optionsTop.bounds.Width + optionsTopLeft.bounds.Width + optionsTopRight.bounds.Width;
var height = optionsLeft.bounds.Height + optionsTopLeft.bounds.Height + optionsBottomLeft.bounds.Height;
var adjust = 8;
menuDrawPos = menuDrawPos + new float2(-width/2, -height/2);
var backgroundDrawPos = menuDrawPos + new float2( (width - optionsBackground.bounds.Width)/2, (height - optionsBackground.bounds.Height)/2);
//draw background
buildPaletteRenderer.DrawSprite(optionsBackground, backgroundDrawPos, PaletteType.Chrome);
//draw borders
buildPaletteRenderer.DrawSprite(optionsTopLeft, menuDrawPos, PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsLeft, menuDrawPos + new float2(0, optionsTopLeft.bounds.Height), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsBottomLeft, menuDrawPos + new float2(0, optionsTopLeft.bounds.Height + optionsLeft.bounds.Height), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsTop, menuDrawPos + new float2(optionsTopLeft.bounds.Width, 0), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsTopRight, menuDrawPos + new float2(optionsTopLeft.bounds.Width + optionsTop.bounds.Width, 0), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsBottom, menuDrawPos + new float2(optionsTopLeft.bounds.Width, optionsTopLeft.bounds.Height + optionsLeft.bounds.Height +adjust), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsBottomRight, menuDrawPos + new float2(optionsBottomLeft.bounds.Width + optionsBottom.bounds.Width, optionsTopLeft.bounds.Height + optionsLeft.bounds.Height), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsRight, menuDrawPos + new float2(optionsTopLeft.bounds.Width + optionsTop.bounds.Width + adjust + 1, optionsTopRight.bounds.Height), PaletteType.Chrome);
buildPaletteRenderer.Flush();
}
} }
void HandleChronosphereButton() void HandleChronosphereButton()
@@ -656,7 +703,10 @@ namespace OpenRa.Game
p += new int2(0, 15); p += new int2(0, 15);
if (!Rules.TechTree.CanBuild(info, Game.LocalPlayer, buildings)) if (!Rules.TechTree.CanBuild(info, Game.LocalPlayer, buildings))
{ {
var prereqs = info.Prerequisite.Select(a => Rules.UnitInfo[a.ToLowerInvariant()].Description); var prereqs = info.Prerequisite
.Select(a => Rules.UnitInfo[a.ToLowerInvariant()])
.Where( u => u.Owner.Any( o => o == Game.LocalPlayer.Race ) )
.Select( a => a.Description );
renderer.DrawText("Requires {0}".F( string.Join( ", ", prereqs.ToArray() ) ), p.ToInt2(), renderer.DrawText("Requires {0}".F( string.Join( ", ", prereqs.ToArray() ) ), p.ToInt2(),
Color.White); Color.White);
} }

View File

@@ -31,6 +31,8 @@ namespace OpenRa.Game.Effects
FiredBy = firedBy; FiredBy = firedBy;
Src = src; Src = src;
Dest = dest; Dest = dest;
SrcAltitude = srcAltitude;
DestAltitude = destAltitude;
VisualDest = Dest + new int2( VisualDest = Dest + new int2(
Game.CosmeticRandom.Next(-10, 10), Game.CosmeticRandom.Next(-10, 10),
Game.CosmeticRandom.Next(-10, 10)); Game.CosmeticRandom.Next(-10, 10));

View File

@@ -21,7 +21,7 @@ namespace OpenRa.Game.Effects
int Altitude; int Altitude;
public Missile(string weapon, Player owner, Actor firedBy, public Missile(string weapon, Player owner, Actor firedBy,
int2 src, Actor target, int altitude) int2 src, Actor target, int altitude, int facing)
{ {
Weapon = Rules.WeaponInfo[weapon]; Weapon = Rules.WeaponInfo[weapon];
Projectile = Rules.ProjectileInfo[Weapon.Projectile]; Projectile = Rules.ProjectileInfo[Weapon.Projectile];
@@ -31,9 +31,7 @@ namespace OpenRa.Game.Effects
Target = target; Target = target;
Pos = src.ToFloat2(); Pos = src.ToFloat2();
Altitude = altitude; Altitude = altitude;
Facing = facing;
/* todo: initial facing should be turret facing, or unit facing if we're not turreted */
Facing = Traits.Util.GetFacing( Target.CenterLocation - src.ToFloat2(), 0 );
if (Projectile.Image != null && Projectile.Image != "none") if (Projectile.Image != null && Projectile.Image != "none")
{ {
@@ -47,7 +45,7 @@ namespace OpenRa.Game.Effects
} }
const int MissileCloseEnough = 7; const int MissileCloseEnough = 7;
const float Scale = .3f; const float Scale = .2f;
public void Tick() public void Tick()
{ {
@@ -73,14 +71,16 @@ namespace OpenRa.Game.Effects
return; return;
} }
var move = (Scale * Weapon.Speed / dist.Length) * dist; var speed = Scale * Weapon.Speed * ((targetAltitude > 0 && Weapon.TurboBoost) ? 1.5f : 1f);
var angle = Facing / 128f * Math.PI;
var move = speed * -float2.FromAngle((float)angle);
Pos += move; Pos += move;
if (Projectile.Animates) if (Projectile.Animates)
Game.world.AddFrameEndTask(w => w.Add(new Smoke((Pos - 1.5f * move - new int2( 0, Altitude )).ToInt2()))); Game.world.AddFrameEndTask(w => w.Add(new Smoke((Pos - 1.5f * move - new int2( 0, Altitude )).ToInt2())));
// todo: running out of fuel // todo: running out of fuel
// todo: turbo boost vs aircraft
} }
public IEnumerable<Renderable> Render() public IEnumerable<Renderable> Render()

View File

@@ -3,12 +3,12 @@ namespace OpenRa.Game.GameRules
{ {
class AftermathInfo class AftermathInfo
{ {
public readonly int MTankDistance; public readonly int MTankDistance = 0;
public readonly float QuakeUnitDamage; public readonly float QuakeUnitDamage = 0f;
public readonly float QuakeBuildingDamage; public readonly float QuakeBuildingDamage = 0f;
public readonly float QuakeInfantryDamage; public readonly float QuakeInfantryDamage = 0f;
public readonly int QuakeDelay; public readonly int QuakeDelay = 0;
public readonly int CarrierLaunchDelay; public readonly int CarrierLaunchDelay = 0;
public readonly int ChronoTankDuration; public readonly int ChronoTankDuration = 0;
} }
} }

View File

@@ -1,126 +1,127 @@
using System;
namespace OpenRa.Game.GameRules namespace OpenRa.Game.GameRules
{ {
class GeneralInfo class GeneralInfo
{ {
/* Crates */ /* Crates */
public readonly int CrateMinimum; public readonly int CrateMinimum = 0;
public readonly int CrateMaximum; public readonly int CrateMaximum = 0;
public readonly float CrateRadius; public readonly float CrateRadius = 0;
public readonly float CrateRegen; public readonly float CrateRegen = 0;
public readonly string UnitCrateType; /* =none, if any */ public readonly string UnitCrateType = null; /* =none, if any */
public readonly float WaterCrateChance; public readonly float WaterCrateChance = 0;
public readonly int SoloCrateMoney; public readonly int SoloCrateMoney = 2000;
public readonly string SilverCrate; /* solo play crate contents */ public readonly string SilverCrate = null; /* solo play crate contents */
public readonly string WaterCrate; public readonly string WaterCrate = null;
public readonly string WoodCrate; public readonly string WoodCrate = null;
/* Special Weapons */ /* Special Weapons */
public readonly int ChronoDuration; public readonly int ChronoDuration = 0;
public readonly bool ChronoKillCargo; public readonly bool ChronoKillCargo = true;
public readonly int ChronoTechLevel; [Obsolete] public readonly int ChronoTechLevel = -1;
public readonly int GPSTechLevel; [Obsolete] public readonly int GPSTechLevel = -1;
public readonly int GapRadius; public readonly int GapRadius = 0;
public readonly float GapRegenInterval; public readonly float GapRegenInterval =0;
public readonly float IronCurtain; /* minutes */ public readonly float IronCurtain = 0; /* minutes */
public readonly int ParaTech; [Obsolete] public readonly int ParaTech = -1;
public readonly int ParabombTech; [Obsolete] public readonly int ParabombTech = -1;
public readonly int RadarJamRadius; public readonly int RadarJamRadius = 1;
public readonly int SpyPlaneTech; [Obsolete] public readonly int SpyPlaneTech = -1;
public readonly int BadgerBombCount; public readonly int BadgerBombCount = 1;
/* Chrono Side Effects */ /* Chrono Side Effects */
public readonly float QuakeChance; public readonly float QuakeChance = 0;
public readonly float QuakeDamage; /* percent */ public readonly float QuakeDamage = 0; /* percent */
public readonly float VortexChance; public readonly float VortexChance = 0;
public readonly int VortexDamage; public readonly int VortexDamage = 0;
public readonly int VortexRange; public readonly int VortexRange = 0;
public readonly int VortexSpeed; public readonly int VortexSpeed = 0;
/* Repair & Refit */ /* Repair & Refit */
public readonly float RefundPercent; public readonly float RefundPercent = 0;
public readonly float ReloadRate; public readonly float ReloadRate = 0;
public readonly float RepairPercent; public readonly float RepairPercent = 0;
public readonly float RepairRate; public readonly float RepairRate = 0;
public readonly int RepairStep; public readonly int RepairStep = 0;
public readonly float URepairPercent; public readonly float URepairPercent = 0;
public readonly int URepairStep; public readonly int URepairStep = 0;
/* Combat & Damage */ /* Combat & Damage */
public readonly float TurboBoost; public readonly float TurboBoost = 1.5f;
public readonly int APMineDamage; public readonly int APMineDamage = 0;
public readonly int AVMineDamage; public readonly int AVMineDamage = 0;
public readonly int AtomDamage; public readonly int AtomDamage = 0;
public readonly float BallisticScatter; public readonly float BallisticScatter = 0;
public readonly int BridgeStrength; public readonly int BridgeStrength = 0;
public readonly float C4Delay; public readonly float C4Delay = 0;
public readonly float Crush; public readonly float Crush = 0;
public readonly float ExpSpread; public readonly float ExpSpread = 0;
public readonly int FireSupress; public readonly int FireSupress = 0;
public readonly float HomingScatter; public readonly float HomingScatter = 0;
public readonly int MaxDamage; public readonly int MaxDamage = 0;
public readonly int MinDamage; public readonly int MinDamage = 0;
public readonly bool OreExplosive; public readonly bool OreExplosive = false;
public readonly bool PlayerAutoCrush; public readonly bool PlayerAutoCrush = false;
public readonly bool PlayerReturnFire; public readonly bool PlayerReturnFire = false;
public readonly bool PlayerScatter; public readonly bool PlayerScatter = false;
public readonly float ProneDamage; public readonly float ProneDamage = 0;
public readonly bool TreeTargeting; public readonly bool TreeTargeting = false;
public readonly int Incoming; public readonly int Incoming = 0;
/* Income & Production */ /* Income & Production */
public readonly int BailCount; public readonly int BailCount = 0;
public readonly float BuildSpeed; public readonly float BuildSpeed = 0;
public readonly float BuildupTime; public readonly float BuildupTime = 0;
public readonly int GemValue; public readonly int GemValue = 0;
public readonly int GoldValue; public readonly int GoldValue = 0;
public readonly float GrowthRate; public readonly float GrowthRate = 0;
public readonly bool OreGrows; public readonly bool OreGrows = true;
public readonly bool OreSpreads; public readonly bool OreSpreads = true;
public readonly float OreTruckRate; public readonly float OreTruckRate = 0;
public readonly bool SeparateAircraft; public readonly bool SeparateAircraft = true;
public readonly float SurvivorRate; public readonly float SurvivorRate = 0;
/* Audo/Visual Map Controls */ /* Audo/Visual Map Controls */
public readonly bool AllyReveal; public readonly bool AllyReveal = true;
public readonly float ConditionRed; public readonly float ConditionRed = 0;
public readonly float ConditionYellow; public readonly float ConditionYellow = 0;
public readonly int DropZoneRadius; public readonly int DropZoneRadius = 0;
public readonly bool EnemyHealth; public readonly bool EnemyHealth = true;
public readonly int Gravity; public readonly int Gravity = 0;
public readonly float IdleActionFrequency; public readonly float IdleActionFrequency = 0;
public readonly float MessageDelay; public readonly float MessageDelay = 0;
public readonly float MovieTime; public readonly float MovieTime = 0;
public readonly bool NamedCivilians; public readonly bool NamedCivilians = false;
public readonly float SavourDelay; public readonly float SavourDelay = 0;
public readonly int ShroudRate; public readonly int ShroudRate = 0;
public readonly int SpeakDelay; public readonly int SpeakDelay = 0;
public readonly int TimerWarning; public readonly int TimerWarning = 0;
public readonly bool FlashLowPower; public readonly bool FlashLowPower = false;
/* Computer & Movement Controls */ /* Computer & Movement Controls */
public readonly bool CurleyShuffle; public readonly bool CurleyShuffle = false;
public readonly float BaseBias; public readonly float BaseBias = 0;
public readonly float BaseDefenseDelay; public readonly float BaseDefenseDelay = 0;
public readonly float CloseEnough; public readonly float CloseEnough = 0;
public readonly int DamageDelay; public readonly int DamageDelay = 0;
public readonly int GameSpeeBias; public readonly int GameSpeeBias = 0;
public readonly int LZScanRadius; public readonly int LZScanRadius = 0;
public readonly bool MineAware; public readonly bool MineAware = false;
public readonly float Stray; public readonly float Stray = 0;
public readonly float SubmergeDelay; public readonly float SubmergeDelay = 0;
public readonly float SuspendDelay; public readonly float SuspendDelay = 0;
public readonly int SuspendPriority; public readonly int SuspendPriority = 0;
public readonly float TeamDelay; public readonly float TeamDelay = 0;
/* Misc */ /* Misc */
public readonly bool FineDiffControl; [Obsolete]
public readonly bool MCVUndeploy; public readonly bool FineDiffControl = false;
public readonly bool MCVUndeploy = false;
/* OpenRA-specific */ /* OpenRA-specific */
public readonly float OreChance; /* chance of spreading to a public readonly float OreChance = 0; /* chance of spreading to a particular eligible cell */
* particular eligible cell */ public readonly int LowPowerSlowdown = 3; /* build time multiplier */
public readonly int LowPowerSlowdown; /* build time multiplier */
} }
} }

View File

@@ -35,8 +35,9 @@ namespace OpenRa.Game.GameRules
return false; return false;
foreach( var p in unit.Prerequisite ) foreach( var p in unit.Prerequisite )
if( playerBuildings[ p ].Count == 0 ) if (Rules.UnitInfo[p.ToLowerInvariant()].Owner.Any(x => x == player.Race))
return false; if( playerBuildings[ p ].Count == 0 )
return false;
if( producesIndex[ Rules.UnitCategory[ unit.Name ] ].All( x => playerBuildings[ x.Name ].Count == 0 ) ) if( producesIndex[ Rules.UnitCategory[ unit.Name ] ].All( x => playerBuildings[ x.Name ].Count == 0 ) )
return false; return false;

View File

@@ -1,4 +1,5 @@
using System;
namespace OpenRa.Game.GameRules namespace OpenRa.Game.GameRules
{ {
public enum ArmorType public enum ArmorType
@@ -19,8 +20,8 @@ namespace OpenRa.Game.GameRules
public readonly int Ammo = -1; public readonly int Ammo = -1;
public readonly ArmorType Armor = ArmorType.none; public readonly ArmorType Armor = ArmorType.none;
public readonly bool DoubleOwned = false; [Obsolete] public readonly bool DoubleOwned = false;
public readonly bool Cloakable = false; [Obsolete] public readonly bool Cloakable = false;
public readonly int Cost = 0; public readonly int Cost = 0;
public readonly bool Crewed = false; public readonly bool Crewed = false;
public readonly bool Explodes = false; public readonly bool Explodes = false;
@@ -35,7 +36,7 @@ namespace OpenRa.Game.GameRules
public readonly int ROT = 255; public readonly int ROT = 255;
public readonly int Reload = 0; public readonly int Reload = 0;
public readonly bool SelfHealing = false; public readonly bool SelfHealing = false;
public readonly bool Sensors = false; // no idea what this does [Obsolete] public readonly bool Sensors = false; // no idea what this does
public readonly int Sight = 1; public readonly int Sight = 1;
public readonly int Strength = 1; public readonly int Strength = 1;
public readonly int TechLevel = -1; public readonly int TechLevel = -1;
@@ -59,6 +60,10 @@ namespace OpenRa.Game.GameRules
public readonly int UnloadFacing = 0; public readonly int UnloadFacing = 0;
public readonly UnitMovementType[] PassengerTypes = null; public readonly UnitMovementType[] PassengerTypes = null;
// weapon origins and firing angles within the turrets. 3 values per position.
public readonly int[] PrimaryLocalOffset = { };
public readonly int[] SecondaryLocalOffset = { };
public UnitInfo(string name) { Name = name; } public UnitInfo(string name) { Name = name; }
} }

View File

@@ -77,6 +77,13 @@ namespace OpenRa.Game.Graphics
foreach (var a in Game.world.Actors.Where(a => a.traits.Contains<Unit>())) 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]); bitmap.SetPixel(a.Location.X, a.Location.Y, Chat.paletteColors[(int)a.Owner.Palette]);
for (var y = 0; y < 128; y++ )
for (var x = 0; x < 128; x++ )
{
if( ! Game.LocalPlayer.Shroud.IsExplored(new int2(x,y)))
bitmap.SetPixel(x, y, Color.Black);
}
sheet.Texture.SetData(bitmap); sheet.Texture.SetData(bitmap);
} }

View File

@@ -43,20 +43,29 @@ namespace OpenRa.Game
dirty = true; dirty = true;
} }
static readonly byte[] ShroudTiles =
{
0xf,0xf,0xf,0xf,
0xf,0xf,0xf,0xf,
0xf,0xf,0xf,0xf,
0xf,0xf,0xf,0xf,
0,7,13,0,
14,6,12,4,
11,3,9,1,
0,2,8,0,
};
static readonly byte[] ExtraShroudTiles =
{
46, 41, 42, 38,
43, 45, 39, 35,
40, 37, 44, 34,
36, 33, 32, 47,
};
Sprite ChooseShroud(int i, int j) Sprite ChooseShroud(int i, int j)
{ {
// bits are for exploredness: left, right, up, down, self // 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; var v = 0;
if (explored[i - 1, j]) v |= 1; if (explored[i - 1, j]) v |= 1;
if (explored[i + 1, j]) v |= 2; if (explored[i + 1, j]) v |= 2;
@@ -64,27 +73,17 @@ namespace OpenRa.Game
if (explored[i, j + 1]) v |= 8; if (explored[i, j + 1]) v |= 8;
if (explored[i, j]) v |= 16; if (explored[i, j]) v |= 16;
var x = n[v]; var x = ShroudTiles[v];
if (x != 0)
return shadowBits[x];
if (x == 0) // bits are for exploredness: TL, TR, BR, BL
{ var u = 0;
// bits are for exploredness: TL, TR, BR, BL if (explored[i - 1, j - 1]) u |= 1;
var m = new[] { if (explored[i + 1, j - 1]) u |= 2;
46, 41, 42, 38, if (explored[i + 1, j + 1]) u |= 4;
43, 45, 39, 35, if (explored[i - 1, j + 1]) u |= 8;
40, 37, 44, 34, return shadowBits[ExtraShroudTiles[u]];
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) public void Draw(SpriteRenderer r)

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using IjwFramework.Types; using IjwFramework.Types;
using OpenRa.Game.Effects; using OpenRa.Game.Effects;
@@ -72,7 +73,7 @@ namespace OpenRa.Game.Traits
var unit = self.traits.GetOrDefault<Unit>(); var unit = self.traits.GetOrDefault<Unit>();
if (self.Info.Primary != null && CheckFire(self, unit, self.Info.Primary, ref primaryFireDelay, if (self.Info.Primary != null && CheckFire(self, unit, self.Info.Primary, ref primaryFireDelay,
self.Info.PrimaryOffset, ref primaryBurst)) self.Info.PrimaryOffset, ref primaryBurst, self.Info.PrimaryLocalOffset))
{ {
secondaryFireDelay = Math.Max(4, secondaryFireDelay); secondaryFireDelay = Math.Max(4, secondaryFireDelay);
primaryRecoil = 1; primaryRecoil = 1;
@@ -80,7 +81,7 @@ namespace OpenRa.Game.Traits
} }
if (self.Info.Secondary != null && CheckFire(self, unit, self.Info.Secondary, ref secondaryFireDelay, if (self.Info.Secondary != null && CheckFire(self, unit, self.Info.Secondary, ref secondaryFireDelay,
self.Info.SecondaryOffset ?? self.Info.PrimaryOffset, ref secondaryBurst)) self.Info.SecondaryOffset ?? self.Info.PrimaryOffset, ref secondaryBurst, self.Info.SecondaryLocalOffset))
{ {
if (self.Info.SecondaryOffset != null) secondaryRecoil = 1; if (self.Info.SecondaryOffset != null) secondaryRecoil = 1;
else primaryRecoil = 1; else primaryRecoil = 1;
@@ -88,7 +89,7 @@ namespace OpenRa.Game.Traits
} }
} }
bool CheckFire(Actor self, Unit unit, string weaponName, ref int fireDelay, int[] offset, ref int burst) bool CheckFire(Actor self, Unit unit, string weaponName, ref int fireDelay, int[] offset, ref int burst, int[] localOffset)
{ {
if (fireDelay > 0) return false; if (fireDelay > 0) return false;
@@ -101,6 +102,17 @@ namespace OpenRa.Game.Traits
if (!Combat.WeaponValidForTarget(weapon, target)) return false; if (!Combat.WeaponValidForTarget(weapon, target)) return false;
var numOffsets = (localOffset.Length + 2) / 3;
if (numOffsets == 0) numOffsets = 1;
var localOffsetForShot = burst % numOffsets;
var thisLocalOffset = localOffset.Skip(3 * localOffsetForShot).Take(3).ToArray();
var fireOffset = new[] {
offset.ElementAtOrDefault(0) + thisLocalOffset.ElementAtOrDefault(0),
offset.ElementAtOrDefault(1) + thisLocalOffset.ElementAtOrDefault(1),
offset.ElementAtOrDefault(2),
offset.ElementAtOrDefault(3) };
if (--burst > 0) if (--burst > 0)
fireDelay = 5; fireDelay = 5;
else else
@@ -109,7 +121,7 @@ namespace OpenRa.Game.Traits
burst = weapon.Burst; burst = weapon.Burst;
} }
var firePos = self.CenterLocation.ToInt2() + Util.GetTurretPosition(self, unit, offset, 0f).ToInt2(); var firePos = self.CenterLocation.ToInt2() + Util.GetTurretPosition(self, unit, fireOffset, 0f).ToInt2();
var thisTarget = target; // closure. var thisTarget = target; // closure.
var destUnit = thisTarget.traits.GetOrDefault<Unit>(); var destUnit = thisTarget.traits.GetOrDefault<Unit>();
@@ -121,9 +133,14 @@ namespace OpenRa.Game.Traits
if( weapon.RenderAsTesla ) if( weapon.RenderAsTesla )
Game.world.Add( new TeslaZap( firePos, thisTarget.CenterLocation.ToInt2() ) ); Game.world.Add( new TeslaZap( firePos, thisTarget.CenterLocation.ToInt2() ) );
if( Rules.ProjectileInfo[ weapon.Projectile ].ROT != 0 ) if (Rules.ProjectileInfo[weapon.Projectile].ROT != 0)
{
var fireFacing = thisLocalOffset.ElementAtOrDefault(2) +
(self.traits.Contains<Turreted>() ? self.traits.Get<Turreted>().turretFacing : unit.Facing);
Game.world.Add(new Missile(weaponName, self.Owner, self, Game.world.Add(new Missile(weaponName, self.Owner, self,
firePos, thisTarget, srcAltitude)); firePos, thisTarget, srcAltitude, fireFacing));
}
else else
Game.world.Add(new Bullet(weaponName, self.Owner, self, Game.world.Add(new Bullet(weaponName, self.Owner, self,
firePos, thisTarget.CenterLocation.ToInt2(), srcAltitude, destAltitude)); firePos, thisTarget.CenterLocation.ToInt2(), srcAltitude, destAltitude));

View File

@@ -1,14 +1,9 @@
using OpenRa.Game.Traits; using System.Linq;
using OpenRa.Game.Orders;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using OpenRa.Game.Effects; using OpenRa.Game.Effects;
using OpenRa.Game.Graphics;
namespace OpenRa.Game.Traits namespace OpenRa.Game.Traits
{ {
class IronCurtainable: IOrder, IDamageModifier, ITick class IronCurtainable : IOrder, IDamageModifier, ITick
{ {
int RemainingTicks = 0; int RemainingTicks = 0;
@@ -26,7 +21,7 @@ namespace OpenRa.Game.Traits
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
{ {
return null; // Chronoshift order is issued through Chrome. return null; // IronCurtain order is issued through Chrome.
} }
public void ResolveOrder(Actor self, Order order) public void ResolveOrder(Actor self, Order order)
@@ -38,7 +33,9 @@ namespace OpenRa.Game.Traits
RemainingTicks = (int)(Rules.General.IronCurtain * 60 * 25); RemainingTicks = (int)(Rules.General.IronCurtain * 60 * 25);
Sound.Play("ironcur9.aud"); Sound.Play("ironcur9.aud");
// Play active anim // Play active anim
var ironCurtain = Game.world.Actors.Where(a => a.Owner == order.Subject.Owner && a.traits.Contains<IronCurtain>()).FirstOrDefault(); var ironCurtain = Game.world.Actors
.Where(a => a.Owner == order.Subject.Owner && a.traits.Contains<IronCurtain>())
.FirstOrDefault();
if (ironCurtain != null) if (ironCurtain != null)
ironCurtain.traits.Get<RenderBuilding>().PlayCustomAnim(ironCurtain, "active"); ironCurtain.traits.Get<RenderBuilding>().PlayCustomAnim(ironCurtain, "active");
} }

View File

@@ -33,6 +33,7 @@ namespace OpenRa.Game.Traits
public Animation Animation; public Animation Animation;
public Func<float2> OffsetFunc; public Func<float2> OffsetFunc;
public Func<bool> DisableFunc; public Func<bool> DisableFunc;
public int ZOffset;
public AnimationWithOffset( Animation a ) public AnimationWithOffset( Animation a )
: this( a, null, null ) : this( a, null, null )
@@ -48,10 +49,9 @@ namespace OpenRa.Game.Traits
public Renderable Image( Actor self ) public Renderable Image( Actor self )
{ {
if( OffsetFunc != null ) var r = Util.Centered( self, Animation.Image, self.CenterLocation
return Util.Centered( self, Animation.Image, self.CenterLocation + OffsetFunc() ); + (OffsetFunc != null ? OffsetFunc() : float2.Zero) );
else return ZOffset != 0 ? r.WithZOffset(ZOffset) : r;
return Util.Centered( self, Animation.Image, self.CenterLocation );
} }
public static implicit operator AnimationWithOffset( Animation a ) public static implicit operator AnimationWithOffset( Animation a )

View File

@@ -19,16 +19,16 @@ namespace OpenRa.Game.Traits
turretAnim.PlayFacing( "turret", () => turreted.turretFacing ); turretAnim.PlayFacing( "turret", () => turreted.turretFacing );
if( self.Info.PrimaryOffset != null ) if( self.Info.PrimaryOffset != null )
anims.Add( "turret_1", new AnimationWithOffset( anims.Add("turret_1", new AnimationWithOffset(
turretAnim, turretAnim,
() => Util.GetTurretPosition( self, unit, self.Info.PrimaryOffset, attack.primaryRecoil ), () => Util.GetTurretPosition(self, unit, self.Info.PrimaryOffset, attack.primaryRecoil),
null ) ); null) { ZOffset = 1 });
if( self.Info.SecondaryOffset != null ) if( self.Info.SecondaryOffset != null )
anims.Add( "turret_2", new AnimationWithOffset( anims.Add("turret_2", new AnimationWithOffset(
turretAnim, turretAnim,
() => Util.GetTurretPosition( self, unit, self.Info.SecondaryOffset, attack.secondaryRecoil ), () => Util.GetTurretPosition(self, unit, self.Info.SecondaryOffset, attack.secondaryRecoil),
null ) ); null) { ZOffset = 1 });
if( self.Info.MuzzleFlash ) if( self.Info.MuzzleFlash )
{ {

View File

@@ -17,7 +17,7 @@ All tracked vehicles
1TNK Works 1TNK Works
2TNK Works 2TNK Works
3TNK Works 3TNK Works
4TNK Gun, missile origins are wrong 4TNK Works
Light vehicles Light vehicles
V2RL Works V2RL Works

View File

@@ -543,10 +543,9 @@ Armor=none
TechLevel=2 TechLevel=2
Sight=4 Sight=4
Speed=3 Speed=3
Owner=allies Owner=allies,soviet
Cost=300 Cost=300
Points=10 Points=10
DoubleOwned=yes
; Flamethrower ; Flamethrower
[E4] [E4]
@@ -602,7 +601,7 @@ Infiltrate=yes
; Tanya ; Tanya
[E7] [E7]
Prerequisite=atek Prerequisite=atek,stek
Primary=Colt45 Primary=Colt45
Secondary=Colt45 Secondary=Colt45
Strength=100 Strength=100
@@ -615,7 +614,6 @@ Cost=1200
Points=25 Points=25
Infiltrate=yes Infiltrate=yes
C4=yes C4=yes
DoubleOwned=yes
; field medic ; field medic
[MEDI] [MEDI]
@@ -1230,7 +1228,7 @@ ROT=30
; big missile silo ; big missile silo
[MSLO] [MSLO]
Prerequisite=stek Prerequisite=stek,atek
Primary=none Primary=none
Strength=400 Strength=400
Armor=heavy Armor=heavy

View File

@@ -1031,7 +1031,10 @@
<sequence name="left-normal" start="0" length="1" /> <sequence name="left-normal" start="0" length="1" />
<sequence name="left-pressed" start="1" length="1" /> <sequence name="left-pressed" start="1" length="1" />
</unit> </unit>
<unit name="sputnik"> <unit name="sputnik"> <sequence name="idle" start="0" length="4" /> </unit> <unit name="dd-crnr"> <sequence name="idle" start="0" length="4" />
<sequence name="idle" start="0" length="4" /> <sequence name="top-left" start="0" length="1" />
<sequence name="top-right" start="1" length="1" />
<sequence name="bottom-left" start="2" length="1" />
<sequence name="bottom-right" start="3" length="1" />
</unit> </unit>
</sequences> </sequences>

View File

@@ -42,6 +42,9 @@ Description=Mammoth Tank
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable, Passenger, IronCurtainable Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable, Passenger, IronCurtainable
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
PrimaryLocalOffset=-4,-5,0,4,-5,0
SecondaryLocalOffset=-7,2,25,7,2,-25
Recoil=4
[ARTY] [ARTY]
Description=Artillery Description=Artillery
Traits=Unit, Mobile, AttackBase, RenderUnit, Explodes, AutoTarget, Repairable, Chronoshiftable, Passenger, IronCurtainable Traits=Unit, Mobile, AttackBase, RenderUnit, Explodes, AutoTarget, Repairable, Chronoshiftable, Passenger, IronCurtainable