@@ -70,7 +70,10 @@ protected override void Created(Actor self)
7070
7171 void INotifyBurstComplete . FiredBurst ( Actor self , in Target target , Armament a )
7272 {
73- self . World . IssueOrder ( new Order ( "Stop" , self , false ) ) ;
73+ if ( attack != null )
74+ attack . OnStopOrder ( self ) ;
75+ else
76+ self . CancelActivity ( ) ;
7477 }
7578 }
7679
@@ -99,12 +102,116 @@ public SelectAttackPowerTarget(Actor self, string order, SupportPowerManager man
99102 cursorBlocked = cursor + "-blocked" ;
100103 }
101104
105+ bool TryGetRanges ( World world , AttackBase attackTrait , out WDist minRange , out WDist maxRange )
106+ {
107+ minRange = WDist . Zero ;
108+ maxRange = WDist . Zero ;
109+
110+ if ( attackTrait == null )
111+ return false ;
112+
113+ try
114+ {
115+ minRange = attackTrait . GetMinimumRange ( ) ;
116+ maxRange = attackTrait . GetMaximumRange ( ) ;
117+ return true ;
118+ }
119+ catch
120+ {
121+ world . CancelInputMode ( ) ;
122+ return false ;
123+ }
124+ }
125+
126+ AttackBase ResolveAttack ( World world )
127+ {
128+ if ( attack != null && ! attack . IsTraitDisabled )
129+ return attack ;
130+
131+ if ( instance == null )
132+ {
133+ world . CancelInputMode ( ) ;
134+ return null ;
135+ }
136+
137+ foreach ( var power in instance . Instances )
138+ {
139+ var actor = power ? . Self ;
140+ if ( actor == null || ! actor . IsInWorld )
141+ continue ;
142+
143+ var attackTrait = actor . TraitsImplementing < AttackBase > ( )
144+ . FirstOrDefault ( a => a != null && ! a . IsTraitDisabled ) ;
145+
146+ if ( attackTrait != null )
147+ return attackTrait ;
148+ }
149+
150+ world . CancelInputMode ( ) ;
151+ return null ;
152+ }
153+
154+ bool TryGetActiveInstances ( World world ,
155+ out SupportPowerInstance powerInstance ,
156+ out IReadOnlyCollection < Actor > activeActors )
157+ {
158+ powerInstance = instance ;
159+ activeActors = null ;
160+ if ( powerInstance == null )
161+ {
162+ world . CancelInputMode ( ) ;
163+ return false ;
164+ }
165+
166+ var active = powerInstance . Instances ?
167+ . Where ( i => i != null
168+ && ! i . IsTraitPaused
169+ && i . Self != null
170+ && ! i . Self . IsDead
171+ && i . Self . IsInWorld
172+ && i . Self . OccupiesSpace != null )
173+ . Select ( i => i . Self )
174+ . ToList ( ) ;
175+ if ( active == null || active . Count == 0 )
176+ return false ;
177+
178+ activeActors = active ;
179+ return true ;
180+ }
181+
102182 bool IsValidTarget ( World world , CPos cell )
103183 {
184+ var currentAttack = ResolveAttack ( world ) ;
185+ if ( currentAttack == null )
186+ return false ;
187+
188+ if ( ! TryGetRanges ( world , currentAttack , out _ , out var maxRange ) )
189+ return false ;
190+
191+ if ( ! TryGetActiveInstances ( world , out _ , out var activeActors ) )
192+ return false ;
193+
104194 var pos = world . Map . CenterOfCell ( cell ) ;
105- var range = attack . GetMaximumRange ( ) . LengthSquared ;
195+ var range = maxRange . LengthSquared ;
196+
197+ if ( ! world . Map . Contains ( cell ) )
198+ return false ;
106199
107- return world . Map . Contains ( cell ) && instance . Instances . Any ( a => ! a . IsTraitPaused && ( a . Self . CenterPosition - pos ) . HorizontalLengthSquared < range ) ;
200+ foreach ( var a in activeActors )
201+ {
202+ if ( a == null || a . World == null || ! a . IsInWorld )
203+ continue ;
204+
205+ var occupies = a . OccupiesSpace ;
206+ if ( occupies == null )
207+ continue ;
208+
209+ var center = occupies . CenterPosition ;
210+ if ( ( center - pos ) . HorizontalLengthSquared < range )
211+ return true ;
212+ }
213+
214+ return false ;
108215 }
109216
110217 protected override IEnumerable < Order > OrderInner ( World world , CPos cell , int2 worldPixel , MouseInput mi )
@@ -120,7 +227,7 @@ protected override IEnumerable<Order> OrderInner(World world, CPos cell, int2 wo
120227 protected override void Tick ( World world )
121228 {
122229 // Cancel the OG if we can't use the power
123- if ( ! manager . Powers . TryGetValue ( order , out var p ) || ! p . Active || ! p . Ready )
230+ if ( ! manager . Powers . TryGetValue ( order , out var p ) || ! p . Active || ! p . Ready || instance == null )
124231 world . CancelInputMode ( ) ;
125232 }
126233
@@ -129,21 +236,43 @@ protected override void Tick(World world)
129236
130237 protected override IEnumerable < IRenderable > RenderAnnotations ( WorldRenderer wr , World world )
131238 {
132- var info = instance . Info as AttackOrderPowerInfo ;
133- foreach ( var a in instance . Instances . Where ( i => ! i . IsTraitPaused ) )
239+ var currentAttack = ResolveAttack ( world ) ;
240+ if ( currentAttack == null )
241+ yield break ;
242+
243+ if ( ! TryGetRanges ( world , currentAttack , out var minRange , out var maxRange ) )
244+ yield break ;
245+
246+ if ( ! TryGetActiveInstances ( world , out var currentInstance , out var activeActors ) )
247+ yield break ;
248+
249+ var info = currentInstance . Info as AttackOrderPowerInfo ;
250+ if ( info == null )
251+ yield break ;
252+
253+ foreach ( var actor in activeActors )
134254 {
255+ if ( actor == null || ! actor . IsInWorld || actor . World == null )
256+ continue ;
257+
258+ var occupies = actor . OccupiesSpace ;
259+ if ( occupies == null )
260+ continue ;
261+
262+ var center = occupies . CenterPosition ;
263+
135264 yield return new RangeCircleAnnotationRenderable (
136- a . Self . CenterPosition ,
137- attack . GetMinimumRange ( ) ,
265+ center ,
266+ minRange ,
138267 0 ,
139268 info . CircleColor ,
140269 info . CircleWidth ,
141270 info . CircleBorderColor ,
142271 info . CircleBorderWidth ) ;
143272
144273 yield return new RangeCircleAnnotationRenderable (
145- a . Self . CenterPosition ,
146- attack . GetMaximumRange ( ) ,
274+ center ,
275+ maxRange ,
147276 0 ,
148277 info . CircleColor ,
149278 info . CircleWidth ,
0 commit comments