diff --git a/OpenRA.Mods.RA2/Traits/SpawnNeighboringActors.cs b/OpenRA.Mods.RA2/Traits/SpawnNeighboringActors.cs new file mode 100644 index 000000000..f567671ce --- /dev/null +++ b/OpenRA.Mods.RA2/Traits/SpawnNeighboringActors.cs @@ -0,0 +1,99 @@ +#region Copyright & License Information +/* + * Copyright 2007-2020 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, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System.Collections.Generic; +using OpenRA.Mods.Common.Traits; +using OpenRA.Primitives; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA2.Traits +{ + [Desc("This actor places other actors around itself, which keep connected as in they get removed when the parent is sold or destroyed.")] + public class SpawnNeighboringActorsInfo : ITraitInfo + { + [FieldLoader.Require] + [ActorReference] + [Desc("Types of actors to place. If multiple are defined, a random one will be selected for each actor spawned.")] + public readonly HashSet ActorTypes = new HashSet(); + + [FieldLoader.Require] + [Desc("Locations to spawn the actors relative to the origin (top-left for buildings) of this actor.")] + public readonly CVec[] Locations = { }; + + public object Create(ActorInitializer init) { return new SpawnNeighboringActors(this, init.Self); } + } + + public class SpawnNeighboringActors : INotifyKilled, INotifyOwnerChanged, INotifyActorDisposing, INotifyAddedToWorld, INotifySold + { + readonly SpawnNeighboringActorsInfo info; + readonly List actors = new List(); + + public SpawnNeighboringActors(SpawnNeighboringActorsInfo info, Actor self) + { + this.info = info; + } + + void INotifyAddedToWorld.AddedToWorld(Actor self) + { + SpawnActors(self); + } + + public void SpawnActors(Actor self) + { + foreach (var offset in info.Locations) + { + self.World.AddFrameEndTask(w => + { + var actorType = info.ActorTypes.Random(self.World.SharedRandom).ToLowerInvariant(); + var cell = self.Location + offset; + + var actor = w.CreateActor(true, actorType, new TypeDictionary + { + new OwnerInit(self.Owner), + new LocationInit(cell) + }); + + actors.Add(actor); + }); + } + } + + public void RemoveActors() + { + foreach (var actor in actors) + actor.Dispose(); + + actors.Clear(); + } + + void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) + { + foreach (var actor in actors) + actor.ChangeOwnerSync(newOwner); + } + + void INotifyKilled.Killed(Actor self, AttackInfo e) + { + RemoveActors(); + } + + void INotifyActorDisposing.Disposing(Actor self) + { + RemoveActors(); + } + + void INotifySold.Selling(Actor self) { } + void INotifySold.Sold(Actor self) + { + RemoveActors(); + } + } +} diff --git a/mods/ra2/rules/aircraft.yaml b/mods/ra2/rules/aircraft.yaml index 429132ab3..1baf84602 100644 --- a/mods/ra2/rules/aircraft.yaml +++ b/mods/ra2/rules/aircraft.yaml @@ -194,7 +194,7 @@ orca: Actor: orcahusk HitShape: Rearmable: - RearmActors: gaairc, amradr + RearmActors: gaairc, amradr, gapad orcahusk: Inherits: ^PlaneHusk diff --git a/mods/ra2/rules/allied-structures.yaml b/mods/ra2/rules/allied-structures.yaml index 4ec984541..53e268a82 100644 --- a/mods/ra2/rules/allied-structures.yaml +++ b/mods/ra2/rules/allied-structures.yaml @@ -283,7 +283,7 @@ gaairc: Factions: korea ProvidesPrerequisite@default: Building: - Footprint: xxx xxx + Footprint: x=x x== Dimensions: 3,2 Selectable: Bounds: 142, 150, -3, -42 @@ -320,17 +320,17 @@ gaairc: Amount: -50 Reservable: Exit@1: - SpawnOffset: -370,370,0 Facing: 224 + SpawnOffset: 1024,512,0 Exit@2: - SpawnOffset: 370,-370,0 Facing: 224 + SpawnOffset: 512,1024,0 Exit@3: - SpawnOffset: 1000,370,0 Facing: 224 + SpawnOffset: -512,512,0 Exit@4: - SpawnOffset: 350,1000,0 Facing: 224 + SpawnOffset: 512,-512,0 Production: Produces: Aircraft ProductionBar: @@ -349,6 +349,20 @@ gaairc: SpawnSurvivors: DeathTypes: ExplosionDeath, BulletDeath Actors: e1, e1 + SpawnNeighboringActors: + ActorTypes: gapad + Locations: 1,0, 1,1, 2,1 + +gapad: + Interactable: + AlwaysVisible: + Reservable: + Building: + Footprint: x + Dimensions: 1,1 + AllowInvalidPlacement: true + Production: + Produces: Aircraft amradr: Inherits: gaairc diff --git a/mods/ra2/rules/defaults.yaml b/mods/ra2/rules/defaults.yaml index 917ec0105..1b2841da6 100644 --- a/mods/ra2/rules/defaults.yaml +++ b/mods/ra2/rules/defaults.yaml @@ -976,6 +976,7 @@ AltitudeVelocity: 120 TakeOffOnCreation: false IdleBehavior: ReturnToBase + InitialFacing: 224 Hovers@CRUISING: RequiresCondition: cruising WithVoxelBody: