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

This commit is contained in:
Alli
2010-01-08 19:05:40 +13:00
22 changed files with 275 additions and 203 deletions

View File

@@ -338,7 +338,7 @@ namespace OpenRa.Game
else else
{ {
//repairButton.ReplaceAnim(Game.controller.orderGenerator is RepairOrderGenerator ? "pressed" : "normal"); //repairButton.ReplaceAnim(Game.controller.orderGenerator is RepairOrderGenerator ? "pressed" : "normal");
AddButton(curtainRect, isLmb => Game.controller.ToggleInputMode<IronCurtainOrderGenerator>()); AddButton(curtainRect, isLmb => HandleIronCurtainButton());
} }
buildPaletteRenderer.DrawSprite(repairButton.Image, curtainDrawPos, PaletteType.Chrome); buildPaletteRenderer.DrawSprite(repairButton.Image, curtainDrawPos, PaletteType.Chrome);
@@ -438,6 +438,12 @@ namespace OpenRa.Game
Sound.Play("slcttgt1.aud"); Sound.Play("slcttgt1.aud");
} }
void HandleIronCurtainButton()
{
if (Game.controller.ToggleInputMode<IronCurtainOrderGenerator>())
Sound.Play("slcttgt1.aud");
}
void DrawChat() void DrawChat()
{ {
var chatpos = new int2(400, Game.viewport.Height - 20); var chatpos = new int2(400, Game.viewport.Height - 20);
@@ -697,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

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using OpenRa.Game.Graphics;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Effects
{
class InvulnEffect : IEffect
{
Actor a;
IronCurtainable b;
public InvulnEffect(Actor a)
{
this.a = a;
this.b = a.traits.Get<IronCurtainable>();
}
public void Tick()
{
if (a.IsDead || b.GetDamageModifier() > 0)
Game.world.AddFrameEndTask(w => w.Remove(this));
}
public IEnumerable<Renderable> Render()
{
foreach (var r in a.Render())
yield return r.WithPalette(PaletteType.Invuln);
}
}
}

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

@@ -0,0 +1,36 @@
using System.Collections.Generic;
using OpenRa.Game.Graphics;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Effects
{
class PowerDownIndicator : IEffect
{
Actor a;
Building b;
Animation anim = new Animation("powerdown");
public PowerDownIndicator(Actor a)
{
this.a = a;
this.b = a.traits.Get<Building>();
anim.PlayRepeating("disabled");
}
public void Tick()
{
if (!b.Disabled || a.IsDead)
Game.world.AddFrameEndTask(w => w.Remove(this));
}
public IEnumerable<Renderable> Render()
{
foreach (var r in a.Render())
yield return r.WithPalette(PaletteType.Disabled);
if (b.ManuallyDisabled)
yield return new Renderable(anim.Image,
a.CenterLocation - .5f * anim.Image.size, PaletteType.Chrome);
}
}
}

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

@@ -6,7 +6,7 @@ namespace OpenRa.Game.Graphics
public enum PaletteType public enum PaletteType
{ {
Gold, Blue, Red, Orange, Teal, Salmon, Green, Gray, Gold, Blue, Red, Orange, Teal, Salmon, Green, Gray,
Shadow, Invuln, Chrome, Shroud, Highlight, Shadow, Invuln, Disabled, Highlight, Shroud, Chrome,
}; };
class HardwarePalette : Sheet class HardwarePalette : Sheet
@@ -23,11 +23,12 @@ namespace OpenRa.Game.Graphics
foreach (string remap in new string[] { "blue", "red", "orange", "teal", "salmon", "green", "gray" }) foreach (string remap in new string[] { "blue", "red", "orange", "teal", "salmon", "green", "gray" })
AddPalette(new Palette(pal, new PlayerColorRemap(FileSystem.Open(remap + ".rem")))); AddPalette(new Palette(pal, new PlayerColorRemap(FileSystem.Open(remap + ".rem"))));
AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(140, 0, 0, 0)))); AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(140, 0, 0, 0)))); // Shadow
AddPalette(pal); // iron curtain. todo: remap! AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(128, 128, 0, 0)))); // Invulnerable (Iron Curtain)
AddPalette(pal); // chrome (it's like gold, but we're not going to hax it in palettemods) AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(180, 0, 0, 0)))); // Disabled / Low power
AddPalette(new Palette(pal, new ShroudPaletteRemap())); AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(128, 255, 255, 255)))); // Highlight
AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(128, 255, 255, 255)))); AddPalette(new Palette(pal, new ShroudPaletteRemap())); // Shroud
AddPalette(pal); // Chrome (it's like gold, but we're not going to hax it in palettemods)
} }
int AddPalette(Palette p) int AddPalette(Palette p)

View File

@@ -83,7 +83,9 @@
<Compile Include="Effects\Corpse.cs" /> <Compile Include="Effects\Corpse.cs" />
<Compile Include="Effects\DelayedAction.cs" /> <Compile Include="Effects\DelayedAction.cs" />
<Compile Include="Effects\FlashTarget.cs" /> <Compile Include="Effects\FlashTarget.cs" />
<Compile Include="Effects\InvulnEffect.cs" />
<Compile Include="Effects\MoveFlash.cs" /> <Compile Include="Effects\MoveFlash.cs" />
<Compile Include="Effects\PowerDownIndicator.cs" />
<Compile Include="Effects\RepairIndicator.cs" /> <Compile Include="Effects\RepairIndicator.cs" />
<Compile Include="Effects\Smoke.cs" /> <Compile Include="Effects\Smoke.cs" />
<Compile Include="Effects\TeslaZap.cs" /> <Compile Include="Effects\TeslaZap.cs" />

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

@@ -26,7 +26,7 @@ namespace OpenRa.Game.Traits
protected override void QueueAttack( Actor self, Order order ) protected override void QueueAttack( Actor self, Order order )
{ {
if (self.traits.Contains<Building>() && self.traits.Get<Building>().InsuffientPower()) if (self.traits.Contains<Building>() && self.traits.Get<Building>().Disabled)
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 */

View File

@@ -9,12 +9,15 @@ using OpenRa.Game.Graphics;
namespace OpenRa.Game.Traits namespace OpenRa.Game.Traits
{ {
class Building : INotifyDamage, IOrder, ITick, IRenderModifier class Building : INotifyDamage, IOrder, ITick
{ {
readonly Actor self; readonly Actor self;
public readonly BuildingInfo unitInfo; public readonly BuildingInfo unitInfo;
bool isRepairing = false; bool isRepairing = false;
bool isPoweredDown = false; bool manuallyDisabled = false;
public bool ManuallyDisabled { get { return manuallyDisabled; } }
public bool Disabled { get { return (manuallyDisabled || (unitInfo.Powered && self.Owner.GetPowerState() != PowerState.Normal)); } }
bool wasDisabled = false;
public Building(Actor self) public Building(Actor self)
{ {
@@ -24,14 +27,9 @@ namespace OpenRa.Game.Traits
* ((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() public int GetPowerUsage()
{ {
if (isPoweredDown) if (manuallyDisabled)
return 0; return 0;
if (unitInfo.Power > 0) /* todo: is this how real-ra scales it? */ if (unitInfo.Power > 0) /* todo: is this how real-ra scales it? */
@@ -40,32 +38,6 @@ namespace OpenRa.Game.Traits
return unitInfo.Power; 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)
{ {
if (e.DamageState == DamageState.Dead) if (e.DamageState == DamageState.Dead)
@@ -92,8 +64,8 @@ namespace OpenRa.Game.Traits
if (order.OrderString == "PowerDown") if (order.OrderString == "PowerDown")
{ {
isPoweredDown = !isPoweredDown; manuallyDisabled = !manuallyDisabled;
Sound.Play((isPoweredDown) ? "bleep12.aud" : "bleep11.aud"); Sound.Play((manuallyDisabled) ? "bleep12.aud" : "bleep11.aud");
} }
} }
@@ -101,6 +73,11 @@ namespace OpenRa.Game.Traits
public void Tick(Actor self) public void Tick(Actor self)
{ {
// If the disabled state has changed since the last frame
if (Disabled ^ wasDisabled
&& (wasDisabled = Disabled)) // Yes, I mean assignment
Game.world.AddFrameEndTask(w => w.Add(new PowerDownIndicator(self)));
if (!isRepairing) return; if (!isRepairing) return;
if (remainingTicks == 0) if (remainingTicks == 0)

View File

@@ -8,7 +8,7 @@ using OpenRa.Game.Graphics;
namespace OpenRa.Game.Traits namespace OpenRa.Game.Traits
{ {
class IronCurtainable: IOrder, IDamageModifier, ITick, IRenderModifier class IronCurtainable: IOrder, IDamageModifier, ITick
{ {
int RemainingTicks = 0; int RemainingTicks = 0;
@@ -23,6 +23,7 @@ namespace OpenRa.Game.Traits
{ {
return (RemainingTicks > 0) ? 0.0f : 1.0f; return (RemainingTicks > 0) ? 0.0f : 1.0f;
} }
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; // Chronoshift order is issued through Chrome.
@@ -32,26 +33,15 @@ namespace OpenRa.Game.Traits
{ {
if (order.OrderString == "IronCurtain") if (order.OrderString == "IronCurtain")
{ {
Game.controller.CancelInputMode();
Game.world.AddFrameEndTask(w => w.Add(new InvulnEffect(self)));
RemainingTicks = (int)(Rules.General.IronCurtain * 60 * 25); RemainingTicks = (int)(Rules.General.IronCurtain * 60 * 25);
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();
Sound.Play("ironcur9.aud");
if (ironCurtain != null) if (ironCurtain != null)
ironCurtain.traits.Get<RenderBuilding>().PlayCustomAnim(ironCurtain, "active"); ironCurtain.traits.Get<RenderBuilding>().PlayCustomAnim(ironCurtain, "active");
} }
} }
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> rs)
{
if (RemainingTicks <= 0)
return rs;
List<Renderable> nrs = new List<Renderable>(rs);
foreach(var r in rs)
{
nrs.Add(r.WithPalette(PaletteType.Shadow));
}
return nrs;
}
} }
} }

View File

@@ -140,7 +140,7 @@ namespace OpenRa.Game.Traits
foreach (var p in primaryProducers) foreach (var p in primaryProducers)
{ {
// Ignore buildings that are disabled // Ignore buildings that are disabled
if (p.traits.Contains<Building>() && p.traits.Get<Building>().InsuffientPower()) if (p.traits.Contains<Building>() && p.traits.Get<Building>().Disabled)
continue; continue;
producer = p; producer = p;
break; break;

View File

@@ -19,7 +19,7 @@ namespace OpenRa.Game.Traits
// Check if powered // Check if powered
var b = self.traits.Get<Building>(); var b = self.traits.Get<Building>();
if (b != null && b.InsuffientPower()) if (b != null && b.Disabled)
return false; return false;
return true; return true;

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]

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