@@ -21,10 +21,10 @@ namespace OpenRA.Mods.CA.Activities
2121{
2222 public class SpawnActor : Activity
2323 {
24- readonly WPos targetPos ;
2524 readonly CPos targetCell ;
25+ readonly WAngle ? initFacing ;
2626 readonly bool skipMakeAnims ;
27- readonly string type ;
27+ readonly string [ ] types ;
2828 readonly string [ ] spawnSounds ;
2929 readonly AmmoPool ammoPool ;
3030 readonly int range ;
@@ -34,14 +34,14 @@ public class SpawnActor : Activity
3434 readonly HashSet < string > allowedTerrainTypes ;
3535 readonly Action < Actor , Actor > onActorSpawned ;
3636
37- public SpawnActor ( Actor self , CPos targetCell , WPos targetPos , string type , bool skipMakeAnims , string [ ] spawnSounds ,
37+ public SpawnActor ( string [ ] types , CPos targetCell , WAngle ? initFacing , bool skipMakeAnims , string [ ] spawnSounds ,
3838 AmmoPool ammoPool , int range , bool avoidActors , WDist maxRange , bool spawnInShroud , HashSet < string > allowedTerrainTypes ,
3939 Action < Actor , Actor > onActorSpawned = null )
4040 {
41- this . targetPos = targetPos ;
4241 this . targetCell = targetCell ;
42+ this . initFacing = initFacing ;
4343 this . skipMakeAnims = skipMakeAnims ;
44- this . type = type ;
44+ this . types = types ;
4545 this . spawnSounds = spawnSounds ;
4646 this . ammoPool = ammoPool ;
4747 this . range = range ;
@@ -50,6 +50,8 @@ public SpawnActor(Actor self, CPos targetCell, WPos targetPos, string type, bool
5050 this . spawnInShroud = spawnInShroud ;
5151 this . allowedTerrainTypes = allowedTerrainTypes ;
5252 this . onActorSpawned = onActorSpawned ;
53+
54+ IsInterruptible = false ;
5355 }
5456
5557 public override bool Tick ( Actor self )
@@ -66,94 +68,102 @@ void Spawn(Actor self)
6668 var map = self . World . Map ;
6769 var targetCells = map . FindTilesInCircle ( targetCell , range ) ;
6870 var cell = targetCells . GetEnumerator ( ) ;
69- var ai = map . Rules . Actors [ type . ToLowerInvariant ( ) ] ;
70- var td = CreateTypeDictionary ( self , targetCell ) ;
71- var placed = false ;
71+ var soundPlayed = false ;
7272
73- self . World . AddFrameEndTask ( w =>
73+ foreach ( var type in types )
7474 {
75- var unit = self . World . CreateActor ( false , type , td ) ;
76- var positionable = unit . TraitOrDefault < IPositionable > ( ) ;
77-
78- cell = targetCells . GetEnumerator ( ) ;
75+ var actorType = type . ToLowerInvariant ( ) ;
76+ var ai = map . Rules . Actors [ actorType ] ;
77+ var td = CreateTypeDictionary ( self , targetCell ) ;
78+ var placed = false ;
7979
80- if ( positionable == null )
80+ self . World . AddFrameEndTask ( w =>
8181 {
82- unit . Dispose ( ) ;
82+ Actor unit = null ;
83+ cell = targetCells . GetEnumerator ( ) ;
8384
84- if ( avoidActors )
85+ if ( ! ai . HasTraitInfo < IPositionableInfo > ( ) )
8586 {
86- while ( cell . MoveNext ( ) && ! placed )
87+ if ( avoidActors )
8788 {
88- if ( ! IsValidTargetCell ( cell . Current , self ) )
89- continue ;
89+ while ( cell . MoveNext ( ) && ! placed )
90+ {
91+ if ( ! IsValidTargetCell ( cell . Current , self ) )
92+ continue ;
9093
91- var actorsInCell = self . World . ActorMap . GetActorsAt ( cell . Current ) ;
94+ var actorsInCell = self . World . ActorMap . GetActorsAt ( cell . Current ) ;
9295
93- if ( actorsInCell . Any ( ) )
94- continue ;
96+ if ( actorsInCell . Any ( ) )
97+ continue ;
9598
96- placed = true ;
97- td = CreateTypeDictionary ( self , cell . Current ) ;
99+ placed = true ;
100+ td = CreateTypeDictionary ( self , cell . Current ) ;
101+ }
98102 }
103+ else
104+ placed = true ;
105+
106+ if ( placed )
107+ unit = self . World . CreateActor ( type , td ) ;
99108 }
100109 else
101- placed = true ;
102-
103- if ( placed )
104- unit = self . World . CreateActor ( type , td ) ;
105- }
106- else
107- {
108- while ( cell . MoveNext ( ) && ! placed )
109110 {
110- var subCell = positionable . GetAvailableSubCell ( cell . Current ) ;
111+ unit = self . World . CreateActor ( false , actorType , td ) ;
112+ var positionable = unit . TraitOrDefault < IPositionable > ( ) ;
113+
114+ while ( cell . MoveNext ( ) && ! placed )
115+ {
116+ var subCell = positionable . GetAvailableSubCell ( cell . Current ) ;
111117
112- if ( ai . HasTraitInfo < AircraftInfo > ( )
113- && ai . TraitInfo < AircraftInfo > ( ) . CanEnterCell ( self . World , unit , cell . Current , SubCell . FullCell , null , BlockedByActor . None ) )
114- subCell = SubCell . FullCell ;
118+ if ( ai . HasTraitInfo < AircraftInfo > ( )
119+ && ai . TraitInfo < AircraftInfo > ( ) . CanEnterCell ( self . World , unit , cell . Current , SubCell . FullCell , null , BlockedByActor . None ) )
120+ subCell = SubCell . FullCell ;
115121
116- if ( ! IsValidTargetCell ( cell . Current , self ) )
117- continue ;
122+ if ( ! IsValidTargetCell ( cell . Current , self ) )
123+ continue ;
118124
119- if ( subCell != SubCell . Invalid )
120- {
121- positionable . SetPosition ( unit , cell . Current , subCell ) ;
125+ if ( subCell != SubCell . Invalid )
126+ {
127+ positionable . SetPosition ( unit , cell . Current , subCell ) ;
122128
123- var pos = unit . CenterPosition ;
129+ var pos = unit . CenterPosition ;
124130
125- positionable . SetCenterPosition ( unit , pos ) ;
126- w . Add ( unit ) ;
131+ positionable . SetCenterPosition ( unit , pos ) ;
132+ w . Add ( unit ) ;
127133
128- unit . QueueActivity ( new FallDown ( unit , pos , 130 ) ) ;
134+ unit . QueueActivity ( new FallDown ( unit , pos , 130 ) ) ;
129135
130- placed = true ;
136+ placed = true ;
137+ }
131138 }
132- }
133139
134- if ( ! placed )
135- unit . Dispose ( ) ;
136- }
140+ if ( ! placed )
141+ unit . Dispose ( ) ;
142+ }
137143
138- if ( placed )
139- {
140- if ( ammoPool != null )
141- ammoPool . TakeAmmo ( self , 1 ) ;
144+ if ( placed && unit != null )
145+ {
146+ if ( ammoPool != null )
147+ ammoPool . TakeAmmo ( self , 1 ) ;
142148
143- if ( spawnSounds . Length > 0 )
144- Game . Sound . Play ( SoundType . World , spawnSounds , self . World , unit . CenterPosition ) ;
149+ if ( ! soundPlayed && spawnSounds . Length > 0 )
150+ {
151+ Game . Sound . Play ( SoundType . World , spawnSounds , self . World , unit . CenterPosition ) ;
152+ soundPlayed = true ;
153+ }
145154
146- onActorSpawned ? . Invoke ( self , unit ) ;
147- }
148- } ) ;
155+ onActorSpawned ? . Invoke ( self , unit ) ;
156+ }
157+ } ) ;
158+ }
149159 }
150160
151161 bool IsValidTargetCell ( CPos cell , Actor self )
152162 {
153163 var targetPos = self . World . Map . CenterOfCell ( cell ) ;
154164 var sourcePos = self . CenterPosition ;
155165
156- return ( ( targetPos - sourcePos ) . Length <= maxRange . Length
166+ return ( ( maxRange == WDist . Zero || ( targetPos - sourcePos ) . Length <= maxRange . Length )
157167 && ( spawnInShroud || self . Owner . Shroud . IsExplored ( cell ) )
158168 && ( allowedTerrainTypes . Count == 0 || allowedTerrainTypes . Contains ( self . World . Map . GetTerrainInfo ( cell ) . Type ) ) ) ;
159169 }
@@ -167,6 +177,9 @@ TypeDictionary CreateTypeDictionary(Actor self, CPos targetCell)
167177 new LocationInit ( targetCell )
168178 } ;
169179
180+ if ( initFacing . HasValue )
181+ td . Add ( new FacingInit ( initFacing . Value ) ) ;
182+
170183 if ( skipMakeAnims )
171184 td . Add ( new SkipMakeAnimsInit ( ) ) ;
172185
0 commit comments