diff --git a/OpenRA.Mods.RA/CrateDrop.cs b/OpenRA.Mods.RA/CrateDrop.cs deleted file mode 100644 index 8540d1b887..0000000000 --- a/OpenRA.Mods.RA/CrateDrop.cs +++ /dev/null @@ -1,117 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 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.FileFormats; -using OpenRA.Mods.RA.Air; -using OpenRA.Mods.RA.Buildings; -using OpenRA.Traits; - -namespace OpenRA.Mods.RA -{ - public class CrateDropInfo : ITraitInfo - { - [Desc("Minimum number of crates")] - public readonly int Minimum = 1; - [Desc("Maximum number of crates")] - public readonly int Maximum = 255; - [Desc("Which terrain types can we drop on?")] - public readonly string[] ValidGround = {"Clear", "Rough", "Road", "Ore", "Beach"}; - [Desc("Which terrain types count as water?")] - public readonly string[] ValidWater = {"Water"}; - [Desc("Average time (seconds) between crate spawn")] - public readonly int SpawnInterval = 180; - [Desc("Chance of generating a water crate instead of a land crate")] - public readonly float WaterChance = .2f; - [ActorReference] - public readonly string CrateActor = "crate"; - [ActorReference] - public readonly string DeliveryAircraft = "badr"; - - public object Create (ActorInitializer init) { return new CrateDrop(this); } - } - - public class CrateDrop : ITick - { - List crates = new List(); - int ticks = 0; - CrateDropInfo Info; - - public CrateDrop(CrateDropInfo info) { Info = info; } - - public void Tick(Actor self) - { - if (!self.World.LobbyInfo.GlobalSettings.Crates) return; - - if (--ticks <= 0) - { - ticks = Info.SpawnInterval * 25; // TODO: randomize - - crates.RemoveAll(x => !x.IsInWorld); // BUG: this removes crates that are cargo of a BADR! - - var toSpawn = Math.Max(0, Info.Minimum - crates.Count) - + (crates.Count < Info.Maximum ? 1 : 0); - - for (var n = 0; n < toSpawn; n++) - SpawnCrate(self); - } - } - - CPos? ChooseDropCell(Actor self, bool inWater, int maxTries) - { - for( var n = 0; n < maxTries; n++ ) - { - var p = self.World.ChooseRandomCell(self.World.SharedRandom); - - // Is this valid terrain? - var terrainType = self.World.GetTerrainType(p); - if (!(inWater ? Info.ValidWater : Info.ValidGround).Contains(terrainType)) continue; - - // Don't drop on any actors - if (self.World.WorldActor.Trait().GetBuildingAt(p) != null) continue; - if (self.World.ActorMap.GetUnitsAt(p).Any()) continue; - - return p; - } - - return null; - } - - void SpawnCrate(Actor self) - { - var inWater = self.World.SharedRandom.NextFloat() < Info.WaterChance; - var pp = ChooseDropCell(self, inWater, 100); - if (pp == null) return; - - var p = pp.Value; - self.World.AddFrameEndTask(w => - { - var crate = w.CreateActor(false, Info.CrateActor, new TypeDictionary { new OwnerInit(w.WorldActor.Owner) }); - crates.Add(crate); - - var startPos = w.ChooseRandomEdgeCell(); - var altitude = Rules.Info[Info.DeliveryAircraft].Traits.Get().CruiseAltitude; - var plane = w.CreateActor(Info.DeliveryAircraft, new TypeDictionary - { - new CenterPositionInit(startPos.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)), - new OwnerInit(w.WorldActor.Owner), - new FacingInit(Util.GetFacing(p - startPos, 0)) - }); - - plane.CancelActivity(); - plane.QueueActivity(new FlyAttack(Target.FromCell(p))); - plane.Trait().SetLZ(p); - plane.Trait().Load(plane, crate); - }); - } - } -} diff --git a/OpenRA.Mods.RA/CrateSpawner.cs b/OpenRA.Mods.RA/CrateSpawner.cs index 137b84f6b5..2cc7a81df3 100644 --- a/OpenRA.Mods.RA/CrateSpawner.cs +++ b/OpenRA.Mods.RA/CrateSpawner.cs @@ -13,75 +13,121 @@ using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; using OpenRA.Mods.RA.Buildings; +using OpenRA.Mods.RA.Air; using OpenRA.Traits; namespace OpenRA.Mods.RA { - public class CrateSpawnerInfo : TraitInfo + public class CrateSpawnerInfo : ITraitInfo { [Desc("Minimum number of crates")] public readonly int Minimum = 1; [Desc("Maximum number of crates")] public readonly int Maximum = 255; - [Desc("Which terrain types can we drop on?")] - public readonly string[] ValidGround = {"Clear", "Rough", "Road", "Ore", "Beach"}; - [Desc("Which terrain types count as water?")] - public readonly string[] ValidWater = {"Water"}; [Desc("Average time (seconds) between crate spawn")] public readonly int SpawnInterval = 180; + [Desc("Which terrain types can we drop on?")] + public readonly string[] ValidGround = { "Clear", "Rough", "Road", "Ore", "Beach" }; + [Desc("Which terrain types count as water?")] + public readonly string[] ValidWater = { "Water" }; [Desc("Chance of generating a water crate instead of a land crate")] public readonly float WaterChance = .2f; + [Desc("Drop crates via DeliveryAircraft: or instantly spawn them on the ground")] + public readonly bool DeliverByAircraft = false; + [Desc("If DeliverByAircraft: yes, this actor will deliver crates"), ActorReference] + public readonly string DeliveryAircraft = "badr"; + [Desc("Crate actor to drop"), ActorReference] + public readonly string CrateActor = "crate"; + + public object Create(ActorInitializer init) { return new CrateSpawner(this); } } public class CrateSpawner : ITick { List crates = new List(); int ticks = 0; + CrateSpawnerInfo Info; + + public CrateSpawner(CrateSpawnerInfo info) { Info = info; } public void Tick(Actor self) { - if (!self.World.LobbyInfo.GlobalSettings.Crates) return; + if (!self.World.LobbyInfo.GlobalSettings.Crates) + return; if (--ticks <= 0) { - var info = self.Info.Traits.Get(); - ticks = info.SpawnInterval * 25; // TODO: randomize + ticks = Info.SpawnInterval * 25; - crates.RemoveAll(x => !x.IsInWorld); + crates.RemoveAll(x => !x.IsInWorld); // BUG: this removes crates that are cargo of a BADR! - var toSpawn = Math.Max(0, info.Minimum - crates.Count) - + (crates.Count < info.Maximum ? 1 : 0); + var toSpawn = Math.Max(0, Info.Minimum - crates.Count) + + (crates.Count < Info.Maximum ? 1 : 0); for (var n = 0; n < toSpawn; n++) - SpawnCrate(self, info); + SpawnCrate(self); } } - void SpawnCrate(Actor self, CrateSpawnerInfo info) + void SpawnCrate(Actor self) { var threshold = 100; - var inWater = self.World.SharedRandom.NextFloat() < info.WaterChance; + var inWater = self.World.SharedRandom.NextFloat() < Info.WaterChance; + var pp = ChooseDropCell(self, inWater, threshold); - for (var n = 0; n < threshold; n++ ) + if (pp == null) + return; + + var p = pp.Value; + + self.World.AddFrameEndTask(w => + { + if (Info.DeliverByAircraft) + { + var crate = w.CreateActor(false, Info.CrateActor, new TypeDictionary { new OwnerInit(w.WorldActor.Owner) }); + crates.Add(crate); + + var startPos = w.ChooseRandomEdgeCell(); + var plane = w.CreateActor(Info.DeliveryAircraft, new TypeDictionary + { + new LocationInit(startPos), + new OwnerInit(w.WorldActor.Owner), + new FacingInit(Util.GetFacing(p - startPos, 0)), + new AltitudeInit(Rules.Info[Info.DeliveryAircraft].Traits.Get().CruiseAltitude), + }); + + plane.CancelActivity(); + plane.QueueActivity(new FlyAttack(Target.FromCell(p))); + plane.Trait().SetLZ(p); + plane.Trait().Load(plane, crate); + } + else + { + crates.Add(w.CreateActor(Info.CrateActor, new TypeDictionary { new OwnerInit(w.WorldActor.Owner), new LocationInit(p) })); + } + }); + } + + CPos? ChooseDropCell(Actor self, bool inWater, int maxTries) + { + for (var n = 0; n < maxTries; n++) { var p = self.World.ChooseRandomCell(self.World.SharedRandom); // Is this valid terrain? var terrainType = self.World.GetTerrainType(p); - if (!(inWater ? info.ValidWater : info.ValidGround).Contains(terrainType)) continue; + if (!(inWater ? Info.ValidWater : Info.ValidGround).Contains(terrainType)) + continue; - // Don't spawn on any actors - if (self.World.WorldActor.Trait().GetBuildingAt(p) != null) continue; - if (self.World.ActorMap.GetUnitsAt(p).Any()) continue; + // Don't drop on any actors + if (self.World.WorldActor.Trait().GetBuildingAt(p) != null + || self.World.ActorMap.GetUnitsAt(p).Any()) + continue; - self.World.AddFrameEndTask( - w => crates.Add(w.CreateActor("crate", new TypeDictionary - { - new LocationInit( p ), - new OwnerInit( self.World.WorldActor.Owner ), - }))); - return; + return p; } + + return null; } } } diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 0e28d6d8a2..cf540afdbb 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -195,7 +195,6 @@ - @@ -538,4 +537,4 @@ copy "FuzzyLogicLibrary.dll" "$(SolutionDir)" cd "$(SolutionDir)" - + \ No newline at end of file diff --git a/mods/ra/rules/system.yaml b/mods/ra/rules/system.yaml index eb320b7e7e..8b479e8c0c 100644 --- a/mods/ra/rules/system.yaml +++ b/mods/ra/rules/system.yaml @@ -551,7 +551,8 @@ World: ChooseBuildTabOnSelect: BridgeLayer: Bridges: bridge1, bridge2, br1, br2, br3, sbridge1, sbridge2, sbridge3, sbridge4 - CrateDrop: + CrateSpawner: + DeliverByAircraft: yes Minimum: 1 Maximum: 3 SpawnInterval: 120