Page MenuHomeWildfire Games

Set isGarrisoned when unit is autogarrisoned, remove autogarrison state
ClosedPublic

Authored by temple on Mar 19 2018, 6:11 AM.

Details

Summary

There's two bugs with unresponsive units on walls. In both situations the units aren't recognized as turrets so instead act like out of world garrisoned units, i.e. they ignore everything around them (until they're attacked).

Units are considered IsTurret in UnitAI if they're garrisoned and have a parent turret.
The first situation is with promoted units, which are garrisoned but don't have a parent turret (yet; it's done on rename).
The second situation is with units placed by trigger scripts (e.g. on Jebel Barkal), which have a parent turret but aren't garrisoned.

We fix the first by cheering before SetGarrisoned (because otherwise the cheer order is ignored, and that gives time for the turret to be set), and fix the second by setting isGarrisoned with Autogarrisoned (and remove the autogarrison state).

Test Plan

See that both bugs are fixed.
Check that units on Sicily Nomad and trigger maps (like Jebel Barkal) are properly garrisoned, as well as autogarrisoned units in production buildings.

Diff Detail

Repository
rP 0 A.D. Public Repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

temple created this revision.Mar 19 2018, 6:11 AM
Vulcan added a subscriber: Vulcan.Mar 19 2018, 6:15 AM

Successful build - Chance fights ever on the side of the prudent.

Linter detected issues:
Executing section Default...
Executing section Source...
Executing section JS...

binaries/data/mods/public/simulation/components/Promotion.js
| 153| »   »   while·(true)
|    | [NORMAL] ESLintBear (no-constant-condition):
|    | Unexpected constant condition.

Link to build: https://jenkins.wildfiregames.com/job/differential/276/display/redirect

Looks like a couple lines can be removed from UnitAI. Maybe Eject should unset it. Etc.

Stan added a subscriber: Stan.Mar 19 2018, 8:20 AM

Dunno if related but in terra_magna since the gate is visiblt garrisonable something is not set breaking the animation. The gate will not open nor close anymore.

elexis added a subscriber: elexis.Mar 19 2018, 5:15 PM

history

refs rP21564 and the one mentioned over there

mimo added a subscriber: mimo.Mar 19 2018, 7:09 PM

isGarrisoned is a UnitAI internal flag, set when entering in the INDIVIDUAL.GARRISON or INDIVIDUAL.AUTOGARRISON state. Thus that would look strange to me to have it set from inside GarrisonHolder. In the cases reported, i suspect that the units were not set in the proper UnitAI state: they should have undergone either a Garrison or an AutoGarrison order and not rely on GarrisonHolder to define their state.

In D1403#57525, @mimo wrote:

isGarrisoned is a UnitAI internal flag, set when entering in the INDIVIDUAL.GARRISON or INDIVIDUAL.AUTOGARRISON state. Thus that would look strange to me to have it set from inside GarrisonHolder. In the cases reported, i suspect that the units were not set in the proper UnitAI state: they should have undergone either a Garrison or an AutoGarrison order and not rely on GarrisonHolder to define their state.

I don't really understand the objection. (There was rP18832 and rP17113/rP17111 which did SetGarrisoned in other places.) Units should be isGarrisoned exactly when they have garrisoned, so that seems the perfect place for it (and then remove it everywhere else).

Alternative solution is for trigger scripts to do SetGarrisoned before AutoGarrison, and for promotion to post the entity renamed message before doing UnitAI stuff.

mimo added a comment.Mar 21 2018, 12:09 AM

What bothers me is that isGarrisoned is a UnitAI flag, which says that the unit is either in a GARRISON or AUTOGARRISON FSM state, which implies two things: the current order is Garrison or AutoGarrison and the holder is the target of that order. Setting it elsewhere without giving also the Garrison or the Autogarrison order may (and certainly will) result in a weird state. And if we need this (Auto)Garrison order, why not set the flag when entering this order as is done currently.

If triggerscripts set correctly the order using cmpUnitAi.(Auto)Garrison, they don't need to SetGarrisoned, see for example maps/scripts/TriggerHelper/SpawnGarrisonedUnits. The only case where it is needed is for Promotion (we do not set the UnitAI order, but only copy the orderQueue) and for initial map garrisoning (in GarrisonHolder/OnGlobalInitGame).

In D1403#57747, @mimo wrote:

If triggerscripts set correctly the order using cmpUnitAi.(Auto)Garrison, they don't need to SetGarrisoned, see for example maps/scripts/TriggerHelper/SpawnGarrisonedUnits.

That's where the problem is! That's the "second situation" of the summary. It needs a SetGarrisoned as I said in the last message. Guess I wasn't explicit enough?
Start a game on Jebel Barkal and notice the units on the walls aren't responsive. They're in the autogarrisoned state but should be in the idle state. Etc., I'm just repeating myself.

What bothers me is that isGarrisoned is a UnitAI flag, which says that the unit is either in a GARRISON or AUTOGARRISON FSM state, which implies two things: the current order is Garrison or AutoGarrison and the holder is the target of that order.

Turrets are garrisoned too.

mimo added a comment.Mar 21 2018, 6:33 PM

And i also repeat myself :) isGarrisoned in an internal UnitAI flag, it does not say that the entity is garrisoned, but that it is in the GARRISON unitAI state, and why would GarrisonHolder have anything to say about the internal guts of UnitAI.
For your specific case, i think it is enough to move the line 3012 of UnitAI (this.isGarrisoned = true) to just after line 747.

In D1403#57747, @mimo wrote:

If triggerscripts set correctly the order using cmpUnitAi.(Auto)Garrison, they don't need to SetGarrisoned, see for example maps/scripts/TriggerHelper/SpawnGarrisonedUnits. The only case where it is needed is for Promotion (we do not set the UnitAI order, but only copy the orderQueue) and for initial map garrisoning (in GarrisonHolder/OnGlobalInitGame).

In fact, thinking again about it, using SetGarrisoned in Promotion was fine, but it was wrong to use it in GarrisonHolder/OnGlobalInitGame. This can be tested by adding an initial hero in sicilia_nomad as clicking on the hero button will then be broken: line 678 of garrisonHolder "cmpUnitAI.SetGarrisoned()" should be replaced by "cmpUnitAI.Autogarrison(this.entity)"

In D1403#57814, @mimo wrote:

And i also repeat myself :) isGarrisoned in an internal UnitAI flag, it does not say that the entity is garrisoned, but that it is in the GARRISON unitAI state,

That's wrong, turrets have this.isGarrisoned = true and are in the IDLE state (or COMBAT.ATTACKING or whatever else they can do while being a turret).

mimo added a comment.Mar 21 2018, 7:37 PM
In D1403#57815, @temple wrote:
In D1403#57814, @mimo wrote:

And i also repeat myself :) isGarrisoned in an internal UnitAI flag, it does not say that the entity is garrisoned, but that it is in the GARRISON unitAI state,

That's wrong, turrets have this.isGarrisoned = true and are in the IDLE state (or COMBAT.ATTACKING or whatever else they can do while being a turret).

Try to not stick to the first meaning of words and understand at it globally: i should have said they are in order Garrison (which is maybe more exact for turrets), but it does not change the main point which is that we are discussing guts of UnitAI here and this SHOULD NOT be driven by GarrisonHolder.

In D1403#57819, @mimo wrote:

Try to not stick to the first meaning of words and understand at it globally: i should have said they are in order Garrison (which is maybe more exact for turrets),

That's not true either, units have Order.Garrison while they're approaching but are still this.isGarrisoned = false, for example. They only set this.isGarrisoned = true when they actually garrison, L2931.

but it does not change the main point which is that we are discussing guts of UnitAI here and this SHOULD NOT be driven by GarrisonHolder.

As far as I can tell, the point of this.IsGarrisoned is to say whether the unit is currently garrisoned inside some garrison holder. As far as I can tell, the only way for that to happen is for the unit to go through Garrison in GarrisonHolder. If that's the case, then it makes perfect sense to set this.isGarrisoned there and nowhere else.

(Is the Garrisonable component supposed to be for garrisonable units? Maybe could stick this.IsGarrisoned in there (as well as GetGarrisonHolder), so it's separate from UnitAI.)

I guess the idea is to have as few non-private UnitAI functions as possible. If the interface is minimal, then it will be as easy to use UnitAI in other components without having to understand those 6500 loc.

mimo added a comment.Mar 22 2018, 8:32 AM
In D1403#57820, @temple wrote:
In D1403#57819, @mimo wrote:

As far as I can tell, the point of this.IsGarrisoned is to say whether the unit is currently garrisoned inside some garrison holder. As far as I can tell, the only way for that to happen is for the unit to go through Garrison in GarrisonHolder. If that's the case, then it makes perfect sense to set this.isGarrisoned there and nowhere else.

Let's reformulate it: isn't the this.IsGarrisoned a propriety of UnitAI, (nearly) exclusively used inside UnitAI? then it makes perfect sense to set it inside UnitAI and nowhere else.

(Is the Garrisonable component supposed to be for garrisonable units? Maybe could stick this.IsGarrisoned in there (as well as GetGarrisonHolder), so it's separate from UnitAI.)

Adding these in Garrisonable would work. But once again, i think UnitAI should then enquire the value of Garrisonable.isGarrisoned for its own use (so removing the UnitAI.isGarrisoned), and not have Garrisonable modify a UnitAi.isGarrisoned property. But these are post A23 changes. For A23, the two changes i described above (moving one line in UnitAI and fixing the InitGarrison stuff) are all we need.

In D1403#57845, @mimo wrote:

For A23, the two changes i described above (moving one line in UnitAI and fixing the InitGarrison stuff) are all we need.

That doesn't fix the first issue, units promoted on walls.

temple added inline comments.Mar 22 2018, 4:33 PM
binaries/data/mods/public/simulation/components/GarrisonHolder.js
202 ↗(On Diff #6220)

...but setting garrisoned here is not okay, ...

209 ↗(On Diff #6220)

... not to mention all the other times we call unit ai functions in other components.

binaries/data/mods/public/simulation/components/Promotion.js
87 ↗(On Diff #6220)

It's just baffling to me, that setting garrison here is okay, ...

elexis added inline comments.Mar 22 2018, 4:55 PM
binaries/data/mods/public/simulation/components/Promotion.js
87 ↗(On Diff #6220)

At least this function, as well as Transformation.js are considered an ugly hack.
leper had a pastebin where the task of copying over properties from old to new entity is done in the components itself. We should do that sometime.

I personally don't have a preference as long as the bug will be fixed sometime.
mimo you seem to have a preference for some implementation, perhaps it's easier to upload a patch that you prefer and have temple give feedback to that?
We can still flip a coin or ask for a third opinion to decide on a UnitAI surface policy.

mimo added a comment.Mar 22 2018, 7:11 PM
In D1403#57908, @temple wrote:
In D1403#57845, @mimo wrote:

For A23, the two changes i described above (moving one line in UnitAI and fixing the InitGarrison stuff) are all we need.

That doesn't fix the first issue, units promoted on walls.

Can you then describe this first issue? i don't reproduce it with the fix below.

Except for potential remaining problem with such promoted units, my proposed patch is

binaries/data/mods/public/simulation/components/GarrisonHolder.js
202 ↗(On Diff #6220)

the question is "is it an improvment compared to what we have currently"? and i would answer no

209 ↗(On Diff #6220)

i'd rather remove such calls when possible, rather than add more.

binaries/data/mods/public/simulation/components/Promotion.js
87 ↗(On Diff #6220)

It is not per se ok, but it is necessary with the present way we promote. And i don't understand how your fix (removing that line) can work: if a turret is promoted while attacking, it will have the cheer order then attack order and never pass through the garrison order (which is essentially why this line is here).

In D1403#57918, @mimo wrote:
In D1403#57908, @temple wrote:
In D1403#57845, @mimo wrote:

For A23, the two changes i described above (moving one line in UnitAI and fixing the InitGarrison stuff) are all we need.

That doesn't fix the first issue, units promoted on walls.

Can you then describe this first issue? i don't reproduce it with the fix below.

???
Garrison a unit on a wall, notice it's in the IDLE state.
Promote it, notice it's now in AUTOGARRISON state.
Instead it should have been CHEERING and then gone back to IDLE.

mimo added a comment.Mar 22 2018, 10:48 PM

Ok now i see the problem when promoting. The visible garrison is only set when messages are processed (EntityRenamed) and thus UnitAI IsTurret is false when the cheer order is processed, and the order is thus killed by line 4851 of UnitAI.
With your approach, this works as IsGarrisoned is also only set when messages are processed. So let's go for it.

Nonetheless, in ProductionQueue, units directly spawned garrisoned uses PerformGarrison, so the setting of IsGarrisoned should be done there instead of inside Garrison. Another option would be to make ProductionQueue use Garrison. That should work (ref discussion on rP21564).

And while testing, there is nonetheless a problem with promotion (not linked to the patch) which is that promoted units don't face towards the same direction as the initial one (usually the opposite direction, i don't understand why). The following patch would fix it. But it is maybe better to add the angle in CCmpPosition:SetTurrentParent?

temple updated this revision to Diff 6275.Mar 26 2018, 12:28 AM
temple retitled this revision from SetGarrisoned when unit is garrisoned to SetGarrisoned when unit is garrisoned, remove autogarrison state.
temple edited the summary of this revision. (Show Details)
temple edited the test plan for this revision. (Show Details)

Remove the AUTOGARRISON state, since there's not really any difference between that and GARRISON.GARRISONED. When entering we can quit early if we're already garrisoned.
The autogarrison order is used for starting entities in TriggerScript and on the Sicily Nomad skirmish map, as well as entities in ProductionQueue that should be immediately garrisoned. (We use PushOrderFront since AddOrder ignores orders after units are garrisoned.)
(Autogarrison added in rP14144.)

Successful build - Chance fights ever on the side of the prudent.

Linter detected issues:
Executing section Default...
Executing section Source...
Executing section JS...

binaries/data/mods/public/simulation/components/Promotion.js
| 153| »   »   while·(true)
|    | [NORMAL] ESLintBear (no-constant-condition):
|    | Unexpected constant condition.
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 229| 229| 		// Move a tile outside the building
| 230| 230| 		let range = 4;
| 231| 231| 		if (this.MoveToTargetRangeExplicit(msg.data.target, range, range))
| 232|    |-		{
|    | 232|+		
| 233| 233| 			// We've started walking to the given point
| 234| 234| 			this.SetNextState("INDIVIDUAL.WALKING");
| 235|    |-		}
|    | 235|+		
| 236| 236| 		else
| 237| 237| 		{
| 238| 238| 			// We are already at the target, or can't move at all
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 234| 234| 			this.SetNextState("INDIVIDUAL.WALKING");
| 235| 235| 		}
| 236| 236| 		else
| 237|    |-		{
|    | 237|+		
| 238| 238| 			// We are already at the target, or can't move at all
| 239| 239| 			this.FinishOrder();
| 240|    |-		}
|    | 240|+		
| 241| 241| 	},
| 242| 242| 
| 243| 243| 	// Individual orders:
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 339| 339| 
| 340| 340| 		var ok = this.MoveToTarget(this.order.data.target);
| 341| 341| 		if (ok)
| 342|    |-		{
|    | 342|+		
| 343| 343| 			// We've started walking to the given point
| 344| 344| 			if (this.IsAnimal())
| 345| 345| 				this.SetNextState("ANIMAL.WALKING");
| 346| 346| 			else
| 347| 347| 				this.SetNextState("INDIVIDUAL.WALKING");
| 348|    |-		}
|    | 348|+		
| 349| 349| 		else
| 350| 350| 		{
| 351| 351| 			// We are already at the target, or can't move at all
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 367| 367| 		var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
| 368| 368| 		if (this.lastShorelinePosition && cmpPosition && (this.lastShorelinePosition.x == cmpPosition.GetPosition().x)
| 369| 369| 		    && (this.lastShorelinePosition.z == cmpPosition.GetPosition().z))
| 370|    |-		{
|    | 370|+		
| 371| 371| 			// we were already on the shoreline, and have not moved since
| 372| 372| 			if (DistanceBetweenEntities(this.entity, this.order.data.target) < 50)
| 373| 373| 				needToMove = false;
| 374|    |-		}
|    | 374|+		
| 375| 375| 
| 376| 376| 		// TODO: what if the units are on a cliff ? the ship will go below the cliff
| 377| 377| 		// and the units won't be able to garrison. Should go to the nearest (accessible) shore
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 365| 365| 		// Check if we need to move     TODO implement a better way to know if we are on the shoreline
| 366| 366| 		var needToMove = true;
| 367| 367| 		var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
| 368|    |-		if (this.lastShorelinePosition && cmpPosition && (this.lastShorelinePosition.x == cmpPosition.GetPosition().x)
| 369|    |-		    && (this.lastShorelinePosition.z == cmpPosition.GetPosition().z))
|    | 368|+		if (this.lastShorelinePosition && cmpPosition && (this.lastShorelinePosition.x == cmpPosition.GetPosition().x) &&
|    | 369|+		    (this.lastShorelinePosition.z == cmpPosition.GetPosition().z))
| 370| 370| 		{
| 371| 371| 			// we were already on the shoreline, and have not moved since
| 372| 372| 			if (DistanceBetweenEntities(this.entity, this.order.data.target) < 50)
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 376| 376| 		// TODO: what if the units are on a cliff ? the ship will go below the cliff
| 377| 377| 		// and the units won't be able to garrison. Should go to the nearest (accessible) shore
| 378| 378| 		if (needToMove && this.MoveToTarget(this.order.data.target))
| 379|    |-		{
|    | 379|+		
| 380| 380| 			this.SetNextState("INDIVIDUAL.PICKUP.APPROACHING");
| 381|    |-		}
|    | 381|+		
| 382| 382| 		else
| 383| 383| 		{
| 384| 384| 			// We are already at the target, or can't move at all
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 405| 405| 		var distance = DistanceBetweenEntities(this.entity, this.order.data.target) + (+this.template.FleeDistance);
| 406| 406| 		var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion);
| 407| 407| 		if (cmpUnitMotion.MoveToTargetRange(this.order.data.target, distance, -1))
| 408|    |-		{
|    | 408|+		
| 409| 409| 			// We've started fleeing from the given target
| 410| 410| 			if (this.IsAnimal())
| 411| 411| 				this.SetNextState("ANIMAL.FLEEING");
| 412| 412| 			else
| 413| 413| 				this.SetNextState("INDIVIDUAL.FLEEING");
| 414|    |-		}
|    | 414|+		
| 415| 415| 		else
| 416| 416| 		{
| 417| 417| 			// We are already at the target, or can't move at all
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 461| 461| 			}
| 462| 462| 
| 463| 463| 			if (this.order.data.attackType == this.oldAttackType)
| 464|    |-			{
|    | 464|+			
| 465| 465| 				if (this.IsAnimal())
| 466| 466| 					this.SetNextState("ANIMAL.COMBAT.ATTACKING");
| 467| 467| 				else
| 468| 468| 					this.SetNextState("INDIVIDUAL.COMBAT.ATTACKING");
| 469|    |-			}
|    | 469|+			
| 470| 470| 			else
| 471| 471| 			{
| 472| 472| 				if (this.IsAnimal())
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 468| 468| 					this.SetNextState("INDIVIDUAL.COMBAT.ATTACKING");
| 469| 469| 			}
| 470| 470| 			else
| 471|    |-			{
|    | 471|+			
| 472| 472| 				if (this.IsAnimal())
| 473| 473| 					this.SetNextStateAlwaysEntering("ANIMAL.COMBAT.ATTACKING");
| 474| 474| 				else
| 475| 475| 					this.SetNextStateAlwaysEntering("INDIVIDUAL.COMBAT.ATTACKING");
| 476|    |-			}
|    | 476|+			
| 477| 477| 			return;
| 478| 478| 		}
| 479| 479| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 606| 606| 					this.PushOrderFront("Walk", this.order.data.lastPos);
| 607| 607| 				}
| 608| 608| 				else
| 609|    |-				{
|    | 609|+				
| 610| 610| 					// We couldn't move there, or the target moved away
| 611| 611| 					this.FinishOrder();
| 612|    |-				}
|    | 612|+				
| 613| 613| 				return;
| 614| 614| 			}
| 615| 615| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 619| 619| 
| 620| 620| 		// Try to move within range
| 621| 621| 		if (this.MoveToTargetRange(this.order.data.target, IID_ResourceGatherer))
| 622|    |-		{
|    | 622|+		
| 623| 623| 			// We've started walking to the given point
| 624| 624| 			this.SetNextState("INDIVIDUAL.GATHER.APPROACHING");
| 625|    |-		}
|    | 625|+		
| 626| 626| 		else
| 627| 627| 		{
| 628| 628| 			// We are already at the target, or can't move at all,
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 696| 696| 	"Order.Repair": function(msg) {
| 697| 697| 		// Try to move within range
| 698| 698| 		if (this.MoveToTargetRange(this.order.data.target, IID_Builder))
| 699|    |-		{
|    | 699|+		
| 700| 700| 			// We've started walking to the given point
| 701| 701| 			this.SetNextState("INDIVIDUAL.REPAIR.APPROACHING");
| 702|    |-		}
|    | 702|+		
| 703| 703| 		else
| 704| 704| 		{
| 705| 705| 			// We are already at the target, or can't move at all,
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 733| 733| 		}
| 734| 734| 
| 735| 735| 		if (this.MoveToGarrisonRange(this.order.data.target))
| 736|    |-		{
|    | 736|+		
| 737| 737| 			this.SetNextState("INDIVIDUAL.GARRISON.APPROACHING");
| 738|    |-		}
|    | 738|+		
| 739| 739| 		else
| 740| 740| 		{
| 741| 741| 			// We do a range check before actually garrisoning
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 861| 861| 			if (!this.CheckTargetAttackRange(target, target))
| 862| 862| 			{
| 863| 863| 				if (this.TargetIsAlive(target) && this.CheckTargetVisible(target))
| 864|    |-				{
|    | 864|+				
| 865| 865| 					if (this.MoveToTargetAttackRange(target, target))
| 866| 866| 					{
| 867| 867| 						this.SetNextState("COMBAT.APPROACHING");
| 868| 868| 						return;
| 869| 869| 					}
| 870|    |-				}
|    | 870|+				
| 871| 871| 				this.FinishOrder();
| 872| 872| 				return;
| 873| 873| 			}
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 886| 886| 			}
| 887| 887| 			// Check if we are already in range, otherwise walk there
| 888| 888| 			if (!this.CheckGarrisonRange(msg.data.target))
| 889|    |-			{
|    | 889|+			
| 890| 890| 				if (!this.CheckTargetVisible(msg.data.target))
| 891| 891| 				{
| 892| 892| 					this.FinishOrder();
| 901| 901| 						return;
| 902| 902| 					}
| 903| 903| 				}
| 904|    |-			}
|    | 904|+			
| 905| 905| 
| 906| 906| 			this.SetNextState("GARRISON.GARRISONING");
| 907| 907| 		},
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 893| 893| 					return;
| 894| 894| 				}
| 895| 895| 				else
| 896|    |-				{
|    | 896|+				
| 897| 897| 					// Out of range; move there in formation
| 898| 898| 					if (this.MoveToGarrisonRange(msg.data.target))
| 899| 899| 					{
| 900| 900| 						this.SetNextState("GARRISON.APPROACHING");
| 901| 901| 						return;
| 902| 902| 					}
| 903|    |-				}
|    | 903|+				
| 904| 904| 			}
| 905| 905| 
| 906| 906| 			this.SetNextState("GARRISON.GARRISONING");
|    | [NORMAL] ESLintBear (no-else-return):
|    | Unnecessary 'else' after 'return'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 892| 892| 					this.FinishOrder();
| 893| 893| 					return;
| 894| 894| 				}
| 895|    |-				else
| 896|    |-				{
|    | 895|+				
| 897| 896| 					// Out of range; move there in formation
| 898| 897| 					if (this.MoveToGarrisonRange(msg.data.target))
| 899| 898| 					{
| 900| 899| 						this.SetNextState("GARRISON.APPROACHING");
| 901| 900| 						return;
| 902| 901| 					}
| 903|    |-				}
|    | 902|+				
| 904| 903| 			}
| 905| 904| 
| 906| 905| 			this.SetNextState("GARRISON.GARRISONING");
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
| 919| 919| 						this.PushOrderFront("Walk", msg.data.lastPos);
| 920| 920| 					}
| 921| 921| 					else
| 922|    |-					{
|    | 922|+					
| 923| 923| 						// We couldn't move there, or the target moved away
| 924| 924| 						this.FinishOrder();
| 925|    |-					}
|    | 925|+					
| 926| 926| 					return;
| 927| 927| 				}
| 928| 928| 
|    | [NORMAL] ESLintBear (key-spacing):
|    | Missing space before value for key 'GARRISON'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1140|1140| 			},
|1141|1141| 		},
|1142|1142| 
|1143|    |-		"GARRISON":{
|    |1143|+		"GARRISON": {
|1144|1144| 			"enter": function() {
|1145|1145| 				// If the garrisonholder should pickup, warn it so it can take needed action
|1146|1146| 				var cmpGarrisonHolder = Engine.QueryInterface(this.order.data.target, IID_GarrisonHolder);
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1321|1321| 			// If the controller handled an order but some members rejected it,
|1322|1322| 			// they will have no orders and be in the FORMATIONMEMBER.IDLE state.
|1323|1323| 			if (this.orderQueue.length)
|1324|    |-			{
|    |1324|+			
|1325|1325| 				// We're leaving the formation, so stop our FormationWalk order
|1326|1326| 				if (this.FinishOrder())
|1327|1327| 					return;
|1328|    |-			}
|    |1328|+			
|1329|1329| 
|1330|1330| 			// No orders left, we're an individual now
|1331|1331| 			if (this.IsAnimal())
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1349|1349| 			// Move a tile outside the building
|1350|1350| 			let range = 4;
|1351|1351| 			if (this.MoveToTargetRangeExplicit(msg.data.target, range, range))
|1352|    |-			{
|    |1352|+			
|1353|1353| 				// We've started walking to the given point
|1354|1354| 				this.SetNextState("WALKINGTOPOINT");
|1355|    |-			}
|    |1355|+			
|1356|1356| 			else
|1357|1357| 			{
|1358|1358| 				// We are already at the target, or can't move at all
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1354|1354| 				this.SetNextState("WALKINGTOPOINT");
|1355|1355| 			}
|1356|1356| 			else
|1357|    |-			{
|    |1357|+			
|1358|1358| 				// We are already at the target, or can't move at all
|1359|1359| 				this.FinishOrder();
|1360|    |-			}
|    |1360|+			
|1361|1361| 		},
|1362|1362| 
|1363|1363| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1555|1555| 
|1556|1556| 			"LosRangeUpdate": function(msg) {
|1557|1557| 				if (this.GetStance().targetVisibleEnemies)
|1558|    |-				{
|    |1558|+				
|1559|1559| 					// Start attacking one of the newly-seen enemy (if any)
|1560|1560| 					this.AttackEntitiesByPreference(msg.data.added);
|1561|    |-				}
|    |1561|+				
|1562|1562| 			},
|1563|1563| 
|1564|1564| 			"LosHealRangeUpdate": function(msg) {
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1741|1741| 						// if nothing better to do, check if the guarded needs to be healed or repaired
|1742|1742| 						var cmpHealth = Engine.QueryInterface(this.isGuardOf, IID_Health);
|1743|1743| 						if (cmpHealth && (cmpHealth.GetHitpoints() < cmpHealth.GetMaxHitpoints()))
|1744|    |-						{
|    |1744|+						
|1745|1745| 							if (this.CanHeal(this.isGuardOf))
|1746|1746| 								this.PushOrderFront("Heal", { "target": this.isGuardOf, "force": false });
|1747|1747| 							else if (this.CanRepair(this.isGuardOf))
|1748|1748| 								this.PushOrderFront("Repair", { "target": this.isGuardOf, "autocontinue": false, "force": false });
|1749|    |-						}
|    |1749|+						
|1750|1750| 					}
|1751|1751| 				},
|1752|1752| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1829|1829| 				"MoveCompleted": function() {
|1830|1830| 
|1831|1831| 					if (this.CheckTargetAttackRange(this.order.data.target, this.order.data.attackType))
|1832|    |-					{
|    |1832|+					
|1833|1833| 						// If the unit needs to unpack, do so
|1834|1834| 						if (this.CanUnpack())
|1835|1835| 						{
|1838|1838| 						}
|1839|1839| 						else
|1840|1840| 							this.SetNextState("ATTACKING");
|1841|    |-					}
|    |1841|+					
|1842|1842| 					else
|1843|1843| 					{
|1844|1844| 						if (this.MoveToTargetAttackRange(this.order.data.target, this.order.data.attackType))
|    | [NORMAL] ESLintBear (no-else-return):
|    | Unnecessary 'else' after 'return'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1836|1836| 							this.PushOrderFront("Unpack", { "force": true });
|1837|1837| 							return;
|1838|1838| 						}
|1839|    |-						else
|1840|    |-							this.SetNextState("ATTACKING");
|    |1839|+						this.SetNextState("ATTACKING");
|1841|1840| 					}
|1842|1841| 					else
|1843|1842| 					{
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1840|1840| 							this.SetNextState("ATTACKING");
|1841|1841| 					}
|1842|1842| 					else
|1843|    |-					{
|    |1843|+					
|1844|1844| 						if (this.MoveToTargetAttackRange(this.order.data.target, this.order.data.attackType))
|1845|1845| 						{
|1846|1846| 							this.SetNextState("APPROACHING");
|1850|1850| 							// Give up
|1851|1851| 							this.FinishOrder();
|1852|1852| 						}
|1853|    |-					}
|    |1853|+					
|1854|1854| 				},
|1855|1855| 			},
|1856|1856| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1842|1842| 					else
|1843|1843| 					{
|1844|1844| 						if (this.MoveToTargetAttackRange(this.order.data.target, this.order.data.attackType))
|1845|    |-						{
|    |1845|+						
|1846|1846| 							this.SetNextState("APPROACHING");
|1847|    |-						}
|    |1847|+						
|1848|1848| 						else
|1849|1849| 						{
|1850|1850| 							// Give up
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1846|1846| 							this.SetNextState("APPROACHING");
|1847|1847| 						}
|1848|1848| 						else
|1849|    |-						{
|    |1849|+						
|1850|1850| 							// Give up
|1851|1851| 							this.FinishOrder();
|1852|    |-						}
|    |1852|+						
|1853|1853| 					}
|1854|1854| 				},
|1855|1855| 			},
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1867|1867| 					}
|1868|1868| 					// Check the target is still alive and attackable
|1869|1869| 					if (this.CanAttack(target) && !this.CheckTargetAttackRange(target, this.order.data.attackType))
|1870|    |-					{
|    |1870|+					
|1871|1871| 						// Can't reach it - try to chase after it
|1872|1872| 						if (this.ShouldChaseTargetedEntity(target, this.order.data.force))
|1873|1873| 						{
|1877|1877| 								return;
|1878|1878| 							}
|1879|1879| 						}
|1880|    |-					}
|    |1880|+					
|1881|1881| 
|1882|1882| 					var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|1883|1883| 					this.attackTimers = cmpAttack.GetTimers(this.order.data.attackType);
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1870|1870| 					{
|1871|1871| 						// Can't reach it - try to chase after it
|1872|1872| 						if (this.ShouldChaseTargetedEntity(target, this.order.data.force))
|1873|    |-						{
|    |1873|+						
|1874|1874| 							if (this.MoveToTargetAttackRange(target, this.order.data.attackType))
|1875|1875| 							{
|1876|1876| 								this.SetNextState("COMBAT.CHASING");
|1877|1877| 								return;
|1878|1878| 							}
|1879|    |-						}
|    |1879|+						
|1880|1880| 					}
|1881|1881| 
|1882|1882| 					var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|    | [NORMAL] ESLintBear (no-unneeded-ternary):
|    | Unnecessary use of boolean literals in conditional expression.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1908|1908| 					// TODO: we should probably only bother syncing projectile attacks, not melee
|1909|1909| 
|1910|1910| 					// If using a non-default prepare time, re-sync the animation when the timer runs.
|1911|    |-					this.resyncAnimation = (prepare != this.attackTimers.prepare) ? true : false;
|    |1911|+					this.resyncAnimation = (prepare != this.attackTimers.prepare);
|1912|1912| 
|1913|1913| 					this.FaceTowardsTarget(this.order.data.target);
|1914|1914| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|1983|1983| 
|1984|1984| 						// Can't reach it - try to chase after it
|1985|1985| 						if (this.ShouldChaseTargetedEntity(target, this.order.data.force))
|1986|    |-						{
|    |1986|+						
|1987|1987| 							if (this.MoveToTargetRange(target, IID_Attack, this.order.data.attackType))
|1988|1988| 							{
|1989|1989| 								this.SetNextState("COMBAT.CHASING");
|1990|1990| 								return;
|1991|1991| 							}
|1992|    |-						}
|    |1992|+						
|1993|1993| 					}
|1994|1994| 
|1995|1995| 					// if we're targetting a formation, find a new member of that formation
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2030|2030| 
|2031|2031| 				"Attacked": function(msg) {
|2032|2032| 					// If we are capturing and are attacked by something that we would not capture, attack that entity instead
|2033|    |-					if (this.order.data.attackType == "Capture" && (this.GetStance().targetAttackersAlways || !this.order.data.force)
|2034|    |-						&& this.order.data.target != msg.data.attacker && this.GetBestAttackAgainst(msg.data.attacker, true) != "Capture")
|    |2033|+					if (this.order.data.attackType == "Capture" && (this.GetStance().targetAttackersAlways || !this.order.data.force) &&
|    |2034|+						this.order.data.target != msg.data.attacker && this.GetBestAttackAgainst(msg.data.attacker, true) != "Capture")
|2035|2035| 						this.RespondToTargetedEntities([msg.data.attacker]);
|2036|2036| 				},
|2037|2037| 			},
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2114|2114| 						// Also don't switch to a different type of huntable animal
|2115|2115| 						var nearby = this.FindNearbyResource(function(ent, type, template) {
|2116|2116| 							return (
|2117|    |-								ent != oldTarget
|2118|    |-								 && ((type.generic == "treasure" && oldType.generic == "treasure")
|    |2117|+								ent != oldTarget &&
|    |2118|+								 ((type.generic == "treasure" && oldType.generic == "treasure")
|2119|2119| 								 || (type.specific == oldType.specific
|2120|2120| 								 && (type.specific != "meat" || oldTemplate == template)))
|2121|2121| 							);
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '||' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2115|2115| 						var nearby = this.FindNearbyResource(function(ent, type, template) {
|2116|2116| 							return (
|2117|2117| 								ent != oldTarget
|2118|    |-								 && ((type.generic == "treasure" && oldType.generic == "treasure")
|2119|    |-								 || (type.specific == oldType.specific
|    |2118|+								 && ((type.generic == "treasure" && oldType.generic == "treasure") ||
|    |2119|+								 (type.specific == oldType.specific
|2120|2120| 								 && (type.specific != "meat" || oldTemplate == template)))
|2121|2121| 							);
|2122|2122| 						}, oldTarget);
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2116|2116| 							return (
|2117|2117| 								ent != oldTarget
|2118|2118| 								 && ((type.generic == "treasure" && oldType.generic == "treasure")
|2119|    |-								 || (type.specific == oldType.specific
|2120|    |-								 && (type.specific != "meat" || oldTemplate == template)))
|    |2119|+								 || (type.specific == oldType.specific &&
|    |2120|+								 (type.specific != "meat" || oldTemplate == template)))
|2121|2121| 							);
|2122|2122| 						}, oldTarget);
|2123|2123| 						if (nearby)
|    | [NORMAL] ESLintBear (no-else-return):
|    | Unnecessary 'else' after 'return'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2125|2125| 							this.PerformGather(nearby, false, false);
|2126|2126| 							return true;
|2127|2127| 						}
|2128|    |-						else
|2129|    |-						{
|    |2128|+						
|2130|2129| 							// It's probably better in this case, to avoid units getting stuck around a dropsite
|2131|2130| 							// in a "Target is far away, full, nearby are no good resources, return to dropsite" loop
|2132|2131| 							// to order it to GatherNear the resource position.
|2147|2146| 									return true;
|2148|2147| 								}
|2149|2148| 							}
|2150|    |-						}
|    |2149|+						
|2151|2150| 						return true;
|2152|2151| 					}
|2153|2152| 					return false;
|    | [NORMAL] ESLintBear (no-else-return):
|    | Unnecessary 'else' after 'return'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2137|2137| 								this.GatherNearPosition(pos.x, pos.z, oldType, oldTemplate);
|2138|2138| 								return true;
|2139|2139| 							}
|2140|    |-							else
|2141|    |-							{
|    |2140|+							
|2142|2141| 								// we're kind of stuck here. Return resource.
|2143|2142| 								var nearby = this.FindNearestDropsite(oldType.generic);
|2144|2143| 								if (nearby)
|2146|2145| 									this.PushOrderFront("ReturnResource", { "target": nearby, "force": false });
|2147|2146| 									return true;
|2148|2147| 								}
|2149|    |-							}
|    |2148|+							
|2150|2149| 						}
|2151|2150| 						return true;
|2152|2151| 					}
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2179|2179| 						// Also don't switch to a different type of huntable animal
|2180|2180| 						var nearby = this.FindNearbyResource(function(ent, type, template) {
|2181|2181| 							return (
|2182|    |-								ent != oldTarget
|2183|    |-								&& ((type.generic == "treasure" && oldType.generic == "treasure")
|    |2182|+								ent != oldTarget &&
|    |2183|+								((type.generic == "treasure" && oldType.generic == "treasure")
|2184|2184| 								|| (type.specific == oldType.specific
|2185|2185| 								&& (type.specific != "meat" || oldTemplate == template)))
|2186|2186| 							);
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '||' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2180|2180| 						var nearby = this.FindNearbyResource(function(ent, type, template) {
|2181|2181| 							return (
|2182|2182| 								ent != oldTarget
|2183|    |-								&& ((type.generic == "treasure" && oldType.generic == "treasure")
|2184|    |-								|| (type.specific == oldType.specific
|    |2183|+								&& ((type.generic == "treasure" && oldType.generic == "treasure") ||
|    |2184|+								(type.specific == oldType.specific
|2185|2185| 								&& (type.specific != "meat" || oldTemplate == template)))
|2186|2186| 							);
|2187|2187| 						});
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2181|2181| 							return (
|2182|2182| 								ent != oldTarget
|2183|2183| 								&& ((type.generic == "treasure" && oldType.generic == "treasure")
|2184|    |-								|| (type.specific == oldType.specific
|2185|    |-								&& (type.specific != "meat" || oldTemplate == template)))
|    |2184|+								|| (type.specific == oldType.specific &&
|    |2185|+								(type.specific != "meat" || oldTemplate == template)))
|2186|2186| 							);
|2187|2187| 						});
|2188|2188| 						if (nearby)
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '||' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2226|2226| 					// Also don't switch to a different type of huntable animal
|2227|2227| 					var nearby = this.FindNearbyResource(function(ent, type, template) {
|2228|2228| 						return (
|2229|    |-							(type.generic == "treasure" && resourceType.generic == "treasure")
|2230|    |-							|| (type.specific == resourceType.specific
|    |2229|+							(type.generic == "treasure" && resourceType.generic == "treasure") ||
|    |2230|+							(type.specific == resourceType.specific
|2231|2231| 							&& (type.specific != "meat" || resourceTemplate == template))
|2232|2232| 						);
|2233|2233| 					});
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2227|2227| 					var nearby = this.FindNearbyResource(function(ent, type, template) {
|2228|2228| 						return (
|2229|2229| 							(type.generic == "treasure" && resourceType.generic == "treasure")
|2230|    |-							|| (type.specific == resourceType.specific
|2231|    |-							&& (type.specific != "meat" || resourceTemplate == template))
|    |2230|+							|| (type.specific == resourceType.specific &&
|    |2231|+							(type.specific != "meat" || resourceTemplate == template))
|2232|2232| 						);
|2233|2233| 					});
|2234|2234| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2343|2343| 
|2344|2344| 					var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply);
|2345|2345| 					if (cmpSupply && cmpSupply.IsAvailable(cmpOwnership.GetOwner(), this.entity))
|2346|    |-					{
|    |2346|+					
|2347|2347| 						// Check we can still reach and gather from the target
|2348|2348| 						if (this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer) && this.CanGather(this.gatheringTarget))
|2349|2349| 						{
|2409|2409| 								return;
|2410|2410| 							}
|2411|2411| 						}
|2412|    |-					}
|    |2412|+					
|2413|2413| 
|2414|2414| 					// We're already in range, can't get anywhere near it or the target is exhausted.
|2415|2415| 
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '||' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2435|2435| 					// Also don't switch to a different type of huntable animal
|2436|2436| 					var nearby = this.FindNearbyResource(function(ent, type, template) {
|2437|2437| 						return (
|2438|    |-							(type.generic == "treasure" && resourceType.generic == "treasure")
|2439|    |-							|| (type.specific == resourceType.specific
|    |2438|+							(type.generic == "treasure" && resourceType.generic == "treasure") ||
|    |2439|+							(type.specific == resourceType.specific
|2440|2440| 							&& (type.specific != "meat" || resourceTemplate == template))
|2441|2441| 						);
|2442|2442| 					});
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2436|2436| 					var nearby = this.FindNearbyResource(function(ent, type, template) {
|2437|2437| 						return (
|2438|2438| 							(type.generic == "treasure" && resourceType.generic == "treasure")
|2439|    |-							|| (type.specific == resourceType.specific
|2440|    |-							&& (type.specific != "meat" || resourceTemplate == template))
|    |2439|+							|| (type.specific == resourceType.specific &&
|    |2440|+							(type.specific != "meat" || resourceTemplate == template))
|2441|2441| 						);
|2442|2442| 					});
|2443|2443| 					if (nearby)
|    | [NORMAL] ESLintBear (no-unneeded-ternary):
|    | Unnecessary use of boolean literals in conditional expression.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2523|2523| 					this.StartTimer(prepare, this.healTimers.repeat);
|2524|2524| 
|2525|2525| 					// If using a non-default prepare time, re-sync the animation when the timer runs.
|2526|    |-					this.resyncAnimation = (prepare != this.healTimers.prepare) ? true : false;
|    |2526|+					this.resyncAnimation = (prepare != this.healTimers.prepare);
|2527|2527| 
|2528|2528| 					this.FaceTowardsTarget(this.order.data.target);
|2529|2529| 				},
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2556|2556| 						}
|2557|2557| 						// Can't reach it - try to chase after it
|2558|2558| 						if (this.ShouldChaseTargetedEntity(target, this.order.data.force))
|2559|    |-						{
|    |2559|+						
|2560|2560| 							if (this.MoveToTargetRange(target, IID_Heal))
|2561|2561| 							{
|2562|2562| 								this.SetNextState("HEAL.CHASING");
|2563|2563| 								return;
|2564|2564| 							}
|2565|    |-						}
|    |2565|+						
|2566|2566| 					}
|2567|2567| 					// Can't reach it, healed to max hp or doesn't exist any more - give up
|2568|2568| 					if (this.FinishOrder())
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2733|2733| 					{
|2734|2734| 						// The building was already finished/fully repaired before we arrived;
|2735|2735| 						// let the ConstructionFinished handler handle this.
|2736|    |-						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget});
|    |2736|+						this.OnGlobalConstructionFinished({ "entity": this.repairTarget, "newentity": this.repairTarget});
|2737|2737| 						return true;
|2738|2738| 					}
|2739|2739| 
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2733|2733| 					{
|2734|2734| 						// The building was already finished/fully repaired before we arrived;
|2735|2735| 						// let the ConstructionFinished handler handle this.
|2736|    |-						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget});
|    |2736|+						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget });
|2737|2737| 						return true;
|2738|2738| 					}
|2739|2739| 
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2773|2773| 					if (this.MoveToTargetRange(this.repairTarget, IID_Builder))
|2774|2774| 						this.SetNextState("APPROACHING");
|2775|2775| 					else if (!this.CheckTargetRange(this.repairTarget, IID_Builder))
|2776|    |-						this.FinishOrder(); //can't approach and isn't in reach
|    |2776|+						this.FinishOrder(); // can't approach and isn't in reach
|2777|2777| 				},
|2778|2778| 			},
|2779|2779| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2860|2860| 
|2861|2861| 				// Unit was approaching and there's nothing to do now, so switch to walking
|2862|2862| 				if (oldState === "INDIVIDUAL.REPAIR.APPROACHING")
|2863|    |-				{
|    |2863|+				
|2864|2864| 					// We're already walking to the given point, so add this as a order.
|2865|2865| 					this.WalkToTarget(msg.data.newentity, true);
|2866|    |-				}
|    |2866|+				
|2867|2867| 			},
|2868|2868| 		},
|2869|2869| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|2913|2913| 
|2914|2914| 					// Check that we can garrison here
|2915|2915| 					if (this.CanGarrison(target))
|2916|    |-					{
|    |2916|+					
|2917|2917| 						// Check that we're in range of the garrison target
|2918|2918| 						if (this.CheckGarrisonRange(target))
|2919|2919| 						{
|2987|2987| 								return false;
|2988|2988| 							}
|2989|2989| 						}
|2990|    |-					}
|    |2990|+					
|2991|2991| 					// Garrisoning failed for some reason, so finish the order
|2992|2992| 					this.FinishOrder();
|2993|2993| 					return true;
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3094|3094| 		"Attacked": function(msg) {
|3095|3095| 			if (this.template.NaturalBehaviour == "skittish" ||
|3096|3096| 			    this.template.NaturalBehaviour == "passive")
|3097|    |-			{
|    |3097|+			
|3098|3098| 				this.Flee(msg.data.attacker, false);
|3099|    |-			}
|    |3099|+			
|3100|3100| 			else if (this.IsDangerousAnimal() || this.template.NaturalBehaviour == "defensive")
|3101|3101| 			{
|3102|3102| 				if (this.CanAttack(msg.data.attacker))
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3103|3103| 					this.Attack(msg.data.attacker, false);
|3104|3104| 			}
|3105|3105| 			else if (this.template.NaturalBehaviour == "domestic")
|3106|    |-			{
|    |3106|+			
|3107|3107| 				// Never flee, stop what we were doing
|3108|3108| 				this.SetNextState("IDLE");
|3109|    |-			}
|    |3109|+			
|3110|3110| 		},
|3111|3111| 
|3112|3112| 		"Order.LeaveFoundation": function(msg) {
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3113|3113| 			// Move a tile outside the building
|3114|3114| 			var range = 4;
|3115|3115| 			if (this.MoveToTargetRangeExplicit(msg.data.target, range, range))
|3116|    |-			{
|    |3116|+			
|3117|3117| 				// We've started walking to the given point
|3118|3118| 				this.SetNextState("WALKING");
|3119|    |-			}
|    |3119|+			
|3120|3120| 			else
|3121|3121| 			{
|3122|3122| 				// We are already at the target, or can't move at all
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3118|3118| 				this.SetNextState("WALKING");
|3119|3119| 			}
|3120|3120| 			else
|3121|    |-			{
|    |3121|+			
|3122|3122| 				// We are already at the target, or can't move at all
|3123|3123| 				this.FinishOrder();
|3124|    |-			}
|    |3124|+			
|3125|3125| 		},
|3126|3126| 
|3127|3127| 		"IDLE": {
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3160|3160| 				}
|3161|3161| 				// Start attacking one of the newly-seen enemy (if any)
|3162|3162| 				else if (this.IsDangerousAnimal())
|3163|    |-				{
|    |3163|+				
|3164|3164| 					this.AttackVisibleEntity(msg.data.added);
|3165|    |-				}
|    |3165|+				
|3166|3166| 
|3167|3167| 				// TODO: if two units enter our range together, we'll attack the
|3168|3168| 				// first and then the second won't trigger another LosRangeUpdate
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3203|3203| 				}
|3204|3204| 				// Start attacking one of the newly-seen enemy (if any)
|3205|3205| 				else if (this.template.NaturalBehaviour == "violent")
|3206|    |-				{
|    |3206|+				
|3207|3207| 					this.AttackVisibleEntity(msg.data.added);
|3208|    |-				}
|    |3208|+				
|3209|3209| 			},
|3210|3210| 
|3211|3211| 			"MoveCompleted": function() { },
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 7.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3220|3220| 		"COMBAT": "INDIVIDUAL.COMBAT", // reuse the same combat behaviour for animals
|3221|3221| 
|3222|3222| 		"WALKING": "INDIVIDUAL.WALKING",	// reuse the same walking behaviour for animals
|3223|    |-							// only used for domestic animals
|    |3223|+		// only used for domestic animals
|3224|3224| 	},
|3225|3225| };
|3226|3226| 
|    | [NORMAL] ESLintBear (no-unneeded-ternary):
|    | Unnecessary use of boolean literals in conditional expression.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3277|3277| 
|3278|3278| UnitAI.prototype.IsAnimal = function()
|3279|3279| {
|3280|    |-	return (this.template.NaturalBehaviour ? true : false);
|    |3280|+	return (!!this.template.NaturalBehaviour);
|3281|3281| };
|3282|3282| 
|3283|3283| UnitAI.prototype.IsDangerousAnimal = function()
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3315|3315| UnitAI.prototype.GetGarrisonHolder = function()
|3316|3316| {
|3317|3317| 	if (this.IsGarrisoned())
|3318|    |-	{
|    |3318|+	
|3319|3319| 		for (let order of this.orderQueue)
|3320|3320| 			if (order.type == "Garrison")
|3321|3321| 				return order.data.target;
|3322|    |-	}
|    |3322|+	
|3323|3323| 	return INVALID_ENTITY;
|3324|3324| };
|3325|3325| 
|    | [NORMAL] ESLintBear (comma-spacing):
|    | A space is required after ','.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3396|3396| 		{
|3397|3397| 			let index = this.GetCurrentState().indexOf(".");
|3398|3398| 			if (index != -1)
|3399|    |-				this.UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0,index));
|    |3399|+				this.UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0, index));
|3400|3400| 			this.Stop(false);
|3401|3401| 		}
|3402|3402| 
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3452|3452| 		if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity)
|3453|3453| 			continue;
|3454|3454| 		if (i == 0)
|3455|    |-			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg});
|    |3455|+			this.UnitFsm.ProcessMessage(this, { "type": "PickupCanceled", "data": msg});
|3456|3456| 		else
|3457|3457| 			this.orderQueue.splice(i, 1);
|3458|3458| 		Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3452|3452| 		if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity)
|3453|3453| 			continue;
|3454|3454| 		if (i == 0)
|3455|    |-			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg});
|    |3455|+			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg });
|3456|3456| 		else
|3457|3457| 			this.orderQueue.splice(i, 1);
|3458|3458| 		Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3536|3536| };
|3537|3537| 
|3538|3538| 
|3539|    |-//// FSM linkage functions ////
|    |3539|+// // FSM linkage functions ////
|3540|3540| 
|3541|3541| UnitAI.prototype.SetNextState = function(state)
|3542|3542| {
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3638|3638| 	{
|3639|3639| 		this.order = order;
|3640|3640| 		let ret = this.UnitFsm.ProcessMessage(this,
|3641|    |-			{"type": "Order."+this.order.type, "data": this.order.data}
|    |3641|+			{ "type": "Order."+this.order.type, "data": this.order.data}
|3642|3642| 		);
|3643|3643| 
|3644|3644| 		// If the order was rejected then immediately take it off
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3638|3638| 	{
|3639|3639| 		this.order = order;
|3640|3640| 		let ret = this.UnitFsm.ProcessMessage(this,
|3641|    |-			{"type": "Order."+this.order.type, "data": this.order.data}
|    |3641|+			{"type": "Order."+this.order.type, "data": this.order.data }
|3642|3642| 		);
|3643|3643| 
|3644|3644| 		// If the order was rejected then immediately take it off
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3674|3674| 		this.orderQueue.unshift(order);
|3675|3675| 		this.order = order;
|3676|3676| 		let ret = this.UnitFsm.ProcessMessage(this,
|3677|    |-			{"type": "Order."+this.order.type, "data": this.order.data}
|    |3677|+			{ "type": "Order."+this.order.type, "data": this.order.data}
|3678|3678| 		);
|3679|3679| 
|3680|3680| 		// If the order was rejected then immediately take it off again;
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3674|3674| 		this.orderQueue.unshift(order);
|3675|3675| 		this.order = order;
|3676|3676| 		let ret = this.UnitFsm.ProcessMessage(this,
|3677|    |-			{"type": "Order."+this.order.type, "data": this.order.data}
|    |3677|+			{"type": "Order."+this.order.type, "data": this.order.data }
|3678|3678| 		);
|3679|3679| 
|3680|3680| 		// If the order was rejected then immediately take it off again;
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3708|3708| 				continue;
|3709|3709| 			if (this.orderQueue[i].type == type)
|3710|3710| 				continue;
|3711|    |-			this.orderQueue.splice(i, 0, {"type": type, "data": data});
|    |3711|+			this.orderQueue.splice(i, 0, { "type": type, "data": data});
|3712|3712| 			Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|3713|3713| 			return;
|3714|3714| 		}
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3708|3708| 				continue;
|3709|3709| 			if (this.orderQueue[i].type == type)
|3710|3710| 				continue;
|3711|    |-			this.orderQueue.splice(i, 0, {"type": type, "data": data});
|    |3711|+			this.orderQueue.splice(i, 0, {"type": type, "data": data });
|3712|3712| 			Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|3713|3713| 			return;
|3714|3714| 		}
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3722|3722| {
|3723|3723| 	// Remember the previous work orders to be able to go back to them later if required
|3724|3724| 	if (data && data.force)
|3725|    |-	{
|    |3725|+	
|3726|3726| 		if (this.IsFormationController())
|3727|3727| 			this.CallMemberFunction("UpdateWorkOrders", [type]);
|3728|3728| 		else
|3729|3729| 			this.UpdateWorkOrders(type);
|3730|    |-	}
|    |3730|+	
|3731|3731| 
|3732|3732| 	let garrisonHolder = this.IsGarrisoned() && type != "Ungarrison" ? this.GetGarrisonHolder() : null;
|3733|3733| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3799|3799| 	{
|3800|3800| 		var cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI);
|3801|3801| 		if (cmpUnitAI)
|3802|    |-		{
|    |3802|+		
|3803|3803| 			for (var i = 0; i < cmpUnitAI.orderQueue.length; ++i)
|3804|3804| 			{
|3805|3805| 				if (isWorkType(cmpUnitAI.orderQueue[i].type))
|3808|3808| 					return;
|3809|3809| 				}
|3810|3810| 			}
|3811|    |-		}
|    |3811|+		
|3812|3812| 	}
|3813|3813| 
|3814|3814| 	// If nothing found, take the unit orders
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'for' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3801|3801| 		if (cmpUnitAI)
|3802|3802| 		{
|3803|3803| 			for (var i = 0; i < cmpUnitAI.orderQueue.length; ++i)
|3804|    |-			{
|    |3804|+			
|3805|3805| 				if (isWorkType(cmpUnitAI.orderQueue[i].type))
|3806|3806| 				{
|3807|3807| 					this.workOrders = cmpUnitAI.orderQueue.slice(i);
|3808|3808| 					return;
|3809|3809| 				}
|3810|    |-			}
|    |3810|+			
|3811|3811| 		}
|3812|3812| 	}
|3813|3813| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'for' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3813|3813| 
|3814|3814| 	// If nothing found, take the unit orders
|3815|3815| 	for (var i = 0; i < this.orderQueue.length; ++i)
|3816|    |-	{
|    |3816|+	
|3817|3817| 		if (isWorkType(this.orderQueue[i].type))
|3818|3818| 		{
|3819|3819| 			this.workOrders = this.orderQueue.slice(i);
|3820|3820| 			return;
|3821|3821| 		}
|3822|    |-	}
|    |3822|+	
|3823|3823| };
|3824|3824| 
|3825|3825| UnitAI.prototype.BackToWork = function()
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3879|3879| 	if (data.timerRepeat === undefined)
|3880|3880| 		this.timer = undefined;
|3881|3881| 
|3882|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness});
|    |3882|+	this.UnitFsm.ProcessMessage(this, { "type": "Timer", "data": data, "lateness": lateness});
|3883|3883| };
|3884|3884| 
|3885|3885| /**
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3879|3879| 	if (data.timerRepeat === undefined)
|3880|3880| 		this.timer = undefined;
|3881|3881| 
|3882|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness});
|    |3882|+	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness });
|3883|3883| };
|3884|3884| 
|3885|3885| /**
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3914|3914| 	this.timer = undefined;
|3915|3915| };
|3916|3916| 
|3917|    |-//// Message handlers /////
|    |3917|+// // Message handlers /////
|3918|3918| 
|3919|3919| UnitAI.prototype.OnMotionChanged = function(msg)
|3920|3920| {
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3919|3919| UnitAI.prototype.OnMotionChanged = function(msg)
|3920|3920| {
|3921|3921| 	if (msg.starting && !msg.error)
|3922|    |-		this.UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg});
|    |3922|+		this.UnitFsm.ProcessMessage(this, { "type": "MoveStarted", "data": msg});
|3923|3923| 	else if (!msg.starting || msg.error)
|3924|3924| 		this.UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg});
|3925|3925| };
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3919|3919| UnitAI.prototype.OnMotionChanged = function(msg)
|3920|3920| {
|3921|3921| 	if (msg.starting && !msg.error)
|3922|    |-		this.UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg});
|    |3922|+		this.UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg });
|3923|3923| 	else if (!msg.starting || msg.error)
|3924|3924| 		this.UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg});
|3925|3925| };
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3921|3921| 	if (msg.starting && !msg.error)
|3922|3922| 		this.UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg});
|3923|3923| 	else if (!msg.starting || msg.error)
|3924|    |-		this.UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg});
|    |3924|+		this.UnitFsm.ProcessMessage(this, { "type": "MoveCompleted", "data": msg});
|3925|3925| };
|3926|3926| 
|3927|3927| UnitAI.prototype.OnGlobalConstructionFinished = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3921|3921| 	if (msg.starting && !msg.error)
|3922|3922| 		this.UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg});
|3923|3923| 	else if (!msg.starting || msg.error)
|3924|    |-		this.UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg});
|    |3924|+		this.UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg });
|3925|3925| };
|3926|3926| 
|3927|3927| UnitAI.prototype.OnGlobalConstructionFinished = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3929|3929| 	// TODO: This is a bit inefficient since every unit listens to every
|3930|3930| 	// construction message - ideally we could scope it to only the one we're building
|3931|3931| 
|3932|    |-	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg});
|    |3932|+	this.UnitFsm.ProcessMessage(this, { "type": "ConstructionFinished", "data": msg});
|3933|3933| };
|3934|3934| 
|3935|3935| UnitAI.prototype.OnGlobalEntityRenamed = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3929|3929| 	// TODO: This is a bit inefficient since every unit listens to every
|3930|3930| 	// construction message - ideally we could scope it to only the one we're building
|3931|3931| 
|3932|    |-	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg});
|    |3932|+	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg });
|3933|3933| };
|3934|3934| 
|3935|3935| UnitAI.prototype.OnGlobalEntityRenamed = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3954|3954| 
|3955|3955| UnitAI.prototype.OnAttacked = function(msg)
|3956|3956| {
|3957|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
|    |3957|+	this.UnitFsm.ProcessMessage(this, { "type": "Attacked", "data": msg});
|3958|3958| };
|3959|3959| 
|3960|3960| UnitAI.prototype.OnGuardedAttacked = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3954|3954| 
|3955|3955| UnitAI.prototype.OnAttacked = function(msg)
|3956|3956| {
|3957|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
|    |3957|+	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg });
|3958|3958| };
|3959|3959| 
|3960|3960| UnitAI.prototype.OnGuardedAttacked = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3959|3959| 
|3960|3960| UnitAI.prototype.OnGuardedAttacked = function(msg)
|3961|3961| {
|3962|    |-	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data});
|    |3962|+	this.UnitFsm.ProcessMessage(this, { "type": "GuardedAttacked", "data": msg.data});
|3963|3963| };
|3964|3964| 
|3965|3965| UnitAI.prototype.OnHealthChanged = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3959|3959| 
|3960|3960| UnitAI.prototype.OnGuardedAttacked = function(msg)
|3961|3961| {
|3962|    |-	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data});
|    |3962|+	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data });
|3963|3963| };
|3964|3964| 
|3965|3965| UnitAI.prototype.OnHealthChanged = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3964|3964| 
|3965|3965| UnitAI.prototype.OnHealthChanged = function(msg)
|3966|3966| {
|3967|    |-	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
|    |3967|+	this.UnitFsm.ProcessMessage(this, { "type": "HealthChanged", "from": msg.from, "to": msg.to});
|3968|3968| };
|3969|3969| 
|3970|3970| UnitAI.prototype.OnRangeUpdate = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3964|3964| 
|3965|3965| UnitAI.prototype.OnHealthChanged = function(msg)
|3966|3966| {
|3967|    |-	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
|    |3967|+	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to });
|3968|3968| };
|3969|3969| 
|3970|3970| UnitAI.prototype.OnRangeUpdate = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3970|3970| UnitAI.prototype.OnRangeUpdate = function(msg)
|3971|3971| {
|3972|3972| 	if (msg.tag == this.losRangeQuery)
|3973|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|    |3973|+		this.UnitFsm.ProcessMessage(this, { "type": "LosRangeUpdate", "data": msg});
|3974|3974| 	else if (msg.tag == this.losHealRangeQuery)
|3975|3975| 		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|3976|3976| };
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3970|3970| UnitAI.prototype.OnRangeUpdate = function(msg)
|3971|3971| {
|3972|3972| 	if (msg.tag == this.losRangeQuery)
|3973|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|    |3973|+		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg });
|3974|3974| 	else if (msg.tag == this.losHealRangeQuery)
|3975|3975| 		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|3976|3976| };
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3972|3972| 	if (msg.tag == this.losRangeQuery)
|3973|3973| 		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|3974|3974| 	else if (msg.tag == this.losHealRangeQuery)
|3975|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|    |3975|+		this.UnitFsm.ProcessMessage(this, { "type": "LosHealRangeUpdate", "data": msg});
|3976|3976| };
|3977|3977| 
|3978|3978| UnitAI.prototype.OnPackFinished = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3972|3972| 	if (msg.tag == this.losRangeQuery)
|3973|3973| 		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|3974|3974| 	else if (msg.tag == this.losHealRangeQuery)
|3975|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|    |3975|+		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg });
|3976|3976| };
|3977|3977| 
|3978|3978| UnitAI.prototype.OnPackFinished = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3977|3977| 
|3978|3978| UnitAI.prototype.OnPackFinished = function(msg)
|3979|3979| {
|3980|    |-	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|    |3980|+	this.UnitFsm.ProcessMessage(this, { "type": "PackFinished", "packed": msg.packed});
|3981|3981| };
|3982|3982| 
|3983|3983| //// Helper functions to be called by the FSM ////
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3977|3977| 
|3978|3978| UnitAI.prototype.OnPackFinished = function(msg)
|3979|3979| {
|3980|    |-	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|    |3980|+	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed });
|3981|3981| };
|3982|3982| 
|3983|3983| //// Helper functions to be called by the FSM ////
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|3980|3980| 	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|3981|3981| };
|3982|3982| 
|3983|    |-//// Helper functions to be called by the FSM ////
|    |3983|+// // Helper functions to be called by the FSM ////
|3984|3984| 
|3985|3985| UnitAI.prototype.GetWalkSpeed = function()
|3986|3986| {
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4084|4084| 	if (!cmpOwnership || cmpOwnership.GetOwner() == INVALID_PLAYER)
|4085|4085| 		return undefined;
|4086|4086| 
|4087|    |-	let cmpPosition = Engine.QueryInterface(this.entity, IID_Position)
|    |4087|+	let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
|4088|4088| 	if (!cmpPosition || !cmpPosition.IsInWorld())
|4089|4089| 		return undefined;
|4090|4090| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4169|4169| 			PlaySound(name, member);
|4170|4170| 	}
|4171|4171| 	else
|4172|    |-	{
|    |4172|+	
|4173|4173| 		// Otherwise use our own sounds
|4174|4174| 		PlaySound(name, this.entity);
|4175|    |-	}
|    |4175|+	
|4176|4176| };
|4177|4177| 
|4178|4178| /*
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4338|4338| 	else
|4339|4339| 		// return false? Or hope you come close enough?
|4340|4340| 		var parabolicMaxRange = 0;
|4341|    |-		//return false;
|    |4341|+		// return false;
|4342|4342| 
|4343|4343| 	// the parabole changes while walking, take something in the middle
|4344|4344| 	var guessedMaxRange = (range.max + parabolicMaxRange)/2;
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4403|4403| 	if (this.IsFormationMember())
|4404|4404| 	{
|4405|4405| 		var cmpFormationUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI);
|4406|    |-		if (cmpFormationUnitAI && cmpFormationUnitAI.IsAttackingAsFormation()
|4407|    |-			&& cmpFormationUnitAI.order.data.target == target)
|    |4406|+		if (cmpFormationUnitAI && cmpFormationUnitAI.IsAttackingAsFormation() &&
|    |4407|+			cmpFormationUnitAI.order.data.target == target)
|4408|4408| 			return true;
|4409|4409| 	}
|4410|4410| 
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4571|4571| UnitAI.prototype.AttackEntityInZone = function(ents)
|4572|4572| {
|4573|4573| 	var target = ents.find(target =>
|4574|    |-		this.CanAttack(target)
|4575|    |-		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|    |4574|+		this.CanAttack(target) &&
|    |4575|+		this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|4576|4576| 		&& (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|4577|4577| 	);
|4578|4578| 	if (!target)
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4572|4572| {
|4573|4573| 	var target = ents.find(target =>
|4574|4574| 		this.CanAttack(target)
|4575|    |-		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|4576|    |-		&& (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|    |4575|+		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true)) &&
|    |4576|+		(this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|4577|4577| 	);
|4578|4578| 	if (!target)
|4579|4579| 		return false;
|    | [NORMAL] ESLintBear (no-multi-spaces):
|    | Multiple spaces found before 'Engine'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4636|4636| 	// If we are guarding/escorting, don't abandon as long as the guarded unit is in target range of the attacker
|4637|4637| 	if (this.isGuardOf)
|4638|4638| 	{
|4639|    |-		var cmpUnitAI =  Engine.QueryInterface(target, IID_UnitAI);
|    |4639|+		var cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI);
|4640|4640| 		var cmpAttack = Engine.QueryInterface(target, IID_Attack);
|4641|4641| 		if (cmpUnitAI && cmpAttack &&
|4642|4642| 		    cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type)))
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4640|4640| 		var cmpAttack = Engine.QueryInterface(target, IID_Attack);
|4641|4641| 		if (cmpUnitAI && cmpAttack &&
|4642|4642| 		    cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type)))
|4643|    |-				return false;
|    |4643|+			return false;
|4644|4644| 	}
|4645|4645| 
|4646|4646| 	// Stop if we're in hold-ground mode and it's too far from the holding point
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4645|4645| 
|4646|4646| 	// Stop if we're in hold-ground mode and it's too far from the holding point
|4647|4647| 	if (this.GetStance().respondHoldGround)
|4648|    |-	{
|    |4648|+	
|4649|4649| 		if (!this.CheckTargetDistanceFromHeldPosition(target, iid, type))
|4650|4650| 			return true;
|4651|    |-	}
|    |4651|+	
|4652|4652| 
|4653|4653| 	// Stop if it's left our vision range, unless we're especially persistent
|4654|4654| 	if (!this.GetStance().respondChaseBeyondVision)
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4652|4652| 
|4653|4653| 	// Stop if it's left our vision range, unless we're especially persistent
|4654|4654| 	if (!this.GetStance().respondChaseBeyondVision)
|4655|    |-	{
|    |4655|+	
|4656|4656| 		if (!this.CheckTargetIsInVisionRange(target))
|4657|4657| 			return true;
|4658|    |-	}
|    |4658|+	
|4659|4659| 
|4660|4660| 	// (Note that CCmpUnitMotion will detect if the target is lost in FoW,
|4661|4661| 	// and will continue moving to its last seen position and then stop)
|    | [NORMAL] ESLintBear (no-multi-spaces):
|    | Multiple spaces found before 'Engine'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4683|4683| 	// If we are guarding/escorting, chase at least as long as the guarded unit is in target range of the attacker
|4684|4684| 	if (this.isGuardOf)
|4685|4685| 	{
|4686|    |-		var cmpUnitAI =  Engine.QueryInterface(target, IID_UnitAI);
|    |4686|+		var cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI);
|4687|4687| 		var cmpAttack = Engine.QueryInterface(target, IID_Attack);
|4688|4688| 		if (cmpUnitAI && cmpAttack &&
|4689|4689| 		    cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type)))
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4696|4696| 	return false;
|4697|4697| };
|4698|4698| 
|4699|    |-//// External interface functions ////
|    |4699|+// // External interface functions ////
|4700|4700| 
|4701|4701| UnitAI.prototype.SetFormationController = function(ent)
|4702|4702| {
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4706|4706| 	// of our own formation (or ourself if not in formation)
|4707|4707| 	var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction);
|4708|4708| 	if (cmpObstruction)
|4709|    |-	{
|    |4709|+	
|4710|4710| 		if (ent == INVALID_ENTITY)
|4711|4711| 			cmpObstruction.SetControlGroup(this.entity);
|4712|4712| 		else
|4713|4713| 			cmpObstruction.SetControlGroup(ent);
|4714|    |-	}
|    |4714|+	
|4715|4715| 
|4716|4716| 	// If we were removed from a formation, let the FSM switch back to INDIVIDUAL
|4717|4717| 	if (ent == INVALID_ENTITY)
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4849|4849| 	// if we already had an old guard order, do nothing if the target is the same
|4850|4850| 	// and the order is running, otherwise remove the previous order
|4851|4851| 	if (this.isGuardOf)
|4852|    |-	{
|    |4852|+	
|4853|4853| 		if (this.isGuardOf == target && this.order && this.order.type == "Guard")
|4854|4854| 			return;
|4855|4855| 		else
|4856|4856| 			this.RemoveGuard();
|4857|    |-	}
|    |4857|+	
|4858|4858| 
|4859|4859| 	this.AddOrder("Guard", { "target": target, "force": false }, queued);
|4860|4860| };
|    | [NORMAL] ESLintBear (no-else-return):
|    | Unnecessary 'else' after 'return'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4852|4852| 	{
|4853|4853| 		if (this.isGuardOf == target && this.order && this.order.type == "Guard")
|4854|4854| 			return;
|4855|    |-		else
|4856|    |-			this.RemoveGuard();
|    |4855|+		this.RemoveGuard();
|4857|4856| 	}
|4858|4857| 
|4859|4858| 	this.AddOrder("Guard", { "target": target, "force": false }, queued);
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4894|4894| 		return;
|4895|4895| 
|4896|4896| 	if (this.order.type == "Guard")
|4897|    |-		this.UnitFsm.ProcessMessage(this, {"type": "RemoveGuard"});
|    |4897|+		this.UnitFsm.ProcessMessage(this, { "type": "RemoveGuard"});
|4898|4898| 	else
|4899|4899| 		for (let i = 1; i < this.orderQueue.length; ++i)
|4900|4900| 			if (this.orderQueue[i].type == "Guard")
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|4894|4894| 		return;
|4895|4895| 
|4896|4896| 	if (this.order.type == "Guard")
|4897|    |-		this.UnitFsm.ProcessMessage(this, {"type": "RemoveGuard"});
|    |4897|+		this.UnitFsm.ProcessMessage(this, {"type": "RemoveGuard" });
|4898|4898| 	else
|4899|4899| 		for (let i = 1; i < this.orderQueue.length; ++i)
|4900|4900| 			if (this.orderQueue[i].type == "Guard")
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5023|5023| 			this.WalkToTarget(target, queued);
|5024|5024| 		return;
|5025|5025| 	}
|5026|    |-	this.AddOrder("Attack", { "target": target, "force": true, "allowCapture": allowCapture}, queued);
|    |5026|+	this.AddOrder("Attack", { "target": target, "force": true, "allowCapture": allowCapture }, queued);
|5027|5027| };
|5028|5028| 
|5029|5029| /**
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5171|5171| 	    this.workOrders.length && this.workOrders[0].type == "Trade")
|5172|5172| 	{
|5173|5173| 		let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader);
|5174|    |-		if (cmpTrader.HasBothMarkets() && 
|    |5174|+		if (cmpTrader.HasBothMarkets() &&
|5175|5175| 		   (cmpTrader.GetFirstMarket() == target && cmpTrader.GetSecondMarket() == source ||
|5176|5176| 		    cmpTrader.GetFirstMarket() == source && cmpTrader.GetSecondMarket() == target))
|5177|5177| 		{
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5452|5452| 				{
|5453|5453| 					var cmpIdentity = Engine.QueryInterface(targ, IID_Identity);
|5454|5454| 					var targetClasses = this.order.data.targetClasses;
|5455|    |-					if (targetClasses.attack && cmpIdentity
|5456|    |-						&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|    |5455|+					if (targetClasses.attack && cmpIdentity &&
|    |5456|+						!MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5457|5457| 						continue;
|5458|5458| 					if (targetClasses.avoid && cmpIdentity
|5459|5459| 						&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5455|5455| 					if (targetClasses.attack && cmpIdentity
|5456|5456| 						&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5457|5457| 						continue;
|5458|    |-					if (targetClasses.avoid && cmpIdentity
|5459|    |-						&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    |5458|+					if (targetClasses.avoid && cmpIdentity &&
|    |5459|+						MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|5460|5460| 						continue;
|5461|5461| 					// Only used by the AIs to prevent some choices of targets
|5462|5462| 					if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ])
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5478|5478| 		{
|5479|5479| 			var cmpIdentity = Engine.QueryInterface(targ, IID_Identity);
|5480|5480| 			var targetClasses = this.order.data.targetClasses;
|5481|    |-			if (cmpIdentity && targetClasses.attack
|5482|    |-				&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|    |5481|+			if (cmpIdentity && targetClasses.attack &&
|    |5482|+				!MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5483|5483| 				continue;
|5484|5484| 			if (cmpIdentity && targetClasses.avoid
|5485|5485| 				&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5481|5481| 			if (cmpIdentity && targetClasses.attack
|5482|5482| 				&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5483|5483| 				continue;
|5484|    |-			if (cmpIdentity && targetClasses.avoid
|5485|    |-				&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    |5484|+			if (cmpIdentity && targetClasses.avoid &&
|    |5485|+				MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|5486|5486| 				continue;
|5487|5487| 			// Only used by the AIs to prevent some choices of targets
|5488|5488| 			if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ])
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5614|5614| 
|5615|5615| UnitAI.prototype.SetHeldPosition = function(x, z)
|5616|5616| {
|5617|    |-	this.heldPosition = {"x": x, "z": z};
|    |5617|+	this.heldPosition = { "x": x, "z": z};
|5618|5618| };
|5619|5619| 
|5620|5620| UnitAI.prototype.SetHeldPositionOnEntity = function(entity)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5614|5614| 
|5615|5615| UnitAI.prototype.SetHeldPosition = function(x, z)
|5616|5616| {
|5617|    |-	this.heldPosition = {"x": x, "z": z};
|    |5617|+	this.heldPosition = {"x": x, "z": z };
|5618|5618| };
|5619|5619| 
|5620|5620| UnitAI.prototype.SetHeldPositionOnEntity = function(entity)
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5641|5641| 	return false;
|5642|5642| };
|5643|5643| 
|5644|    |-//// Helper functions ////
|    |5644|+// // Helper functions ////
|5645|5645| 
|5646|5646| UnitAI.prototype.CanAttack = function(target)
|5647|5647| {
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5845|5845| 	return (cmpPack && cmpPack.IsPacking());
|5846|5846| };
|5847|5847| 
|5848|    |-//// Formation specific functions ////
|    |5848|+// // Formation specific functions ////
|5849|5849| 
|5850|5850| UnitAI.prototype.IsAttackingAsFormation = function()
|5851|5851| {
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5850|5850| UnitAI.prototype.IsAttackingAsFormation = function()
|5851|5851| {
|5852|5852| 	var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|5853|    |-	return cmpAttack && cmpAttack.CanAttackAsFormation()
|5854|    |-		&& this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|    |5853|+	return cmpAttack && cmpAttack.CanAttackAsFormation() &&
|    |5854|+		this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|5855|5855| };
|5856|5856| 
|5857|5857| //// Animal specific functions ////
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitAI.js
|5854|5854| 		&& this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|5855|5855| };
|5856|5856| 
|5857|    |-//// Animal specific functions ////
|    |5857|+// // Animal specific functions ////
|5858|5858| 
|5859|5859| UnitAI.prototype.MoveRandomly = function(distance)
|5860|5860| {

binaries/data/mods/public/simulation/components/UnitAI.js
|2425| »   »   »   »   »   »   let·nearby·=·this.FindNearestDropsite(resourceType.generic);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'nearby' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|3784| »   var·isWorkType·=·type·=>·type·==·"Gather"·||·type·==·"Trade"·||·type·==·"Repair"·||·type·==·"ReturnResource";
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'type' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4558| »   var·target·=·ents.find(target·=>·this.CanAttack(target));
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'target' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4573| »   var·target·=·ents.find(target·=>
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'target' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4619| »   var·ent·=·ents.find(ent·=>·this.CanHeal(ent));
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'ent' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4642| »   »   ····cmpAttack.GetAttackTypes().some(type·=>·cmpUnitAI.CheckTargetAttackRange(this.isGuardOf,·type)))
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'type' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|5102| »   var·lastPos·=·undefined;
|    | [NORMAL] ESLintBear (no-undef-init):
|    | It's not necessary to initialize 'lastPos' to undefined.

binaries/data/mods/public/simulation/components/UnitAI.js
| 369| »   »   ····&&·(this.lastShorelinePosition.z·==·cmpPosition.GetPosition().z))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|1900| »   »   »   »   »   »   var·cmpFormation·=·Engine.QueryInterface(this.formationController,·IID_Formation);
|    | [NORMAL] JSHintBear:
|    | 'cmpFormation' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2034| »   »   »   »   »   »   &&·this.order.data.target·!=·msg.data.attacker·&&·this.GetBestAttackAgainst(msg.data.attacker,·true)·!=·"Capture")
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|2118| »   »   »   »   »   »   »   »   ·&&·((type.generic·==·"treasure"·&&·oldType.generic·==·"treasure")
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|2119| »   »   »   »   »   »   »   »   ·||·(type.specific·==·oldType.specific
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '||'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|2120| »   »   »   »   »   »   »   »   ·&&·(type.specific·!=·"meat"·||·oldTemplate·==·template)))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|2143| »   »   »   »   »   »   »   »   var·nearby·=·this.FindNearestDropsite(oldType.generic);
|    | [NORMAL] JSHintBear:
|    | 'nearby' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2183| »   »   »   »   »   »   »   »   &&·((type.generic·==·"treasure"·&&·oldType.generic·==·"treasure")
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|2184| »   »   »   »   »   »   »   »   ||·(type.specific·==·oldType.specific
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '||'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|2185| »   »   »   »   »   »   »   »   &&·(type.specific·!=·"meat"·||·oldTemplate·==·template)))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|2230| »   »   »   »   »   »   »   ||·(type.specific·==·resourceType.specific
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '||'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|2231| »   »   »   »   »   »   »   &&·(type.specific·!=·"meat"·||·resourceTemplate·==·template))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|2247| »   »   »   »   »   var·nearby·=·this.FindNearestDropsite(resourceType.generic);
|    | [NORMAL] JSHintBear:
|    | 'nearby' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2420| »   »   »   »   »   var·cmpResourceGatherer·=·Engine.QueryInterface(this.entity,·IID_ResourceGatherer);
|    | [NORMAL] JSHintBear:
|    | 'cmpResourceGatherer' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2436| »   »   »   »   »   var·nearby·=·this.FindNearbyResource(function(ent,·type,·template)·{
|    | [NORMAL] JSHintBear:
|    | 'nearby' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2439| »   »   »   »   »   »   »   ||·(type.specific·==·resourceType.specific
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '||'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|2440| »   »   »   »   »   »   »   &&·(type.specific·!=·"meat"·||·resourceTemplate·==·template))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|2460| »   »   »   »   »   var·nearby·=·this.FindNearestDropsite(resourceType.generic);
|    | [NORMAL] JSHintBear:
|    | 'nearby' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2644| »   »   »   »   »   var·cmpResourceGatherer·=·Engine.QueryInterface(this.entity,·IID_ResourceGatherer);
|    | [NORMAL] JSHintBear:
|    | 'cmpResourceGatherer' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2839| »   »   »   »   »   var·cmpResourceDropsite·=·Engine.QueryInterface(msg.data.newentity,·IID_ResourceDropsite);
|    | [NORMAL] JSHintBear:
|    | 'cmpResourceDropsite' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2915| »   »   »   »   »   if·(this.CanGarrison(target))
|    | [NORMAL] JSHintBear:
|    | 'target' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|2918| »   »   »   »   »   »   if·(this.CheckGarrisonRange(target))
|    | [NORMAL] JSHintBear:
|    | 'target' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|2920| »   »   »   »   »   »   »   var·cmpGarrisonHolder·=·Engine.QueryInterface(target,·IID_GarrisonHolder);
|    | [NORMAL] JSHintBear:
|    | 'target' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|2940| »   »   »   »   »   »   »   »   var·cmpResourceDropsite·=·Engine.QueryInterface(target,·IID_ResourceDropsite);
|    | [NORMAL] JSHintBear:
|    | 'target' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|2941| »   »   »   »   »   »   »   »   if·(cmpResourceDropsite·&&·this.CanReturnResource(target,·true))
|    | [NORMAL] JSHintBear:
|    | 'target' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|2956| »   »   »   »   »   »   »   »   »   var·cmpHolderPosition·=·Engine.QueryInterface(target,·IID_Position);
|    | [NORMAL] JSHintBear:
|    | 'target' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|2957| »   »   »   »   »   »   »   »   »   var·cmpHolderUnitAI·=·Engine.QueryInterface(target,·IID_UnitAI);
|    | [NORMAL] JSHintBear:
|    | 'target' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|2984| »   »   »   »   »   »   »   if·(this.MoveToTarget(target))
|    | [NORMAL] JSHintBear:
|    | 'target' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|3746| »   »   var·order·=·{·"type":·type,·"data":·data·};
|    | [NORMAL] JSHintBear:
|    | 'order' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|3815| »   for·(var·i·=·0;·i·<·this.orderQueue.length;·++i)
|    | [NORMAL] JSHintBear:
|    | 'i' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|4087| »   let·cmpPosition·=·Engine.QueryInterface(this.entity,·IID_Position)
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.

binaries/data/mods/public/simulation/components/UnitAI.js
|4340| »   »   var·parabolicMaxRange·=·0;
|    | [NORMAL] JSHintBear:
|    | 'parabolicMaxRange' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|4344| »   var·guessedMaxRange·=·(range.max·+·parabolicMaxRange)/2;
|    | [NORMAL] JSHintBear:
|    | 'parabolicMaxRange' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4351| »   return·cmpUnitMotion.MoveToTargetRange(target,·range.min,·Math.min(range.max,·parabolicMaxRange));
|    | [NORMAL] JSHintBear:
|    | 'parabolicMaxRange' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4407| »   »   »   &&·cmpFormationUnitAI.order.data.target·==·target)
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|4575| »   »   &&·this.CheckTargetDistanceFromHeldPosition(target,·IID_Attack,·this.GetBestAttackAgainst(target,·true))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|4576| »   »   &&·(this.GetStance().respondChaseBeyondVision·||·this.CheckTargetIsInVisionRange(target))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5102| »   var·lastPos·=·undefined;
|    | [NORMAL] JSHintBear:
|    | It's not necessary to initialize 'lastPos' to 'undefined'.

binaries/data/mods/public/simulation/components/UnitAI.js
|5456| »   »   »   »   »   »   &&·!MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.attack))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5459| »   »   »   »   »   »   &&·MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.avoid))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5472| »   var·targets·=·this.GetTargetsFromUnit();
|    | [NORMAL] JSHintBear:
|    | 'targets' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5473| »   for·(var·targ·of·targets)
|    | [NORMAL] JSHintBear:
|    | 'targ' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5479| »   »   »   var·cmpIdentity·=·Engine.QueryInterface(targ,·IID_Identity);
|    | [NORMAL] JSHintBear:
|    | 'cmpIdentity' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5480| »   »   »   var·targetClasses·=·this.order.data.targetClasses;
|    | [NORMAL] JSHintBear:
|    | 'targetClasses' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5482| »   »   »   »   &&·!MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.attack))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5485| »   »   »   »   &&·MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.avoid))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5560| »   »   var·cmpVision·=·Engine.QueryInterface(this.entity,·IID_Vision);
|    | [NORMAL] JSHintBear:
|    | 'cmpVision' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5563| »   »   var·range·=·cmpVision.GetRange();
|    | [NORMAL] JSHintBear:
|    | 'range' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5568| »   »   var·cmpRanged·=·Engine.QueryInterface(this.entity,·iid);
|    | [NORMAL] JSHintBear:
|    | 'cmpRanged' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5571| »   »   var·range·=·iid·!==·IID_Attack·?·cmpRanged.GetRange()·:·cmpRanged.GetFullAttackRange();
|    | [NORMAL] JSHintBear:
|    | 'range' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5571| »   »   var·range·=·iid·!==·IID_Attack·?·cmpRanged.GetRange()·:·cmpRanged.GetFullAttackRange();
|    | [MAJOR] JSHintBear:
|    | Too many errors. (93% scanned).

Link to build: https://jenkins.wildfiregames.com/job/differential/312/display/redirect

temple added a comment.EditedMar 26 2018, 1:57 AM
In D1403#57928, @mimo wrote:

Nonetheless, in ProductionQueue, units directly spawned garrisoned uses PerformGarrison, so the setting of IsGarrisoned should be done there instead of inside Garrison.

Done.

Another option would be to make ProductionQueue use Garrison. That should work (ref discussion on rP21564).

I didn't want to get into that since I wasn't sure about the concept of visible garrison points. Can we have them on production buildings, e.g. I think I've seen a screenshot with units on forts or civic centers. But the code doesn't seem to allow having visible garrison points only for some units, e.g. ranged units visible but then melee inside. So, I'll leave it for someone else to figure out.

And while testing, there is nonetheless a problem with promotion (not linked to the patch) which is that promoted units don't face towards the same direction as the initial one (usually the opposite direction, i don't understand why). The following patch would fix it. But it is maybe better to add the angle in CCmpPosition:SetTurrentParent?

I noticed that too, hadn't explored it yet. (The other thing I noticed was their selection rings are still on the ground, when maybe they should be offset vertically too. And garrisoning on a gate, should ignore collisions with the turret.)

There's a problem with my patch and promotion, since the garrisoning happens after the orders are replaced, so units will leave the GARRISON.GARRISONED state, ugh.

temple updated this revision to Diff 6277.Mar 26 2018, 6:43 PM
temple retitled this revision from SetGarrisoned when unit is garrisoned, remove autogarrison state to Set isGarrisoned when unit is autogarrisoned, remove autogarrison state.
temple edited the summary of this revision. (Show Details)

If we SetGarrisoned after the cheer order, then the cheer order will be processed and there's time for the turret parent to be set, so I think this works.

mimo accepted this revision.Mar 26 2018, 8:26 PM

Patch is good (including the removal of AutoGarrison state) and works as expected in my tests.
There is nonetheless a remaining test on AutoGarrison in gui/session.js which should now be removed.

This revision is now accepted and ready to land.Mar 26 2018, 8:26 PM
In D1403#58135, @mimo wrote:

There is nonetheless a remaining test on AutoGarrison in gui/session.js which should now be removed.

Thanks, and thanks for the discussion and review.

This revision was automatically updated to reflect the committed changes.
Owners added a subscriber: Restricted Owners Package.Mar 27 2018, 1:20 AM
In D1403#57928, @mimo wrote:

And while testing, there is nonetheless a problem with promotion (not linked to the patch) which is that promoted units don't face towards the same direction as the initial one (usually the opposite direction, i don't understand why). The following patch would fix it. But it is maybe better to add the angle in CCmpPosition:SetTurrentParent?

From CCmpPosition.cpp: "when the entity is a turret, only m_RotY is used, and this is the rotation relative to the parent entity". I can see why that's useful, but it causes some problems here. Units sometimes do a weird twirl when they first garrison, I'm guessing related to interpolation and that change in m_RotY meaning.

mimo added a comment.EditedMar 28 2018, 8:20 PM
In D1403#58155, @temple wrote:
In D1403#57928, @mimo wrote:

And while testing, there is nonetheless a problem with promotion (not linked to the patch) which is that promoted units don't face towards the same direction as the initial one (usually the opposite direction, i don't understand why). The following patch would fix it. But it is maybe better to add the angle in CCmpPosition:SetTurrentParent?

From CCmpPosition.cpp: "when the entity is a turret, only m_RotY is used, and this is the rotation relative to the parent entity". I can see why that's useful, but it causes some problems here. Units sometimes do a weird twirl when they first garrison, I'm guessing related to interpolation and that change in m_RotY meaning.

Yes, only the relative angle is used inside CCmpPosition. Then the approach in the uploaded patch should be fine. Having this half-turn rotation when promoting is really bad.

Edit: see in fact D1420