diff --git a/OpenRa.Game/Actor.cs b/OpenRa.Game/Actor.cs index 978aff61d8..76dbd858af 100755 --- a/OpenRa.Game/Actor.cs +++ b/OpenRa.Game/Actor.cs @@ -45,9 +45,15 @@ namespace OpenRa.Game case "1tnk": case "2tnk": case "3tnk": - case "4tnk": + case "4tnk": + traits.Add( new Traits.Mobile( this ) ); + traits.Add( new Traits.Turreted( this ) ); + traits.Add( new Traits.AttackTurreted( this ) ); + traits.Add( new Traits.RenderUnitTurreted( this ) ); + break; case "mrj": case "mgg": + // TODO: these aren't actually turreted; they just have spinning-things traits.Add( new Traits.Mobile( this ) ); traits.Add( new Traits.Turreted( this ) ); traits.Add( new Traits.RenderUnitTurreted( this ) ); diff --git a/OpenRa.Game/Bullet.cs b/OpenRa.Game/Bullet.cs index 5f8d2cfaa5..cc4926a792 100644 --- a/OpenRa.Game/Bullet.cs +++ b/OpenRa.Game/Bullet.cs @@ -47,8 +47,8 @@ namespace OpenRa.Game game.PlaySound(Weapon.Report + ".aud", false); t += dt; - if (t > TotalTime()) - t = 0; /* temporary! loop the bullet forever */ + //if (t > TotalTime()) + // t = 0; /* temporary! loop the bullet forever */ } public IEnumerable> Render() diff --git a/OpenRa.Game/MainWindow.cs b/OpenRa.Game/MainWindow.cs index 734619431d..2f41d8e37f 100644 --- a/OpenRa.Game/MainWindow.cs +++ b/OpenRa.Game/MainWindow.cs @@ -6,7 +6,7 @@ using OpenRa.TechTree; namespace OpenRa.Game { - using GRegion = OpenRa.Game.Graphics.Region; + using GRegion = OpenRa.Game.Graphics.Region; using System.Runtime.InteropServices; class MainWindow : Form @@ -22,9 +22,9 @@ using System.Runtime.InteropServices; return new Size(settings.GetValue("width", desktopResolution.Width), settings.GetValue("height", desktopResolution.Height)); - } - - [DllImport("user32")] + } + + [DllImport("user32")] static extern int ShowCursor([MarshalAs(UnmanagedType.Bool)] bool visible); public MainWindow(Settings settings) @@ -33,11 +33,11 @@ using System.Runtime.InteropServices; FileSystem.Mount(new Package("redalert.mix")); FileSystem.Mount(new Package("conquer.mix")); FileSystem.Mount(new Package("hires.mix")); - FileSystem.Mount(new Package("general.mix")); - FileSystem.Mount(new Package("local.mix")); - FileSystem.Mount(new Package("sounds.mix")); - FileSystem.Mount(new Package("speech.mix")); - FileSystem.Mount(new Package("allies.mix")); + FileSystem.Mount(new Package("general.mix")); + FileSystem.Mount(new Package("local.mix")); + FileSystem.Mount(new Package("sounds.mix")); + FileSystem.Mount(new Package("speech.mix")); + FileSystem.Mount(new Package("allies.mix")); FileSystem.Mount(new Package("russian.mix")); FormBorderStyle = FormBorderStyle.None; @@ -52,22 +52,25 @@ using System.Runtime.InteropServices; game = new Game(settings.GetValue("map", "scg11eb.ini"), renderer, new int2(ClientSize)); - SequenceProvider.ForcePrecache(); + SequenceProvider.ForcePrecache(); Traits.RenderBuilding.Prefetch(); game.world.Add( new Actor( "mcv", new int2( 5, 5 ), game.players[ 3 ]) ); game.world.Add( new Actor( "mcv", new int2( 7, 5 ), game.players[ 2 ] ) ); - game.world.Add( new Actor( "mcv", new int2( 9, 5 ), game.players[ 0 ] ) ); - game.world.Add( new Actor( "jeep", new int2( 9, 7 ), game.players[ 1 ] ) ); - - game.world.Add(new Bullet("105mm", game.players[1], null, - new int2(200, 200), new int2(400, 200), game)); + game.world.Add( new Actor( "mcv", new int2( 9, 5 ), game.players[ 0 ] ) ); + var jeep = new Actor( "jeep", new int2( 9, 7 ), game.players[ 1 ] ); + game.world.Add( jeep ); + var tank = new Actor( "3tnk", new int2( 12, 7 ), game.players[ 1 ] ); + game.world.Add( tank ); + tank.traits.Get().target = jeep; - sidebar = new Sidebar(renderer, game); + sidebar = new Sidebar(renderer, game); + + renderer.BuildPalette(game.map); + + ShowCursor(false); - renderer.BuildPalette(game.map); - - ShowCursor(false); + game.world.ResetTimer(); } internal void Run() @@ -76,9 +79,9 @@ using System.Runtime.InteropServices; { game.Tick(); - // rude hack - game.viewport.cursor = (game.controller.orderGenerator is UnitOrderGenerator) - && (game.controller.orderGenerator as UnitOrderGenerator).selection.Count > 0 + // rude hack + game.viewport.cursor = (game.controller.orderGenerator is UnitOrderGenerator) + && (game.controller.orderGenerator as UnitOrderGenerator).selection.Count > 0 ? OpenRa.Game.Cursor.Move : OpenRa.Game.Cursor.Default; Application.DoEvents(); diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index 9764bf668c..640d0a9edd 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -126,6 +126,7 @@ + diff --git a/OpenRa.Game/Traits/AttackTurreted.cs b/OpenRa.Game/Traits/AttackTurreted.cs new file mode 100755 index 0000000000..45ba26534b --- /dev/null +++ b/OpenRa.Game/Traits/AttackTurreted.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits +{ + class AttackTurreted : ITick + { + public Actor target; + + // time (in frames) until each weapon can fire again. + int primaryFireDelay = 0; + int secondaryFireDelay = 0; + + public AttackTurreted( Actor self ) + { + self.traits.Get(); + } + + public void Tick( Actor self, Game game, int dt ) + { + if( primaryFireDelay > 0 ) + --primaryFireDelay; + if( secondaryFireDelay > 0 ) + --secondaryFireDelay; + + if( target == null ) + return; + + var mobile = self.traits.Get(); + var turreted = self.traits.Get(); + turreted.desiredFacing = mobile.GetFacing( target.Location - self.Location ); + if( turreted.desiredFacing != turreted.turretFacing ) + return; + + if( self.unitInfo.Primary != null && CheckFire( self, game, self.unitInfo.Primary, ref primaryFireDelay ) ) + { + secondaryFireDelay = Math.Max( 4, secondaryFireDelay ); + return; + } + if( self.unitInfo.Secondary != null && CheckFire( self, game, self.unitInfo.Secondary, ref secondaryFireDelay ) ) + return; + } + + bool CheckFire( Actor self, Game game, string weaponName, ref int fireDelay ) + { + if( fireDelay > 0 ) + return false; + var weapon = Rules.WeaponInfo[ weaponName ]; + var d = target.Location - self.Location; + if( weapon.Range * weapon.Range < d.X * d.X + d.Y * d.Y ) + return false; + + // FIXME: rules specifies ROF in 1/15 sec units; ticks are 1/25 sec + fireDelay = weapon.ROF; + + game.world.Add( new Bullet( weaponName, self.Owner, self, self.CenterLocation.ToInt2(), target.CenterLocation.ToInt2(), game ) ); + return true; + } + } +} diff --git a/OpenRa.Game/Traits/Mobile.cs b/OpenRa.Game/Traits/Mobile.cs index f278069561..5ba35a57cd 100644 --- a/OpenRa.Game/Traits/Mobile.cs +++ b/OpenRa.Game/Traits/Mobile.cs @@ -35,7 +35,8 @@ namespace OpenRa.Game.Traits static float2[] fvecs = Util.MakeArray(32, i => -float2.FromAngle(i / 16.0f * (float)Math.PI) * new float2(1f, 1.3f)); - int GetFacing(float2 d) + // TODO: move this somewhere more appropriate, now that AttackTurreted uses it. + public int GetFacing(float2 d) { if (float2.WithinEpsilon(d, float2.Zero, 0.001f)) return facing; diff --git a/OpenRa.Game/Traits/Turreted.cs b/OpenRa.Game/Traits/Turreted.cs index 906dfc1258..4e8e3fe667 100644 --- a/OpenRa.Game/Traits/Turreted.cs +++ b/OpenRa.Game/Traits/Turreted.cs @@ -5,18 +5,30 @@ using System.Text; namespace OpenRa.Game.Traits { - class Turreted : ITick // temporary. + class Turreted : ITick { - public int turretFacing = Game.CellSize; + public int turretFacing = 0; + public int? desiredFacing; public Turreted(Actor self) { } - // temporary. public void Tick(Actor self, Game game, int dt) { - turretFacing = (turretFacing + 1) % 32; + // TODO: desiredFacing should follow the base unit's facing only when not in combat. + // also, we want to be able to use this for GUN; avoid referencing Mobile. + var df = desiredFacing ?? self.traits.Get().facing; + + if( turretFacing != desiredFacing ) + { + var leftTurn = ( 32 + turretFacing - desiredFacing ) % 32; + var rightTurn = ( 32 + desiredFacing - turretFacing ) % 32; + if( leftTurn > rightTurn ) + turretFacing = ( turretFacing + 1 ) % 32; + else + turretFacing = ( turretFacing + 31 ) % 32; + } } } } diff --git a/OpenRa.Game/World.cs b/OpenRa.Game/World.cs index bab55dd2bf..928e19eb56 100644 --- a/OpenRa.Game/World.cs +++ b/OpenRa.Game/World.cs @@ -1,53 +1,58 @@ using System; using System.Collections.Generic; -using System.Windows.Forms; +using System.Windows.Forms; using OpenRa.Game.Graphics; namespace OpenRa.Game { class World - { - List actors = new List(); + { + List actors = new List(); List bullets = new List(); List> frameEndActions = new List>(); - readonly Game game; - int lastTime = Environment.TickCount; - const int timestep = 40; + readonly Game game; + int lastTime = Environment.TickCount; + const int timestep = 40; - public World(Game game) { this.game = game; } - - public void Add(Actor a) { actors.Add(a); ActorAdded(a); } - public void Remove(Actor a) { actors.Remove(a); ActorRemoved(a); } - - public void Add(Bullet b) { bullets.Add(b); } + public World(Game game) { this.game = game; } + + public void Add(Actor a) { actors.Add(a); ActorAdded(a); } + public void Remove(Actor a) { actors.Remove(a); ActorRemoved(a); } + + public void Add(Bullet b) { bullets.Add(b); } public void Remove(Bullet b) { bullets.Remove(b); } - public void AddFrameEndTask( Action a ) { frameEndActions.Add( a ); } + public void AddFrameEndTask( Action a ) { frameEndActions.Add( a ); } + + public event Action ActorAdded = _ => { }; + public event Action ActorRemoved = _ => { }; - public event Action ActorAdded = _ => { }; - public event Action ActorRemoved = _ => { }; + public void ResetTimer() + { + lastTime = Environment.TickCount; + } public void Update() { int t = Environment.TickCount; int dt = t - lastTime; if( dt >= timestep ) - { + { lastTime += timestep; - foreach( var a in actors ) - a.Tick(game, timestep); - foreach (var b in bullets) - b.Tick(game, timestep); - + foreach( var a in actors ) + a.Tick(game, timestep); + foreach (var b in bullets) + b.Tick(game, timestep); + Renderer.waterFrame += 0.00125f * timestep; } foreach (Action a in frameEndActions) a(this); frameEndActions.Clear(); - } - - public IEnumerable Actors { get { return actors; } } + } + + public IEnumerable Actors { get { return actors; } } public IEnumerable Bullets { get { return bullets; } } } }