diff --git a/OpenRA.Mods.Cnc/AttackPopupTurreted.cs b/OpenRA.Mods.Cnc/AttackPopupTurreted.cs new file mode 100644 index 0000000000..cb158cad14 --- /dev/null +++ b/OpenRA.Mods.Cnc/AttackPopupTurreted.cs @@ -0,0 +1,144 @@ +#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.Linq; +using OpenRA.Mods.RA.Activities; +using OpenRA.Mods.RA.Buildings; +using OpenRA.Mods.RA.Move; +using OpenRA.Traits; +using OpenRA.Traits.Activities; +using OpenRA.Mods.RA.Render; +using OpenRA.Mods.RA; + +namespace OpenRA.Mods.Cnc +{ + class AttackPopupTurretedInfo : AttackBaseInfo + { + public int CloseDelay = 125; + public override object Create(ActorInitializer init) { return new AttackPopupTurreted( init.self, this ); } + } + + class AttackPopupTurreted : AttackBase, INotifyBuildComplete, INotifyIdle + { + enum PopupState + { + Open, + Transitioning, + Closed + }; + + protected Target target; + AttackPopupTurretedInfo Info; + int IdleTicks = 0; + PopupState State = PopupState.Open; + + public AttackPopupTurreted(Actor self, AttackPopupTurretedInfo info) : base(self) + { + Info = info; + } + + protected override bool CanAttack( Actor self, Target target ) + { + if (State == PopupState.Transitioning) + return false; + + if( self.HasTrait() && !buildComplete ) + return false; + + if (!base.CanAttack( self, target )) + return false; + + IdleTicks = 0; + if (State == PopupState.Closed) + { + State = PopupState.Transitioning; + var rb = self.Trait(); + rb.PlayCustomAnimThen(self, "opening", () => + { + State = PopupState.Open; + rb.PlayCustomAnimRepeating(self, "idle"); + }); + return false; + } + + var turreted = self.Trait(); + turreted.desiredFacing = Util.GetFacing( target.CenterLocation - self.CenterLocation, turreted.turretFacing ); + if( turreted.desiredFacing != turreted.turretFacing ) + return false; + + return true; + } + + public override void Tick(Actor self) + { + base.Tick(self); + DoAttack( self, target ); + } + + public void TickIdle(Actor self) + { + if (State == PopupState.Open && IdleTicks++ > Info.CloseDelay) + { + State = PopupState.Transitioning; + var rb = self.Trait(); + rb.PlayCustomAnimThen(self, "closing", () => + { + State = PopupState.Closed; + rb.PlayCustomAnimRepeating(self, "closed-idle"); + }); + } + } + + public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove) + { + return new AttackActivity( newTarget ); + } + + public override void ResolveOrder(Actor self, Order order) + { + base.ResolveOrder(self, order); + + if (order.OrderString == "Stop") + target = Target.None; + } + + bool buildComplete = false; + public void BuildingComplete(Actor self) { buildComplete = true; } + + class AttackActivity : CancelableActivity + { + readonly Target target; + public AttackActivity( Target newTarget ) { this.target = newTarget; } + + public override IActivity Tick( Actor self ) + { + if( IsCanceled || !target.IsValid ) return NextActivity; + + if (self.TraitsImplementing().Any(d => d.Disabled)) + return this; + + var attack = self.Trait(); + const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */ + var weapon = attack.ChooseWeaponForTarget(target); + if (weapon != null) + { + attack.target = target; + + if (self.HasTrait() && !self.Info.Traits.Get().OnRails) + return Util.SequenceActivities( + new Follow( target, Math.Max( 0, (int)weapon.Info.Range - RangeTolerance ) ), + this ); + } + return NextActivity; + } + } + } +} diff --git a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj index decbcf69b4..7cf3ef9040 100644 --- a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj +++ b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj @@ -68,6 +68,7 @@ + diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml index 929426fad5..adb7220bd6 100644 --- a/mods/cnc/rules/structures.yaml +++ b/mods/cnc/rules/structures.yaml @@ -660,11 +660,10 @@ SAM: ROT: 30 InitialFacing: 0 RenderBuildingTurreted: - AttackTurreted: + AttackPopupTurreted: PrimaryWeapon: Nike AutoTarget: -RenderBuilding: - -DeadBuildingState: RenderRangeCircle: GTWR: diff --git a/mods/cnc/sequences/structures.yaml b/mods/cnc/sequences/structures.yaml index 3c4e64c8dd..abb4d9d8d8 100644 --- a/mods/cnc/sequences/structures.yaml +++ b/mods/cnc/sequences/structures.yaml @@ -341,12 +341,30 @@ gun: Length: * sam: + closed-idle: + Start:0 + opening: + Start: 1 + Length: 16 idle: Start: 17 Facings: 32 + closing: + Start: 50 + Length: 14 + damaged-closed-idle: + Start:64 + damaged-opening: + Start: 65 + Length: 16 damaged-idle: Start: 81 Facings: 32 + damaged-closing: + Start: 114 + Length: 14 + dead: + Start: 128 make: sammake Start: 0 Length: 20