Shift Actor.Health onto a trait.
Known regressions: - cnc only - health bar colors - can't repair buildings
This commit is contained in:
@@ -31,8 +31,6 @@ namespace OpenRA
|
|||||||
public int2 Location { get { return traits.Get<IOccupySpace>().TopLeft; } }
|
public int2 Location { get { return traits.Get<IOccupySpace>().TopLeft; } }
|
||||||
[Sync]
|
[Sync]
|
||||||
public Player Owner;
|
public Player Owner;
|
||||||
[Sync]
|
|
||||||
public int Health;
|
|
||||||
|
|
||||||
IActivity currentActivity;
|
IActivity currentActivity;
|
||||||
public Group Group;
|
public Group Group;
|
||||||
@@ -51,8 +49,6 @@ namespace OpenRA
|
|||||||
throw new NotImplementedException("No rules definition for unit {0}".F(name.ToLowerInvariant()));
|
throw new NotImplementedException("No rules definition for unit {0}".F(name.ToLowerInvariant()));
|
||||||
|
|
||||||
Info = Rules.Info[name.ToLowerInvariant()];
|
Info = Rules.Info[name.ToLowerInvariant()];
|
||||||
Health = this.GetMaxHP();
|
|
||||||
|
|
||||||
foreach (var trait in Info.TraitsInConstructOrder())
|
foreach (var trait in Info.TraitsInConstructOrder())
|
||||||
traits.Add(trait.Create(init));
|
traits.Add(trait.Create(init));
|
||||||
}
|
}
|
||||||
@@ -147,66 +143,7 @@ namespace OpenRA
|
|||||||
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
|
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsDead { get { return Health <= 0; } }
|
|
||||||
public bool IsInWorld { get; set; }
|
public bool IsInWorld { get; set; }
|
||||||
public bool RemoveOnDeath = true;
|
|
||||||
|
|
||||||
public DamageState GetDamageState()
|
|
||||||
{
|
|
||||||
if (Health <= 0)
|
|
||||||
return DamageState.Dead;
|
|
||||||
|
|
||||||
if (Health < this.GetMaxHP() * World.Defaults.ConditionYellow)
|
|
||||||
return DamageState.Half;
|
|
||||||
|
|
||||||
return DamageState.Normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void InflictDamage(Actor attacker, int damage, WarheadInfo warhead)
|
|
||||||
{
|
|
||||||
if (IsDead) return; /* overkill! don't count extra hits as more kills! */
|
|
||||||
|
|
||||||
var oldState = GetDamageState();
|
|
||||||
|
|
||||||
/* apply the damage modifiers, if we have any. */
|
|
||||||
var modifier = (float)traits.WithInterface<IDamageModifier>()
|
|
||||||
.Select(t => t.GetDamageModifier(warhead)).Product();
|
|
||||||
|
|
||||||
damage = (int)(damage * modifier);
|
|
||||||
|
|
||||||
Health -= damage;
|
|
||||||
if (Health <= 0)
|
|
||||||
{
|
|
||||||
Health = 0;
|
|
||||||
|
|
||||||
attacker.Owner.Kills++;
|
|
||||||
Owner.Deaths++;
|
|
||||||
|
|
||||||
if (RemoveOnDeath)
|
|
||||||
World.AddFrameEndTask(w => w.Remove(this));
|
|
||||||
|
|
||||||
Log.Write("debug", "{0} #{1} killed by {2} #{3}", Info.Name, ActorID, attacker.Info.Name, attacker.ActorID);
|
|
||||||
}
|
|
||||||
|
|
||||||
var maxHP = this.GetMaxHP();
|
|
||||||
|
|
||||||
if (Health > maxHP) Health = maxHP;
|
|
||||||
|
|
||||||
// Log.Write("debug", "InflictDamage: {0} #{1} -> {2} #{3} raw={4} adj={5} hp={6} mod={7}",
|
|
||||||
// attacker.Info.Name, attacker.ActorID, Info.Name, ActorID, rawDamage, damage, Health, modifier);
|
|
||||||
|
|
||||||
var newState = GetDamageState();
|
|
||||||
|
|
||||||
foreach (var nd in traits.WithInterface<INotifyDamage>())
|
|
||||||
nd.Damaged(this, new AttackInfo
|
|
||||||
{
|
|
||||||
Attacker = attacker,
|
|
||||||
Damage = damage,
|
|
||||||
DamageState = newState,
|
|
||||||
DamageStateChanged = newState != oldState,
|
|
||||||
Warhead = warhead
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void QueueActivity( IActivity nextActivity )
|
public void QueueActivity( IActivity nextActivity )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace OpenRA.Effects
|
|||||||
|
|
||||||
public void Tick( World world )
|
public void Tick( World world )
|
||||||
{
|
{
|
||||||
if (--framesLeft == 0 || a.IsDead)
|
if (--framesLeft == 0 || a.IsDead())
|
||||||
world.AddFrameEndTask(w => w.Remove(this));
|
world.AddFrameEndTask(w => w.Remove(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,13 +34,6 @@ namespace OpenRA
|
|||||||
return xs.Aggregate(1f, (a, x) => a * x);
|
return xs.Aggregate(1f, (a, x) => a * x);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetMaxHP(this Actor self)
|
|
||||||
{
|
|
||||||
var oai = self.Info.Traits.GetOrDefault<OwnedActorInfo>();
|
|
||||||
if (oai == null) return 0;
|
|
||||||
return oai.HP;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k )
|
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k )
|
||||||
where V : new()
|
where V : new()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,7 +31,13 @@ namespace OpenRA.GameRules
|
|||||||
public readonly int Delay = 0; // delay in ticks before dealing the damage. 0=instant (old model)
|
public readonly int Delay = 0; // delay in ticks before dealing the damage. 0=instant (old model)
|
||||||
public readonly DamageModel DamageModel = DamageModel.Normal; // which damage model to use
|
public readonly DamageModel DamageModel = DamageModel.Normal; // which damage model to use
|
||||||
|
|
||||||
public float EffectivenessAgainst(ArmorType at) { return Verses[(int)at]; }
|
public float EffectivenessAgainst(Actor self)
|
||||||
|
{
|
||||||
|
var health = self.Info.Traits.GetOrDefault<HealthInfo>();
|
||||||
|
if (health == null) return 0f;
|
||||||
|
|
||||||
|
return Verses[(int)(health.Armor)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ArmorType
|
public enum ArmorType
|
||||||
|
|||||||
@@ -229,6 +229,8 @@
|
|||||||
<Compile Include="Traits\Player\DeveloperMode.cs" />
|
<Compile Include="Traits\Player\DeveloperMode.cs" />
|
||||||
<Compile Include="Traits\RevealsShroud.cs" />
|
<Compile Include="Traits\RevealsShroud.cs" />
|
||||||
<Compile Include="Traits\Targetable.cs" />
|
<Compile Include="Traits\Targetable.cs" />
|
||||||
|
<Compile Include="Traits\Health.cs" />
|
||||||
|
<Compile Include="Traits\RepairableBuilding.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||||
|
|||||||
@@ -22,11 +22,13 @@ namespace OpenRA.Traits.Activities
|
|||||||
{
|
{
|
||||||
var csv = self.Info.Traits.GetOrDefault<CustomSellValueInfo>();
|
var csv = self.Info.Traits.GetOrDefault<CustomSellValueInfo>();
|
||||||
var cost = csv != null ? csv.Value : self.Info.Traits.Get<ValuedInfo>().Cost;
|
var cost = csv != null ? csv.Value : self.Info.Traits.Get<ValuedInfo>().Cost;
|
||||||
var hp = self.Info.Traits.Get<OwnedActorInfo>().HP;
|
|
||||||
var refund = self.World.Defaults.RefundPercent * self.Health * cost / hp;
|
|
||||||
|
|
||||||
self.Owner.PlayerActor.traits.Get<PlayerResources>().GiveCash((int)refund);
|
var health = self.traits.GetOrDefault<Health>();
|
||||||
self.Health = 0;
|
var refundFraction = self.World.Defaults.RefundPercent * (health == null ? 1f : health.HPFraction);
|
||||||
|
|
||||||
|
self.Owner.PlayerActor.traits.Get<PlayerResources>().GiveCash((int)(refundFraction * cost));
|
||||||
|
self.Kill(self);
|
||||||
|
|
||||||
foreach (var ns in self.traits.WithInterface<INotifySold>())
|
foreach (var ns in self.traits.WithInterface<INotifySold>())
|
||||||
ns.Sold(self);
|
ns.Sold(self);
|
||||||
self.World.AddFrameEndTask( _ => self.World.Remove( self ) );
|
self.World.AddFrameEndTask( _ => self.World.Remove( self ) );
|
||||||
|
|||||||
@@ -18,13 +18,7 @@ using OpenRA.Traits.Activities;
|
|||||||
|
|
||||||
namespace OpenRA.Traits
|
namespace OpenRA.Traits
|
||||||
{
|
{
|
||||||
public class OwnedActorInfo
|
public class BuildingInfo : ITraitInfo
|
||||||
{
|
|
||||||
public readonly int HP = 0;
|
|
||||||
public readonly ArmorType Armor = ArmorType.none;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BuildingInfo : OwnedActorInfo, ITraitInfo
|
|
||||||
{
|
{
|
||||||
public readonly int Power = 0;
|
public readonly int Power = 0;
|
||||||
public readonly bool BaseNormal = true;
|
public readonly bool BaseNormal = true;
|
||||||
@@ -44,14 +38,12 @@ namespace OpenRA.Traits
|
|||||||
public object Create(ActorInitializer init) { return new Building(init); }
|
public object Create(ActorInitializer init) { return new Building(init); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Building : INotifyDamage, IResolveOrder, ITick, IRenderModifier, IOccupySpace, IRadarSignature
|
public class Building : INotifyDamage, IResolveOrder, IRenderModifier, IOccupySpace, IRadarSignature
|
||||||
{
|
{
|
||||||
readonly Actor self;
|
readonly Actor self;
|
||||||
public readonly BuildingInfo Info;
|
public readonly BuildingInfo Info;
|
||||||
[Sync]
|
[Sync]
|
||||||
readonly int2 topLeft;
|
readonly int2 topLeft;
|
||||||
[Sync]
|
|
||||||
bool isRepairing = false;
|
|
||||||
|
|
||||||
public bool Disabled
|
public bool Disabled
|
||||||
{
|
{
|
||||||
@@ -74,10 +66,12 @@ namespace OpenRA.Traits
|
|||||||
.Select(t => t.GetPowerModifier())
|
.Select(t => t.GetPowerModifier())
|
||||||
.Product();
|
.Product();
|
||||||
|
|
||||||
var maxHP = self.Info.Traits.Get<BuildingInfo>().HP;
|
|
||||||
|
|
||||||
if (Info.Power > 0)
|
if (Info.Power > 0)
|
||||||
return (int)(modifier*(self.Health * Info.Power) / maxHP);
|
{
|
||||||
|
var health = self.traits.GetOrDefault<Health>();
|
||||||
|
var healthFraction = (health == null) ? 1f : health.HPFraction;
|
||||||
|
return (int)(modifier * healthFraction * Info.Power);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return (int)(modifier * Info.Power);
|
return (int)(modifier * Info.Power);
|
||||||
}
|
}
|
||||||
@@ -98,44 +92,6 @@ namespace OpenRA.Traits
|
|||||||
self.CancelActivity();
|
self.CancelActivity();
|
||||||
self.QueueActivity(new Sell());
|
self.QueueActivity(new Sell());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order.OrderString == "Repair")
|
|
||||||
{
|
|
||||||
isRepairing = !isRepairing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int remainingTicks;
|
|
||||||
|
|
||||||
public void Tick(Actor self)
|
|
||||||
{
|
|
||||||
if (!isRepairing) return;
|
|
||||||
|
|
||||||
if (remainingTicks == 0)
|
|
||||||
{
|
|
||||||
var csv = self.Info.Traits.GetOrDefault<CustomSellValueInfo>();
|
|
||||||
var buildingValue = csv != null ? csv.Value : self.Info.Traits.Get<ValuedInfo>().Cost;
|
|
||||||
var maxHP = self.Info.Traits.Get<BuildingInfo>().HP;
|
|
||||||
var costPerHp = (self.World.Defaults.RepairPercent * buildingValue) / maxHP;
|
|
||||||
var hpToRepair = Math.Min(self.World.Defaults.RepairStep, maxHP - self.Health);
|
|
||||||
var cost = (int)Math.Ceiling(costPerHp * hpToRepair);
|
|
||||||
if (!self.Owner.PlayerActor.traits.Get<PlayerResources>().TakeCash(cost))
|
|
||||||
{
|
|
||||||
remainingTicks = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.World.AddFrameEndTask(w => w.Add(new RepairIndicator(self)));
|
|
||||||
self.InflictDamage(self, -hpToRepair, null);
|
|
||||||
if (self.Health == maxHP)
|
|
||||||
{
|
|
||||||
isRepairing = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
remainingTicks = (int)(self.World.Defaults.RepairRate * 60 * 25);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
--remainingTicks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
|
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
|
||||||
|
|||||||
186
OpenRA.Game/Traits/Health.cs
Normal file
186
OpenRA.Game/Traits/Health.cs
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see LICENSE.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Effects;
|
||||||
|
using OpenRA.Traits.Activities;
|
||||||
|
using OpenRA.GameRules;
|
||||||
|
|
||||||
|
namespace OpenRA.Traits
|
||||||
|
{
|
||||||
|
public class HealthInfo : ITraitInfo
|
||||||
|
{
|
||||||
|
public readonly int HP = 0;
|
||||||
|
public readonly int InitialHP = 0;
|
||||||
|
public readonly ArmorType Armor = ArmorType.none;
|
||||||
|
|
||||||
|
public readonly float ConditionRed = 0.25f;
|
||||||
|
public readonly float ConditionYellow = 0.5f;
|
||||||
|
|
||||||
|
public virtual object Create(ActorInitializer init) { return new Health(init, this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ExtendedDamageState { Normal, ThreeQuarter, Half, Quarter, Dead };
|
||||||
|
|
||||||
|
public class Health
|
||||||
|
{
|
||||||
|
public readonly HealthInfo Info;
|
||||||
|
|
||||||
|
[Sync]
|
||||||
|
int hp;
|
||||||
|
|
||||||
|
public Health(ActorInitializer init, HealthInfo info)
|
||||||
|
{
|
||||||
|
Info = info;
|
||||||
|
MaxHP = info.HP;
|
||||||
|
hp = (info.InitialHP == 0) ? MaxHP : info.InitialHP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int HP { get { return hp; } }
|
||||||
|
public readonly int MaxHP;
|
||||||
|
public float HPFraction { get { return hp*1f/MaxHP; } }
|
||||||
|
|
||||||
|
public bool IsDead { get { return hp <= 0; } }
|
||||||
|
public bool RemoveOnDeath = true;
|
||||||
|
|
||||||
|
public Color HealthColor
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (hp < Info.ConditionRed) ? Color.Red
|
||||||
|
: (hp < Info.ConditionYellow) ? Color.Yellow
|
||||||
|
: Color.LimeGreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DamageState DamageState
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (hp <= 0)
|
||||||
|
return DamageState.Dead;
|
||||||
|
|
||||||
|
if (hp < MaxHP * Info.ConditionYellow)
|
||||||
|
return DamageState.Half;
|
||||||
|
|
||||||
|
return DamageState.Normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedDamageState ExtendedDamageState
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (hp <= 0)
|
||||||
|
return ExtendedDamageState.Dead;
|
||||||
|
|
||||||
|
if (hp < MaxHP * Info.ConditionRed)
|
||||||
|
return ExtendedDamageState.Quarter;
|
||||||
|
|
||||||
|
if (hp < MaxHP * Info.ConditionYellow)
|
||||||
|
return ExtendedDamageState.Half;
|
||||||
|
|
||||||
|
if (hp < MaxHP * 0.75)
|
||||||
|
return ExtendedDamageState.ThreeQuarter;
|
||||||
|
|
||||||
|
return ExtendedDamageState.Normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InflictDamage(Actor self, Actor attacker, int damage, WarheadInfo warhead)
|
||||||
|
{
|
||||||
|
if (IsDead) return; /* overkill! don't count extra hits as more kills! */
|
||||||
|
|
||||||
|
var oldState = this.DamageState;
|
||||||
|
var oldExtendedState = this.ExtendedDamageState;
|
||||||
|
|
||||||
|
/* apply the damage modifiers, if we have any. */
|
||||||
|
var modifier = (float)self.traits.WithInterface<IDamageModifier>()
|
||||||
|
.Select(t => t.GetDamageModifier(warhead)).Product();
|
||||||
|
|
||||||
|
damage = (int)(damage * modifier);
|
||||||
|
|
||||||
|
hp -= damage;
|
||||||
|
if (hp <= 0)
|
||||||
|
{
|
||||||
|
hp = 0;
|
||||||
|
|
||||||
|
attacker.Owner.Kills++;
|
||||||
|
self.Owner.Deaths++;
|
||||||
|
|
||||||
|
if (RemoveOnDeath)
|
||||||
|
self.World.AddFrameEndTask(w => w.Remove(self));
|
||||||
|
|
||||||
|
Log.Write("debug", "{0} #{1} killed by {2} #{3}", self.Info.Name, self.ActorID, attacker.Info.Name, attacker.ActorID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hp > MaxHP) hp = MaxHP;
|
||||||
|
|
||||||
|
foreach (var nd in self.traits.WithInterface<INotifyDamage>())
|
||||||
|
nd.Damaged(self, new AttackInfo
|
||||||
|
{
|
||||||
|
Attacker = attacker,
|
||||||
|
Damage = damage,
|
||||||
|
DamageState = this.DamageState,
|
||||||
|
ExtendedDamageState = this.ExtendedDamageState,
|
||||||
|
DamageStateChanged = this.DamageState != oldState,
|
||||||
|
ExtendedDamageStateChanged = this.ExtendedDamageState != oldExtendedState,
|
||||||
|
Warhead = warhead
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TransferHPFromActor(Actor self, Actor from, bool transferPercentage)
|
||||||
|
{
|
||||||
|
var fromHealth = from.traits.GetOrDefault<Health>();
|
||||||
|
if (fromHealth == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hp = (transferPercentage) ? (int)(fromHealth.HPFraction*MaxHP) : Math.Min(fromHealth.HP, MaxHP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HealthExts
|
||||||
|
{
|
||||||
|
public static int Health(this Actor self)
|
||||||
|
{
|
||||||
|
var health = self.traits.GetOrDefault<Health>();
|
||||||
|
return (health == null) ? 0 : health.HP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsDead(this Actor self)
|
||||||
|
{
|
||||||
|
var health = self.traits.GetOrDefault<Health>();
|
||||||
|
return (health == null) ? true : health.IsDead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DamageState GetDamageState(this Actor self)
|
||||||
|
{
|
||||||
|
var health = self.traits.GetOrDefault<Health>();
|
||||||
|
return (health == null) ? DamageState.Normal : health.DamageState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void InflictDamage(this Actor self, Actor attacker, int damage, WarheadInfo warhead)
|
||||||
|
{
|
||||||
|
var health = self.traits.GetOrDefault<Health>();
|
||||||
|
if (health == null) return;
|
||||||
|
health.InflictDamage(self, attacker, damage, warhead);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Kill(this Actor self, Actor attacker)
|
||||||
|
{
|
||||||
|
var health = self.traits.GetOrDefault<Health>();
|
||||||
|
if (health == null) return;
|
||||||
|
health.InflictDamage(self, attacker, health.HP, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
85
OpenRA.Game/Traits/RepairableBuilding.cs
Normal file
85
OpenRA.Game/Traits/RepairableBuilding.cs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see LICENSE.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Effects;
|
||||||
|
using OpenRA.GameRules;
|
||||||
|
using OpenRA.Traits.Activities;
|
||||||
|
|
||||||
|
namespace OpenRA.Traits
|
||||||
|
{
|
||||||
|
public class RepairableBuildingInfo : ITraitInfo, ITraitPrerequisite<HealthInfo>
|
||||||
|
{
|
||||||
|
public readonly float RepairPercent = 0.2f;
|
||||||
|
public readonly float RepairRate = 0.016f;
|
||||||
|
public readonly int RepairStep = 7;
|
||||||
|
public object Create(ActorInitializer init) { return new RepairableBuilding(init.self, this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RepairableBuilding : ITick, IResolveOrder
|
||||||
|
{
|
||||||
|
[Sync]
|
||||||
|
bool isRepairing = false;
|
||||||
|
|
||||||
|
Health Health;
|
||||||
|
RepairableBuildingInfo Info;
|
||||||
|
public RepairableBuilding(Actor self, RepairableBuildingInfo info)
|
||||||
|
{
|
||||||
|
Health = self.traits.Get<Health>();
|
||||||
|
Info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResolveOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
if (order.OrderString == "Repair")
|
||||||
|
{
|
||||||
|
isRepairing = !isRepairing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int remainingTicks;
|
||||||
|
public void Tick(Actor self)
|
||||||
|
{
|
||||||
|
if (!isRepairing) return;
|
||||||
|
|
||||||
|
if (remainingTicks == 0)
|
||||||
|
{
|
||||||
|
var csv = self.Info.Traits.GetOrDefault<CustomSellValueInfo>();
|
||||||
|
var buildingValue = csv != null ? csv.Value : self.Info.Traits.Get<ValuedInfo>().Cost;
|
||||||
|
|
||||||
|
var costPerHp = (Info.RepairPercent * buildingValue) / Health.MaxHP;
|
||||||
|
var hpToRepair = Math.Min(Info.RepairStep, Health.MaxHP - Health.HP);
|
||||||
|
var cost = (int)Math.Ceiling(costPerHp * hpToRepair);
|
||||||
|
if (!self.Owner.PlayerActor.traits.Get<PlayerResources>().TakeCash(cost))
|
||||||
|
{
|
||||||
|
remainingTicks = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.World.AddFrameEndTask(w => w.Add(new RepairIndicator(self)));
|
||||||
|
self.InflictDamage(self, -hpToRepair, null);
|
||||||
|
if (Health.HP == Health.MaxHP)
|
||||||
|
{
|
||||||
|
isRepairing = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
remainingTicks = (int)(Info.RepairRate * 60 * 25);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
--remainingTicks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class AllowsBuildingRepairInfo : TraitInfo<AllowsBuildingRepair> {}
|
||||||
|
public class AllowsBuildingRepair {}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -61,22 +61,22 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
void DrawHealthBar(Actor self, float2 xy, float2 Xy)
|
void DrawHealthBar(Actor self, float2 xy, float2 Xy)
|
||||||
{
|
{
|
||||||
|
var health = self.traits.GetOrDefault<Health>();
|
||||||
|
if (health == null)
|
||||||
|
return;
|
||||||
|
|
||||||
var c = Color.Gray;
|
var c = Color.Gray;
|
||||||
Game.Renderer.LineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c);
|
Game.Renderer.LineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c);
|
||||||
Game.Renderer.LineRenderer.DrawLine(Xy + new float2(0, -2), Xy + new float2(0, -4), c, c);
|
Game.Renderer.LineRenderer.DrawLine(Xy + new float2(0, -2), Xy + new float2(0, -4), c, c);
|
||||||
|
|
||||||
var healthAmount = (float)self.Health / self.Info.Traits.Get<OwnedActorInfo>().HP;
|
var healthColor = health.HealthColor;
|
||||||
var healthColor = (healthAmount < self.World.Defaults.ConditionRed) ? Color.Red
|
|
||||||
: (healthAmount < self.World.Defaults.ConditionYellow) ? Color.Yellow
|
|
||||||
: Color.LimeGreen;
|
|
||||||
|
|
||||||
var healthColor2 = Color.FromArgb(
|
var healthColor2 = Color.FromArgb(
|
||||||
255,
|
255,
|
||||||
healthColor.R / 2,
|
healthColor.R / 2,
|
||||||
healthColor.G / 2,
|
healthColor.G / 2,
|
||||||
healthColor.B / 2);
|
healthColor.B / 2);
|
||||||
|
|
||||||
var z = float2.Lerp(xy, Xy, healthAmount);
|
var z = float2.Lerp(xy, Xy, health.HPFraction);
|
||||||
|
|
||||||
Game.Renderer.LineRenderer.DrawLine(z + new float2(0, -4), Xy + new float2(0, -4), c, c);
|
Game.Renderer.LineRenderer.DrawLine(z + new float2(0, -4), Xy + new float2(0, -4), c, c);
|
||||||
Game.Renderer.LineRenderer.DrawLine(z + new float2(0, -2), Xy + new float2(0, -2), c, c);
|
Game.Renderer.LineRenderer.DrawLine(z + new float2(0, -2), Xy + new float2(0, -2), c, c);
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ namespace OpenRA.Traits
|
|||||||
public WarheadInfo Warhead;
|
public WarheadInfo Warhead;
|
||||||
public int Damage;
|
public int Damage;
|
||||||
public DamageState DamageState;
|
public DamageState DamageState;
|
||||||
|
public ExtendedDamageState ExtendedDamageState;
|
||||||
public bool DamageStateChanged;
|
public bool DamageStateChanged;
|
||||||
|
public bool ExtendedDamageStateChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ITick { void Tick(Actor self); }
|
public interface ITick { void Tick(Actor self); }
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace OpenRA.Traits
|
namespace OpenRA.Traits
|
||||||
{
|
{
|
||||||
public class UnitInfo : OwnedActorInfo, ITraitInfo
|
public class UnitInfo : ITraitInfo
|
||||||
{
|
{
|
||||||
public readonly int InitialFacing = 128;
|
public readonly int InitialFacing = 128;
|
||||||
public readonly int ROT = 255;
|
public readonly int ROT = 255;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ namespace OpenRA.Traits
|
|||||||
public void Update(Actor self, IOccupyAir unit)
|
public void Update(Actor self, IOccupyAir unit)
|
||||||
{
|
{
|
||||||
Remove(self, unit);
|
Remove(self, unit);
|
||||||
if (!self.IsDead) Add(self, unit);
|
if (!self.IsDead()) Add(self, unit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,6 @@ namespace OpenRA.Traits
|
|||||||
public readonly float RepairPercent = 0.2f;
|
public readonly float RepairPercent = 0.2f;
|
||||||
public readonly float RepairRate = 0.016f;
|
public readonly float RepairRate = 0.016f;
|
||||||
public readonly int RepairStep = 7;
|
public readonly int RepairStep = 7;
|
||||||
|
|
||||||
/* Audo/Visual Map Controls */
|
|
||||||
public readonly float ConditionRed = 0.25f;
|
|
||||||
public readonly float ConditionYellow = 0.5f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GlobalDefaults {}
|
public class GlobalDefaults {}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ namespace OpenRA.Traits
|
|||||||
public void Update(Actor self, IOccupySpace unit)
|
public void Update(Actor self, IOccupySpace unit)
|
||||||
{
|
{
|
||||||
Remove(self, unit);
|
Remove(self, unit);
|
||||||
if (!self.IsDead) Add(self, unit);
|
if (!self.IsDead()) Add(self, unit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Cnc
|
namespace OpenRA.Mods.Cnc
|
||||||
{
|
{
|
||||||
class CriticalBuildingStateInfo : ITraitInfo
|
class CriticalBuildingStateInfo : ITraitInfo, ITraitPrerequisite<HealthInfo>
|
||||||
{
|
{
|
||||||
public readonly int LingerTime = 20;
|
public readonly int LingerTime = 20;
|
||||||
public object Create(ActorInitializer init) { return new CriticalBuildingState(init.self, this); }
|
public object Create(ActorInitializer init) { return new CriticalBuildingState(init.self, this); }
|
||||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.Cnc
|
|||||||
public CriticalBuildingState(Actor self, CriticalBuildingStateInfo info)
|
public CriticalBuildingState(Actor self, CriticalBuildingStateInfo info)
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.info = info;
|
||||||
self.RemoveOnDeath = false;
|
self.traits.Get<Health>().RemoveOnDeath = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Damaged(Actor self, AttackInfo e)
|
public void Damaged(Actor self, AttackInfo e)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace OpenRA.Mods.Cnc
|
|||||||
a.QueueActivity(new Land(self));
|
a.QueueActivity(new Land(self));
|
||||||
a.QueueActivity(new CallFunc(() =>
|
a.QueueActivity(new CallFunc(() =>
|
||||||
{
|
{
|
||||||
if (self.IsDead)
|
if (self.IsDead())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var actor = cargo.Unload(self);
|
var actor = cargo.Unload(self);
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace OpenRA.Mods.Cnc
|
|||||||
|
|
||||||
public void Damaged (Actor self, AttackInfo e)
|
public void Damaged (Actor self, AttackInfo e)
|
||||||
{
|
{
|
||||||
if (self.IsDead)
|
if (e.DamageState == DamageState.Dead)
|
||||||
CancelDock(self, dockedHarv);
|
CancelDock(self, dockedHarv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
|
|
||||||
public IActivity Tick(Actor self)
|
public IActivity Tick(Actor self)
|
||||||
{
|
{
|
||||||
if (target == null || target.IsDead) return NextActivity;
|
if (target == null || target.IsDead()) return NextActivity;
|
||||||
|
|
||||||
target.World.AddFrameEndTask(w =>
|
target.World.AddFrameEndTask(w =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
|
|
||||||
public IActivity Tick(Actor self)
|
public IActivity Tick(Actor self)
|
||||||
{
|
{
|
||||||
if (target == null || target.IsDead) return NextActivity;
|
if (target == null || target.IsDead()) return NextActivity;
|
||||||
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(25 * 2,
|
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(25 * 2,
|
||||||
() => target.InflictDamage(self, target.Health, null))));
|
() => target.Kill(self))));
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
|
|
||||||
public IActivity Tick(Actor self)
|
public IActivity Tick(Actor self)
|
||||||
{
|
{
|
||||||
if (target == null || target.IsDead) return NextActivity;
|
if (target == null || target.IsDead()) return NextActivity;
|
||||||
if (target.Owner == self.Owner) return NextActivity;
|
if (target.Owner == self.Owner) return NextActivity;
|
||||||
|
|
||||||
foreach (var t in target.traits.WithInterface<IAcceptSpy>())
|
foreach (var t in target.traits.WithInterface<IAcceptSpy>())
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
|
|
||||||
public IActivity Tick(Actor self)
|
public IActivity Tick(Actor self)
|
||||||
{
|
{
|
||||||
if (Structure != null && Structure.IsDead)
|
if (Structure != null && Structure.IsDead())
|
||||||
{
|
{
|
||||||
Structure = null;
|
Structure = null;
|
||||||
isCanceled = true;
|
isCanceled = true;
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
.SetPosition(self, Util.CellContaining(target.CenterLocation));
|
.SetPosition(self, Util.CellContaining(target.CenterLocation));
|
||||||
|
|
||||||
if (target.IsActor)
|
if (target.IsActor)
|
||||||
target.Actor.InflictDamage(self, target.Actor.Health, null); // kill it
|
target.Actor.Kill(self);
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,13 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
if (isCanceled) return NextActivity;
|
if (isCanceled) return NextActivity;
|
||||||
if (remainingTicks == 0)
|
if (remainingTicks == 0)
|
||||||
{
|
{
|
||||||
var unitCost = self.Info.Traits.Get<ValuedInfo>().Cost;
|
var health = self.traits.GetOrDefault<Health>();
|
||||||
var hp = self.Info.Traits.Get<OwnedActorInfo>().HP;
|
if (health == null) return NextActivity;
|
||||||
|
|
||||||
var costPerHp = (host.Info.Traits.Get<RepairsUnitsInfo>().URepairPercent * unitCost) / hp;
|
var unitCost = self.Info.Traits.Get<ValuedInfo>().Cost;
|
||||||
var hpToRepair = Math.Min(host.Info.Traits.Get<RepairsUnitsInfo>().URepairStep, hp - self.Health);
|
|
||||||
|
var costPerHp = (host.Info.Traits.Get<RepairsUnitsInfo>().URepairPercent * unitCost) / health.MaxHP;
|
||||||
|
var hpToRepair = Math.Min(host.Info.Traits.Get<RepairsUnitsInfo>().URepairStep, health.MaxHP - health.HP);
|
||||||
var cost = (int)Math.Ceiling(costPerHp * hpToRepair);
|
var cost = (int)Math.Ceiling(costPerHp * hpToRepair);
|
||||||
if (!self.Owner.PlayerActor.traits.Get<PlayerResources>().TakeCash(cost))
|
if (!self.Owner.PlayerActor.traits.Get<PlayerResources>().TakeCash(cost))
|
||||||
{
|
{
|
||||||
@@ -41,7 +43,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.InflictDamage(self, -hpToRepair, null);
|
self.InflictDamage(self, -hpToRepair, null);
|
||||||
if (self.Health == hp)
|
if (health.MaxHP == health.HP)
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
|
|
||||||
if (host != null)
|
if (host != null)
|
||||||
|
|||||||
@@ -22,11 +22,12 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
|
|
||||||
public IActivity Tick(Actor self)
|
public IActivity Tick(Actor self)
|
||||||
{
|
{
|
||||||
if (target == null || target.IsDead) return NextActivity;
|
if (target == null || target.IsDead()) return NextActivity;
|
||||||
if (target.Health == target.GetMaxHP())
|
var health = target.traits.Get<Health>();
|
||||||
|
if (health.HP == health.MaxHP)
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
|
|
||||||
target.InflictDamage(self, -target.GetMaxHP(), null);
|
target.InflictDamage(self, -health.MaxHP, null);
|
||||||
self.World.AddFrameEndTask(w => w.Remove(self));
|
self.World.AddFrameEndTask(w => w.Remove(self));
|
||||||
|
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
|
|||||||
@@ -47,7 +47,11 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
Sound.PlayToPlayer(self.Owner, s, self.CenterLocation);
|
Sound.PlayToPlayer(self.Owner, s, self.CenterLocation);
|
||||||
|
|
||||||
var a = w.CreateActor(actor, self.Location + offset, self.Owner);
|
var a = w.CreateActor(actor, self.Location + offset, self.Owner);
|
||||||
a.Health = GetHealthToTransfer(self, a, transferPercentage);
|
var health = a.traits.GetOrDefault<Health>();
|
||||||
|
if (health != null)
|
||||||
|
{
|
||||||
|
health.TransferHPFromActor(a, self, transferPercentage);
|
||||||
|
}
|
||||||
|
|
||||||
if (selected)
|
if (selected)
|
||||||
w.Selection.Add(w, a);
|
w.Selection.Add(w, a);
|
||||||
@@ -56,14 +60,5 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Cancel(Actor self) { isCanceled = true; NextActivity = null; }
|
public void Cancel(Actor self) { isCanceled = true; NextActivity = null; }
|
||||||
|
|
||||||
public static int GetHealthToTransfer(Actor from, Actor to, bool transferPercentage)
|
|
||||||
{
|
|
||||||
var oldHP = from.GetMaxHP();
|
|
||||||
var newHP = to.GetMaxHP();
|
|
||||||
return (transferPercentage)
|
|
||||||
? (int)((float)from.Health / oldHP * newHP)
|
|
||||||
: Math.Min(from.Health, newHP);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,13 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
w.Remove(self);
|
w.Remove(self);
|
||||||
|
|
||||||
var mcv = w.CreateActor("mcv", self.Location + new int2(1, 1), self.Owner);
|
var mcv = w.CreateActor("mcv", self.Location + new int2(1, 1), self.Owner);
|
||||||
mcv.Health = TransformIntoActor.GetHealthToTransfer(self, mcv, true);
|
|
||||||
|
var health = mcv.traits.GetOrDefault<Health>();
|
||||||
|
if (health != null)
|
||||||
|
{
|
||||||
|
health.TransferHPFromActor(mcv, self, true);
|
||||||
|
}
|
||||||
|
|
||||||
mcv.traits.Get<Unit>().Facing = 96;
|
mcv.traits.Get<Unit>().Facing = 96;
|
||||||
|
|
||||||
if (selected)
|
if (selected)
|
||||||
|
|||||||
@@ -218,10 +218,16 @@ namespace OpenRA.Mods.RA
|
|||||||
{
|
{
|
||||||
// we can never "heal ground"; that makes no sense.
|
// we can never "heal ground"; that makes no sense.
|
||||||
if (!target.IsActor) return null;
|
if (!target.IsActor) return null;
|
||||||
|
|
||||||
// unless forced, only heal allies.
|
// unless forced, only heal allies.
|
||||||
if (self.Owner.Stances[underCursor.Owner] != Stance.Ally && !forceFire) return null;
|
if (self.Owner.Stances[underCursor.Owner] != Stance.Ally && !forceFire) return null;
|
||||||
|
|
||||||
|
// we can only heal actors with health
|
||||||
|
var health = underCursor.traits.GetOrDefault<Health>();
|
||||||
|
if (health == null) return null;
|
||||||
|
|
||||||
// don't allow healing of fully-healed stuff!
|
// don't allow healing of fully-healed stuff!
|
||||||
if (underCursor.Health >= underCursor.GetMaxHP()) return null;
|
if (health.HP >= health.MaxHP) return null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,8 +37,9 @@ namespace OpenRA.Mods.RA
|
|||||||
return true; // he's dead.
|
return true; // he's dead.
|
||||||
if ((attack.target.CenterLocation - self.Location).LengthSquared > range * range + 2)
|
if ((attack.target.CenterLocation - self.Location).LengthSquared > range * range + 2)
|
||||||
return true; // wandered off faster than we could follow
|
return true; // wandered off faster than we could follow
|
||||||
if (attack.target.IsActor && attack.target.Actor.Health
|
|
||||||
== attack.target.Actor.Info.Traits.Get<OwnedActorInfo>().HP)
|
var health = attack.target.Actor.traits.GetOrDefault<Health>();
|
||||||
|
if (attack.target.IsActor && health.HP == health.MaxHP)
|
||||||
return true; // fully healed
|
return true; // fully healed
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -59,7 +60,7 @@ namespace OpenRA.Mods.RA
|
|||||||
return inRange
|
return inRange
|
||||||
.Where(a => a != self && self.Owner.Stances[ a.Owner ] == Stance.Ally)
|
.Where(a => a != self && self.Owner.Stances[ a.Owner ] == Stance.Ally)
|
||||||
.Where(a => Combat.HasAnyValidWeapons(self, Target.FromActor(a)))
|
.Where(a => Combat.HasAnyValidWeapons(self, Target.FromActor(a)))
|
||||||
.Where(a => a.Health < a.Info.Traits.Get<OwnedActorInfo>().HP)
|
.Where(a => a.traits.Contains<Health>() && a.traits.Get<Health>().HPFraction < 1f)
|
||||||
.OrderBy(a => (a.Location - self.Location).LengthSquared)
|
.OrderBy(a => (a.Location - self.Location).LengthSquared)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,8 +66,6 @@ namespace OpenRA.Mods.RA
|
|||||||
{
|
{
|
||||||
if (!self.IsIdle) return;
|
if (!self.IsIdle) return;
|
||||||
|
|
||||||
if (!e.Attacker.Info.Traits.Contains<OwnedActorInfo>()) return;
|
|
||||||
|
|
||||||
// not a lot we can do about things we can't hurt... although maybe we should automatically run away?
|
// not a lot we can do about things we can't hurt... although maybe we should automatically run away?
|
||||||
if (!Combat.HasAnyValidWeapons(self, Target.FromActor(e.Attacker))) return;
|
if (!Combat.HasAnyValidWeapons(self, Target.FromActor(e.Attacker))) return;
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.RA
|
namespace OpenRA.Mods.RA
|
||||||
{
|
{
|
||||||
class BridgeInfo : ITraitInfo
|
class BridgeInfo : ITraitInfo, ITraitPrerequisite<HealthInfo>
|
||||||
{
|
{
|
||||||
public readonly bool Long = false;
|
public readonly bool Long = false;
|
||||||
|
|
||||||
@@ -75,11 +75,13 @@ namespace OpenRA.Mods.RA
|
|||||||
BridgeInfo Info;
|
BridgeInfo Info;
|
||||||
public string Type;
|
public string Type;
|
||||||
Bridge northNeighbour, southNeighbour;
|
Bridge northNeighbour, southNeighbour;
|
||||||
|
Health Health;
|
||||||
|
|
||||||
public Bridge(Actor self, BridgeInfo info)
|
public Bridge(Actor self, BridgeInfo info)
|
||||||
{
|
{
|
||||||
this.self = self;
|
this.self = self;
|
||||||
self.RemoveOnDeath = false;
|
Health = self.traits.Get<Health>();
|
||||||
|
Health.RemoveOnDeath = false;
|
||||||
this.Info = info;
|
this.Info = info;
|
||||||
this.Type = self.Info.Name;
|
this.Type = self.Info.Name;
|
||||||
}
|
}
|
||||||
@@ -88,9 +90,9 @@ namespace OpenRA.Mods.RA
|
|||||||
{
|
{
|
||||||
currentTemplate = template;
|
currentTemplate = template;
|
||||||
if (template == Info.DamagedTemplate)
|
if (template == Info.DamagedTemplate)
|
||||||
self.Health = (int)(self.World.Defaults.ConditionYellow*self.GetMaxHP());
|
Health.InflictDamage(self, self, Health.MaxHP/2, null);
|
||||||
else if (template != Info.Template)
|
else if (template != Info.Template)
|
||||||
self.Health = 0;
|
Health.InflictDamage(self, self, Health.MaxHP, null);
|
||||||
|
|
||||||
// Create a new cache to store the tile data
|
// Create a new cache to store the tile data
|
||||||
if (cachedTileset != self.World.Map.Tileset)
|
if (cachedTileset != self.World.Map.Tileset)
|
||||||
@@ -141,7 +143,7 @@ namespace OpenRA.Mods.RA
|
|||||||
|
|
||||||
bool IsIntact(Bridge b)
|
bool IsIntact(Bridge b)
|
||||||
{
|
{
|
||||||
return b != null && b.self.IsInWorld && b.self.Health > 0;
|
return b != null && b.self.IsInWorld && !b.self.IsDead();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KillUnitsOnBridge()
|
void KillUnitsOnBridge()
|
||||||
@@ -151,23 +153,21 @@ namespace OpenRA.Mods.RA
|
|||||||
foreach (var c in TileSprites[currentTemplate].Keys)
|
foreach (var c in TileSprites[currentTemplate].Keys)
|
||||||
foreach (var a in uim.GetUnitsAt(c))
|
foreach (var a in uim.GetUnitsAt(c))
|
||||||
if (!a.traits.Get<IMove>().CanEnterCell(c))
|
if (!a.traits.Get<IMove>().CanEnterCell(c))
|
||||||
a.InflictDamage(self, a.Health, null);
|
a.Kill(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dead = false;
|
bool dead = false;
|
||||||
void UpdateState()
|
void UpdateState()
|
||||||
{
|
{
|
||||||
var ds = self.GetDamageState();
|
|
||||||
|
|
||||||
// If this is a long bridge next to a destroyed shore piece, we need die to give clean edges to the break
|
// If this is a long bridge next to a destroyed shore piece, we need die to give clean edges to the break
|
||||||
if (Info.Long && ds != DamageState.Dead &&
|
if (Info.Long && Health.DamageState != DamageState.Dead &&
|
||||||
((southNeighbour != null && Info.ShorePieces.Contains(southNeighbour.Type) && !IsIntact(southNeighbour)) ||
|
((southNeighbour != null && Info.ShorePieces.Contains(southNeighbour.Type) && !IsIntact(southNeighbour)) ||
|
||||||
(northNeighbour != null && Info.ShorePieces.Contains(northNeighbour.Type) && !IsIntact(northNeighbour))))
|
(northNeighbour != null && Info.ShorePieces.Contains(northNeighbour.Type) && !IsIntact(northNeighbour))))
|
||||||
{
|
{
|
||||||
self.Health = 0;
|
self.Kill(self); // this changes the damagestate
|
||||||
ds = DamageState.Dead;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ds = Health.DamageState;
|
||||||
currentTemplate = (ds == DamageState.Half && Info.DamagedTemplate > 0) ? Info.DamagedTemplate :
|
currentTemplate = (ds == DamageState.Half && Info.DamagedTemplate > 0) ? Info.DamagedTemplate :
|
||||||
(ds == DamageState.Dead && Info.DestroyedTemplate > 0) ? Info.DestroyedTemplate : Info.Template;
|
(ds == DamageState.Dead && Info.DestroyedTemplate > 0) ? Info.DestroyedTemplate : Info.Template;
|
||||||
|
|
||||||
|
|||||||
@@ -94,8 +94,7 @@ namespace OpenRA.Mods.RA
|
|||||||
foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
|
foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
|
||||||
foreach (var unit in world.FindUnits(Game.CellSize * t, Game.CellSize * (t + new float2(1,1))))
|
foreach (var unit in world.FindUnits(Game.CellSize * t, Game.CellSize * (t + new float2(1,1))))
|
||||||
unit.InflictDamage(args.firedBy,
|
unit.InflictDamage(args.firedBy,
|
||||||
(int)(warhead.Damage * warhead.EffectivenessAgainst(
|
(int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead);
|
||||||
unit.Info.Traits.Get<OwnedActorInfo>().Armor)), warhead);
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,7 +153,7 @@ namespace OpenRA.Mods.RA
|
|||||||
var distance = (int)Math.Max(0, (target.CenterLocation - args.dest).Length - radius);
|
var distance = (int)Math.Max(0, (target.CenterLocation - args.dest).Length - radius);
|
||||||
var falloff = (float)GetDamageFalloff(distance / warhead.Spread);
|
var falloff = (float)GetDamageFalloff(distance / warhead.Spread);
|
||||||
var rawDamage = (float)(warhead.Damage * modifier * falloff);
|
var rawDamage = (float)(warhead.Damage * modifier * falloff);
|
||||||
var multiplier = (float)warhead.EffectivenessAgainst(target.Info.Traits.Get<OwnedActorInfo>().Armor);
|
var multiplier = (float)warhead.EffectivenessAgainst(target);
|
||||||
|
|
||||||
return (float)(rawDamage * multiplier);
|
return (float)(rawDamage * multiplier);
|
||||||
}
|
}
|
||||||
@@ -171,8 +170,7 @@ namespace OpenRA.Mods.RA
|
|||||||
if (targetable == null || !weapon.ValidTargets.Intersect(targetable.TargetTypes).Any())
|
if (targetable == null || !weapon.ValidTargets.Intersect(targetable.TargetTypes).Any())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var ownedInfo = target.Actor.Info.Traits.GetOrDefault<OwnedActorInfo>();
|
if (weapon.Warheads.All( w => w.EffectivenessAgainst(target.Actor) <= 0))
|
||||||
if (weapon.Warheads.All( w => w.EffectivenessAgainst(ownedInfo.Armor) <= 0))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA
|
|||||||
|
|
||||||
Game.Debug("{0} is defeated.".F(self.Owner.PlayerName));
|
Game.Debug("{0} is defeated.".F(self.Owner.PlayerName));
|
||||||
foreach (var a in self.World.Queries.OwnedBy[self.Owner])
|
foreach (var a in self.World.Queries.OwnedBy[self.Owner])
|
||||||
a.InflictDamage(a, a.Health, null);
|
a.Kill(a);
|
||||||
|
|
||||||
self.Owner.Shroud.Disabled = true;
|
self.Owner.Shroud.Disabled = true;
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA
|
|||||||
Sound.Play(report + ".aud", self.CenterLocation);
|
Sound.Play(report + ".aud", self.CenterLocation);
|
||||||
|
|
||||||
// Remove from world
|
// Remove from world
|
||||||
self.Health = 0;
|
self.Kill(self);
|
||||||
detonatedBy.Owner.Kills++;
|
detonatedBy.Owner.Kills++;
|
||||||
self.Owner.Deaths++;
|
self.Owner.Deaths++;
|
||||||
w.Remove(self);
|
w.Remove(self);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
|
|
||||||
public void Tick( World world )
|
public void Tick( World world )
|
||||||
{
|
{
|
||||||
if (a.IsDead || b.GetDamageModifier(null) > 0)
|
if (a.IsDead() || b.GetDamageModifier(null) > 0)
|
||||||
world.AddFrameEndTask(w => w.Remove(this));
|
world.AddFrameEndTask(w => w.Remove(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ namespace OpenRA.Mods.RA
|
|||||||
var csv = self.Info.Traits.GetOrDefault<CustomSellValueInfo>();
|
var csv = self.Info.Traits.GetOrDefault<CustomSellValueInfo>();
|
||||||
var valued = self.Info.Traits.GetOrDefault<ValuedInfo>();
|
var valued = self.Info.Traits.GetOrDefault<ValuedInfo>();
|
||||||
var cost = csv != null ? csv.Value : (valued != null ? valued.Cost : 0);
|
var cost = csv != null ? csv.Value : (valued != null ? valued.Cost : 0);
|
||||||
var hp = self.Info.Traits.Get<OwnedActorInfo>().HP;
|
|
||||||
var hpFraction = Math.Max(info.MinHpFraction, hp / self.GetMaxHP());
|
var health = self.traits.GetOrDefault<Health>();
|
||||||
|
var hpFraction = (health == null) ? 1f : health.HPFraction;
|
||||||
var dudesValue = (int)(hpFraction * info.ValueFraction * cost);
|
var dudesValue = (int)(hpFraction * info.ValueFraction * cost);
|
||||||
var eligibleLocations = Footprint.Tiles(self).ToList();
|
var eligibleLocations = Footprint.Tiles(self).ToList();
|
||||||
var actorTypes = info.ActorTypes.Select(a => new { Name = a, Cost = Rules.Info[a].Traits.Get<ValuedInfo>().Cost }).ToArray();
|
var actorTypes = info.ActorTypes.Select(a => new { Name = a, Cost = Rules.Info[a].Traits.Get<ValuedInfo>().Cost }).ToArray();
|
||||||
|
|||||||
@@ -39,19 +39,25 @@ namespace OpenRA.Mods.RA
|
|||||||
{
|
{
|
||||||
if (order.OrderString != "EngineerRepair") return null;
|
if (order.OrderString != "EngineerRepair") return null;
|
||||||
if (order.TargetActor == null) return null;
|
if (order.TargetActor == null) return null;
|
||||||
|
var health = order.TargetActor.traits.GetOrDefault<Health>();
|
||||||
return (order.TargetActor.Health == order.TargetActor.GetMaxHP()) ? "goldwrench-blocked" : "goldwrench";
|
if (health == null) return null;
|
||||||
|
return (health.HP == health.MaxHP) ? "goldwrench-blocked" : "goldwrench";
|
||||||
}
|
}
|
||||||
|
|
||||||
public string VoicePhraseForOrder(Actor self, Order order)
|
public string VoicePhraseForOrder(Actor self, Order order)
|
||||||
{
|
{
|
||||||
|
var health = order.TargetActor.traits.GetOrDefault<Health>();
|
||||||
|
if (health == null) return null;
|
||||||
return (order.OrderString == "EngineerRepair"
|
return (order.OrderString == "EngineerRepair"
|
||||||
&& order.TargetActor.Health < order.TargetActor.GetMaxHP()) ? "Attack" : null;
|
&& health.HP < health.MaxHP) ? "Attack" : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResolveOrder(Actor self, Order order)
|
public void ResolveOrder(Actor self, Order order)
|
||||||
{
|
{
|
||||||
if (order.OrderString == "EngineerRepair" && order.TargetActor.Health < order.TargetActor.GetMaxHP())
|
var health = order.TargetActor.traits.GetOrDefault<Health>();
|
||||||
|
if (health == null) return;
|
||||||
|
|
||||||
|
if (order.OrderString == "EngineerRepair" && health.HP < health.MaxHP)
|
||||||
{
|
{
|
||||||
if (self.Owner == self.World.LocalPlayer)
|
if (self.Owner == self.World.LocalPlayer)
|
||||||
self.World.AddFrameEndTask(w =>
|
self.World.AddFrameEndTask(w =>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace OpenRA.Mods.RA
|
|||||||
{
|
{
|
||||||
public void Damaged(Actor self, AttackInfo e)
|
public void Damaged(Actor self, AttackInfo e)
|
||||||
{
|
{
|
||||||
if (self.IsDead)
|
if (e.DamageState == DamageState.Dead)
|
||||||
{
|
{
|
||||||
var weapon = ChooseWeaponForExplosion(self);
|
var weapon = ChooseWeaponForExplosion(self);
|
||||||
if (weapon != null)
|
if (weapon != null)
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ namespace OpenRA.Mods.RA
|
|||||||
|
|
||||||
public void Damaged(Actor self, AttackInfo e)
|
public void Damaged(Actor self, AttackInfo e)
|
||||||
{
|
{
|
||||||
if (self.IsDead)
|
if (e.DamageState == DamageState.Dead)
|
||||||
if (LinkedProc != null)
|
if (LinkedProc != null)
|
||||||
LinkedProc.traits.WithInterface<IAcceptOre>().FirstOrDefault().UnlinkHarvester(LinkedProc,self);
|
LinkedProc.traits.WithInterface<IAcceptOre>().FirstOrDefault().UnlinkHarvester(LinkedProc,self);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ namespace OpenRA.Mods.RA
|
|||||||
|
|
||||||
public void Tick(World world)
|
public void Tick(World world)
|
||||||
{
|
{
|
||||||
if (minelayer.IsDead || !minelayer.IsInWorld)
|
if (minelayer.IsDead() || !minelayer.IsInWorld)
|
||||||
world.CancelInputMode();
|
world.CancelInputMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ namespace OpenRA.Mods.RA.Orders
|
|||||||
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
||||||
|
|
||||||
var building = underCursor != null ? underCursor.Info.Traits.Get<BuildingInfo>() : null;
|
var building = underCursor != null ? underCursor.Info.Traits.Get<BuildingInfo>() : null;
|
||||||
|
var health = underCursor != null ? underCursor.traits.GetOrDefault<Health>() : null;
|
||||||
|
|
||||||
if (building != null && building.Repairable && underCursor.Health < building.HP)
|
if (building != null && building.Repairable && health != null && health.HPFraction < 1f)
|
||||||
yield return new Order("Repair", underCursor);
|
yield return new Order("Repair", underCursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ namespace OpenRA.Mods.RA
|
|||||||
|
|
||||||
public void Damaged (Actor self, AttackInfo e)
|
public void Damaged (Actor self, AttackInfo e)
|
||||||
{
|
{
|
||||||
if (self.IsDead)
|
if (e.DamageState == DamageState.Dead)
|
||||||
foreach (var harv in LinkedHarv)
|
foreach (var harv in LinkedHarv)
|
||||||
harv.traits.Get<Harvester> ().UnlinkProc(harv, self);
|
harv.traits.Get<Harvester> ().UnlinkProc(harv, self);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,37 +31,13 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
anim.PlayFetchIndex(seqName, () => adjacentWalls);
|
anim.PlayFetchIndex(seqName, () => adjacentWalls);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ExtendedDamageState { Normal, ThreeQuarter, Half, Quarter, Dead };
|
|
||||||
|
|
||||||
ExtendedDamageState GetExtendedState( Actor self, int damage )
|
|
||||||
{
|
|
||||||
var effectiveHealth = self.Health + damage;
|
|
||||||
|
|
||||||
if (effectiveHealth <= 0)
|
|
||||||
return ExtendedDamageState.Dead;
|
|
||||||
|
|
||||||
if (effectiveHealth < self.GetMaxHP() * self.World.Defaults.ConditionRed)
|
|
||||||
return ExtendedDamageState.Quarter;
|
|
||||||
|
|
||||||
if (effectiveHealth < self.GetMaxHP() * self.World.Defaults.ConditionYellow)
|
|
||||||
return ExtendedDamageState.Half;
|
|
||||||
|
|
||||||
if (effectiveHealth < self.GetMaxHP() * 0.75)
|
|
||||||
return ExtendedDamageState.ThreeQuarter;
|
|
||||||
|
|
||||||
return ExtendedDamageState.Normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Damaged(Actor self, AttackInfo e)
|
public override void Damaged(Actor self, AttackInfo e)
|
||||||
{
|
{
|
||||||
var oldState = GetExtendedState(self, e.Damage);
|
|
||||||
var newState = GetExtendedState(self, 0);
|
|
||||||
|
|
||||||
var numStates = self.Info.Traits.Get<RenderBuildingWallInfo>().DamageStates;
|
var numStates = self.Info.Traits.Get<RenderBuildingWallInfo>().DamageStates;
|
||||||
|
|
||||||
if (oldState == newState) return;
|
if (!e.ExtendedDamageStateChanged) return;
|
||||||
|
|
||||||
switch (newState)
|
switch (e.ExtendedDamageState)
|
||||||
{
|
{
|
||||||
case ExtendedDamageState.Normal:
|
case ExtendedDamageState.Normal:
|
||||||
seqName = "idle";
|
seqName = "idle";
|
||||||
|
|||||||
@@ -17,10 +17,21 @@ using System.Drawing;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.RA
|
namespace OpenRA.Mods.RA
|
||||||
{
|
{
|
||||||
class RepairableInfo : TraitInfo<Repairable> { public readonly string[] RepairBuildings = { "fix" }; }
|
class RepairableInfo : ITraitInfo, ITraitPrerequisite<HealthInfo>
|
||||||
|
{
|
||||||
|
public readonly string[] RepairBuildings = { "fix" };
|
||||||
|
|
||||||
|
public virtual object Create(ActorInitializer init) { return new Repairable(init.self); }
|
||||||
|
}
|
||||||
|
|
||||||
class Repairable : IIssueOrder, IResolveOrder, IOrderCursor, IOrderVoice
|
class Repairable : IIssueOrder, IResolveOrder, IOrderCursor, IOrderVoice
|
||||||
{
|
{
|
||||||
|
Health Health;
|
||||||
|
public Repairable(Actor self)
|
||||||
|
{
|
||||||
|
Health = self.traits.Get<Health>();
|
||||||
|
}
|
||||||
|
|
||||||
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) return null;
|
if (mi.Button != MouseButton.Right) return null;
|
||||||
@@ -36,7 +47,7 @@ namespace OpenRA.Mods.RA
|
|||||||
bool CanRepair(Actor self)
|
bool CanRepair(Actor self)
|
||||||
{
|
{
|
||||||
var li = self.traits.GetOrDefault<LimitedAmmo>();
|
var li = self.traits.GetOrDefault<LimitedAmmo>();
|
||||||
return (self.Health < self.GetMaxHP() || (li != null && !li.FullAmmo()) );
|
return (Health.HPFraction < 1f || (li != null && !li.FullAmmo()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public string CursorForOrder(Actor self, Order order)
|
public string CursorForOrder(Actor self, Order order)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ using System.Drawing;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.RA
|
namespace OpenRA.Mods.RA
|
||||||
{
|
{
|
||||||
class RepairableNearInfo : TraitInfo<RepairableNear>
|
class RepairableNearInfo : TraitInfo<RepairableNear>, ITraitPrerequisite<HealthInfo>
|
||||||
{
|
{
|
||||||
[ActorReference]
|
[ActorReference]
|
||||||
public readonly string[] Buildings = { "spen", "syrd" };
|
public readonly string[] Buildings = { "spen", "syrd" };
|
||||||
@@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA
|
|||||||
|
|
||||||
if (underCursor.Owner == self.Owner &&
|
if (underCursor.Owner == self.Owner &&
|
||||||
self.Info.Traits.Get<RepairableNearInfo>().Buildings.Contains( underCursor.Info.Name ) &&
|
self.Info.Traits.Get<RepairableNearInfo>().Buildings.Contains( underCursor.Info.Name ) &&
|
||||||
self.Health < self.GetMaxHP())
|
self.traits.Get<Health>().HPFraction < 1f)
|
||||||
return new Order("Enter", self, underCursor);
|
return new Order("Enter", self, underCursor);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA
|
|||||||
if (reservedFor == null)
|
if (reservedFor == null)
|
||||||
return; /* nothing to do */
|
return; /* nothing to do */
|
||||||
|
|
||||||
if (reservedFor.IsDead) reservedFor = null; /* not likely to arrive now. */
|
if (reservedFor.IsDead()) reservedFor = null; /* not likely to arrive now. */
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDisposable Reserve(Actor forActor)
|
public IDisposable Reserve(Actor forActor)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.RA
|
namespace OpenRA.Mods.RA
|
||||||
{
|
{
|
||||||
class SelfHealingInfo : TraitInfo<SelfHealing>
|
class SelfHealingInfo : TraitInfo<SelfHealing>, ITraitPrerequisite<HealthInfo>
|
||||||
{
|
{
|
||||||
public readonly int Step = 5;
|
public readonly int Step = 5;
|
||||||
public readonly int Ticks = 5;
|
public readonly int Ticks = 5;
|
||||||
@@ -27,8 +27,7 @@ namespace OpenRA.Mods.RA
|
|||||||
public void Tick(Actor self)
|
public void Tick(Actor self)
|
||||||
{
|
{
|
||||||
var info = self.Info.Traits.Get<SelfHealingInfo>();
|
var info = self.Info.Traits.Get<SelfHealingInfo>();
|
||||||
|
if (self.traits.Get<Health>().HPFraction >= info.HealIfBelow)
|
||||||
if ((float)self.Health / self.GetMaxHP() >= info.HealIfBelow)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (--ticks <= 0)
|
if (--ticks <= 0)
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ namespace OpenRA.Mods.RA
|
|||||||
|
|
||||||
public void Damaged(Actor self, AttackInfo e)
|
public void Damaged(Actor self, AttackInfo e)
|
||||||
{
|
{
|
||||||
if (self.IsDead && Player.GetSiloFullness() > 0)
|
if (self.IsDead() && Player.GetSiloFullness() > 0)
|
||||||
Player.TakeOre(Stored(self)); // Lose the stored ore
|
Player.TakeOre(Stored(self)); // Lose the stored ore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,6 @@ namespace OpenRA.Mods.RA
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<string> CrushClasses { get { return info.CrushClasses; } }
|
public IEnumerable<string> CrushClasses { get { return info.CrushClasses; } }
|
||||||
public void OnCrush(Actor crusher) { self.InflictDamage(crusher, self.Health, null); }
|
public void OnCrush(Actor crusher) { self.Kill(crusher); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ V33:
|
|||||||
BARB:
|
BARB:
|
||||||
Inherits: ^Wall
|
Inherits: ^Wall
|
||||||
Building:
|
Building:
|
||||||
|
Health:
|
||||||
HP: 100
|
HP: 100
|
||||||
Armor: none
|
Armor: none
|
||||||
Valued:
|
Valued:
|
||||||
@@ -152,6 +153,7 @@ BARB:
|
|||||||
WOOD:
|
WOOD:
|
||||||
Inherits: ^Wall
|
Inherits: ^Wall
|
||||||
Building:
|
Building:
|
||||||
|
Health:
|
||||||
HP: 100
|
HP: 100
|
||||||
Armor: none
|
Armor: none
|
||||||
Valued:
|
Valued:
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
^Infantry:
|
^Infantry:
|
||||||
Category: Infantry
|
Category: Infantry
|
||||||
Unit:
|
Unit:
|
||||||
|
Health:
|
||||||
Armor: none
|
Armor: none
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 4
|
Range: 4
|
||||||
@@ -119,10 +120,11 @@
|
|||||||
|
|
||||||
^CivBuilding:
|
^CivBuilding:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
Building:
|
Health:
|
||||||
Repairable: false
|
|
||||||
HP: 400
|
HP: 400
|
||||||
Armor: wood
|
Armor: wood
|
||||||
|
Building:
|
||||||
|
Repairable: false
|
||||||
Valued:
|
Valued:
|
||||||
Description: Civilian Building
|
Description: Civilian Building
|
||||||
|
|
||||||
@@ -186,6 +188,7 @@
|
|||||||
Unit:
|
Unit:
|
||||||
ROT: 0
|
ROT: 0
|
||||||
Speed: 0
|
Speed: 0
|
||||||
|
Health:
|
||||||
HP: 140
|
HP: 140
|
||||||
Armor: Heavy
|
Armor: Heavy
|
||||||
Husk:
|
Husk:
|
||||||
@@ -201,11 +204,12 @@
|
|||||||
Targetable:
|
Targetable:
|
||||||
TargetTypes: Ground, Water
|
TargetTypes: Ground, Water
|
||||||
BelowUnits:
|
BelowUnits:
|
||||||
|
Health:
|
||||||
|
HP: 1000
|
||||||
Building:
|
Building:
|
||||||
DamagedSound: xplos.aud
|
DamagedSound: xplos.aud
|
||||||
DestroyedSound: xplobig4.aud
|
DestroyedSound: xplobig4.aud
|
||||||
Footprint: ______ ______ ______ ______
|
Footprint: ______ ______ ______ ______
|
||||||
Dimensions: 6,4
|
Dimensions: 6,4
|
||||||
HP: 1000
|
|
||||||
RadarColorFromTerrain:
|
RadarColorFromTerrain:
|
||||||
Terrain: Road
|
Terrain: Road
|
||||||
@@ -10,8 +10,9 @@ E1:
|
|||||||
Selectable:
|
Selectable:
|
||||||
Bounds: 12,17,0,-6
|
Bounds: 12,17,0,-6
|
||||||
Unit:
|
Unit:
|
||||||
HP: 50
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 50
|
||||||
AttackBase:
|
AttackBase:
|
||||||
PrimaryWeapon: M16
|
PrimaryWeapon: M16
|
||||||
TakeCover:
|
TakeCover:
|
||||||
@@ -29,8 +30,9 @@ E2:
|
|||||||
Selectable:
|
Selectable:
|
||||||
Bounds: 12,17,0,-6
|
Bounds: 12,17,0,-6
|
||||||
Unit:
|
Unit:
|
||||||
HP: 50
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 50
|
||||||
AttackBase:
|
AttackBase:
|
||||||
PrimaryWeapon: Grenade
|
PrimaryWeapon: Grenade
|
||||||
PrimaryOffset: 0,0,0,-10
|
PrimaryOffset: 0,0,0,-10
|
||||||
@@ -49,8 +51,9 @@ E3:
|
|||||||
Selectable:
|
Selectable:
|
||||||
Bounds: 12,17,0,-6
|
Bounds: 12,17,0,-6
|
||||||
Unit:
|
Unit:
|
||||||
HP: 45
|
|
||||||
Speed: 3
|
Speed: 3
|
||||||
|
Health:
|
||||||
|
HP: 45
|
||||||
AttackBase:
|
AttackBase:
|
||||||
PrimaryWeapon: Rockets
|
PrimaryWeapon: Rockets
|
||||||
PrimaryOffset: 0,0,0,-10
|
PrimaryOffset: 0,0,0,-10
|
||||||
@@ -70,8 +73,9 @@ E4:
|
|||||||
Selectable:
|
Selectable:
|
||||||
Bounds: 12,17,0,-6
|
Bounds: 12,17,0,-6
|
||||||
Unit:
|
Unit:
|
||||||
HP: 90
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 90
|
||||||
AttackBase:
|
AttackBase:
|
||||||
PrimaryWeapon: Flamethrower
|
PrimaryWeapon: Flamethrower
|
||||||
PrimaryOffset: 0,0,0,-5
|
PrimaryOffset: 0,0,0,-5
|
||||||
@@ -94,8 +98,9 @@ E5:
|
|||||||
Selectable:
|
Selectable:
|
||||||
Bounds: 12,17,0,-6
|
Bounds: 12,17,0,-6
|
||||||
Unit:
|
Unit:
|
||||||
HP: 90
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 90
|
||||||
AttackBase:
|
AttackBase:
|
||||||
PrimaryWeapon: Chemspray
|
PrimaryWeapon: Chemspray
|
||||||
PrimaryOffset: 0,0,0,-5
|
PrimaryOffset: 0,0,0,-5
|
||||||
@@ -118,8 +123,9 @@ E6:
|
|||||||
Selectable:
|
Selectable:
|
||||||
Bounds: 12,17,0,-6
|
Bounds: 12,17,0,-6
|
||||||
Unit:
|
Unit:
|
||||||
HP: 25
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 25
|
||||||
TakeCover:
|
TakeCover:
|
||||||
Passenger:
|
Passenger:
|
||||||
ColorOfCargoPip: Yellow
|
ColorOfCargoPip: Yellow
|
||||||
@@ -141,8 +147,9 @@ RMBO:
|
|||||||
Bounds: 12,17,0,-6
|
Bounds: 12,17,0,-6
|
||||||
Voice: CommandoVoice
|
Voice: CommandoVoice
|
||||||
Unit:
|
Unit:
|
||||||
HP: 200
|
|
||||||
Speed: 5
|
Speed: 5
|
||||||
|
Health:
|
||||||
|
HP: 200
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 5
|
Range: 5
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -160,8 +167,9 @@ C1:
|
|||||||
Cost: 70
|
Cost: 70
|
||||||
Description: Technician
|
Description: Technician
|
||||||
Unit:
|
Unit:
|
||||||
HP: 20
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 20
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 2
|
Range: 2
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -176,8 +184,9 @@ C2:
|
|||||||
Cost: 70
|
Cost: 70
|
||||||
Description: Technician
|
Description: Technician
|
||||||
Unit:
|
Unit:
|
||||||
HP: 20
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 20
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 2
|
Range: 2
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -192,8 +201,9 @@ C3:
|
|||||||
Cost: 70
|
Cost: 70
|
||||||
Description: Technician
|
Description: Technician
|
||||||
Unit:
|
Unit:
|
||||||
HP: 20
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 20
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 2
|
Range: 2
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -208,8 +218,9 @@ C4:
|
|||||||
Cost: 70
|
Cost: 70
|
||||||
Description: Technician
|
Description: Technician
|
||||||
Unit:
|
Unit:
|
||||||
HP: 20
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 20
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 2
|
Range: 2
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -224,8 +235,9 @@ C5:
|
|||||||
Cost: 70
|
Cost: 70
|
||||||
Description: Technician
|
Description: Technician
|
||||||
Unit:
|
Unit:
|
||||||
HP: 20
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 20
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 2
|
Range: 2
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -240,8 +252,9 @@ C6:
|
|||||||
Cost: 70
|
Cost: 70
|
||||||
Description: Technician
|
Description: Technician
|
||||||
Unit:
|
Unit:
|
||||||
HP: 20
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 20
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 2
|
Range: 2
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -256,8 +269,9 @@ C7:
|
|||||||
Cost: 70
|
Cost: 70
|
||||||
Description: Technician
|
Description: Technician
|
||||||
Unit:
|
Unit:
|
||||||
HP: 20
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 20
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 2
|
Range: 2
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -271,8 +285,9 @@ C8:
|
|||||||
Cost: 70
|
Cost: 70
|
||||||
Description: Technician
|
Description: Technician
|
||||||
Unit:
|
Unit:
|
||||||
HP: 20
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 20
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 2
|
Range: 2
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -287,8 +302,9 @@ C9:
|
|||||||
Cost: 70
|
Cost: 70
|
||||||
Description: Technician
|
Description: Technician
|
||||||
Unit:
|
Unit:
|
||||||
HP: 20
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 20
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 2
|
Range: 2
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -303,8 +319,9 @@ C10:
|
|||||||
Cost: 70
|
Cost: 70
|
||||||
Description: Technician
|
Description: Technician
|
||||||
Unit:
|
Unit:
|
||||||
HP: 20
|
|
||||||
Speed: 4
|
Speed: 4
|
||||||
|
Health:
|
||||||
|
HP: 20
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 2
|
Range: 2
|
||||||
AttackBase:
|
AttackBase:
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ FACT:
|
|||||||
Footprint: xxx xxx xxx
|
Footprint: xxx xxx xxx
|
||||||
Dimensions: 3,3
|
Dimensions: 3,3
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 800
|
HP: 800
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -31,6 +32,7 @@ NUKE:
|
|||||||
Footprint: x_ xx
|
Footprint: x_ xx
|
||||||
Dimensions: 2,2
|
Dimensions: 2,2
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 400
|
HP: 400
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -52,6 +54,7 @@ PROC.proxy:
|
|||||||
Footprint: ___xx xxxxx xxx__ xxx__
|
Footprint: ___xx xxxxx xxx__ xxx__
|
||||||
Dimensions: 5,4
|
Dimensions: 5,4
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 900
|
HP: 900
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -70,6 +73,7 @@ PROC:
|
|||||||
Footprint: ___ xxx ===
|
Footprint: ___ xxx ===
|
||||||
Dimensions: 3,3
|
Dimensions: 3,3
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 900
|
HP: 900
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -112,6 +116,7 @@ SILO:
|
|||||||
Footprint: xx
|
Footprint: xx
|
||||||
Dimensions: 2,1
|
Dimensions: 2,1
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 300
|
HP: 300
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -140,6 +145,7 @@ PYLE:
|
|||||||
Footprint: xx xx
|
Footprint: xx xx
|
||||||
Dimensions: 2,2
|
Dimensions: 2,2
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 800
|
HP: 800
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -165,6 +171,7 @@ HAND:
|
|||||||
Footprint: __ xx xx
|
Footprint: __ xx xx
|
||||||
Dimensions: 2,3
|
Dimensions: 2,3
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 800
|
HP: 800
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -190,6 +197,7 @@ AFLD:
|
|||||||
Footprint: xxxx xxxx
|
Footprint: xxxx xxxx
|
||||||
Dimensions: 4,2
|
Dimensions: 4,2
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 1000
|
HP: 1000
|
||||||
Armor: heavy
|
Armor: heavy
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -216,6 +224,7 @@ WEAP:
|
|||||||
Footprint: ___ xxx ===
|
Footprint: ___ xxx ===
|
||||||
Dimensions: 3,3
|
Dimensions: 3,3
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 400
|
HP: 400
|
||||||
Armor: light
|
Armor: light
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -243,6 +252,7 @@ HQ:
|
|||||||
Footprint: __ xx
|
Footprint: __ xx
|
||||||
Dimensions: 2,2
|
Dimensions: 2,2
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 1000
|
HP: 1000
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -267,6 +277,7 @@ NUK2:
|
|||||||
Footprint: xx xx
|
Footprint: xx xx
|
||||||
Dimensions: 2,2
|
Dimensions: 2,2
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 600
|
HP: 600
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -288,6 +299,7 @@ FIX:
|
|||||||
Footprint: _x_ xxx _x_
|
Footprint: _x_ xxx _x_
|
||||||
Dimensions: 3,3
|
Dimensions: 3,3
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 800
|
HP: 800
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -312,6 +324,7 @@ HPAD:
|
|||||||
Footprint: xx xx
|
Footprint: xx xx
|
||||||
Dimensions: 2,2
|
Dimensions: 2,2
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 800
|
HP: 800
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -343,6 +356,7 @@ EYE:
|
|||||||
Footprint: __ xx
|
Footprint: __ xx
|
||||||
Dimensions: 2,2
|
Dimensions: 2,2
|
||||||
Capturable: true
|
Capturable: true
|
||||||
|
Health:
|
||||||
HP: 1000
|
HP: 1000
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -369,6 +383,7 @@ TMPL:
|
|||||||
Footprint: ___ xxx xxx
|
Footprint: ___ xxx xxx
|
||||||
Dimensions: 3,3
|
Dimensions: 3,3
|
||||||
Capturable: false
|
Capturable: false
|
||||||
|
Health:
|
||||||
HP: 2000
|
HP: 2000
|
||||||
Armor: light
|
Armor: light
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -393,6 +408,7 @@ OBLI:
|
|||||||
Power: -150
|
Power: -150
|
||||||
Footprint: _ x
|
Footprint: _ x
|
||||||
Dimensions: 1,2
|
Dimensions: 1,2
|
||||||
|
Health:
|
||||||
HP: 400
|
HP: 400
|
||||||
Armor: light
|
Armor: light
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -419,7 +435,7 @@ CYCL:
|
|||||||
Cost: 25
|
Cost: 25
|
||||||
Description: Chain Link Barrier
|
Description: Chain Link Barrier
|
||||||
LongDesc: Stops infantry and blocks enemy fire.\nCan be crushed by tanks.
|
LongDesc: Stops infantry and blocks enemy fire.\nCan be crushed by tanks.
|
||||||
Building:
|
Health:
|
||||||
HP: 300
|
HP: 300
|
||||||
Armor: none
|
Armor: none
|
||||||
RenderBuildingWall:
|
RenderBuildingWall:
|
||||||
@@ -436,7 +452,7 @@ SBAG:
|
|||||||
Cost: 25
|
Cost: 25
|
||||||
Description: Sandbag Barrier
|
Description: Sandbag Barrier
|
||||||
LongDesc: Stops infantry and blocks enemy fire.\nCan be crushed by tanks.
|
LongDesc: Stops infantry and blocks enemy fire.\nCan be crushed by tanks.
|
||||||
Building:
|
Health:
|
||||||
HP: 250
|
HP: 250
|
||||||
Armor: none
|
Armor: none
|
||||||
|
|
||||||
@@ -451,7 +467,7 @@ BRIK:
|
|||||||
Cost: 100
|
Cost: 100
|
||||||
Description: Concrete Barrier
|
Description: Concrete Barrier
|
||||||
LongDesc: Stop units and blocks enemy fire.
|
LongDesc: Stop units and blocks enemy fire.
|
||||||
Building:
|
Health:
|
||||||
HP: 1000
|
HP: 1000
|
||||||
Armor: heavy
|
Armor: heavy
|
||||||
RenderBuildingWall:
|
RenderBuildingWall:
|
||||||
@@ -472,6 +488,7 @@ GUN:
|
|||||||
LongDesc: Anti-Armor base defense.\n Strong vs Tanks\n Weak vs Infantry, Aircraft
|
LongDesc: Anti-Armor base defense.\n Strong vs Tanks\n Weak vs Infantry, Aircraft
|
||||||
Building:
|
Building:
|
||||||
Power: -20
|
Power: -20
|
||||||
|
Health:
|
||||||
HP: 400
|
HP: 400
|
||||||
Armor: heavy
|
Armor: heavy
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -501,6 +518,7 @@ SAM:
|
|||||||
Power: -20
|
Power: -20
|
||||||
Footprint: xx
|
Footprint: xx
|
||||||
Dimensions: 2,1
|
Dimensions: 2,1
|
||||||
|
Health:
|
||||||
HP: 400
|
HP: 400
|
||||||
Armor: heavy
|
Armor: heavy
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -528,6 +546,7 @@ GTWR:
|
|||||||
LongDesc: Basic defensive structure.\n Strong vs Infantry, Light Vehicles\n Weak vs Tanks, Aircraft
|
LongDesc: Basic defensive structure.\n Strong vs Infantry, Light Vehicles\n Weak vs Tanks, Aircraft
|
||||||
Building:
|
Building:
|
||||||
Power: -10
|
Power: -10
|
||||||
|
Health:
|
||||||
HP: 400
|
HP: 400
|
||||||
Armor: wood
|
Armor: wood
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -552,6 +571,7 @@ ATWR:
|
|||||||
LongDesc: Anti-armor defensive structure.\n Strong vs Light Vehicles, Tanks\n Weak vs Infantry
|
LongDesc: Anti-armor defensive structure.\n Strong vs Light Vehicles, Tanks\n Weak vs Infantry
|
||||||
Building:
|
Building:
|
||||||
Power: -20
|
Power: -20
|
||||||
|
Health:
|
||||||
HP: 600
|
HP: 600
|
||||||
Armor: light
|
Armor: light
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
|
|||||||
@@ -158,6 +158,5 @@ CRATE:
|
|||||||
SelectionShares: 5
|
SelectionShares: 5
|
||||||
Effect: hide-map
|
Effect: hide-map
|
||||||
Unit:
|
Unit:
|
||||||
HP: 1
|
|
||||||
RenderUnit:
|
RenderUnit:
|
||||||
BelowUnits:
|
BelowUnits:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
SPLIT2:
|
SPLIT2:
|
||||||
Inherits: ^Building
|
Inherits: ^Tree
|
||||||
RenderBuilding:
|
RenderBuilding:
|
||||||
Palette: terrain
|
Palette: terrain
|
||||||
SeedsResource:
|
SeedsResource:
|
||||||
@@ -11,7 +11,7 @@ SPLIT2:
|
|||||||
Terrain: Ore
|
Terrain: Ore
|
||||||
|
|
||||||
SPLIT3:
|
SPLIT3:
|
||||||
Inherits: ^Building
|
Inherits: ^Tree
|
||||||
RenderBuilding:
|
RenderBuilding:
|
||||||
Palette: terrain
|
Palette: terrain
|
||||||
SeedsResource:
|
SeedsResource:
|
||||||
|
|||||||
@@ -11,9 +11,10 @@ MCV:
|
|||||||
Selectable:
|
Selectable:
|
||||||
Priority: 3
|
Priority: 3
|
||||||
Unit:
|
Unit:
|
||||||
|
Speed: 6
|
||||||
|
Health:
|
||||||
HP: 600
|
HP: 600
|
||||||
Armor: light
|
Armor: light
|
||||||
Speed: 6
|
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 4
|
Range: 4
|
||||||
TransformsOnDeploy:
|
TransformsOnDeploy:
|
||||||
@@ -43,9 +44,10 @@ HARV:
|
|||||||
PipColor: Green
|
PipColor: Green
|
||||||
Capacity: 28
|
Capacity: 28
|
||||||
Unit:
|
Unit:
|
||||||
|
Speed: 6
|
||||||
|
Health:
|
||||||
HP: 600
|
HP: 600
|
||||||
Armor: light
|
Armor: light
|
||||||
Speed: 6
|
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 4
|
Range: 4
|
||||||
RenderUnit:
|
RenderUnit:
|
||||||
@@ -61,10 +63,11 @@ APC:
|
|||||||
Description: Armored Personnel Carrier
|
Description: Armored Personnel Carrier
|
||||||
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
|
||||||
Unit:
|
Unit:
|
||||||
HP: 200
|
|
||||||
Armor: heavy
|
|
||||||
ROT: 5
|
ROT: 5
|
||||||
Speed: 15
|
Speed: 15
|
||||||
|
Health:
|
||||||
|
HP: 200
|
||||||
|
Armor: heavy
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 5
|
Range: 5
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -90,10 +93,11 @@ ARTY:
|
|||||||
Description: Artillery
|
Description: Artillery
|
||||||
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
|
||||||
Unit:
|
Unit:
|
||||||
HP: 75
|
|
||||||
Armor: light
|
|
||||||
ROT: 2
|
ROT: 2
|
||||||
Speed: 6
|
Speed: 6
|
||||||
|
Health:
|
||||||
|
HP: 75
|
||||||
|
Armor: light
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 6
|
Range: 6
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -113,10 +117,11 @@ FTNK:
|
|||||||
Description: Flame Tank
|
Description: Flame Tank
|
||||||
LongDesc: Heavily armored flame-throwing vehicle.\n Strong vs Infantry, Buildings\n Weak vs Aircraft
|
LongDesc: Heavily armored flame-throwing vehicle.\n Strong vs Infantry, Buildings\n Weak vs Aircraft
|
||||||
Unit:
|
Unit:
|
||||||
HP: 300
|
|
||||||
Armor: heavy
|
|
||||||
ROT: 5
|
ROT: 5
|
||||||
Speed: 9
|
Speed: 9
|
||||||
|
Health:
|
||||||
|
HP: 300
|
||||||
|
Armor: heavy
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 4
|
Range: 4
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -137,10 +142,11 @@ BGGY:
|
|||||||
Description: Nod Buggy
|
Description: Nod Buggy
|
||||||
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
|
||||||
Unit:
|
Unit:
|
||||||
HP: 140
|
|
||||||
Armor: light
|
|
||||||
ROT: 10
|
ROT: 10
|
||||||
Speed: 18
|
Speed: 18
|
||||||
|
Health:
|
||||||
|
HP: 140
|
||||||
|
Armor: light
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 5
|
Range: 5
|
||||||
Turreted:
|
Turreted:
|
||||||
@@ -163,10 +169,11 @@ BIKE:
|
|||||||
Description: Recon Bike
|
Description: Recon Bike
|
||||||
LongDesc: Fast scout vehicle, armed with \nrockets.\n Strong vs Vehicles, Aircraft\n Weak vs Infantry
|
LongDesc: Fast scout vehicle, armed with \nrockets.\n Strong vs Vehicles, Aircraft\n Weak vs Infantry
|
||||||
Unit:
|
Unit:
|
||||||
HP: 160
|
|
||||||
Armor: none
|
|
||||||
ROT: 10
|
ROT: 10
|
||||||
Speed: 20
|
Speed: 20
|
||||||
|
Health:
|
||||||
|
HP: 160
|
||||||
|
Armor: none
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 7
|
Range: 7
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -190,10 +197,11 @@ JEEP:
|
|||||||
Description: Hum-Vee
|
Description: Hum-Vee
|
||||||
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
|
||||||
Unit:
|
Unit:
|
||||||
HP: 150
|
|
||||||
Armor: light
|
|
||||||
ROT: 10
|
ROT: 10
|
||||||
Speed: 15
|
Speed: 15
|
||||||
|
Health:
|
||||||
|
HP: 150
|
||||||
|
Armor: light
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 7
|
Range: 7
|
||||||
Turreted:
|
Turreted:
|
||||||
@@ -216,9 +224,10 @@ LTNK:
|
|||||||
Description: Light Tank
|
Description: Light Tank
|
||||||
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
|
||||||
Unit:
|
Unit:
|
||||||
|
Speed: 9
|
||||||
|
Health:
|
||||||
HP: 300
|
HP: 300
|
||||||
Armor: Heavy
|
Armor: Heavy
|
||||||
Speed: 9
|
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 4
|
Range: 4
|
||||||
Turreted:
|
Turreted:
|
||||||
@@ -245,9 +254,10 @@ MTNK:
|
|||||||
Description: Medium Tank
|
Description: Medium Tank
|
||||||
LongDesc: General-Purpose GDI Tank.\n Strong vs Tanks, Light Vehicles\n Weak vs Infantry, Aircraft
|
LongDesc: General-Purpose GDI Tank.\n Strong vs Tanks, Light Vehicles\n Weak vs Infantry, Aircraft
|
||||||
Unit:
|
Unit:
|
||||||
|
Speed: 9
|
||||||
|
Health:
|
||||||
HP: 400
|
HP: 400
|
||||||
Armor: heavy
|
Armor: heavy
|
||||||
Speed: 9
|
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 5
|
Range: 5
|
||||||
Turreted:
|
Turreted:
|
||||||
@@ -274,9 +284,10 @@ HTNK:
|
|||||||
Description: Mammoth Tank
|
Description: Mammoth Tank
|
||||||
LongDesc: Heavily armored GDI Tank.\n Strong vs Everything
|
LongDesc: Heavily armored GDI Tank.\n Strong vs Everything
|
||||||
Unit:
|
Unit:
|
||||||
|
Speed: 3
|
||||||
|
Health:
|
||||||
HP: 600
|
HP: 600
|
||||||
Armor: heavy
|
Armor: heavy
|
||||||
Speed: 3
|
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 6
|
Range: 6
|
||||||
Turreted:
|
Turreted:
|
||||||
@@ -309,9 +320,10 @@ MSAM:
|
|||||||
Description: Rocket Launcher
|
Description: Rocket Launcher
|
||||||
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
|
||||||
Unit:
|
Unit:
|
||||||
|
Speed: 6
|
||||||
|
Health:
|
||||||
HP: 120
|
HP: 120
|
||||||
Armor: light
|
Armor: light
|
||||||
Speed: 6
|
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 6
|
Range: 6
|
||||||
Turreted:
|
Turreted:
|
||||||
@@ -337,9 +349,10 @@ MLRS:
|
|||||||
Description: SSM Launcher
|
Description: SSM Launcher
|
||||||
LongDesc: Long range artillery.\n Strong vs Infantry, Aircraft\n Weak vs Tanks, Aircraft
|
LongDesc: Long range artillery.\n Strong vs Infantry, Aircraft\n Weak vs Tanks, Aircraft
|
||||||
Unit:
|
Unit:
|
||||||
|
Speed: 6
|
||||||
|
Health:
|
||||||
HP: 120
|
HP: 120
|
||||||
Armor: light
|
Armor: light
|
||||||
Speed: 6
|
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 10
|
Range: 10
|
||||||
Turreted:
|
Turreted:
|
||||||
@@ -361,9 +374,10 @@ STNK:
|
|||||||
Description: Stealth Tank
|
Description: Stealth Tank
|
||||||
LongDesc: Missile tank that can bend light around \nitself to become invisible\n Strong vs Infantry, Aircraft\n Weak vs Tanks
|
LongDesc: Missile tank that can bend light around \nitself to become invisible\n Strong vs Infantry, Aircraft\n Weak vs Tanks
|
||||||
Unit:
|
Unit:
|
||||||
|
Speed: 15
|
||||||
|
Health:
|
||||||
HP: 110
|
HP: 110
|
||||||
Armor: light
|
Armor: light
|
||||||
Speed: 15
|
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 4
|
Range: 4
|
||||||
Cloak:
|
Cloak:
|
||||||
@@ -388,11 +402,12 @@ TRAN:
|
|||||||
Description: Chinook Transport
|
Description: Chinook Transport
|
||||||
LongDesc: Fast Infantry Transport Helicopter.\n Unarmed
|
LongDesc: Fast Infantry Transport Helicopter.\n Unarmed
|
||||||
Unit:
|
Unit:
|
||||||
HP: 90
|
|
||||||
Armor: light
|
|
||||||
InitialFacing: 20
|
InitialFacing: 20
|
||||||
ROT: 5
|
ROT: 5
|
||||||
Speed: 15
|
Speed: 15
|
||||||
|
Health:
|
||||||
|
HP: 90
|
||||||
|
Armor: light
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 8
|
Range: 8
|
||||||
RenderUnitRotor:
|
RenderUnitRotor:
|
||||||
@@ -415,11 +430,12 @@ HELI:
|
|||||||
Description: Apache Longbow
|
Description: Apache Longbow
|
||||||
LongDesc: Helicopter Gunship with AG Missiles.\n Strong vs Buildings, Tanks\n Weak vs Infantry
|
LongDesc: Helicopter Gunship with AG Missiles.\n Strong vs Buildings, Tanks\n Weak vs Infantry
|
||||||
Unit:
|
Unit:
|
||||||
HP: 125
|
|
||||||
Armor: heavy
|
|
||||||
InitialFacing: 20
|
InitialFacing: 20
|
||||||
ROT: 4
|
ROT: 4
|
||||||
Speed: 20
|
Speed: 20
|
||||||
|
Health:
|
||||||
|
HP: 125
|
||||||
|
Armor: heavy
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 8
|
Range: 8
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -443,11 +459,12 @@ ORCA:
|
|||||||
Description: Orca
|
Description: Orca
|
||||||
LongDesc: Helicopter Gunship with AG Missiles.\n Strong vs Buildings, Tanks\n Weak vs Infantry
|
LongDesc: Helicopter Gunship with AG Missiles.\n Strong vs Buildings, Tanks\n Weak vs Infantry
|
||||||
Unit:
|
Unit:
|
||||||
HP: 125
|
|
||||||
Armor: heavy
|
|
||||||
InitialFacing: 20
|
InitialFacing: 20
|
||||||
ROT: 4
|
ROT: 4
|
||||||
Speed: 20
|
Speed: 20
|
||||||
|
Health:
|
||||||
|
HP: 125
|
||||||
|
Armor: heavy
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 8
|
Range: 8
|
||||||
AttackBase:
|
AttackBase:
|
||||||
@@ -463,10 +480,11 @@ C17:
|
|||||||
LZRange: 1
|
LZRange: 1
|
||||||
Inherits: ^Plane
|
Inherits: ^Plane
|
||||||
Unit:
|
Unit:
|
||||||
HP: 25
|
|
||||||
Armor: light
|
|
||||||
ROT: 5
|
ROT: 5
|
||||||
Speed: 25
|
Speed: 25
|
||||||
|
Health:
|
||||||
|
HP: 25
|
||||||
|
Armor: light
|
||||||
Plane:
|
Plane:
|
||||||
RenderUnit:
|
RenderUnit:
|
||||||
WithShadow:
|
WithShadow:
|
||||||
@@ -480,10 +498,11 @@ C17:
|
|||||||
A10:
|
A10:
|
||||||
Inherits: ^Plane
|
Inherits: ^Plane
|
||||||
Unit:
|
Unit:
|
||||||
HP: 60
|
|
||||||
Armor: light
|
|
||||||
ROT: 4
|
ROT: 4
|
||||||
Speed: 25
|
Speed: 25
|
||||||
|
Health:
|
||||||
|
HP: 60
|
||||||
|
Armor: light
|
||||||
Plane:
|
Plane:
|
||||||
RenderUnit:
|
RenderUnit:
|
||||||
WithShadow:
|
WithShadow:
|
||||||
|
|||||||
Reference in New Issue
Block a user