@@ -619,6 +619,8 @@
|
||||
<Compile Include="UtilityCommands\CheckSequenceSprites.cs" />
|
||||
<Compile Include="UtilityCommands\FixClassicTilesets.cs" />
|
||||
<Compile Include="Graphics\TilesetSpecificSpriteSequence.cs" />
|
||||
<Compile Include="Traits\Pluggable.cs" />
|
||||
<Compile Include="Traits\Plug.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace OpenRA.Mods.Common.Orders
|
||||
readonly string building;
|
||||
readonly BuildingInfo buildingInfo;
|
||||
readonly PlaceBuildingInfo placeBuildingInfo;
|
||||
readonly BuildingInfluence buildingInfluence;
|
||||
readonly string race;
|
||||
readonly Sprite buildOk;
|
||||
readonly Sprite buildBlocked;
|
||||
@@ -52,6 +53,8 @@ namespace OpenRA.Mods.Common.Orders
|
||||
|
||||
buildOk = map.SequenceProvider.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
|
||||
buildBlocked = map.SequenceProvider.GetSequence("overlay", "build-invalid").GetSprite(0);
|
||||
|
||||
buildingInfluence = producer.World.WorldActor.Trait<BuildingInfluence>();
|
||||
}
|
||||
|
||||
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
|
||||
@@ -73,16 +76,33 @@ namespace OpenRA.Mods.Common.Orders
|
||||
|
||||
if (mi.Button == MouseButton.Left)
|
||||
{
|
||||
var orderType = "PlaceBuilding";
|
||||
var topLeft = xy - FootprintUtils.AdjustForBuildingSize(buildingInfo);
|
||||
if (!world.CanPlaceBuilding(building, buildingInfo, topLeft, null)
|
||||
|| !buildingInfo.IsCloseEnoughToBase(world, producer.Owner, building, topLeft))
|
||||
|
||||
var plugInfo = world.Map.Rules.Actors[building].Traits.GetOrDefault<PlugInfo>();
|
||||
if (plugInfo != null)
|
||||
{
|
||||
Sound.PlayNotification(world.Map.Rules, producer.Owner, "Speech", "BuildingCannotPlaceAudio", producer.Owner.Country.Race);
|
||||
yield break;
|
||||
orderType = "PlacePlug";
|
||||
if (!AcceptsPlug(topLeft, plugInfo))
|
||||
{
|
||||
Sound.PlayNotification(world.Map.Rules, producer.Owner, "Speech", "BuildingCannotPlaceAudio", producer.Owner.Country.Race);
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!world.CanPlaceBuilding(building, buildingInfo, topLeft, null)
|
||||
|| !buildingInfo.IsCloseEnoughToBase(world, producer.Owner, building, topLeft))
|
||||
{
|
||||
Sound.PlayNotification(world.Map.Rules, producer.Owner, "Speech", "BuildingCannotPlaceAudio", producer.Owner.Country.Race);
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (world.Map.Rules.Actors[building].Traits.Contains<LineBuildInfo>())
|
||||
orderType = "LineBuild";
|
||||
}
|
||||
|
||||
var isLineBuild = world.Map.Rules.Actors[building].Traits.Contains<LineBuildInfo>();
|
||||
yield return new Order(isLineBuild ? "LineBuild" : "PlaceBuilding", producer.Owner.PlayerActor, false)
|
||||
yield return new Order(orderType, producer.Owner.PlayerActor, false)
|
||||
{
|
||||
TargetLocation = topLeft,
|
||||
TargetActor = producer,
|
||||
@@ -101,6 +121,16 @@ namespace OpenRA.Mods.Common.Orders
|
||||
p.Tick();
|
||||
}
|
||||
|
||||
bool AcceptsPlug(CPos cell, PlugInfo plug)
|
||||
{
|
||||
var host = buildingInfluence.GetBuildingAt(cell);
|
||||
if (host == null)
|
||||
return false;
|
||||
|
||||
var location = host.Location;
|
||||
return host.TraitsImplementing<Pluggable>().Any(p => location + p.Info.Offset == cell && p.AcceptsPlug(host, plug.Type));
|
||||
}
|
||||
|
||||
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
|
||||
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world)
|
||||
{
|
||||
@@ -116,10 +146,17 @@ namespace OpenRA.Mods.Common.Orders
|
||||
|
||||
var cells = new Dictionary<CPos, bool>();
|
||||
|
||||
// Linebuild for walls.
|
||||
// Requires a 1x1 footprint
|
||||
if (rules.Actors[building].Traits.Contains<LineBuildInfo>())
|
||||
var plugInfo = rules.Actors[building].Traits.GetOrDefault<PlugInfo>();
|
||||
if (plugInfo != null)
|
||||
{
|
||||
if (buildingInfo.Dimensions.X != 1 || buildingInfo.Dimensions.Y != 1)
|
||||
throw new InvalidOperationException("Plug requires a 1x1 sized Building");
|
||||
|
||||
cells.Add(topLeft, AcceptsPlug(topLeft, plugInfo));
|
||||
}
|
||||
else if (rules.Actors[building].Traits.Contains<LineBuildInfo>())
|
||||
{
|
||||
// Linebuild for walls.
|
||||
if (buildingInfo.Dimensions.X != 1 || buildingInfo.Dimensions.Y != 1)
|
||||
throw new InvalidOperationException("LineBuild requires a 1x1 sized Building");
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public abstract class AttackBaseInfo : ITraitInfo
|
||||
public abstract class AttackBaseInfo : UpgradableTraitInfo, ITraitInfo
|
||||
{
|
||||
[Desc("Armament names")]
|
||||
public readonly string[] Armaments = { "primary", "secondary" };
|
||||
@@ -35,11 +35,10 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public abstract object Create(ActorInitializer init);
|
||||
}
|
||||
|
||||
public abstract class AttackBase : IIssueOrder, IResolveOrder, IOrderVoice, ISync
|
||||
public abstract class AttackBase : UpgradableTrait<AttackBaseInfo>, IIssueOrder, IResolveOrder, IOrderVoice, ISync
|
||||
{
|
||||
[Sync] public bool IsAttacking { get; internal set; }
|
||||
public IEnumerable<Armament> Armaments { get { return getArmaments(); } }
|
||||
public readonly AttackBaseInfo Info;
|
||||
|
||||
protected Lazy<IFacing> facing;
|
||||
protected Lazy<Building> building;
|
||||
@@ -49,9 +48,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
readonly Actor self;
|
||||
|
||||
public AttackBase(Actor self, AttackBaseInfo info)
|
||||
: base(info)
|
||||
{
|
||||
this.self = self;
|
||||
Info = info;
|
||||
|
||||
var armaments = Exts.Lazy(() => self.TraitsImplementing<Armament>()
|
||||
.Where(a => info.Armaments.Contains(a.Info.Name)));
|
||||
@@ -65,7 +64,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
protected virtual bool CanAttack(Actor self, Target target)
|
||||
{
|
||||
if (!self.IsInWorld)
|
||||
if (!self.IsInWorld || IsTraitDisabled)
|
||||
return false;
|
||||
|
||||
if (!HasAnyValidWeapons(target))
|
||||
@@ -101,7 +100,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
get
|
||||
{
|
||||
var armament = Armaments.FirstOrDefault(a => a.Weapon.Warheads.Any(w => (w is DamageWarhead)));
|
||||
if (armament == null)
|
||||
if (armament == null || IsTraitDisabled)
|
||||
yield break;
|
||||
|
||||
var negativeDamage = (armament.Weapon.Warheads.FirstOrDefault(w => (w is DamageWarhead)) as DamageWarhead).Damage < 0;
|
||||
@@ -149,6 +148,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public bool HasAnyValidWeapons(Target t)
|
||||
{
|
||||
if (IsTraitDisabled)
|
||||
return false;
|
||||
|
||||
if (Info.AttackRequiresEnteringCell && !positionable.Value.CanEnterCell(t.Actor.Location, null, false))
|
||||
return false;
|
||||
|
||||
@@ -157,14 +159,19 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public WRange GetMaximumRange()
|
||||
{
|
||||
return Armaments.Select(a => a.Weapon.Range).Append(WRange.Zero).Max();
|
||||
if (IsTraitDisabled)
|
||||
return WRange.Zero;
|
||||
|
||||
return Armaments.Where(a => !a.IsTraitDisabled)
|
||||
.Select(a => a.Weapon.Range)
|
||||
.Append(WRange.Zero).Max();
|
||||
}
|
||||
|
||||
public Armament ChooseArmamentForTarget(Target t) { return Armaments.FirstOrDefault(a => a.Weapon.IsValidAgainst(t, self.World, self)); }
|
||||
|
||||
public void AttackTarget(Target target, bool queued, bool allowMove)
|
||||
{
|
||||
if (self.IsDisabled())
|
||||
if (self.IsDisabled() || IsTraitDisabled)
|
||||
return;
|
||||
|
||||
if (!target.IsValidFor(self))
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (!Cloaked || self.Owner.IsAlliedWith(viewer))
|
||||
return true;
|
||||
|
||||
return self.World.ActorsWithTrait<DetectCloaked>().Any(a => a.Actor.Owner.IsAlliedWith(viewer)
|
||||
return self.World.ActorsWithTrait<DetectCloaked>().Any(a => !a.Trait.IsTraitDisabled && a.Actor.Owner.IsAlliedWith(viewer)
|
||||
&& Info.CloakTypes.Intersect(a.Trait.Info.CloakTypes).Any()
|
||||
&& (self.CenterPosition - a.Actor.CenterPosition).Length <= WRange.FromCells(a.Trait.Info.Range).Range);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ using OpenRA.Traits;
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Actor can reveal Cloak actors in a specified range.")]
|
||||
public class DetectCloakedInfo : ITraitInfo
|
||||
public class DetectCloakedInfo : UpgradableTraitInfo, ITraitInfo
|
||||
{
|
||||
[Desc("Specific cloak classifications I can reveal.")]
|
||||
public readonly string[] CloakTypes = { "Cloak" };
|
||||
@@ -24,13 +24,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public object Create(ActorInitializer init) { return new DetectCloaked(this); }
|
||||
}
|
||||
|
||||
public class DetectCloaked
|
||||
public class DetectCloaked : UpgradableTrait<DetectCloakedInfo>
|
||||
{
|
||||
public readonly DetectCloakedInfo Info;
|
||||
|
||||
public DetectCloaked(DetectCloakedInfo info)
|
||||
{
|
||||
Info = info;
|
||||
}
|
||||
public DetectCloaked(DetectCloakedInfo info) : base(info) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "PlaceBuilding" || order.OrderString == "LineBuild")
|
||||
if (order.OrderString == "PlaceBuilding" || order.OrderString == "LineBuild" || order.OrderString == "PlacePlug")
|
||||
{
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
@@ -69,6 +69,27 @@ namespace OpenRA.Mods.Common.Traits
|
||||
playSounds = false;
|
||||
}
|
||||
}
|
||||
else if (order.OrderString == "PlacePlug")
|
||||
{
|
||||
var host = self.World.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(order.TargetLocation);
|
||||
if (host == null)
|
||||
return;
|
||||
|
||||
var plugInfo = unit.Traits.GetOrDefault<PlugInfo>();
|
||||
if (plugInfo == null)
|
||||
return;
|
||||
|
||||
var location = host.Location;
|
||||
var pluggable = host.TraitsImplementing<Pluggable>()
|
||||
.FirstOrDefault(p => location + p.Info.Offset == order.TargetLocation && p.AcceptsPlug(host, plugInfo.Type));
|
||||
|
||||
if (pluggable == null)
|
||||
return;
|
||||
|
||||
pluggable.EnablePlug(host, plugInfo.Type);
|
||||
foreach (var s in buildingInfo.BuildSounds)
|
||||
Sound.PlayToPlayer(order.Player, s, host.CenterPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!self.World.CanPlaceBuilding(order.TargetString, buildingInfo, order.TargetLocation, null)
|
||||
|
||||
24
OpenRA.Mods.Common/Traits/Plug.cs
Normal file
24
OpenRA.Mods.Common/Traits/Plug.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2015 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 COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public class PlugInfo : TraitInfo<Plug>
|
||||
{
|
||||
[Desc("Plug type (matched against Upgrades in Pluggable)")]
|
||||
public readonly string Type = null;
|
||||
}
|
||||
|
||||
public class Plug { }
|
||||
}
|
||||
79
OpenRA.Mods.Common/Traits/Pluggable.cs
Normal file
79
OpenRA.Mods.Common/Traits/Pluggable.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2015 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 COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public class PluggableInfo : ITraitInfo, Requires<UpgradeManagerInfo>
|
||||
{
|
||||
[Desc("Footprint cell offset where a plug can be placed.")]
|
||||
public readonly CVec Offset = CVec.Zero;
|
||||
|
||||
[FieldLoader.LoadUsing("LoadUpgrades")]
|
||||
[Desc("Upgrades to grant for each accepted plug type.")]
|
||||
public readonly Dictionary<string, string[]> Upgrades = null;
|
||||
|
||||
static object LoadUpgrades(MiniYaml y)
|
||||
{
|
||||
MiniYaml upgrades;
|
||||
|
||||
if (!y.ToDictionary().TryGetValue("Upgrades", out upgrades))
|
||||
return new Dictionary<string, string[]>();
|
||||
|
||||
return upgrades.Nodes.ToDictionary(
|
||||
kv => kv.Key,
|
||||
kv => FieldLoader.GetValue<string[]>("(value)", kv.Value.Value));
|
||||
}
|
||||
|
||||
public object Create(ActorInitializer init) { return new Pluggable(init.Self, this); }
|
||||
}
|
||||
|
||||
public class Pluggable
|
||||
{
|
||||
public readonly PluggableInfo Info;
|
||||
readonly UpgradeManager upgradeManager;
|
||||
string active;
|
||||
|
||||
public Pluggable(Actor self, PluggableInfo info)
|
||||
{
|
||||
Info = info;
|
||||
upgradeManager = self.Trait<UpgradeManager>();
|
||||
}
|
||||
|
||||
public bool AcceptsPlug(Actor self, string type)
|
||||
{
|
||||
return active == null && Info.Upgrades.ContainsKey(type);
|
||||
}
|
||||
|
||||
public void EnablePlug(Actor self, string type)
|
||||
{
|
||||
string[] upgrades;
|
||||
if (!Info.Upgrades.TryGetValue(type, out upgrades))
|
||||
return;
|
||||
|
||||
foreach (var u in upgrades)
|
||||
upgradeManager.GrantUpgrade(self, u, this);
|
||||
|
||||
active = type;
|
||||
}
|
||||
|
||||
public void DisablePlug(Actor self, string type)
|
||||
{
|
||||
if (type != active)
|
||||
return;
|
||||
|
||||
foreach (var u in Info.Upgrades[type])
|
||||
upgradeManager.RevokeUpgrade(self, u, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Traits;
|
||||
@@ -32,9 +33,17 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (self.Owner != self.World.LocalPlayer)
|
||||
yield break;
|
||||
|
||||
var range = self.TraitsImplementing<DetectCloaked>()
|
||||
.Where(a => !a.IsTraitDisabled)
|
||||
.Select(a => WRange.FromCells(a.Info.Range))
|
||||
.Append(WRange.Zero).Max();
|
||||
|
||||
if (range == WRange.Zero)
|
||||
yield break;
|
||||
|
||||
yield return new RangeCircleRenderable(
|
||||
self.CenterPosition,
|
||||
WRange.FromCells(self.Info.Traits.Get<DetectCloakedInfo>().Range),
|
||||
range,
|
||||
0,
|
||||
Color.FromArgb(128, Color.LimeGreen),
|
||||
Color.FromArgb(96, Color.Black));
|
||||
|
||||
@@ -27,7 +27,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public IEnumerable<IRenderable> Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition)
|
||||
{
|
||||
var armaments = ai.Traits.WithInterface<ArmamentInfo>();
|
||||
var armaments = ai.Traits.WithInterface<ArmamentInfo>()
|
||||
.Where(a => a.UpgradeMinEnabledLevel == 0);
|
||||
var range = FallbackRange;
|
||||
|
||||
if (armaments.Any())
|
||||
@@ -69,9 +70,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (self.Owner != self.World.LocalPlayer)
|
||||
yield break;
|
||||
|
||||
var range = attack.GetMaximumRange();
|
||||
if (range == WRange.Zero)
|
||||
yield break;
|
||||
|
||||
yield return new RangeCircleRenderable(
|
||||
self.CenterPosition,
|
||||
attack.GetMaximumRange(),
|
||||
range,
|
||||
0,
|
||||
Color.FromArgb(128, Color.Yellow),
|
||||
Color.FromArgb(96, Color.Black));
|
||||
|
||||
@@ -17,7 +17,7 @@ using OpenRA.Traits;
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Renders a decorative animation on units and buildings.")]
|
||||
public class WithIdleOverlayInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
|
||||
public class WithIdleOverlayInfo : UpgradableTraitInfo, ITraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
|
||||
{
|
||||
[Desc("Sequence name to use")]
|
||||
public readonly string Sequence = "idle-overlay";
|
||||
@@ -37,6 +37,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||
{
|
||||
if (UpgradeMinEnabledLevel > 0)
|
||||
yield break;
|
||||
|
||||
var body = init.Actor.Traits.Get<BodyOrientationInfo>();
|
||||
var facing = init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : 0;
|
||||
var anim = new Animation(init.World, image, () => facing);
|
||||
@@ -48,12 +51,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public class WithIdleOverlay : INotifyDamageStateChanged, INotifyBuildComplete, INotifySold, INotifyTransform
|
||||
public class WithIdleOverlay : UpgradableTrait<WithIdleOverlayInfo>, INotifyDamageStateChanged, INotifyBuildComplete, INotifySold, INotifyTransform
|
||||
{
|
||||
Animation overlay;
|
||||
bool buildComplete;
|
||||
|
||||
public WithIdleOverlay(Actor self, WithIdleOverlayInfo info)
|
||||
: base(info)
|
||||
{
|
||||
var rs = self.Trait<RenderSprites>();
|
||||
var body = self.Trait<IBodyOrientation>();
|
||||
@@ -65,7 +69,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
rs.Add("idle_overlay_{0}".F(info.Sequence),
|
||||
new AnimationWithOffset(overlay,
|
||||
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
|
||||
() => !buildComplete,
|
||||
() => IsTraitDisabled || !buildComplete,
|
||||
() => info.PauseOnLowPower && disabled.Any(d => d.Disabled),
|
||||
p => WithTurret.ZOffsetFromCenter(self, p, 1)),
|
||||
info.Palette, info.IsPlayerPalette);
|
||||
|
||||
@@ -17,7 +17,7 @@ using OpenRA.Traits;
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Renders the MuzzleSequence from the Armament trait.")]
|
||||
class WithMuzzleFlashInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<AttackBaseInfo>, Requires<ArmamentInfo>
|
||||
class WithMuzzleFlashInfo : UpgradableTraitInfo, ITraitInfo, Requires<RenderSpritesInfo>, Requires<AttackBaseInfo>, Requires<ArmamentInfo>
|
||||
{
|
||||
[Desc("Ignore the weapon position, and always draw relative to the center of the actor")]
|
||||
public readonly bool IgnoreOffset = false;
|
||||
@@ -25,13 +25,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public object Create(ActorInitializer init) { return new WithMuzzleFlash(init.Self, this); }
|
||||
}
|
||||
|
||||
class WithMuzzleFlash : INotifyAttack, IRender, ITick
|
||||
class WithMuzzleFlash : UpgradableTrait<WithMuzzleFlashInfo>, INotifyAttack, IRender, ITick
|
||||
{
|
||||
Dictionary<Barrel, bool> visible = new Dictionary<Barrel, bool>();
|
||||
Dictionary<Barrel, AnimationWithOffset> anims = new Dictionary<Barrel, AnimationWithOffset>();
|
||||
Func<int> getFacing;
|
||||
|
||||
public WithMuzzleFlash(Actor self, WithMuzzleFlashInfo info)
|
||||
: base(info)
|
||||
{
|
||||
var render = self.Trait<RenderSprites>();
|
||||
var facing = self.TraitOrDefault<IFacing>();
|
||||
@@ -64,7 +65,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
anims.Add(barrel,
|
||||
new AnimationWithOffset(muzzleFlash,
|
||||
() => info.IgnoreOffset ? WVec.Zero : armClosure.MuzzleOffset(self, barrel),
|
||||
() => !visible[barrel],
|
||||
() => IsTraitDisabled || !visible[barrel],
|
||||
() => false,
|
||||
p => WithTurret.ZOffsetFromCenter(self, p, 2)));
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ using OpenRA.Traits;
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Renders turrets for units with the Turreted trait.")]
|
||||
public class WithTurretInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>, Requires<TurretedInfo>, Requires<IBodyOrientationInfo>
|
||||
public class WithTurretInfo : UpgradableTraitInfo, ITraitInfo, IRenderActorPreviewSpritesInfo,
|
||||
Requires<RenderSpritesInfo>, Requires<TurretedInfo>, Requires<IBodyOrientationInfo>
|
||||
{
|
||||
[Desc("Sequence name to use")]
|
||||
public readonly string Sequence = "turret";
|
||||
@@ -35,6 +36,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||
{
|
||||
if (UpgradeMinEnabledLevel > 0)
|
||||
yield break;
|
||||
|
||||
var body = init.Actor.Traits.Get<BodyOrientationInfo>();
|
||||
var t = init.Actor.Traits.WithInterface<TurretedInfo>()
|
||||
.First(tt => tt.Turret == Turret);
|
||||
@@ -52,9 +56,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public class WithTurret : ITick
|
||||
public class WithTurret : UpgradableTrait<WithTurretInfo>, ITick
|
||||
{
|
||||
WithTurretInfo info;
|
||||
RenderSprites rs;
|
||||
IBodyOrientation body;
|
||||
AttackBase ab;
|
||||
@@ -63,8 +66,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
Animation anim;
|
||||
|
||||
public WithTurret(Actor self, WithTurretInfo info)
|
||||
: base(info)
|
||||
{
|
||||
this.info = info;
|
||||
rs = self.Trait<RenderSprites>();
|
||||
body = self.Trait<IBodyOrientation>();
|
||||
|
||||
@@ -76,8 +79,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
anim = new Animation(self.World, rs.GetImage(self), () => t.TurretFacing);
|
||||
anim.Play(info.Sequence);
|
||||
rs.Add("turret_{0}".F(info.Turret), new AnimationWithOffset(
|
||||
anim, () => TurretOffset(self), null, () => false, p => ZOffsetFromCenter(self, p, 1)));
|
||||
rs.Add("turret_{0}_{1}".F(info.Turret, info.Sequence), new AnimationWithOffset(
|
||||
anim, () => TurretOffset(self), () => IsTraitDisabled, () => false, p => ZOffsetFromCenter(self, p, 1)));
|
||||
|
||||
// Restrict turret facings to match the sprite
|
||||
t.QuantizedFacings = anim.CurrentSequence.Facings;
|
||||
@@ -85,7 +88,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
WVec TurretOffset(Actor self)
|
||||
{
|
||||
if (!info.Recoils)
|
||||
if (!Info.Recoils)
|
||||
return t.Position(self);
|
||||
|
||||
var recoil = arms.Aggregate(WRange.Zero, (a, b) => a + b.Recoil);
|
||||
@@ -97,10 +100,10 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (info.AimSequence == null)
|
||||
if (Info.AimSequence == null)
|
||||
return;
|
||||
|
||||
var sequence = ab.IsAttacking ? info.AimSequence : info.Sequence;
|
||||
var sequence = ab.IsAttacking ? Info.AimSequence : Info.Sequence;
|
||||
anim.ReplaceAnim(sequence);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public abstract class SupportPowerInfo : ITraitInfo
|
||||
public abstract class SupportPowerInfo : UpgradableTraitInfo, ITraitInfo
|
||||
{
|
||||
[Desc("Measured in seconds.")]
|
||||
public readonly int ChargeTime = 0;
|
||||
@@ -53,15 +53,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public SupportPowerInfo() { OrderName = GetType().Name + "Order"; }
|
||||
}
|
||||
|
||||
public class SupportPower
|
||||
public class SupportPower : UpgradableTrait<SupportPowerInfo>
|
||||
{
|
||||
public readonly Actor Self;
|
||||
public readonly SupportPowerInfo Info;
|
||||
protected RadarPing ping;
|
||||
|
||||
public SupportPower(Actor self, SupportPowerInfo info)
|
||||
: base(info)
|
||||
{
|
||||
Info = info;
|
||||
Self = self;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (!Powers.TryGetValue(key, out sp))
|
||||
return;
|
||||
|
||||
sp.Disabled = false;
|
||||
sp.PrerequisitesAvailable(true);
|
||||
}
|
||||
|
||||
public void PrerequisitesUnavailable(string key)
|
||||
@@ -141,7 +141,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (!Powers.TryGetValue(key, out sp))
|
||||
return;
|
||||
|
||||
sp.Disabled = true;
|
||||
sp.PrerequisitesAvailable(false);
|
||||
sp.RemainingTime = sp.TotalTime;
|
||||
}
|
||||
|
||||
@@ -158,17 +158,25 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public int RemainingTime;
|
||||
public int TotalTime;
|
||||
public bool Active { get; private set; }
|
||||
public bool Disabled { get; set; }
|
||||
public bool Disabled { get { return !prereqsAvailable || !upgradeAvailable; } }
|
||||
|
||||
public SupportPowerInfo Info { get { return Instances.Select(i => i.Info).FirstOrDefault(); } }
|
||||
public bool Ready { get { return Active && RemainingTime == 0; } }
|
||||
|
||||
bool upgradeAvailable;
|
||||
bool prereqsAvailable = true;
|
||||
|
||||
public SupportPowerInstance(string key, SupportPowerManager manager)
|
||||
{
|
||||
this.manager = manager;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public void PrerequisitesAvailable(bool available)
|
||||
{
|
||||
prereqsAvailable = available;
|
||||
}
|
||||
|
||||
static bool InstanceDisabled(SupportPower sp)
|
||||
{
|
||||
return sp.Self.TraitsImplementing<IDisable>().Any(d => d.Disabled);
|
||||
@@ -178,6 +186,10 @@ namespace OpenRA.Mods.Common.Traits
|
||||
bool notifiedReady;
|
||||
public void Tick()
|
||||
{
|
||||
upgradeAvailable = Instances.Any(i => !i.IsTraitDisabled);
|
||||
if (!upgradeAvailable)
|
||||
RemainingTime = TotalTime;
|
||||
|
||||
Active = !Disabled && Instances.Any(i => !i.Self.IsDisabled());
|
||||
if (!Active)
|
||||
return;
|
||||
@@ -226,7 +238,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
notifiedCharging = notifiedReady = false;
|
||||
|
||||
if (Info.OneShot)
|
||||
Disabled = true;
|
||||
PrerequisitesAvailable(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +141,13 @@
|
||||
CloakDelay: 90
|
||||
MustBeDestroyed:
|
||||
|
||||
^BuildingPlug:
|
||||
Building:
|
||||
BuildSounds: place2.aud
|
||||
KillsSelf:
|
||||
RemoveInstead: true
|
||||
RenderSprites:
|
||||
|
||||
^Infantry:
|
||||
AppearsOnRadar:
|
||||
Health:
|
||||
|
||||
@@ -86,6 +86,46 @@ GAPOWR:
|
||||
TargetTypes: Ground, C4, DetonateAttack, SpyInfiltrate
|
||||
ScalePowerWithHealth:
|
||||
DisabledOverlay:
|
||||
Pluggable@pluga:
|
||||
Offset: 0,1
|
||||
Upgrades:
|
||||
powrup: powrup.a
|
||||
Power@pluga:
|
||||
UpgradeTypes: powrup.a
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Amount: 50
|
||||
WithIdleOverlay@pluga:
|
||||
UpgradeTypes: powrup.a
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Sequence: idle-powrupa
|
||||
Pluggable@plugb:
|
||||
Offset: 1,1
|
||||
Upgrades:
|
||||
powrup: powrup.b
|
||||
WithIdleOverlay@plugb:
|
||||
UpgradeTypes: powrup.b
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Sequence: idle-powrupb
|
||||
Power@plugb:
|
||||
UpgradeTypes: powrup.b
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Amount: 50
|
||||
|
||||
GAPOWRUP:
|
||||
Inherits: ^BuildingPlug
|
||||
Valued:
|
||||
Cost: 150
|
||||
Tooltip:
|
||||
Name: Power Turbine
|
||||
Description: Provides extra power generation
|
||||
Buildable:
|
||||
Queue: Defense
|
||||
BuildPaletteOrder: 10
|
||||
Prerequisites: gapowr, ~structures.gdi
|
||||
Plug:
|
||||
Type: powrup
|
||||
Power:
|
||||
Amount: 50
|
||||
|
||||
GAPILE:
|
||||
Inherits: ^Building
|
||||
@@ -430,7 +470,7 @@ GAWALL:
|
||||
Inherits: ^Wall
|
||||
Buildable:
|
||||
Queue: Defense
|
||||
BuildPaletteOrder: 1001
|
||||
BuildPaletteOrder: 20
|
||||
Prerequisites: ~structures.gdi
|
||||
SoundOnDamageTransition:
|
||||
DamagedSounds:
|
||||
@@ -910,14 +950,13 @@ NASTLH:
|
||||
Selectable:
|
||||
Bounds: 124, 64, 15, 13
|
||||
|
||||
#TODO: Placeholder, replace with Component Tower + Vulcan Upgrade
|
||||
GAVULC:
|
||||
GACTWR:
|
||||
Inherits: ^Building
|
||||
Valued:
|
||||
Cost: 600
|
||||
Tooltip:
|
||||
Name: Vulcan Tower
|
||||
Description: Basic base defense. \nRequires no power to operate.\n Strong vs infantry and light armor\n Cannot target Aircraft
|
||||
Name: Component Tower
|
||||
Description: Modular tower for base defenses.
|
||||
Buildable:
|
||||
Queue: Defense
|
||||
BuildPaletteOrder: 30
|
||||
@@ -938,26 +977,60 @@ GAVULC:
|
||||
RenderRangeCircle:
|
||||
RenderDetectionCircle:
|
||||
DetectCloaked:
|
||||
UpgradeTypes: tower
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Range: 5
|
||||
AutoTarget:
|
||||
Turreted:
|
||||
ROT: 10
|
||||
InitialFacing: 50
|
||||
AttackTurreted:
|
||||
WithTurret:
|
||||
UpgradeTypes: tower
|
||||
UpgradeMinEnabledLevel: 1
|
||||
CanPowerDown:
|
||||
WithTurret@VULC:
|
||||
UpgradeTypes: tower.vulcan
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Recoils: no
|
||||
Armament@PRIMARY:
|
||||
Sequence: turret-vulcan
|
||||
WithTurret@ROCKET:
|
||||
UpgradeTypes: tower.rocket
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Recoils: no
|
||||
Sequence: turret-rocket
|
||||
WithTurret@SAM:
|
||||
UpgradeTypes: tower.sam
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Recoils: no
|
||||
Sequence: turret-sam
|
||||
Armament@VULCPRIMARY:
|
||||
UpgradeTypes: tower.vulcan
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Weapon: VulcanTower
|
||||
LocalOffset: 768,85,512
|
||||
MuzzleSequence: muzzle
|
||||
MuzzleSplitFacings: 8
|
||||
Armament@SECONDARY:
|
||||
Armament@VULCSECONDARY:
|
||||
UpgradeTypes: tower.vulcan
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Name: secondary
|
||||
Weapon: VulcanTower
|
||||
LocalOffset: 768,-85,512
|
||||
MuzzleSequence: muzzle
|
||||
MuzzleSplitFacings: 8
|
||||
Armament@ROCKET:
|
||||
UpgradeTypes: tower.rocket
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Weapon: RPGTower
|
||||
LocalOffset: 512,-128,512
|
||||
Armament@SAM:
|
||||
UpgradeTypes: tower.sam
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Weapon: SAMTower
|
||||
LocalOffset: 512,0,512
|
||||
WithMuzzleFlash:
|
||||
UpgradeTypes: tower.vulcan
|
||||
UpgradeMinEnabledLevel: 1
|
||||
WithIdleOverlay@LIGHTS:
|
||||
Sequence: idle-lights
|
||||
LineBuildNode:
|
||||
@@ -965,106 +1038,67 @@ GAVULC:
|
||||
-RenderBuilding:
|
||||
RenderBuildingWall:
|
||||
Type: wall
|
||||
Power@base:
|
||||
Amount: -10
|
||||
Power@turrets:
|
||||
UpgradeTypes: tower
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Amount: -20
|
||||
Power@samextra:
|
||||
UpgradeTypes: tower.sam
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Amount: -10
|
||||
Pluggable:
|
||||
Upgrades:
|
||||
tower.vulcan: tower, tower.vulcan
|
||||
tower.rocket: tower, tower.rocket
|
||||
tower.sam: tower, tower.sam
|
||||
|
||||
GAVULC:
|
||||
Inherits: ^BuildingPlug
|
||||
Valued:
|
||||
Cost: 150
|
||||
Tooltip:
|
||||
Name: Vulcan Tower
|
||||
Description: Basic base defense. \nRequires no power to operate.\n Strong vs infantry and light armor\n Cannot target Aircraft
|
||||
Buildable:
|
||||
Queue: Defense
|
||||
BuildPaletteOrder: 40
|
||||
Prerequisites: gactwr, gapile, ~structures.gdi
|
||||
Plug:
|
||||
Type: tower.vulcan
|
||||
Power:
|
||||
Amount: -20
|
||||
|
||||
#TODO: Placeholder, replace with Component Tower + RPG Upgrade
|
||||
GAROCK:
|
||||
Inherits: ^Building
|
||||
Inherits: ^BuildingPlug
|
||||
Valued:
|
||||
Cost: 1000
|
||||
Cost: 600
|
||||
Tooltip:
|
||||
Name: RPG Tower
|
||||
Name: RPG Upgrade
|
||||
Description: GDI Advanced base defense.\nRequires power to operate.\n Strong vs armored ground units\n Cannot target Aircraft
|
||||
Buildable:
|
||||
Queue: Defense
|
||||
BuildPaletteOrder: 40
|
||||
Prerequisites: gapile, ~structures.gdi
|
||||
Building:
|
||||
Selectable:
|
||||
Bounds: 48, 48, 0, -12
|
||||
RequiresPower:
|
||||
DisabledOverlay:
|
||||
-GivesBuildableArea:
|
||||
Health:
|
||||
HP: 500
|
||||
Armor:
|
||||
Type: Light
|
||||
RevealsShroud:
|
||||
Range: 6c0
|
||||
BodyOrientation:
|
||||
QuantizedFacings: 32
|
||||
RenderRangeCircle:
|
||||
RenderDetectionCircle:
|
||||
DetectCloaked:
|
||||
Range: 5
|
||||
AutoTarget:
|
||||
Turreted:
|
||||
ROT: 10
|
||||
InitialFacing: 50
|
||||
AttackTurreted:
|
||||
WithTurret:
|
||||
Recoils: no
|
||||
Armament:
|
||||
Weapon: RPGTower
|
||||
LocalOffset: 512,-128,512
|
||||
WithIdleOverlay@LIGHTS:
|
||||
Sequence: idle-lights
|
||||
LineBuildNode:
|
||||
Types: turret
|
||||
-RenderBuilding:
|
||||
RenderBuildingWall:
|
||||
Type: wall
|
||||
Prerequisites: gactwr, gapile, ~structures.gdi
|
||||
Plug:
|
||||
Type: tower.rocket
|
||||
Power:
|
||||
Amount: -50
|
||||
Amount: -20
|
||||
|
||||
#TODO: Placeholder, replace with Component Tower + SAM Upgrade
|
||||
GACSAM:
|
||||
Inherits: ^Building
|
||||
Inherits: ^BuildingPlug
|
||||
Valued:
|
||||
Cost: 600
|
||||
Cost: 300
|
||||
Tooltip:
|
||||
Name: S.A.M. Tower
|
||||
Name: SAM. Upgrade
|
||||
Description: GDI Anti-Air base defense. \nRequires power to operate.\n Strong vs all Aircraft\n Cannot target ground units
|
||||
Buildable:
|
||||
Queue: Defense
|
||||
BuildPaletteOrder: 60
|
||||
Prerequisites: garadr, ~structures.gdi
|
||||
Building:
|
||||
Selectable:
|
||||
Bounds: 48, 48, 0, -12
|
||||
RequiresPower:
|
||||
DisabledOverlay:
|
||||
-GivesBuildableArea:
|
||||
Health:
|
||||
HP: 500
|
||||
Armor:
|
||||
Type: Light
|
||||
RevealsShroud:
|
||||
Range: 6c0
|
||||
BodyOrientation:
|
||||
QuantizedFacings: 32
|
||||
RenderRangeCircle:
|
||||
RenderDetectionCircle:
|
||||
DetectCloaked:
|
||||
Range: 5
|
||||
AutoTarget:
|
||||
Turreted:
|
||||
ROT: 10
|
||||
InitialFacing: 50
|
||||
AttackTurreted:
|
||||
WithTurret:
|
||||
Recoils: no
|
||||
Armament:
|
||||
Weapon: SAMTower
|
||||
LocalOffset: 512,0,512
|
||||
WithIdleOverlay@LIGHTS:
|
||||
Sequence: idle-lights
|
||||
LineBuildNode:
|
||||
Types: turret
|
||||
-RenderBuilding:
|
||||
RenderBuildingWall:
|
||||
Type: wall
|
||||
BuildPaletteOrder: 40
|
||||
Prerequisites: gactwr, garadr, ~structures.gdi
|
||||
Plug:
|
||||
Type: tower.sam
|
||||
Power:
|
||||
Amount: -30
|
||||
|
||||
@@ -1291,16 +1325,16 @@ NAMISL:
|
||||
GAPLUG:
|
||||
Inherits: ^Building
|
||||
Valued:
|
||||
Cost: 1800
|
||||
Cost: 1000
|
||||
Tooltip:
|
||||
Name: GDI Upgrade Center
|
||||
Description: Provides the Orbital Ion Cannon support power.\nRequires power to operate.
|
||||
Description: Can be upgraded for additional technology
|
||||
Selectable:
|
||||
Bounds: 115,120,0,-20
|
||||
Buildable:
|
||||
BuildPaletteOrder: 100
|
||||
Prerequisites: proc, gatech
|
||||
Queue: Defense
|
||||
Queue: Building
|
||||
Building:
|
||||
Footprint: xxx xxx
|
||||
Dimensions: 2,3
|
||||
@@ -1321,6 +1355,8 @@ GAPLUG:
|
||||
RevealsShroud:
|
||||
Range: 6c0
|
||||
IonCannonPower:
|
||||
UpgradeTypes: plug.ioncannon
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Icon: ioncannon
|
||||
Effect: ionbeam
|
||||
ChargeTime: 180
|
||||
@@ -1336,6 +1372,42 @@ GAPLUG:
|
||||
SupportPowerChargeBar:
|
||||
Power:
|
||||
Amount: -150
|
||||
Power@ioncannon:
|
||||
UpgradeTypes: plug.ioncannon
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Amount: -100
|
||||
Pluggable@pluga:
|
||||
Offset: 0,2
|
||||
Upgrades:
|
||||
plug.ioncannon: plug.ioncannon, plug.ioncannona
|
||||
WithIdleOverlay@ioncannona:
|
||||
UpgradeTypes: plug.ioncannona
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Sequence: idle-ioncannona
|
||||
Pluggable@plugb:
|
||||
Offset: 1,2
|
||||
Upgrades:
|
||||
plug.ioncannon: plug.ioncannon, plug.ioncannonb
|
||||
WithIdleOverlay@ioncannonb:
|
||||
UpgradeTypes: plug.ioncannonb
|
||||
UpgradeMinEnabledLevel: 1
|
||||
Sequence: idle-ioncannonb
|
||||
|
||||
GAPLUG3:
|
||||
Inherits: ^BuildingPlug
|
||||
Valued:
|
||||
Cost: 1500
|
||||
Tooltip:
|
||||
Name: Ion Cannon Uplink
|
||||
Description: Enables use of the Ion Cannon
|
||||
Buildable:
|
||||
Queue: Defense
|
||||
BuildPaletteOrder: 1000
|
||||
Prerequisites: gaplug, gatech, ~structures.gdi
|
||||
Plug:
|
||||
Type: plug.ioncannon
|
||||
Power:
|
||||
Amount: -100
|
||||
|
||||
ANYPOWER:
|
||||
Tooltip:
|
||||
|
||||
@@ -67,6 +67,22 @@ gapowr:
|
||||
damaged-idle-plug: gtpowr_b
|
||||
Length: 12
|
||||
Tick: 200
|
||||
idle-powrupa: gtpowr_b
|
||||
Length: 12
|
||||
Tick: 200
|
||||
Offset: -48, -24
|
||||
damaged-idle-powrupa: gtpowr_b
|
||||
Length: 12
|
||||
Tick: 200
|
||||
Offset: -48, -24
|
||||
idle-powrupb: gtpowr_b
|
||||
Length: 12
|
||||
Tick: 200
|
||||
Offset: -24, -12
|
||||
damaged-idle-powrupb: gtpowr_b
|
||||
Length: 12
|
||||
Tick: 200
|
||||
Offset: -24, -12
|
||||
make: gtpowrmk
|
||||
Length: 20
|
||||
ShadowStart: 20
|
||||
@@ -74,6 +90,9 @@ gapowr:
|
||||
Offset: 0, 0
|
||||
UseTilesetCode: false
|
||||
|
||||
gapowrup:
|
||||
icon: turbicon
|
||||
|
||||
gapile:
|
||||
Defaults:
|
||||
Offset: 0, -24
|
||||
@@ -654,7 +673,7 @@ nastlh:
|
||||
Offset: 0, 0
|
||||
UseTilesetCode: false
|
||||
|
||||
gavulc:
|
||||
gactwr:
|
||||
Defaults:
|
||||
Offset: 0, -12
|
||||
UseTilesetCode: true
|
||||
@@ -667,7 +686,21 @@ gavulc:
|
||||
Start: 2
|
||||
ShadowStart: 5
|
||||
Tick: 400
|
||||
turret: gtctwr_b
|
||||
idle-lights: gtctwr_a
|
||||
Length: 6
|
||||
Tick: 200
|
||||
damaged-idle-lights: gtctwr_a
|
||||
Length: 6
|
||||
Tick: 200
|
||||
make: gtctwrmk
|
||||
Length: 11
|
||||
ShadowStart: 11
|
||||
turret-vulcan: gtctwr_b
|
||||
Facings: 32
|
||||
turret-rocket: gtctwr_c
|
||||
Facings: 32
|
||||
UseTilesetCode: false
|
||||
turret-sam: gtctwr_d
|
||||
Facings: 32
|
||||
muzzle0: mgun-n
|
||||
Length: *
|
||||
@@ -693,74 +726,18 @@ gavulc:
|
||||
muzzle7: mgun-ne
|
||||
Length: *
|
||||
UseTilesetCode: false
|
||||
idle-lights: gtctwr_a
|
||||
Length: 6
|
||||
Tick: 200
|
||||
damaged-idle-lights: gtctwr_a
|
||||
Length: 6
|
||||
Tick: 200
|
||||
make: gtctwrmk
|
||||
Length: 11
|
||||
ShadowStart: 11
|
||||
icon: twr1icon
|
||||
icon: towricon
|
||||
Offset: 0, 0
|
||||
UseTilesetCode: false
|
||||
|
||||
gavulc:
|
||||
icon: twr1icon
|
||||
|
||||
garock:
|
||||
Defaults:
|
||||
Offset: 0, -12
|
||||
UseTilesetCode: true
|
||||
idle: gtctwr
|
||||
ShadowStart: 3
|
||||
damaged-idle: gtctwr
|
||||
Start: 1
|
||||
ShadowStart: 4
|
||||
dead: gtctwr
|
||||
Start: 2
|
||||
ShadowStart: 5
|
||||
Tick: 400
|
||||
turret: gtctwr_c
|
||||
Facings: 32
|
||||
idle-lights: gtctwr_a
|
||||
Length: 6
|
||||
Tick: 200
|
||||
damaged-idle-lights: gtctwr_a
|
||||
Length: 6
|
||||
Tick: 200
|
||||
make: gtctwrmk
|
||||
Length: 11
|
||||
ShadowStart: 11
|
||||
icon: twr2icon
|
||||
Offset: 0, 0
|
||||
UseTilesetCode: false
|
||||
|
||||
gacsam:
|
||||
Defaults:
|
||||
Offset: 0, -12
|
||||
UseTilesetCode: true
|
||||
idle: gtctwr
|
||||
ShadowStart: 3
|
||||
damaged-idle: gtctwr
|
||||
Start: 1
|
||||
ShadowStart: 4
|
||||
dead: gtctwr
|
||||
Start: 2
|
||||
ShadowStart: 5
|
||||
Tick: 400
|
||||
turret: gtctwr_d
|
||||
Facings: 32
|
||||
idle-lights: gtctwr_a
|
||||
Length: 6
|
||||
Tick: 200
|
||||
damaged-idle-lights: gtctwr_a
|
||||
Length: 6
|
||||
Tick: 200
|
||||
make: gtctwrmk
|
||||
Length: 11
|
||||
ShadowStart: 11
|
||||
icon: twr3icon
|
||||
Offset: 0, 0
|
||||
UseTilesetCode: false
|
||||
|
||||
gahpad:
|
||||
Defaults:
|
||||
@@ -1038,9 +1015,21 @@ gaplug:
|
||||
Start: 8
|
||||
Length: 8
|
||||
Tick: 120
|
||||
idle-ioncannona: gaplug_f
|
||||
Length: 15
|
||||
Tick: 120
|
||||
Reverses: true
|
||||
Offset: -12, -42
|
||||
idle-ioncannonb: gaplug_f
|
||||
Length: 15
|
||||
Reverses: true
|
||||
Tick: 120
|
||||
make: gtplugmk
|
||||
Length: 17
|
||||
ShadowStart: 17
|
||||
icon: plugicon
|
||||
Offset: 0, 0
|
||||
UseTilesetCode: false
|
||||
|
||||
gaplug3:
|
||||
icon: rad3icon
|
||||
Reference in New Issue
Block a user