diff --git a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj index 39acd08bc9..0a64324e53 100644 --- a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj +++ b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj @@ -92,6 +92,7 @@ + diff --git a/OpenRA.Mods.D2k/Traits/SpiceBloom.cs b/OpenRA.Mods.D2k/Traits/SpiceBloom.cs new file mode 100644 index 0000000000..aec763cc9d --- /dev/null +++ b/OpenRA.Mods.D2k/Traits/SpiceBloom.cs @@ -0,0 +1,148 @@ +#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; +using System.Collections.Generic; +using System.Linq; +using OpenRA.Effects; +using OpenRA.GameRules; +using OpenRA.Graphics; +using OpenRA.Mods.Common.Traits; +using OpenRA.Primitives; +using OpenRA.Traits; + +namespace OpenRA.Mods.D2k.Traits +{ + [Desc("Seeds resources by explosive eruptions after accumulation times.")] + public class SpiceBloomInfo : ITraitInfo, Requires + { + [SequenceReference] + public readonly string[] GrowthSequences = { "grow1", "grow2", "grow3" }; + + [Desc("The range of time (in ticks) that the spicebloom will take to respawn.")] + public readonly int[] RespawnDelay = { 1500, 2500 }; + + [Desc("The range of time (in ticks) that the spicebloom will take to grow.")] + public readonly int[] GrowthDelay = { 1000, 1500 }; + + public readonly string ResourceType = "Spice"; + + [Desc("The weapon to use for spice creation.")] + [WeaponReference] + public readonly string Weapon = "SpiceExplosion"; + + [Desc("The amount of spice to expel.")] + public readonly int[] Pieces = { 3, 10 }; + + [Desc("The maximum distance in cells that spice may be expelled.")] + public readonly int Range = 5; + + public object Create(ActorInitializer init) { return new SpiceBloom(init, this); } + } + + public class SpiceBloom : ITick, INotifyKilled + { + readonly Actor self; + readonly SpiceBloomInfo info; + readonly ResourceType resType; + readonly ResourceLayer resLayer; + readonly AnimationWithOffset anim; + + readonly int respawnTicks; + readonly int growTicks; + int ticks; + + public SpiceBloom(ActorInitializer init, SpiceBloomInfo info) + { + this.info = info; + self = init.Self; + + resLayer = self.World.WorldActor.Trait(); + resType = self.World.WorldActor.TraitsImplementing().First(t => t.Info.Name == info.ResourceType); + + var render = self.Trait(); + anim = new AnimationWithOffset(new Animation(init.Self.World, render.GetImage(self)), null, () => self.IsDead); + render.Add(anim); + + respawnTicks = self.World.SharedRandom.Next(info.RespawnDelay[0], info.RespawnDelay[1]); + growTicks = self.World.SharedRandom.Next(info.GrowthDelay[0], info.GrowthDelay[1]); + anim.Animation.Play(info.GrowthSequences[0]); + } + + public void Tick(Actor self) + { + ticks++; + + if (ticks >= growTicks) + self.Kill(self); + else + { + var index = info.GrowthSequences.Length * ticks / growTicks; + anim.Animation.Play(info.GrowthSequences[index]); + } + } + + public void Killed(Actor self, AttackInfo e) + { + var args = new ProjectileArgs + { + Weapon = self.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()], + Facing = 0, + + DamageModifiers = self.TraitsImplementing() + .Select(a => a.GetFirepowerModifier()).ToArray(), + + InaccuracyModifiers = self.TraitsImplementing() + .Select(a => a.GetInaccuracyModifier()).ToArray(), + + Source = self.CenterPosition, + SourceActor = self, + }; + + var pieces = self.World.SharedRandom.Next(info.Pieces[0], info.Pieces[1]) * ticks / growTicks; + for (var i = 0; pieces > i; i++) + { + var cells = OpenRA.Traits.Util.RandomWalk(self.Location, self.World.SharedRandom); + var cell = cells.Take(info.Range).SkipWhile(p => resLayer.GetResource(p) == resType && resLayer.IsFull(p)).Cast().RandomOrDefault(self.World.SharedRandom); + if (cell == null) + cell = cells.Take(info.Range).Random(self.World.SharedRandom); + + args.PassiveTarget = self.World.Map.CenterOfCell(cell.Value); + + self.World.AddFrameEndTask(_ => + { + if (args.Weapon.Projectile != null) + { + var projectile = args.Weapon.Projectile.Create(args); + if (projectile != null) + self.World.Add(projectile); + + if (args.Weapon.Report != null && args.Weapon.Report.Any()) + Game.Sound.Play(args.Weapon.Report.Random(self.World.SharedRandom), self.CenterPosition); + } + }); + } + + self.World.AddFrameEndTask(t => t.Add(new DelayedAction(respawnTicks, () => + { + var td = new TypeDictionary + { + new ParentActorInit(self), + new LocationInit(self.Location), + new CenterPositionInit(self.CenterPosition), + new OwnerInit(self.Owner), + new FactionInit(self.Owner.Faction.InternalName), + new SkipMakeAnimsInit() + }; + self.World.CreateActor(self.Info.Name, td); + }))); + } + } +} diff --git a/mods/d2k/bits/spicebloom.shp b/mods/d2k/bits/spicebloom.shp deleted file mode 100644 index 0e0bb76d3f..0000000000 Binary files a/mods/d2k/bits/spicebloom.shp and /dev/null differ diff --git a/mods/d2k/rules/arrakis.yaml b/mods/d2k/rules/arrakis.yaml index fafde1bb88..f03cc2aa6a 100644 --- a/mods/d2k/rules/arrakis.yaml +++ b/mods/d2k/rules/arrakis.yaml @@ -1,20 +1,29 @@ spicebloom: - Inherits@1: ^SpriteActor HiddenUnderShroud: - WithSpriteBody: - Building: - Footprint: x - Dimensions: 1,1 + BodyOrientation: + QuantizedFacings: 1 + AutoSelectionSize: + RenderSprites: AppearsOnRadar: + UseLocation: yes Tooltip: Name: Spice Bloom - SeedsResource: - ResourceType: Spice - Interval: 75 - WithActiveAnimation: + SpiceBloom: + Weapon: SpiceExplosion + Crushable: + CrushClasses: spicebloom + CrushedByFriendlies: true RadarColorFromTerrain: Terrain: Spice - WithMakeAnimation: + Immobile: + Health: + HP: 1 + Radius: 512 + Targetable: + TargetTypes: Ground + RequiresForceFire: yes + Armor: + Type: None sandworm: Inherits@1: ^SpriteActor diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml index 5d618528d9..b3ab29fe3c 100644 --- a/mods/d2k/rules/defaults.yaml +++ b/mods/d2k/rules/defaults.yaml @@ -58,7 +58,7 @@ Inherits@2: ^GainsExperience Inherits@3: ^SpriteActor Mobile: - Crushes: crate + Crushes: crate, spicebloom TerrainSpeeds: Sand: 100 Rock: 100 @@ -99,7 +99,7 @@ ^Tank: Inherits: ^Vehicle Mobile: - Crushes: crate, infantry + Crushes: crate, infantry, spicebloom ^Husk: Inherits@1: ^SpriteActor @@ -165,7 +165,7 @@ RevealsShroud: Range: 6c0 Mobile: - Crushes: crate + Crushes: crate, spicebloom SharesCell: true TerrainSpeeds: Sand: 100 diff --git a/mods/d2k/rules/vehicles.yaml b/mods/d2k/rules/vehicles.yaml index f6dffa3d99..d36e7bcd54 100644 --- a/mods/d2k/rules/vehicles.yaml +++ b/mods/d2k/rules/vehicles.yaml @@ -20,7 +20,7 @@ mcv: Type: light Mobile: Speed: 31 - Crushes: crate, infantry + Crushes: crate, infantry, spicebloom RevealsShroud: Range: 8c0 MustBeDestroyed: @@ -73,7 +73,7 @@ harvester: Type: harvester Mobile: Speed: 43 - Crushes: crate, infantry + Crushes: crate, infantry, spicebloom RevealsShroud: Range: 4c0 Explodes: @@ -184,7 +184,6 @@ siege_tank: Mobile: Speed: 43 ROT: 3 - Crushes: crate, infantry RevealsShroud: Range: 8c0 Turreted: @@ -304,7 +303,6 @@ devastator: Mobile: ROT: 3 Speed: 31 - Crushes: crate, infantry RevealsShroud: Range: 7c0 Armament: @@ -440,7 +438,6 @@ deviator: Mobile: Speed: 75 ROT: 5 - Crushes: crate, infantry RevealsShroud: Range: 8c0 Turreted: @@ -499,7 +496,6 @@ combat_tank_o: Mobile: Speed: 85 ROT: 5 - Crushes: crate, infantry Health: HP: 1800 SpawnActorOnDeath: diff --git a/mods/d2k/sequences/misc.yaml b/mods/d2k/sequences/misc.yaml index 1b3c5ec0b0..756bf5dba3 100644 --- a/mods/d2k/sequences/misc.yaml +++ b/mods/d2k/sequences/misc.yaml @@ -327,19 +327,20 @@ crate: ZOffset: -511 Offset: -16,-16 -# TODO: keep the redundant spicebloom.shp for now for the awful WinForms maps editor spicebloom: - make: DATA.R8 + grow1: DATA.R8 Start: 107 - Length: 3 + Length: 1 ZOffset: -1023 Offset: -16,-16 - active: DATA.R8 - Start: 109 + grow2: DATA.R8 + Start: 108 + Length: 1 ZOffset: -1023 Offset: -16,-16 - idle: DATA.R8 + grow3: DATA.R8 Start: 109 + Length: 1 ZOffset: -1023 Offset: -16,-16 diff --git a/mods/d2k/weapons.yaml b/mods/d2k/weapons.yaml index 85e50dd447..9ec67da457 100644 --- a/mods/d2k/weapons.yaml +++ b/mods/d2k/weapons.yaml @@ -829,6 +829,13 @@ SardDeath: ImpactSound: EXPLSML2.WAV SpiceExplosion: + Report: EXPLMD1.WAV + Projectile: Bullet + Speed: 50, 75 + High: true + Angle: 91, 264 + Trail: large_trail + Image: null Warhead@1Dam: SpreadDamage Spread: 480 Falloff: 100, 100, 100, 95, 60, 25, 0