diff --git a/OpenRA.Mods.Common/Activities/Attack.cs b/OpenRA.Mods.Common/Activities/Attack.cs index e7da8526d0..10bba255f4 100644 --- a/OpenRA.Mods.Common/Activities/Attack.cs +++ b/OpenRA.Mods.Common/Activities/Attack.cs @@ -9,6 +9,7 @@ */ #endregion +using System; using System.Linq; using OpenRA.Activities; using OpenRA.Mods.Common.Traits; @@ -19,8 +20,11 @@ namespace OpenRA.Mods.Common.Activities /* non-turreted attack */ public class Attack : Activity { + [Flags] + enum AttackStatus { UnableToAttack, NeedsToTurn, NeedsToMove, Attacking } + protected readonly Target Target; - readonly AttackBase attack; + readonly AttackBase[] attackTraits; readonly IMove move; readonly IFacing facing; readonly IPositionable positionable; @@ -28,6 +32,9 @@ namespace OpenRA.Mods.Common.Activities WDist minRange; WDist maxRange; + Activity turnActivity; + Activity moveActivity; + AttackStatus attackStatus = AttackStatus.UnableToAttack; public Attack(Actor self, Target target, bool allowMovement, bool forceAttack) { @@ -35,7 +42,7 @@ namespace OpenRA.Mods.Common.Activities this.forceAttack = forceAttack; - attack = self.Trait(); + attackTraits = self.TraitsImplementing().ToArray(); facing = self.Trait(); positionable = self.Trait(); @@ -44,9 +51,25 @@ namespace OpenRA.Mods.Common.Activities public override Activity Tick(Actor self) { - var ret = InnerTick(self, attack); - attack.IsAttacking = ret == this; - return ret; + turnActivity = moveActivity = null; + attackStatus = AttackStatus.UnableToAttack; + + foreach (var attack in attackTraits.Where(x => !x.IsTraitDisabled)) + { + var activity = InnerTick(self, attack); + attack.IsAttacking = activity == this; + } + + if (attackStatus.HasFlag(AttackStatus.Attacking)) + return this; + + if (attackStatus.HasFlag(AttackStatus.NeedsToTurn)) + return turnActivity; + + if (attackStatus.HasFlag(AttackStatus.NeedsToMove)) + return moveActivity; + + return NextActivity; } protected virtual Activity InnerTick(Actor self, AttackBase attack) @@ -82,13 +105,21 @@ namespace OpenRA.Mods.Common.Activities // Try to move within range, drop the target otherwise if (move == null) return NextActivity; - return ActivityUtils.SequenceActivities(move.MoveWithinRange(Target, minRange, maxRange), this); + + attackStatus |= AttackStatus.NeedsToMove; + moveActivity = ActivityUtils.SequenceActivities(move.MoveWithinRange(Target, minRange, maxRange), this); + return NextActivity; } var desiredFacing = (Target.CenterPosition - self.CenterPosition).Yaw.Facing; if (facing.Facing != desiredFacing) - return ActivityUtils.SequenceActivities(new Turn(self, desiredFacing), this); + { + attackStatus |= AttackStatus.NeedsToTurn; + turnActivity = ActivityUtils.SequenceActivities(new Turn(self, desiredFacing), this); + return NextActivity; + } + attackStatus |= AttackStatus.Attacking; attack.DoAttack(self, Target, armaments); return this; diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs index d9410fd50a..e8004b0768 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs @@ -31,6 +31,12 @@ namespace OpenRA.Mods.Common.Traits public virtual void Tick(Actor self) { + if (IsTraitDisabled) + { + Target = Target.Invalid; + return; + } + DoAttack(self, Target); IsAttacking = Target.IsValidFor(self); } diff --git a/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs b/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs index 511e504064..e8b02a42e7 100644 --- a/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs +++ b/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs @@ -28,17 +28,15 @@ namespace OpenRA.Mods.Common.Traits public class CombatDebugOverlay : IPostRender, INotifyDamage, INotifyCreated { readonly DeveloperMode devMode; - readonly HealthInfo healthInfo; + readonly Lazy coords; + IBlocksProjectiles[] allBlockers; - Lazy attack; - Lazy coords; public CombatDebugOverlay(Actor self) { healthInfo = self.Info.TraitInfoOrDefault(); - attack = Exts.Lazy(() => self.TraitOrDefault()); - coords = Exts.Lazy(() => self.Trait()); + coords = Exts.Lazy(self.Trait); var localPlayer = self.World.LocalPlayer; devMode = localPlayer != null ? localPlayer.PlayerActor.Trait() : null; @@ -72,14 +70,16 @@ namespace OpenRA.Mods.Common.Traits TargetLineRenderable.DrawTargetMarker(wr, hc, hb); } - // No armaments to draw - if (attack.Value == null) - return; + foreach (var attack in self.TraitsImplementing().Where(x => !x.IsTraitDisabled)) + DrawArmaments(self, attack, wr, wcr, iz); + } + void DrawArmaments(Actor self, AttackBase attack, WorldRenderer wr, RgbaColorRenderer wcr, float iz) + { var c = Color.White; // Fire ports on garrisonable structures - var garrison = attack.Value as AttackGarrisoned; + var garrison = attack as AttackGarrisoned; if (garrison != null) { var bodyOrientation = coords.Value.QuantizeOrientation(self, self.Orientation); @@ -99,7 +99,7 @@ namespace OpenRA.Mods.Common.Traits return; } - foreach (var a in attack.Value.Armaments) + foreach (var a in attack.Armaments) { foreach (var b in a.Barrels) { diff --git a/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs b/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs index 7a06785b5f..2b2c6efb75 100644 --- a/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs +++ b/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs @@ -150,6 +150,12 @@ namespace OpenRA.Mods.TS.UtilityCommands { 0x03, new byte[] { 0x7E } } }; + private static readonly Dictionary DeployableActors = new Dictionary() + { + { "gadpsa", "lpst" }, + { "gatick", "ttnk" } + }; + [Desc("FILENAME", "Convert a Tiberian Sun map to the OpenRA format.")] public void Run(ModData modData, string[] args) { @@ -388,9 +394,17 @@ namespace OpenRA.Mods.TS.UtilityCommands var structuresSection = file.GetSection(type, true); foreach (var kv in structuresSection) { + var isDeployed = false; var entries = kv.Value.Split(','); var name = entries[1].ToLowerInvariant(); + + if (DeployableActors.ContainsKey(name)) + { + name = DeployableActors[name]; + isDeployed = true; + } + var health = short.Parse(entries[2]); var rx = int.Parse(entries[3]); var ry = int.Parse(entries[4]); @@ -408,6 +422,9 @@ namespace OpenRA.Mods.TS.UtilityCommands new FacingInit(facing), }; + if (isDeployed) + ar.Add(new DeployStateInit(DeployState.Deployed)); + if (!map.Rules.Actors.ContainsKey(name)) Console.WriteLine("Ignoring unknown actor type: `{0}`".F(name)); else diff --git a/mods/ts/rules/nod-support.yaml b/mods/ts/rules/nod-support.yaml index 3aa53567ee..b1c9a20f70 100644 --- a/mods/ts/rules/nod-support.yaml +++ b/mods/ts/rules/nod-support.yaml @@ -163,49 +163,6 @@ NASAM: SelectionDecorations: VisualBounds: 40, 36, -3, -8 -GATICK: - Inherits: ^DeployedVehicle - Valued: - Cost: 800 - Tooltip: - Name: Tick Tank - Health: - HP: 350 - Armor: - Type: Concrete - RevealsShroud: - Range: 5c0 - Turreted: - ROT: 6 - InitialFacing: 224 - Offset: 0,96,224 - Armament@PRIMARY: - Weapon: 90mm - LocalOffset: 448,0,348 - UpgradeTypes: eliteweapon - UpgradeMaxEnabledLevel: 0 - UpgradeMaxAcceptedLevel: 1 - MuzzleSequence: muzzle - Armament@ELITE: - Weapon: 120mmx - LocalOffset: 448,0,348 - UpgradeTypes: eliteweapon - UpgradeMinEnabledLevel: 1 - MuzzleSequence: muzzle - BodyOrientation: - QuantizedFacings: 32 - RenderVoxels: - WithVoxelBarrel: - LocalOffset: 128,0,348 - WithVoxelTurret: - Transforms: - IntoActor: ttnk - Facing: 159 - TransformSounds: place2.aud - NoTransformSounds: - Voice: Move - WithMuzzleOverlay: - GAARTY: Inherits@1: ^DeployedVehicle Valued: diff --git a/mods/ts/rules/nod-vehicles.yaml b/mods/ts/rules/nod-vehicles.yaml index d6944d5d15..105b45ec08 100644 --- a/mods/ts/rules/nod-vehicles.yaml +++ b/mods/ts/rules/nod-vehicles.yaml @@ -82,8 +82,8 @@ TTNK: HP: 350 Armor: Type: Light - AttackFrontal: - Voice: Attack + UpgradeTypes: undeployed + UpgradeMinEnabledLevel: 1 Armament@PRIMARY: Weapon: 90mm LocalOffset: 256,0,256 @@ -100,12 +100,67 @@ TTNK: WithMuzzleOverlay: RevealsShroud: Range: 5c0 - Transforms: - IntoActor: gatick - Facing: 159 - TransformSounds: place2.aud - NoTransformSounds: - Voice: Move + RenderSprites: + Image: ttnk + DeployToUpgrade: + DeployedUpgrades: deployed, notmobile + UndeployedUpgrades: undeployed + DeployAnimation: make + Facing: 160 + AllowedTerrainTypes: Clear, Road, DirtRoad, Rough + DeploySound: place2.aud + UndeploySound: clicky1.aud + WithVoxelBody: + UpgradeTypes: undeployed + UpgradeMinEnabledLevel: 1 + WithSpriteBody@deployed: + UpgradeTypes: undeployed + UpgradeMaxEnabledLevel: 0 + AttackFrontal: + Voice: Attack + UpgradeTypes: undeployed + UpgradeMinEnabledLevel: 1 + UpgradeMaxAcceptedLevel: 1 + Turreted: + ROT: 6 + Turret: deployed + InitialFacing: 128 + Offset: -20, -130, 180 + WithVoxelBarrel: + Armament: deployed + LocalOffset: 128, 0, 256 + UpgradeTypes: deployed + UpgradeMinEnabledLevel: 1 + WithVoxelTurret@deployed: + Turret: deployed + UpgradeTypes: deployed + UpgradeMinEnabledLevel: 1 + AttackTurreted@deployed: + Voice: Attack + Armaments: deployed + UpgradeTypes: deployed + UpgradeMinEnabledLevel: 1 + Armament@deployed: + Name: deployed + Turret: deployed + Weapon: 90mm + LocalOffset: 384,0,256 + UpgradeTypes: eliteweapon + UpgradeMaxEnabledLevel: 0 + UpgradeMaxAcceptedLevel: 1 + MuzzleSequence: muzzle + Armament@deployedElite: + Name: deployed + Turret: deployed + Weapon: 120mmx + LocalOffset: 384,0,256 + UpgradeTypes: eliteweapon + UpgradeMinEnabledLevel: 1 + MuzzleSequence: muzzle + Armor@deployed: + Type: Concrete + UpgradeTypes: deployed + UpgradeMinEnabledLevel: 1 ART2: Inherits: ^VoxelTank diff --git a/mods/ts/sequences/structures.yaml b/mods/ts/sequences/structures.yaml index 10ee981ff3..4585647479 100644 --- a/mods/ts/sequences/structures.yaml +++ b/mods/ts/sequences/structures.yaml @@ -735,29 +735,6 @@ nawall: Offset: 0, 0 UseTilesetCode: false -gatick: - Defaults: - Offset: 0, -13 - UseTilesetCode: true - idle: - ShadowStart: 3 - damaged-idle: - Start: 1 - ShadowStart: 4 - muzzle: gunfire - Length: * - Offset: 0, 0 - UseTilesetCode: false - emp-overlay: emp_fx01 - Length: * - Offset: 0, 0 - UseTilesetCode: false - ZOffset: 512 - BlendMode: Additive - make: gatickmk - Length: 24 - ShadowStart: 24 - gaicbm: Defaults: Offset: 0, -12 diff --git a/mods/ts/sequences/vehicles.yaml b/mods/ts/sequences/vehicles.yaml index 753bc8a19f..eadef7b244 100644 --- a/mods/ts/sequences/vehicles.yaml +++ b/mods/ts/sequences/vehicles.yaml @@ -135,6 +135,17 @@ sonic: icon: soniicon ttnk: + idle: gatick + ShadowStart: 3 + Offset: 0, -12 + damaged-idle: gatick + Start: 1 + ShadowStart: 4 + Offset: 0, -12 + make: gatickmk + Length: 24 + ShadowStart: 24 + Offset: 0, -12 muzzle: gunfire Length: * emp-overlay: emp_fx01 diff --git a/mods/ts/sequences/voxels.yaml b/mods/ts/sequences/voxels.yaml index fa919c83ec..3b16296652 100644 --- a/mods/ts/sequences/voxels.yaml +++ b/mods/ts/sequences/voxels.yaml @@ -33,8 +33,6 @@ bike: ttnk: idle: - -gatick: turret: ttnktur barrel: ttnkbarl