Page MenuHomeWildfire Games

Make commutative behaviour in the IsInRange function family and migrate them to a better home
Needs RevisionPublic

Authored by bb on Oct 24 2017, 6:39 PM.

Details

Reviewers
wraitii
Group Reviewers
Restricted Owners Package(Owns No Changed Paths)
Summary

The IsInRange function family is currently placed in the UnitMotion component. Which is stupid since, why does a range check depend on being able to move? These function might (and will be in some of my WIP's) become useful for buildings and other non-unitMotion entities. So we need to move these function to a better place.

This patch is based on D13 (at least a split of it) with wraitii's approval. There and here the functions are moved to the ObstructionManager, since that is a system component and these functions use some of that. However if someone proposes something better, we can ship with that. (Do notice that "position" is not really an option due to the isPointinPointRange function, which doesn't require it to be units. And we use this for some cases in the other functions.)

What is changed based on D13:

  • remove IsPointInTarget range, since that is a duplicate of IsInPoint range,
  • Add support for square to square checks,
  • Better support for sphere-square minrange
  • rounding fix instead of navcell
Test Plan

build and run tests
Make sure the squares and sqrt's doesn't case OOS'es
Comment on the new location.
Comment on the proposed behaviour
Proof or let proof the used identities in geometry (and make the comments updated if they are unclear).
Test attacking, healing, garrisoning etc. with min and max ranges
Let some airplane fly
see there are no overflows even on a giant map

Diff Detail

Repository
rP 0 A.D. Public Repository
Branch
/ps/trunk
Lint
Lint OK
Unit
No Unit Test Coverage
Build Status
Buildable 6272
Build 10408: Vulcan BuildJenkins
Build 10407: arc lint + arc unit

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
bb added a comment.Oct 30 2017, 10:15 PM

add const script interfaces

Executing section Default...
Executing section Source...
Executing section JS...

binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 182| »   »   »   var·targetHeight·=·ground·+·(+this.template.FlyingHeight);
|    | [NORMAL] JSHintBear:
|    | 'targetHeight' is already defined.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 310| »   for·(var·ent·of·unitAIs)
|    | [NORMAL] JSHintBear:
|    | 'ent' is already defined.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 313| »   for·(var·ent·of·unitAIs)
|    | [NORMAL] JSHintBear:
|    | 'ent' is already defined.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 305| »   »   TS_ASSERT_EQUALS(unitAI.fsmStateName,·"INDIVIDUAL.COMBAT.ATTACKING");
|    | [NORMAL] JSHintBear:
|    | 'unitAI' used out of scope.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 314| »   »   TS_ASSERT_EQUALS(unitAI.fsmStateName,·"INDIVIDUAL.COMBAT.ATTACKING");
|    | [NORMAL] JSHintBear:
|    | 'unitAI' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
| 363| »   »   ····&&·(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
|1923| »   »   »   »   »   »   var·cmpFormation·=·Engine.QueryInterface(this.formationController,·IID_Formation);
|    | [NORMAL] JSHintBear:
|    | 'cmpFormation' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2149| »   »   »   »   »   »   »   »   ·&&·((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
|2150| »   »   »   »   »   »   »   »   ·||·(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
|2151| »   »   »   »   »   »   »   »   ·&&·(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
|2174| »   »   »   »   »   »   »   »   var·nearby·=·this.FindNearestDropsite(oldType.generic);
|    | [NORMAL] JSHintBear:
|    | 'nearby' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2214| »   »   »   »   »   »   »   »   &&·((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
|2215| »   »   »   »   »   »   »   »   ||·(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
|2216| »   »   »   »   »   »   »   »   &&·(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
|2260| »   »   »   »   »   »   »   ||·(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
|2261| »   »   »   »   »   »   »   &&·(type.specific·!=·"meat"·||·resourceTemplate·==·template))
|    | [NORMAL] JSHintBear:
|    | Misleading line break bef

http://jenkins-master:8080/job/phabricator_lint/648/ for more details.

Build was aborted

Updating workspaces...
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDAnimation]’:
FCollada/FCDocument/FCDLibrary.cpp:149:30:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
  const T* cptr = ((const FCDLibrary<T>*)l1)->GetEntity(0);
           ^
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDAnimationClip]’:
FCollada/FCDocument/FCDLibrary.cpp:150:34:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDCamera]’:
FCollada/FCDocument/FCDLibrary.cpp:151:27:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDController]’:
FCollada/FCDocument/FCDLibrary.cpp:152:31:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDEffect]’:
FCollada/FCDocument/FCDLibrary.cpp:153:27:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDEmitter]’:
FCollada/FCDocument/FCDLibrary.cpp:154:28:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDForceField]’:
FCollada/FCDocument/FCDLibrary.cpp:155:31:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDGeometry]’:
FCollada/FCDocument/FCDLibrary.cpp:156:29:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDImage]’:
FCollada/FCDocument/FCDLibrary.cpp:157:26:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDLight]’:
FCollada/FCDocument/FCDLibrary.cpp:158:26:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDMaterial]’:
FCollada/FCDocument/FCDLibrary.cpp:159:29:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDSceneNode]’:
FCollada/FCDocument/FCDLibrary.cpp:160:30:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDPhysicsModel]’:
FCollada/FCDocument/FCDLibrary.cpp:161:33:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDPhysicsMaterial]’:
FCollada/FCDocument/FCDLibrary.cpp:162:36:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ s

Link to build: http://jenkins-master:8080/job/phabricator/2196/
See console output for more information: http://jenkins-master:8080/job/phabricator/2196/console

Itms added a subscriber: Itms.Oct 30 2017, 11:25 PM

The build got stuck for some reason when trying to apply the patch. It doesn't look like there is something wrong with the build scripts, the machine just got stuck 🤔 I am going to re-trigger the build.

Itms added a comment.Oct 30 2017, 11:54 PM

Sorry, the problem was between my keyboard and my chair: the build was too long for the taste of Jenkins and it colored it in red, so I thought it was stuck. I aborted it five minutes before completion or something...

The good news is that this is going to be the first build with Imarok's changes to the build output! If everything goes well, the result will be clean and tidy.

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

Updating workspaces...
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDAnimation]’:
FCollada/FCDocument/FCDLibrary.cpp:149:30:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
  const T* cptr = ((const FCDLibrary<T>*)l1)->GetEntity(0);
           ^
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDAnimationClip]’:
FCollada/FCDocument/FCDLibrary.cpp:150:34:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDCamera]’:
FCollada/FCDocument/FCDLibrary.cpp:151:27:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDController]’:
FCollada/FCDocument/FCDLibrary.cpp:152:31:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDEffect]’:
FCollada/FCDocument/FCDLibrary.cpp:153:27:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDEmitter]’:
FCollada/FCDocument/FCDLibrary.cpp:154:28:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDForceField]’:
FCollada/FCDocument/FCDLibrary.cpp:155:31:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDGeometry]’:
FCollada/FCDocument/FCDLibrary.cpp:156:29:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDImage]’:
FCollada/FCDocument/FCDLibrary.cpp:157:26:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDLight]’:
FCollada/FCDocument/FCDLibrary.cpp:158:26:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDMaterial]’:
FCollada/FCDocument/FCDLibrary.cpp:159:29:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDSceneNode]’:
FCollada/FCDocument/FCDLibrary.cpp:160:30:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDPhysicsModel]’:
FCollada/FCDocument/FCDLibrary.cpp:161:33:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ set but not used [-Wunused-but-set-variable]
FCollada/FCDocument/FCDLibrary.cpp: In instantiation of ‘void LibraryExport() [with T = FCDPhysicsMaterial]’:
FCollada/FCDocument/FCDLibrary.cpp:162:36:   required from here
FCollada/FCDocument/FCDLibrary.cpp:141:11: warning: variable ‘cptr’ s

http://jenkins-master:8080/job/phabricator/2197/ for more details.

fatherbushido added a subscriber: fatherbushido.EditedOct 31 2017, 8:24 AM

Do not agree on that fully, since splitting the move and behaviour change will result in changing EVERY line that needs to be changed in the unitMotion twice. Also the public mod code is changed twice almost every line. So only those helpers in geometry and fixedVector stuff are not changed twice. As a result we change about 1.75 times as many lines as we need to. I don't mind splitting patches at all (especially since this is a split already), but this split doesn't seem to have clear benefit.
When the split is required however please let me know.

I was interested by looking at that (just to have fun) but I was lazy to see what had changed and what hadn't (it's easier to compare than to read the two things :p) so I hadn't fun :)

/end{mylife}

temple added a subscriber: temple.Dec 1 2017, 12:21 AM
temple added inline comments.
source/simulation2/components/CCmpObstructionManager.cpp
713

What weirdness?

731

I didn't think we had circular obstructions? Are they planned?

source/simulation2/helpers/Geometry.h
129

Maybe "SquaredDistance..." rather than "Distance...Squared". (I'd say the same for JS vector functions.)

temple added inline comments.Dec 1 2017, 2:15 AM
source/simulation2/components/CCmpObstructionManager.cpp
732–733

I don't like this definition.
Rhetorical: What purpose does a minimum range have? Obviously if we can hit something 10m away we can hit something at 2m away, because to get to a point 10m away it has to travel through some point 2m away. So the minimum range is representing something abstract, like we don't have power or accuracy or something with nearby targets.
If we use opposite edge to opposite edge, then we're doing the 10m shot but going through the 2m point, and how can that work? We're shooting through the front wall of a building to hit the far wall? Or if we're a building, then we're shooting from the back wall through the living room to hit a target out front? It doesn't really make sense. (I don't see how you could get the "murder hole" technology to work with this, at least for square buildings.)

So I think we should use the closest distance for both the maximum and minimum range comparisons.

(I assume there's other things we'll have to figure out, e.g. I think attack uses the center of footprints, so we might have to change that, when attacking structures at least.)

source/simulation2/helpers/Geometry.cpp
192–193

Unless they're overlapping in a weird way (two rectangles in a cross), but that's unlikely to happen.

210–211

minus u2

wraitii added inline comments.Dec 1 2017, 7:27 AM
source/simulation2/components/CCmpObstructionManager.cpp
731

units are spherical.

wraitii added inline comments.Dec 1 2017, 11:21 AM
source/simulation2/components/CCmpObstructionManager.cpp
732–733

The issue is that I want commutative behaviour (i.e. the source and target order shouldn't always return the same even if swapped).

If I want commutative behaviour, we have a bad case for buildings vs units, as I wrote below (and indeed I describe this very issue in the comment L 756).

Take a catapult with a min-range. To attack a building, if we check from closest edge to closest edge, then the catapult needs to be some distance away. But maybe the building is really large and the far-side is easily inside our min-range.
That strikes me as a bit odd. It's generally what's be done in RTS, but I don't like it all that much.

That being said, buildings ought to fire from well-defined points so the issue is moot here.
And that being said too, I'm not opposed to changing this.

temple added inline comments.Dec 1 2017, 3:21 PM
source/simulation2/components/CCmpObstructionManager.cpp
731

I see the change in D13.

732–733

How can he hit the far edge without shooting through the near edge?

It would be nice to have an attack ground command.

Buildings having subobstructions or whatever for BuildingAI makes sense.

wraitii added inline comments.Dec 1 2017, 4:14 PM
source/simulation2/components/CCmpObstructionManager.cpp
731

Ah, that could very well be the case indeed.

732–733

How can he hit the far edge without shooting through the near edge?

Well, above, or it's a flat building. Not everything is a fortress.

I think in general we should avoid shape-shape range detections, and go shape->point which is much easier. But the shape-shape behaviour should be decided on.

wraitii requested changes to this revision.Dec 3 2017, 10:43 AM

@bb opinion on the above discussion?

I'm requesting changes as I think this warrant tests before committing, if we're going to do it properly.

This revision now requires changes to proceed.Dec 3 2017, 10:43 AM
bb added inline comments.Dec 4 2017, 12:47 PM
source/simulation2/components/CCmpObstructionManager.cpp
713

Mainly rounding errors, the position can be shifted a bit due to the navcell grid and in some edgy cases that could result in rough edges. Also f.e. when the minrange is 0 (thus attack always) and we are at the same position (thus distance =0), we should be in range, so we need a little threshold

732–733

The fact that buildings fire from well defined locations, should be fixed with using turrets when they are implemented

The murderholes tech would still work, we probably need to adjust the range a bit, we only take it from the opposite edge now.

There are indeed multiple views on this matter:

  1. Opposite edge allows us to shoot over buildings and hit the back, so we have a more true minrange.

    For having turrets, which have an offset on the obstruction it is usefull to get the whole ent inside some range, and that can be achieved easier (with messing with minranges and stuff) with this approach
  1. Shortest edge allows us to use the minrange for avoiding colliding animations too (has been suggested some time on forum, but can also be done with setting obstructions correctly).

    Probably more trivial in coding, and maintaining (but coding already done :P)
source/simulation2/helpers/Geometry.cpp
192–193

True, but do notice this is already counted as 0, since at least 1 corner will be inside the other square (and we set the last argument to true)

210–211

Woot woot

Opposite edge allows us to shoot over buildings and hit the back, so we have a more true minrange.

They don't shoot over, they shoot through! You have a catapult with 12m min range at the base of a 30x30m fort. If it can hit anywhere 12m+ away (or less if we go from the backside of the catapult too), then it can attack the fort sitting right in front of it, even though it's a huge wall. How does that make sense? Why even have a minimum range if that's what's going to happen?

Here's a picture of the different distance definitions, so we're on the same page.

source/simulation2/components/CCmpObstructionManager.cpp
713

navcellFix = 1.5m, which seems a lot for rounding errors! Swordsmen have a 2m max range!
We use true positions here so I'm not seeing how the navcell grid is relevant. What am I missing?

source/simulation2/helpers/Geometry.cpp
192–193

I'm saying if you have two long rectangles overlapping in a cross, like +, then they only overlap in the center, so none of the corners of one rectangle will be inside the other rectangle. It should be distance = 0 but instead will be something > 0. We won't often/ever have rectangles overlapping like this so it's not really a concern. (Units are circles, so rectangle vs rectangle would have to be something like fort vs fort, and they'll never overlap.)

They don't shoot over, they shoot through! You have a catapult with 12m min range at the base of a 30x30m fort. If it can hit anywhere 12m+ away (or less if we go from the backside of the catapult too), then it can attack the fort sitting right in front of it, even though it's a huge wall. How does that make sense? Why even have a minimum range if that's what's going to happen?

Well that makes sense to me, actually. The idea behind "min range" for catapults is that you can't actually fire something with enough power, given the way the catapult is shaped, to hit a few meters in front of you on the ground. You can totally hit a wall right in front of you though.
So you can hit a fortress, or a wall, but you can't hit a unit.

The problem here is that min-range represents something "realistic" that's rather awkward to translate in the game.

source/simulation2/components/CCmpObstructionManager.cpp
713

I'm pretty sure I added this because of some peculiarity I ran into when testing the D13 changes, but honestly I haven't documented why and I don't remember. I'd advise "remove it and see if it breaks things".

In D981#44096, @wraitii wrote:

They don't shoot over, they shoot through! You have a catapult with 12m min range at the base of a 30x30m fort. If it can hit anywhere 12m+ away (or less if we go from the backside of the catapult too), then it can attack the fort sitting right in front of it, even though it's a huge wall. How does that make sense? Why even have a minimum range if that's what's going to happen?

Well that makes sense to me, actually. The idea behind "min range" for catapults is that you can't actually fire something with enough power, given the way the catapult is shaped, to hit a few meters in front of you on the ground. You can totally hit a wall right in front of you though.
So you can hit a fortress, or a wall, but you can't hit a unit.

???
If you want heights to be included in the minimum range calculation then you should propose that. Currently, this patch says we can attack something if it's long and wide, but your argument in this comment is it's okay to attack something nearby because it's tall. The two have nothing to do with each other.

bb added a comment.Dec 5 2017, 4:50 PM

Do notice that also A22 doesn't take the centerpoint but does some strange non trivial calculation. Further exactly what wraitii says: with a min range you can't hit on the ground inside the minrange, but when firing anything you will always go through the 0m point (thus inside the min range). And if there is an obstruction you hit it, ok thats just physics.
So f.e. you have a cata 12m min range, and be out in the open. Then you won't stop firing also when there is a bird flying right in the minrange (You hit it, so what). Still the bird is killed ofc thus you can hit something inside your minrange, but it has to be in the air then.

And what is wrong about hitting a big wall right in your face? Ok you might damage yourself (but use splash for that), but the wall will also be damaged. (okay there could be an issue here with a small wall, that you can't attack from the position, but will hit through, but that is more an arrow collision problem imo)

Also see the situation that you are right next to a fort with your cata and try to hit a building at the other site? It will go through the fort and hit the other building. Isn't that just more odd?

source/simulation2/components/CCmpObstructionManager.cpp
713

These function tie in very tied with moving to a certain position, which ofc is based on the pathfinder and thus uses navcells

source/simulation2/helpers/Geometry.cpp
192–193

How could I miss that, we can simply test for TestSquareSquare avoiding this issue

temple added a comment.Dec 5 2017, 6:01 PM
In D981#44207, @bb wrote:

Do notice that also A22 doesn't take the centerpoint but does some strange non trivial calculation.

Yeah, I realized/remembered that after posting the picture. I even made a ticket #4585 about units attacking buildings in a square shape (seems the pictures have disappeared from my post in the forum).

Has the comment here been considered?

bool CCmpUnitMotion::IsInTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange) const
{
	// This function closely mirrors MoveToTargetRange - it needs to return true
	​// after that Move has completed

Further exactly what wraitii says: with a min range you can't hit on the ground inside the minrange, but when firing anything you will always go through the 0m point (thus inside the min range). And if there is an obstruction you hit it, ok thats just physics.

So f.e. you have a cata 12m min range, and be out in the open. Then you won't stop firing also when there is a bird flying right in the minrange (You hit it, so what). Still the bird is killed ofc thus you can hit something inside your minrange, but it has to be in the air then.

And what is wrong about hitting a big wall right in your face? Ok you might damage yourself (but use splash for that), but the wall will also be damaged. (okay there could be an issue here with a small wall, that you can't attack from the position, but will hit through, but that is more an arrow collision problem imo)

Also see the situation that you are right next to a fort with your cata and try to hit a building at the other site? It will go through the fort and hit the other building. Isn't that just more odd?

That would be odd too. It'd be nice if we couldn't shoot through walls or mountains.

My understanding is this is just saying whether a target's in range, we'll still aim the projectile at its center. So maybe changes to Attack (when attacking large buildings) are needed regardless of what's decided here.

Bolt shooters shoot at ground level but have an 8m minimum range, are there plans to change that? If/when secondary attacks are implemented, will archers etc. have a minimum range?

My general feeling is using farthest-point distances are going to make everything more complicated and confusing (e.g., using closest point we could set a tower's minimum range to be 4m before murder holes (and do the same for forts), whereas using the center point like we currently do is weird (see rP19747) and using the farthest point is going to be even more confusing -- and we'd have to change it for any civ that changes their tower's obstruction size). The only tiny benefit is this case of letting catapults attack buildings when they're right next to them, and that's not something that I agree with anyway. It would be much easier to just add an attack-ground command to solve that problem.

bb added a comment.Dec 8 2017, 11:43 PM
In D981#44251, @temple wrote:

Has the comment here been considered?

bool CCmpUnitMotion::IsInTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange) const
{
	// This function closely mirrors MoveToTargetRange - it needs to return true
	​// after that Move has completed

Well these range checks are the most conservative meaningful checks there are, thus it will still return true with this, though it is misleading and should be removed. Further D13 will change a lot regarding that, thus partially out of scope (but related ofc)

That would be odd too. It'd be nice if we couldn't shoot through walls or mountains.

Entirely agree that would be super-nice, but rather hard to implement sadly enough

My understanding is this is just saying whether a target's in range, we'll still aim the projectile at its center. So maybe changes to Attack (when attacking large buildings) are needed regardless of what's decided here.

Not opposed to changing that

Bolt shooters shoot at ground level but have an 8m minimum range, are there plans to change that?

The question is can they hit the ground inside the 8m range.

If/when secondary attacks are implemented, will archers etc. have a minimum range?

Can

My general feeling is using farthest-point distances are going to make everything more complicated and confusing (e.g., using closest point we could set a tower's minimum range to be 4m before murder holes (and do the same for forts), whereas using the center point like we currently do is weird (see rP19747) and using the farthest point is going to be even more confusing -- and we'd have to change it for any civ that changes their tower's obstruction size). The only tiny benefit is this case of letting catapults attack buildings when they're right next to them, and that's not something that I agree with anyway. It would be much easier to just add an attack-ground command to solve that problem.

But this also implies that a tower can't attack a siege unit parked at the towers foot, when its back is clearly outside the minrange, and that can't be fixed like "hitting the wall" instead of "tunneling through". Also as said with using subunits/turrets this approach is easier to code, and these would also solve the "shoot from back of building" issues. However the things you mention are the price to pay for that.

bb updated this revision to Diff 4675.Dec 9 2017, 8:56 PM
bb edited the summary of this revision. (Show Details)
bb edited the test plan for this revision. (Show Details)

Remove the squares due to overflows, fix the minus u2, make the distance 0 for crossed squares

Vulcan added a comment.Dec 9 2017, 9:54 PM

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

Updating workspaces...
Build (release)...
Build (debug)...
Running release tests...
Running cxxtest tests (308 tests)....................................................................................................................................................................................................................................................................................................................OK!
Running debug tests...
Running cxxtest tests (308 tests)....................................................................................................................................................................................................................................................................................................................OK!
Checking XML files...
Vulcan added a comment.Dec 9 2017, 9:55 PM
Executing section Default...
Executing section Source...
Executing section JS...

binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 182| »   »   »   var·targetHeight·=·ground·+·(+this.template.FlyingHeight);
|    | [NORMAL] JSHintBear:
|    | 'targetHeight' is already defined.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 310| »   for·(var·ent·of·unitAIs)
|    | [NORMAL] JSHintBear:
|    | 'ent' is already defined.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 313| »   for·(var·ent·of·unitAIs)
|    | [NORMAL] JSHintBear:
|    | 'ent' is already defined.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 305| »   »   TS_ASSERT_EQUALS(unitAI.fsmStateName,·"INDIVIDUAL.COMBAT.ATTACKING");
|    | [NORMAL] JSHintBear:
|    | 'unitAI' used out of scope.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 314| »   »   TS_ASSERT_EQUALS(unitAI.fsmStateName,·"INDIVIDUAL.COMBAT.ATTACKING");
|    | [NORMAL] JSHintBear:
|    | 'unitAI' used out of scope.

binaries/data/mods/public/simulation/components/UnitAI.js
| 356| »   »   ····&&·(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
|1906| »   »   »   »   »   »   var·cmpFormation·=·Engine.QueryInterface(this.formationController,·IID_Formation);
|    | [NORMAL] JSHintBear:
|    | 'cmpFormation' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2038| »   »   »   »   »   »   &&·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
|2122| »   »   »   »   »   »   »   »   ·&&·((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
|2123| »   »   »   »   »   »   »   »   ·||·(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
|2124| »   »   »   »   »   »   »   »   ·&&·(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
|2147| »   »   »   »   »   »   »   »   var·nearby·=·this.FindNearestDropsite(oldType.generic);
|    | [NORMAL] JSHintBear:
|    | 'nearby' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2187| »   »   »   »   »   »   »   »   &&·((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
|2188| »   »   »   »   »   »   »   »   ||·(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
|2189| »   »   »   »   »   »   »   »   &&·(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
|2233| »   »   »   »   »   »   »   ||·(type.specific·==·resourceType.specific
|    | [NOR

This is definitely a gameplay decision, but I personally side with the "farthest" as I think it's more flexible.

Then again, perhaps we should change how we handle attack range. Max range should be "how far can this reach before it hits the ground", and thus closest edge here makes sense. Min Range should perhaps be removed in favour of a linear "minimal height at X meters for this unit to hit". But that's more complicated.

I don't like it, but I guess I'm outvoted.

So we have towers and siege units with attacking minimum range. Are these functions used elsewhere with a minimum range (does Petra use it?), and is the new definition okay in those places?

elexis added a subscriber: elexis.Dec 10 2017, 4:39 PM

Can someone retitle this to reflect the gamedesign change?

bb added a comment.Dec 11 2017, 1:36 PM
In D981#45615, @temple wrote:

So we have towers and siege units with attacking minimum range. Are these functions used elsewhere with a minimum range (does Petra use it?), and is the new definition okay in those places?

They are directly used for healing and garrisoning too (but I believe they don't have any set minranges)
But via unitmotion they are used for about any move.

Thus you might have a point in using the shortest distance regarding fleeing...

bb retitled this revision from Migrate IsInRange function family to a better home to Make commutative behaviour in the IsInRange function family and migrate them to a better home.Dec 11 2017, 1:37 PM
wraitii added a reviewer: Restricted Owners Package.Dec 17 2017, 1:41 PM
bb updated this revision to Diff 4899.Dec 23 2017, 12:33 AM

Split the distance calculations from the checks and add a opposite option, so we can still use this for fleeing.

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

Updating workspaces...
Build (release)...
Build (debug)...
Running release tests...
Running cxxtest tests (308 tests)....................................................................................................................................................................................................................................................................................................................OK!
Running debug tests...
Running cxxtest tests (308 tests)....................................................................................................................................................................................................................................................................................................................OK!
Checking XML files...
Executing section Default...
Executing section Source...
Executing section JS...

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 310| »   for·(var·ent·of·unitAIs)
|    | [NORMAL] JSHintBear:
|    | 'ent' is already defined.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 313| »   for·(var·ent·of·unitAIs)
|    | [NORMAL] JSHintBear:
|    | 'ent' is already defined.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 305| »   »   TS_ASSERT_EQUALS(unitAI.fsmStateName,·"INDIVIDUAL.COMBAT.ATTACKING");
|    | [NORMAL] JSHintBear:
|    | 'unitAI' used out of scope.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 314| »   »   TS_ASSERT_EQUALS(unitAI.fsmStateName,·"INDIVIDUAL.COMBAT.ATTACKING");
|    | [NORMAL] JSHintBear:
|    | 'unitAI' used out of scope.

binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 182| »   »   »   var·targetHeight·=·ground·+·(+this.template.FlyingHeight);
|    | [NORMAL] JSHintBear:
|    | 'targetHeight' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
| 356| »   »   ····&&·(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
|1908| »   »   »   »   »   »   var·cmpFormation·=·Engine.QueryInterface(this.formationController,·IID_Formation);
|    | [NORMAL] JSHintBear:
|    | 'cmpFormation' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2040| »   »   »   »   »   »   &&·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
|2124| »   »   »   »   »   »   »   »   ·&&·((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
|2125| »   »   »   »   »   »   »   »   ·||·(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
|2126| »   »   »   »   »   »   »   »   ·&&·(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
|2149| »   »   »   »   »   »   »   »   var·nearby·=·this.FindNearestDropsite(oldType.generic);
|    | [NORMAL] JSHintBear:
|    | 'nearby' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2189| »   »   »   »   »   »   »   »   &&·((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
|2190| »   »   »   »   »   »   »   »   ||·(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
|2191| »   »   »   »   »   »   »   »   &&·(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
|2235| »   »   »   »   »   »   »   ||·(type.specific·==·resourceType.specific
|    | [NOR
bb added a comment.Dec 23 2017, 2:39 PM

A bug I notice when testing is that units move closer to the building than is required by this check, that could be abused by players who order the units directly to the maxrange point and attack directly (units will attack from there). Fixing this needs to rewrite the unitmotion...

A bug I notice when testing is that units move closer to the building than is required by this check, that could be abused by players who order the units directly to the maxrange point and attack directly (units will attack from there). Fixing this needs to rewrite the unitmotion...

This is addressed in D13 by switching most cases of "MoveCompleted" to instances of Timer. Which I guess could be done easily for SVN too.

bb added a comment.Dec 23 2017, 4:07 PM

Don't know exactly what is done in D13, but the current problem is that unitmotion just goes to the "wrong" point, so fixing that with some unitAI hiding crap, looks even worse too me (nothing breaks, just some unit move more than they have to).

In D981#46964, @bb wrote:

Don't know exactly what is done in D13, but the current problem is that unitmotion just goes to the "wrong" point, so fixing that with some unitAI hiding crap, looks even worse too me (nothing breaks, just some unit move more than they have to).

The behaviour here is/ought to be unitAI driven. The unit tries to go towards the building, and unitAI stops when it thinks it's there. Thus how D13 handles it on a timer: check every few turns if we're there yet and if so do the action, don't rely on unitMotion (which shouldn't be concerned with this).

bb added a comment.Dec 23 2017, 4:23 PM

That might be what D13 unitmotion expects, but now the unitmotion triex to go to a point which is wrong, so I let this issue be handled by D13.

bb updated this revision to Diff 5230.Jan 11 2018, 8:05 PM
bb edited the summary of this revision. (Show Details)

Should have listened to @temple, the navcellfix is causing the bug noticed above, removing it doesn't seem to break (tested with small maxRanges and small differece between minRange and maxRange)

Do you mean that with current unitMotion the unit starts doing the thing right when they get in range (i.e. as fast as a player could do it?)

bb added a comment.Jan 12 2018, 5:55 PM

for maxrange: yes (minrange is a different story), or at least I didn't notice a difference

bb added a comment.Jan 12 2018, 6:48 PM

for maxrange: yes (minrange is a different story), or at least I didn't notice a difference

source/simulation2/helpers/Geometry.cpp
242–245

indentation

bb updated this revision to Diff 5580.Jan 30 2018, 1:12 AM

rebase and years

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

Updating workspaces...
Build (release)...
Build (debug)...
Running release tests...
Running cxxtest tests (309 tests).....................................................................................................................................................................................................................................................................................................................OK!
Running debug tests...
Running cxxtest tests (309 tests).....................................................................................................................................................................................................................................................................................................................OK!
Checking XML files...
Executing section Default...
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPassabilityClass' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/phabricator_lint/binaries/data/mods/public/simulation/components/tests/test_UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/phabricator_lint/binaries/data/mods/public/simulation/components/tests/test_UnitMotionFlying.js
|   8|   8| let height = 5;
|   9|   9| 
|  10|  10| AddMock(SYSTEM_ENTITY, IID_Pathfinder, {
|  11|    |-	GetPassabilityClass: (name) => 1 << 8
|    |  11|+	"GetPassabilityClass": (name) => 1 << 8
|  12|  12| });
|  13|  13| 
|  14|  14| let cmpUnitMotionFlying = ConstructComponent(entity, "UnitMotionFlying", {

binaries/data/mods/public/simulation/components/tests/test_UnitMotionFlying.js
|  46| »   "SetHeightFixed":·(y)·=>·height·=·y,
|    | [NORMAL] ESLintBear (no-return-assign):
|    | Arrow function should not return assignment.
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/phabricator_lint/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/phabricator_lint/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|  74|  74| 	var newangle = angle;
|  75|  75| 	var canTurn = true;
|  76|  76| 	if (this.landing)
|  77|    |-	{
|    |  77|+	
|  78|  78| 		if (this.speed > 0 && this.onGround)
|  79|  79| 		{
|  80|  80| 			if (pos.y <= cmpWaterManager.GetWaterLevel(pos.x, pos.z) && this.template.DiesInWater == "true")
| 153| 153| 					this.waterDeath = true;
| 154| 154| 			}
| 155| 155| 		}
| 156|    |-	}
|    | 156|+	
| 157| 157| 	else
| 158| 158| 	{
| 159| 159| 		// If we haven't reached max speed yet then we're still on the ground;
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/phabricator_lint/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/phabricator_lint/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|  93|  93| 				pos.y = Math.max(ground, pos.y - turnLength * this.template.ClimbRate);
|  94|  94| 		}
|  95|  95| 		else if (this.speed == 0 && this.onGround)
|  96|    |-		{
|    |  96|+		
|  97|  97| 			if (this.waterDeath && cmpHealth)
|  98|  98| 				cmpHealth.Kill();
|  99|  99| 			else
| 128| 128| 					newangle += Math.PI;
| 129| 129| 				}
| 130| 130| 			}
| 131|    |-		}
|    | 131|+		
| 132| 132| 		else
| 133| 133| 		{
| 134| 134| 			// Final Approach
|    | [NORMAL] ESLintBear (comma-spacing):
|    | A space is required after ','.
|----|    | /mnt/data/jenkins-phabricator/workspace/phabricator_lint/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/phabricator_lint/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 101| 101| 				this.pitch = 0;
| 102| 102| 				// We've stopped.
| 103| 103| 				if (cmpGarrisonHolder)
| 104|    |-					cmpGarrisonHolder.AllowGarrisoning(true,"UnitMotionFlying");
|    | 104|+					cmpGarrisonHolder.AllowGarrisoning(true, "UnitMotionFlying");
| 105| 105| 				canTurn = false;
| 106| 106| 				this.hasTarget = false;
| 107| 107| 				this.landing = false;
|    | [NORMAL] ESLintBear (space-unary-ops):
|    | Unexpected space after unary operator '-'.
|----|    | /mnt/data/jenkins-phabricator/workspace/phabricator_lint/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/phabricator_lint/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 138| 138| 			var targetHeight = ground;
| 139| 139| 			// Steep, then gradual descent.
| 140| 140| 			if ((pos.y - targetHeight) / this.template.FlyingHeight > 1 / SHORT_FINAL)
| 141|    |-				this.pitch = - Math.PI / 18;
|    | 141|+				this.pitch = -Math.PI / 18;
| 142| 1
wraitii requested changes to this revision.May 5 2018, 3:17 PM

@bb Add some tests and I'll approve this.

This revision now requires changes to proceed.May 5 2018, 3:17 PM

I think (haven't tested precisely as it's annoying) your DistanceBetweenShapes function is slightly (about fixed::Epsilon * 100) inconsistent with PathGoal::NearestPointOnGoal for non-AA square goals. This is a annoying, but it sounds difficult to fix.

The problem is that D13 requires the range checks to be at least as permissive as whatever MakeGoalReachable returns, and that uses PathGoal::NearestPointOnGoal.
I think it'd still be good to add a small buffer to IsInRange checks (maybe not the distance checks themselves), about 0.01.

Addendum: well while the above still seems true, another problem is that makeGoalReachable does not use a rounded rectangle but a flat one.

bb added a comment.Jun 28 2018, 5:03 PM
In D981#60827, @wraitii wrote:

Addendum: well while the above still seems true, another problem is that makeGoalReachable does not use a rounded rectangle but a flat one.

Don't see where is proposed code uses rounded rectangles.

In D981#60814, @wraitii wrote:

I think (haven't tested precisely as it's annoying) your DistanceBetweenShapes function is slightly (about fixed::Epsilon * 100) inconsistent with PathGoal::NearestPointOnGoal for non-AA square goals. This is a annoying, but it sounds difficult to fix.

The problem is that D13 requires the range checks to be at least as permissive as whatever MakeGoalReachable returns, and that uses PathGoal::NearestPointOnGoal.

One should be careful with such demands as obstructions can change during walking the path (buildings can be destroyed/build), but that is more a D13 concern.

I think it'd still be good to add a small buffer to IsInRange checks (maybe not the distance checks themselves), about 0.01.

As proven by the tests rounding errors can occur, so we indeed need a small buffer (only just smaller than proposed previously), absolutely disliking the magnicness of it

bb updated this revision to Diff 6792.Jun 28 2018, 5:03 PM
bb edited the summary of this revision. (Show Details)

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

Linter detected issues:
Executing section Default...
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPassabilityClass' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitMotionFlying.js
|   8|   8| let height = 5;
|   9|   9| 
|  10|  10| AddMock(SYSTEM_ENTITY, IID_Pathfinder, {
|  11|    |-	GetPassabilityClass: (name) => 1 << 8
|    |  11|+	"GetPassabilityClass": (name) => 1 << 8
|  12|  12| });
|  13|  13| 
|  14|  14| let cmpUnitMotionFlying = ConstructComponent(entity, "UnitMotionFlying", {

binaries/data/mods/public/simulation/components/tests/test_UnitMotionFlying.js
|  46| »   "SetHeightFixed":·(y)·=>·height·=·y,
|    | [NORMAL] ESLintBear (no-return-assign):
|    | Arrow function should not return assignment.
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|  74|  74| 	var newangle = angle;
|  75|  75| 	var canTurn = true;
|  76|  76| 	if (this.landing)
|  77|    |-	{
|    |  77|+	
|  78|  78| 		if (this.speed > 0 && this.onGround)
|  79|  79| 		{
|  80|  80| 			if (pos.y <= cmpWaterManager.GetWaterLevel(pos.x, pos.z) && this.template.DiesInWater == "true")
| 153| 153| 					this.waterDeath = true;
| 154| 154| 			}
| 155| 155| 		}
| 156|    |-	}
|    | 156|+	
| 157| 157| 	else
| 158| 158| 	{
| 159| 159| 		// If we haven't reached max speed yet then we're still on the ground;
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|  93|  93| 				pos.y = Math.max(ground, pos.y - turnLength * this.template.ClimbRate);
|  94|  94| 		}
|  95|  95| 		else if (this.speed == 0 && this.onGround)
|  96|    |-		{
|    |  96|+		
|  97|  97| 			if (this.waterDeath && cmpHealth)
|  98|  98| 				cmpHealth.Kill();
|  99|  99| 			else
| 128| 128| 					newangle += Math.PI;
| 129| 129| 				}
| 130| 130| 			}
| 131|    |-		}
|    | 131|+		
| 132| 132| 		else
| 133| 133| 		{
| 134| 134| 			// Final Approach
|    | [NORMAL] ESLintBear (comma-spacing):
|    | A space is required after ','.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 101| 101| 				this.pitch = 0;
| 102| 102| 				// We've stopped.
| 103| 103| 				if (cmpGarrisonHolder)
| 104|    |-					cmpGarrisonHolder.AllowGarrisoning(true,"UnitMotionFlying");
|    | 104|+					cmpGarrisonHolder.AllowGarrisoning(true, "UnitMotionFlying");
| 105| 105| 				canTurn = false;
| 106| 106| 				this.hasTarget = false;
| 107| 107| 				this.landing = false;
|    | [NORMAL] ESLintBear (space-unary-ops):
|    | Unexpected space after unary operator '-'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 138| 138| 			var targetHeight = ground;
| 139| 139| 			// Steep, then gradual descent.
| 140| 140| 			if ((pos.y - targetHeight) / this.template.FlyingHeight > 1 / SHORT_FINAL)
| 141|    |-				this.pitch = - Math.PI / 18;
|    | 141|+				this.pitch = -Math.PI / 18;
| 142| 142| 			else
| 143| 143| 				this.pitch = Math.PI / 18;
| 144| 144| 			var descentRate = ((pos.y - targetHeight) / this.template.FlyingHeight * this.template.ClimbRate + SHORT_FINAL) * SHORT_FINAL;
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 155| 155| 		}
| 156| 156| 	}
| 157| 157| 	else
| 158|    |-	{
|    | 158|+	
| 159| 159| 		// If we haven't reached max speed yet then we're still on the ground;
| 160| 160| 		// otherwise we're taking off or flying
| 161| 161| 		// this.onGround in case of a go-around after landing (but not fully stopped)
| 195| 195| 				this.pitch = -1 * this.pitch;
| 196| 196| 			}
| 197| 197| 		}
| 198|    |-	}
|    | 198|+	
| 199| 199| 
| 200| 200| 	// If we're in range of the target then tell people that we've reached it
| 201| 201| 	// (TODO: quantisation breaks this)
|    | [NORMAL] ESLintBear (comma-spacing):
|    | A space is required after ','.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 163| 163| 		if (this.speed < this.template.TakeoffSpeed && this.onGround)
| 164| 164| 		{
| 165| 165| 			if (cmpGarrisonHolder)
| 166|    |-				cmpGarrisonHolder.AllowGarrisoning(false,"UnitMotionFlying");
|    | 166|+				cmpGarrisonHolder.AllowGarrisoning(false, "UnitMotionFlying");
| 167| 167| 			this.pitch = 0;
| 168| 168| 			// Accelerate forwards
| 169| 169| 			this.speed = Math.min(this.template.MaxSpeed, this.speed + turnLength * this.template.AccelRate);
|    | [NORMAL] ESLintBear (space-unary-ops):
|    | Unexpected space after unary operator '-'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 230| 230| 		if (newangle - angle > Math.PI / 18)
| 231| 231| 			this.roll = Math.PI / 9;
| 232| 232| 		else if (newangle - angle < -Math.PI / 18)
| 233|    |-			this.roll = - Math.PI / 9;
|    | 233|+			this.roll = -Math.PI / 9;
| 234| 234| 		else
| 235| 235| 			this.roll = newangle - angle;
| 236| 236| 	}
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 318| 318| 
| 319| 319| UnitMotionFlying.prototype.StopMoving = function()
| 320| 320| {
| 321|    |-	//Invert
|    | 321|+	// Invert
| 322| 322| 	if (!this.waterDeath)
| 323| 323| 		this.landing = !this.landing;
| 324| 324| 

binaries/data/mods/public/simulation/components/UnitMotionFlying.js
| 182| »   »   »   var·targetHeight·=·ground·+·(+this.template.FlyingHeight);
|    | [NORMAL] JSHintBear:
|    | 'targetHeight' is already defined.
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'SetInterval' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  34|  34| 
|  35|  35| 
|  36|  36| 	AddMock(SYSTEM_ENTITY, IID_Timer, {
|  37|    |-		SetInterval: function() { },
|    |  37|+		"SetInterval": function() { },
|  38|  38| 		SetTimeout: function() { },
|  39|  39| 	});
|  40|  40| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'SetTimeout' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  35|  35| 
|  36|  36| 	AddMock(SYSTEM_ENTITY, IID_Timer, {
|  37|  37| 		SetInterval: function() { },
|  38|    |-		SetTimeout: function() { },
|    |  38|+		"SetTimeout": function() { },
|  39|  39| 	});
|  40|  40| 
|  41|  41| 	AddMock(SYSTEM_ENTITY, IID_RangeManager, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'CreateActiveQuery' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  39|  39| 	});
|  40|  40| 
|  41|  41| 	AddMock(SYSTEM_ENTITY, IID_RangeManager, {
|  42|    |-		CreateActiveQuery: function(ent, minRange, maxRange, players, iid, flags) {
|    |  42|+		"CreateActiveQuery": function(ent, minRange, maxRange, players, iid, flags) {
|  43|  43| 			return 1;
|  44|  44| 		},
|  45|  45| 		EnableActiveQuery: function(id) { },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'EnableActiveQuery' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  42|  42| 		CreateActiveQuery: function(ent, minRange, maxRange, players, iid, flags) {
|  43|  43| 			return 1;
|  44|  44| 		},
|  45|    |-		EnableActiveQuery: function(id) { },
|    |  45|+		"EnableActiveQuery": function(id) { },
|  46|  46| 		ResetActiveQuery: function(id) { if (mode == 0) return []; else return [enemy]; },
|  47|  47| 		DisableActiveQuery: function(id) { },
|  48|  48| 		GetEntityFlagMask: function(identifier) { },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'ResetActiveQuery' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  43|  43| 			return 1;
|  44|  44| 		},
|  45|  45| 		EnableActiveQuery: function(id) { },
|  46|    |-		ResetActiveQuery: function(id) { if (mode == 0) return []; else return [enemy]; },
|    |  46|+		"ResetActiveQuery": function(id) { if (mode == 0) return []; else return [enemy]; },
|  47|  47| 		DisableActiveQuery: function(id) { },
|  48|  48| 		GetEntityFlagMask: function(identifier) { },
|  49|  49| 	});
|    | [NORMAL] ESLintBear (no-else-return):
|    | Unnecessary 'else' after 'return'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  43|  43| 			return 1;
|  44|  44| 		},
|  45|  45| 		EnableActiveQuery: function(id) { },
|  46|    |-		ResetActiveQuery: function(id) { if (mode == 0) return []; else return [enemy]; },
|    |  46|+		ResetActiveQuery: function(id) { if (mode == 0) return []; return [enemy]; },
|  47|  47| 		DisableActiveQuery: function(id) { },
|  48|  48| 		GetEntityFlagMask: function(identifier) { },
|  49|  49| 	});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'DisableActiveQuery' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  44|  44| 		},
|  45|  45| 		EnableActiveQuery: function(id) { },
|  46|  46| 		ResetActiveQuery: function(id) { if (mode == 0) return []; else return [enemy]; },
|  47|    |-		DisableActiveQuery: function(id) { },
|    |  47|+		"DisableActiveQuery": function(id) { },
|  48|  48| 		GetEntityFlagMask: function(identifier) { },
|  49|  49| 	});
|  50|  50| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetEntityFlagMask' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  45|  45| 		EnableActiveQuery: function(id) { },
|  46|  46| 		ResetActiveQuery: function(id) { if (mode == 0) return []; else return [enemy]; },
|  47|  47| 		DisableActiveQuery: function(id) { },
|  48|    |-		GetEntityFlagMask: function(identifier) { },
|    |  48|+		"GetEntityFlagMask": function(identifier) { },
|  49|  49| 	});
|  50|  50| 
|  51|  51| 	AddMock(SYSTEM_ENTITY, IID_TemplateManager, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetCurrentTemplateName' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  49|  49| 	});
|  50|  50| 
|  51|  51| 	AddMock(SYSTEM_ENTITY, IID_TemplateManager, {
|  52|    |-		GetCurrentTemplateName: function(ent) { return "special/formations/line_closed"; },
|    |  52|+		"GetCurrentTemplateName": function(ent) { return "special/formations/line_closed"; },
|  53|  53| 	});
|  54|  54| 
|  55|  55| 	AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPlayerByID' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  53|  53| 	});
|  54|  54| 
|  55|  55| 	AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
|  56|    |-		GetPlayerByID: function(id) { return playerEntity; },
|    |  56|+		"GetPlayerByID": function(id) { return playerEntity; },
|  57|  57| 		GetNumPlayers: function() { return 2; },
|  58|  58| 	});
|  59|  59| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetNumPlayers' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  54|  54| 
|  55|  55| 	AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
|  56|  56| 		GetPlayerByID: function(id) { return playerEntity; },
|  57|    |-		GetNumPlayers: function() { return 2; },
|    |  57|+		"GetNumPlayers": function() { return 2; },
|  58|  58| 	});
|  59|  59| 
|  60|  60| 	AddMock(playerEntity, IID_Player, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'IsAlly' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  58|  58| 	});
|  59|  59| 
|  60|  60| 	AddMock(playerEntity, IID_Player, {
|  61|    |-		IsAlly: function() { return false; },
|    |  61|+		"IsAlly": function() { return false; },
|  62|  62| 		IsEnemy: function() { return true; },
|  63|  63| 		GetEnemies: function() { return []; },
|  64|  64| 	});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'IsEnemy' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  59|  59| 
|  60|  60| 	AddMock(playerEntity, IID_Player, {
|  61|  61| 		IsAlly: function() { return false; },
|  62|    |-		IsEnemy: function() { return true; },
|    |  62|+		"IsEnemy": function() { return true; },
|  63|  63| 		GetEnemies: function() { return []; },
|  64|  64| 	});
|  65|  65| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetEnemies' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  60|  60| 	AddMock(playerEntity, IID_Player, {
|  61|  61| 		IsAlly: function() { return false; },
|  62|  62| 		IsEnemy: function() { return true; },
|  63|    |-		GetEnemies: function() { return []; },
|    |  63|+		"GetEnemies": function() { return []; },
|  64|  64| 	});
|  65|  65| 
|  66|  66| 	AddMock(SYSTEM_ENTITY, IID_ObstructionManager, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'IsInTargetRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  64|  64| 	});
|  65|  65| 
|  66|  66| 	AddMock(SYSTEM_ENTITY, IID_ObstructionManager, {
|  67|    |-		IsInTargetRange: function(ent, target, min, max, opposite) { return true; }
|    |  67|+		"IsInTargetRange": function(ent, target, min, max, opposite) { return true; }
|  68|  68| 	});
|  69|  69| 
|  70|  70| 	var unitAI = ConstructComponent(unit, "UnitAI", { "FormationController": "false", "DefaultStance": "aggressive" });
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetClassesList' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  70|  70| 	var unitAI = ConstructComponent(unit, "UnitAI", { "FormationController": "false", "DefaultStance": "aggressive" });
|  71|  71| 
|  72|  72| 	AddMock(unit, IID_Identity, {
|  73|    |-		GetClassesList: function() { return []; },
|    |  73|+		"GetClassesList": function() { return []; },
|  74|  74| 	});
|  75|  75| 
|  76|  76| 	AddMock(unit, IID_Ownership, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetOwner' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  74|  74| 	});
|  75|  75| 
|  76|  76| 	AddMock(unit, IID_Ownership, {
|  77|    |-		GetOwner: function() { return 1; },
|    |  77|+		"GetOwner": function() { return 1; },
|  78|  78| 	});
|  79|  79| 
|  80|  80| 	AddMock(unit, IID_Position, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetTurretParent' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  78|  78| 	});
|  79|  79| 
|  80|  80| 	AddMock(unit, IID_Position, {
|  81|    |-		GetTurretParent: function() { return INVALID_ENTITY; },
|    |  81|+		"GetTurretParent": function() { return INVALID_ENTITY; },
|  82|  82| 		GetPosition: function() { return new Vector3D(); },
|  83|  83| 		GetPosition2D: function() { return new Vector2D(); },
|  84|  84| 		GetRotation: function() { return { "y": 0 }; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPosition' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  79|  79| 
|  80|  80| 	AddMock(unit, IID_Position, {
|  81|  81| 		GetTurretParent: function() { return INVALID_ENTITY; },
|  82|    |-		GetPosition: function() { return new Vector3D(); },
|    |  82|+		"GetPosition": function() { return new Vector3D(); },
|  83|  83| 		GetPosition2D: function() { return new Vector2D(); },
|  84|  84| 		GetRotation: function() { return { "y": 0 }; },
|  85|  85| 		IsInWorld: function() { return true; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPosition2D' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  80|  80| 	AddMock(unit, IID_Position, {
|  81|  81| 		GetTurretParent: function() { return INVALID_ENTITY; },
|  82|  82| 		GetPosition: function() { return new Vector3D(); },
|  83|    |-		GetPosition2D: function() { return new Vector2D(); },
|    |  83|+		"GetPosition2D": function() { return new Vector2D(); },
|  84|  84| 		GetRotation: function() { return { "y": 0 }; },
|  85|  85| 		IsInWorld: function() { return true; },
|  86|  86| 	});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetRotation' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  81|  81| 		GetTurretParent: function() { return INVALID_ENTITY; },
|  82|  82| 		GetPosition: function() { return new Vector3D(); },
|  83|  83| 		GetPosition2D: function() { return new Vector2D(); },
|  84|    |-		GetRotation: function() { return { "y": 0 }; },
|    |  84|+		"GetRotation": function() { return { "y": 0 }; },
|  85|  85| 		IsInWorld: function() { return true; },
|  86|  86| 	});
|  87|  87| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'IsInWorld' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  82|  82| 		GetPosition: function() { return new Vector3D(); },
|  83|  83| 		GetPosition2D: function() { return new Vector2D(); },
|  84|  84| 		GetRotation: function() { return { "y": 0 }; },
|  85|    |-		IsInWorld: function() { return true; },
|    |  85|+		"IsInWorld": function() { return true; },
|  86|  86| 	});
|  87|  87| 
|  88|  88| 	AddMock(unit, IID_UnitMotion, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetWalkSpeed' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  86|  86| 	});
|  87|  87| 
|  88|  88| 	AddMock(unit, IID_UnitMotion, {
|  89|    |-		GetWalkSpeed: function() { return 1; },
|    |  89|+		"GetWalkSpeed": function() { return 1; },
|  90|  90| 		MoveToFormationOffset: function(target, x, z) { },
|  91|  91| 		MoveToTargetRange: function(target, min, max) { },
|  92|  92| 		StopMoving: function() { },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'MoveToFormationOffset' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  87|  87| 
|  88|  88| 	AddMock(unit, IID_UnitMotion, {
|  89|  89| 		GetWalkSpeed: function() { return 1; },
|  90|    |-		MoveToFormationOffset: function(target, x, z) { },
|    |  90|+		"MoveToFormationOffset": function(target, x, z) { },
|  91|  91| 		MoveToTargetRange: function(target, min, max) { },
|  92|  92| 		StopMoving: function() { },
|  93|  93| 		GetPassabilityClassName: function() { return "default"; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'MoveToTargetRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  88|  88| 	AddMock(unit, IID_UnitMotion, {
|  89|  89| 		GetWalkSpeed: function() { return 1; },
|  90|  90| 		MoveToFormationOffset: function(target, x, z) { },
|  91|    |-		MoveToTargetRange: function(target, min, max) { },
|    |  91|+		"MoveToTargetRange": function(target, min, max) { },
|  92|  92| 		StopMoving: function() { },
|  93|  93| 		GetPassabilityClassName: function() { return "default"; },
|  94|  94| 	});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'StopMoving' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  89|  89| 		GetWalkSpeed: function() { return 1; },
|  90|  90| 		MoveToFormationOffset: function(target, x, z) { },
|  91|  91| 		MoveToTargetRange: function(target, min, max) { },
|  92|    |-		StopMoving: function() { },
|    |  92|+		"StopMoving": function() { },
|  93|  93| 		GetPassabilityClassName: function() { return "default"; },
|  94|  94| 	});
|  95|  95| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPassabilityClassName' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  90|  90| 		MoveToFormationOffset: function(target, x, z) { },
|  91|  91| 		MoveToTargetRange: function(target, min, max) { },
|  92|  92| 		StopMoving: function() { },
|  93|    |-		GetPassabilityClassName: function() { return "default"; },
|    |  93|+		"GetPassabilityClassName": function() { return "default"; },
|  94|  94| 	});
|  95|  95| 
|  96|  96| 	AddMock(unit, IID_Vision, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  94|  94| 	});
|  95|  95| 
|  96|  96| 	AddMock(unit, IID_Vision, {
|  97|    |-		GetRange: function() { return 10; },
|    |  97|+		"GetRange": function() { return 10; },
|  98|  98| 	});
|  99|  99| 
| 100| 100| 	AddMock(unit, IID_Attack, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  98|  98| 	});
|  99|  99| 
| 100| 100| 	AddMock(unit, IID_Attack, {
| 101|    |-		GetRange: function() { return { "max": 10, "min": 0}; },
|    | 101|+		"GetRange": function() { return { "max": 10, "min": 0}; },
| 102| 102| 		GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 103| 103| 		GetBestAttackAgainst: function(t) { return "melee"; },
| 104| 104| 		GetPreference: function(t) { return 0; },
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  98|  98| 	});
|  99|  99| 
| 100| 100| 	AddMock(unit, IID_Attack, {
| 101|    |-		GetRange: function() { return { "max": 10, "min": 0}; },
|    | 101|+		GetRange: function() { return { "max": 10, "min": 0 }; },
| 102| 102| 		GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 103| 103| 		GetBestAttackAgainst: function(t) { return "melee"; },
| 104| 104| 		GetPreference: function(t) { return 0; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetFullAttackRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  99|  99| 
| 100| 100| 	AddMock(unit, IID_Attack, {
| 101| 101| 		GetRange: function() { return { "max": 10, "min": 0}; },
| 102|    |-		GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
|    | 102|+		"GetFullAttackRange": function() { return { "max": 40, "min": 0}; },
| 103| 103| 		GetBestAttackAgainst: function(t) { return "melee"; },
| 104| 104| 		GetPreference: function(t) { return 0; },
| 105| 105| 		GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  99|  99| 
| 100| 100| 	AddMock(unit, IID_Attack, {
| 101| 101| 		GetRange: function() { return { "max": 10, "min": 0}; },
| 102|    |-		GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
|    | 102|+		GetFullAttackRange: function() { return { "max": 40, "min": 0 }; },
| 103| 103| 		GetBestAttackAgainst: function(t) { return "melee"; },
| 104| 104| 		GetPreference: function(t) { return 0; },
| 105| 105| 		GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetBestAttackAgainst' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 100| 100| 	AddMock(unit, IID_Attack, {
| 101| 101| 		GetRange: function() { return { "max": 10, "min": 0}; },
| 102| 102| 		GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 103|    |-		GetBestAttackAgainst: function(t) { return "melee"; },
|    | 103|+		"GetBestAttackAgainst": function(t) { return "melee"; },
| 104| 104| 		GetPreference: function(t) { return 0; },
| 105| 105| 		GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
| 106| 106| 		CanAttack: function(v) { return true; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPreference' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 101| 101| 		GetRange: function() { return { "max": 10, "min": 0}; },
| 102| 102| 		GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 103| 103| 		GetBestAttackAgainst: function(t) { return "melee"; },
| 104|    |-		GetPreference: function(t) { return 0; },
|    | 104|+		"GetPreference": function(t) { return 0; },
| 105| 105| 		GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
| 106| 106| 		CanAttack: function(v) { return true; },
| 107| 107| 		CompareEntitiesByPreference: function(a, b) { return 0; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetTimers' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 102| 102| 		GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 103| 103| 		GetBestAttackAgainst: function(t) { return "melee"; },
| 104| 104| 		GetPreference: function(t) { return 0; },
| 105|    |-		GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
|    | 105|+		"GetTimers": function() { return { "prepare": 500, "repeat": 1000 }; },
| 106| 106| 		CanAttack: function(v) { return true; },
| 107| 107| 		CompareEntitiesByPreference: function(a, b) { return 0; },
| 108| 108| 	});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'CanAttack' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 103| 103| 		GetBestAttackAgainst: function(t) { return "melee"; },
| 104| 104| 		GetPreference: function(t) { return 0; },
| 105| 105| 		GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
| 106|    |-		CanAttack: function(v) { return true; },
|    | 106|+		"CanAttack": function(v) { return true; },
| 107| 107| 		CompareEntitiesByPreference: function(a, b) { return 0; },
| 108| 108| 	});
| 109| 109| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'CompareEntitiesByPreference' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 104| 104| 		GetPreference: function(t) { return 0; },
| 105| 105| 		GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
| 106| 106| 		CanAttack: function(v) { return true; },
| 107|    |-		CompareEntitiesByPreference: function(a, b) { return 0; },
|    | 107|+		"CompareEntitiesByPreference": function(a, b) { return 0; },
| 108| 108| 	});
| 109| 109| 
| 110| 110| 	unitAI.OnCreate();
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetHitpoints' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 115| 115| 	if (mode == 1)
| 116| 116| 	{
| 117| 117| 		AddMock(enemy, IID_Health, {
| 118|    |-			GetHitpoints: function() { return 10; },
|    | 118|+			"GetHitpoints": function() { return 10; },
| 119| 119| 		});
| 120| 120| 		AddMock(enemy, IID_UnitAI, {
| 121| 121| 			IsAnimal: function() { return false; }
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'IsAnimal' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 118| 118| 			GetHitpoints: function() { return 10; },
| 119| 119| 		});
| 120| 120| 		AddMock(enemy, IID_UnitAI, {
| 121|    |-			IsAnimal: function() { return false; }
|    | 121|+			"IsAnimal": function() { return false; }
| 122| 122| 		});
| 123| 123| 	}
| 124| 124| 	else if (mode == 2)
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetHitpoints' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 123| 123| 	}
| 124| 124| 	else if (mode == 2)
| 125| 125| 		AddMock(enemy, IID_Health, {
| 126|    |-			GetHitpoints: function() { return 0; },
|    | 126|+			"GetHitpoints": function() { return 0; },
| 127| 127| 		});
| 128| 128| 
| 129| 129| 	var controllerFormation = ConstructComponent(controller, "Formation", {"FormationName": "Line Closed", "FormationShape": "square", "ShiftRows": "false", "SortingClasses": "", "WidthDepthRatio": 1, "UnitSeparationWidthMultiplier": 1, "UnitSeparationDepthMultiplier": 1, "SpeedMultiplier": 1, "Sloppyness": 0});
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 126| 126| 			GetHitpoints: function() { return 0; },
| 127| 127| 		});
| 128| 128| 
| 129|    |-	var controllerFormation = ConstructComponent(controller, "Formation", {"FormationName": "Line Closed", "FormationShape": "square", "ShiftRows": "false", "SortingClasses": "", "WidthDepthRatio": 1, "UnitSeparationWidthMultiplier": 1, "UnitSeparationDepthMultiplier": 1, "SpeedMultiplier": 1, "Sloppyness": 0});
|    | 129|+	var controllerFormation = ConstructComponent(controller, "Formation", { "FormationName": "Line Closed", "FormationShape": "square", "ShiftRows": "false", "SortingClasses": "", "WidthDepthRatio": 1, "UnitSeparationWidthMultiplier": 1, "UnitSeparationDepthMultiplier": 1, "SpeedMultiplier": 1, "Sloppyness": 0});
| 130| 130| 	var controllerAI = ConstructComponent(controller, "UnitAI", { "FormationController": "true", "DefaultStance": "aggressive" });
| 131| 131| 
| 132| 132| 	AddMock(controller, IID_Position, {
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 126| 126| 			GetHitpoints: function() { return 0; },
| 127| 127| 		});
| 128| 128| 
| 129|    |-	var controllerFormation = ConstructComponent(controller, "Formation", {"FormationName": "Line Closed", "FormationShape": "square", "ShiftRows": "false", "SortingClasses": "", "WidthDepthRatio": 1, "UnitSeparationWidthMultiplier": 1, "UnitSeparationDepthMultiplier": 1, "SpeedMultiplier": 1, "Sloppyness": 0});
|    | 129|+	var controllerFormation = ConstructComponent(controller, "Formation", {"FormationName": "Line Closed", "FormationShape": "square", "ShiftRows": "false", "SortingClasses": "", "WidthDepthRatio": 1, "UnitSeparationWidthMultiplier": 1, "UnitSeparationDepthMultiplier": 1, "SpeedMultiplier": 1, "Sloppyness": 0 });
| 130| 130| 	var controllerAI = ConstructComponent(controller, "UnitAI", { "FormationController": "true", "DefaultStance": "aggressive" });
| 131| 131| 
| 132| 132| 	AddMock(controller, IID_Position, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'JumpTo' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 130| 130| 	var controllerAI = ConstructComponent(controller, "UnitAI", { "FormationController": "true", "DefaultStance": "aggressive" });
| 131| 131| 
| 132| 132| 	AddMock(controller, IID_Position, {
| 133|    |-		JumpTo: function(x, z) { this.x = x; this.z = z; },
|    | 133|+		"JumpTo": function(x, z) { this.x = x; this.z = z; },
| 134| 134| 		GetTurretParent: function() { return INVALID_ENTITY; },
| 135| 135| 		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
| 136| 136| 		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetTurretParent' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 131| 131| 
| 132| 132| 	AddMock(controller, IID_Position, {
| 133| 133| 		JumpTo: function(x, z) { this.x = x; this.z = z; },
| 134|    |-		GetTurretParent: function() { return INVALID_ENTITY; },
|    | 134|+		"GetTurretParent": function() { return INVALID_ENTITY; },
| 135| 135| 		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
| 136| 136| 		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
| 137| 137| 		GetRotation: function() { return { "y": 0 }; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPosition' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 132| 132| 	AddMock(controller, IID_Position, {
| 133| 133| 		JumpTo: function(x, z) { this.x = x; this.z = z; },
| 134| 134| 		GetTurretParent: function() { return INVALID_ENTITY; },
| 135|    |-		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
|    | 135|+		"GetPosition": function() { return new Vector3D(this.x, 0, this.z); },
| 136| 136| 		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
| 137| 137| 		GetRotation: function() { return { "y": 0 }; },
| 138| 138| 		IsInWorld: function() { return true; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPosition2D' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 133| 133| 		JumpTo: function(x, z) { this.x = x; this.z = z; },
| 134| 134| 		GetTurretParent: function() { return INVALID_ENTITY; },
| 135| 135| 		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
| 136|    |-		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
|    | 136|+		"GetPosition2D": function() { return new Vector2D(this.x, this.z); },
| 137| 137| 		GetRotation: function() { return { "y": 0 }; },
| 138| 138| 		IsInWorld: function() { return true; },
| 139| 139| 	});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetRotation' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 134| 134| 		GetTurretParent: function() { return INVALID_ENTITY; },
| 135| 135| 		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
| 136| 136| 		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
| 137|    |-		GetRotation: function() { return { "y": 0 }; },
|    | 137|+		"GetRotation": function() { return { "y": 0 }; },
| 138| 138| 		IsInWorld: function() { return true; },
| 139| 139| 	});
| 140| 140| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'IsInWorld' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 135| 135| 		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
| 136| 136| 		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
| 137| 137| 		GetRotation: function() { return { "y": 0 }; },
| 138|    |-		IsInWorld: function() { return true; },
|    | 138|+		"IsInWorld": function() { return true; },
| 139| 139| 	});
| 140| 140| 
| 141| 141| 	AddMock(controller, IID_UnitMotion, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'SetSpeed' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 139| 139| 	});
| 140| 140| 
| 141| 141| 	AddMock(controller, IID_UnitMotion, {
| 142|    |-		SetSpeed: function(speed) { },
|    | 142|+		"SetSpeed": function(speed) { },
| 143| 143| 		MoveToPointRange: function(x, z, minRange, maxRange) { },
| 144| 144| 		GetPassabilityClassName: function() { return "default"; },
| 145| 145| 	});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'MoveToPointRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 140| 140| 
| 141| 141| 	AddMock(controller, IID_UnitMotion, {
| 142| 142| 		SetSpeed: function(speed) { },
| 143|    |-		MoveToPointRange: function(x, z, minRange, maxRange) { },
|    | 143|+		"MoveToPointRange": function(x, z, minRange, maxRange) { },
| 144| 144| 		GetPassabilityClassName: function() { return "default"; },
| 145| 145| 	});
| 146| 146| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPassabilityClassName' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 141| 141| 	AddMock(controller, IID_UnitMotion, {
| 142| 142| 		SetSpeed: function(speed) { },
| 143| 143| 		MoveToPointRange: function(x, z, minRange, maxRange) { },
| 144|    |-		GetPassabilityClassName: function() { return "default"; },
|    | 144|+		"GetPassabilityClassName": function() { return "default"; },
| 145| 145| 	});
| 146| 146| 
| 147| 147| 	controllerAI.OnCreate();
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'SetInterval' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 182| 182| 	var unitAIs = [];
| 183| 183| 
| 184| 184| 	AddMock(SYSTEM_ENTITY, IID_Timer, {
| 185|    |-		SetInterval: function() { },
|    | 185|+		"SetInterval": function() { },
| 186| 186| 		SetTimeout: function() { },
| 187| 187| 	});
| 188| 188| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'SetTimeout' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 183| 183| 
| 184| 184| 	AddMock(SYSTEM_ENTITY, IID_Timer, {
| 185| 185| 		SetInterval: function() { },
| 186|    |-		SetTimeout: function() { },
|    | 186|+		"SetTimeout": function() { },
| 187| 187| 	});
| 188| 188| 
| 189| 189| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'CreateActiveQuery' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 188| 188| 
| 189| 189| 
| 190| 190| 	AddMock(SYSTEM_ENTITY, IID_RangeManager, {
| 191|    |-		CreateActiveQuery: function(ent, minRange, maxRange, players, iid, flags) {
|    | 191|+		"CreateActiveQuery": function(ent, minRange, maxRange, players, iid, flags) {
| 192| 192| 			return 1;
| 193| 193| 		},
| 194| 194| 		EnableActiveQuery: function(id) { },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'EnableActiveQuery' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 191| 191| 		CreateActiveQuery: function(ent, minRange, maxRange, players, iid, flags) {
| 192| 192| 			return 1;
| 193| 193| 		},
| 194|    |-		EnableActiveQuery: function(id) { },
|    | 194|+		"EnableActiveQuery": function(id) { },
| 195| 195| 		ResetActiveQuery: function(id) { return [enemy]; },
| 196| 196| 		DisableActiveQuery: function(id) { },
| 197| 197| 		GetEntityFlagMask: function(identifier) { },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'ResetActiveQuery' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 192| 192| 			return 1;
| 193| 193| 		},
| 194| 194| 		EnableActiveQuery: function(id) { },
| 195|    |-		ResetActiveQuery: function(id) { return [enemy]; },
|    | 195|+		"ResetActiveQuery": function(id) { return [enemy]; },
| 196| 196| 		DisableActiveQuery: function(id) { },
| 197| 197| 		GetEntityFlagMask: function(identifier) { },
| 198| 198| 	});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'DisableActiveQuery' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 193| 193| 		},
| 194| 194| 		EnableActiveQuery: function(id) { },
| 195| 195| 		ResetActiveQuery: function(id) { return [enemy]; },
| 196|    |-		DisableActiveQuery: function(id) { },
|    | 196|+		"DisableActiveQuery": function(id) { },
| 197| 197| 		GetEntityFlagMask: function(identifier) { },
| 198| 198| 	});
| 199| 199| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetEntityFlagMask' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 194| 194| 		EnableActiveQuery: function(id) { },
| 195| 195| 		ResetActiveQuery: function(id) { return [enemy]; },
| 196| 196| 		DisableActiveQuery: function(id) { },
| 197|    |-		GetEntityFlagMask: function(identifier) { },
|    | 197|+		"GetEntityFlagMask": function(identifier) { },
| 198| 198| 	});
| 199| 199| 
| 200| 200| 	AddMock(SYSTEM_ENTITY, IID_TemplateManager, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetCurrentTemplateName' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 198| 198| 	});
| 199| 199| 
| 200| 200| 	AddMock(SYSTEM_ENTITY, IID_TemplateManager, {
| 201|    |-		GetCurrentTemplateName: function(ent) { return "special/formations/line_closed"; },
|    | 201|+		"GetCurrentTemplateName": function(ent) { return "special/formations/line_closed"; },
| 202| 202| 	});
| 203| 203| 
| 204| 204| 	AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPlayerByID' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 202| 202| 	});
| 203| 203| 
| 204| 204| 	AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
| 205|    |-		GetPlayerByID: function(id) { return playerEntity; },
|    | 205|+		"GetPlayerByID": function(id) { return playerEntity; },
| 206| 206| 		GetNumPlayers: function() { return 2; },
| 207| 207| 	});
| 208| 208| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetNumPlayers' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 203| 203| 
| 204| 204| 	AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
| 205| 205| 		GetPlayerByID: function(id) { return playerEntity; },
| 206|    |-		GetNumPlayers: function() { return 2; },
|    | 206|+		"GetNumPlayers": function() { return 2; },
| 207| 207| 	});
| 208| 208| 
| 209| 209| 	AddMock(SYSTEM_ENTITY, IID_ObstructionManager, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'IsInTargetRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 207| 207| 	});
| 208| 208| 
| 209| 209| 	AddMock(SYSTEM_ENTITY, IID_ObstructionManager, {
| 210|    |-		IsInTargetRange: function(ent, target, min, max) { return true; }
|    | 210|+		"IsInTargetRange": function(ent, target, min, max) { return true; }
| 211| 211| 	});
| 212| 212| 
| 213| 213| 	AddMock(playerEntity, IID_Player, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'IsAlly' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 211| 211| 	});
| 212| 212| 
| 213| 213| 	AddMock(playerEntity, IID_Player, {
| 214|    |-		IsAlly: function() { return false; },
|    | 214|+		"IsAlly": function() { return false; },
| 215| 215| 		IsEnemy: function() { return true; },
| 216| 216| 		GetEnemies: function() { return []; },
| 217| 217| 	});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'IsEnemy' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 212| 212| 
| 213| 213| 	AddMock(playerEntity, IID_Player, {
| 214| 214| 		IsAlly: function() { return false; },
| 215|    |-		IsEnemy: function() { return true; },
|    | 215|+		"IsEnemy": function() { return true; },
| 216| 216| 		GetEnemies: function() { return []; },
| 217| 217| 	});
| 218| 218| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetEnemies' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 213| 213| 	AddMock(playerEntity, IID_Player, {
| 214| 214| 		IsAlly: function() { return false; },
| 215| 215| 		IsEnemy: function() { return true; },
| 216|    |-		GetEnemies: function() { return []; },
|    | 216|+		"GetEnemies": function() { return []; },
| 217| 217| 	});
| 218| 218| 
| 219| 219| 	// create units
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetClassesList' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 224| 224| 		var unitAI = ConstructComponent(unit + i, "UnitAI", { "FormationController": "false", "DefaultStance": "aggressive" });
| 225| 225| 
| 226| 226| 		AddMock(unit + i, IID_Identity, {
| 227|    |-			GetClassesList: function() { return []; },
|    | 227|+			"GetClassesList": function() { return []; },
| 228| 228| 		});
| 229| 229| 
| 230| 230| 		AddMock(unit + i, IID_Ownership, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetOwner' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 228| 228| 		});
| 229| 229| 
| 230| 230| 		AddMock(unit + i, IID_Ownership, {
| 231|    |-			GetOwner: function() { return 1; },
|    | 231|+			"GetOwner": function() { return 1; },
| 232| 232| 		});
| 233| 233| 
| 234| 234| 		AddMock(unit + i, IID_Position, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetTurretParent' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 232| 232| 		});
| 233| 233| 
| 234| 234| 		AddMock(unit + i, IID_Position, {
| 235|    |-			GetTurretParent: function() { return INVALID_ENTITY; },
|    | 235|+			"GetTurretParent": function() { return INVALID_ENTITY; },
| 236| 236| 			GetPosition: function() { return new Vector3D(); },
| 237| 237| 			GetPosition2D: function() { return new Vector2D(); },
| 238| 238| 			GetRotation: function() { return { "y": 0 }; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPosition' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 233| 233| 
| 234| 234| 		AddMock(unit + i, IID_Position, {
| 235| 235| 			GetTurretParent: function() { return INVALID_ENTITY; },
| 236|    |-			GetPosition: function() { return new Vector3D(); },
|    | 236|+			"GetPosition": function() { return new Vector3D(); },
| 237| 237| 			GetPosition2D: function() { return new Vector2D(); },
| 238| 238| 			GetRotation: function() { return { "y": 0 }; },
| 239| 239| 			IsInWorld: function() { return true; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPosition2D' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 234| 234| 		AddMock(unit + i, IID_Position, {
| 235| 235| 			GetTurretParent: function() { return INVALID_ENTITY; },
| 236| 236| 			GetPosition: function() { return new Vector3D(); },
| 237|    |-			GetPosition2D: function() { return new Vector2D(); },
|    | 237|+			"GetPosition2D": function() { return new Vector2D(); },
| 238| 238| 			GetRotation: function() { return { "y": 0 }; },
| 239| 239| 			IsInWorld: function() { return true; },
| 240| 240| 		});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetRotation' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 235| 235| 			GetTurretParent: function() { return INVALID_ENTITY; },
| 236| 236| 			GetPosition: function() { return new Vector3D(); },
| 237| 237| 			GetPosition2D: function() { return new Vector2D(); },
| 238|    |-			GetRotation: function() { return { "y": 0 }; },
|    | 238|+			"GetRotation": function() { return { "y": 0 }; },
| 239| 239| 			IsInWorld: function() { return true; },
| 240| 240| 		});
| 241| 241| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'IsInWorld' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 236| 236| 			GetPosition: function() { return new Vector3D(); },
| 237| 237| 			GetPosition2D: function() { return new Vector2D(); },
| 238| 238| 			GetRotation: function() { return { "y": 0 }; },
| 239|    |-			IsInWorld: function() { return true; },
|    | 239|+			"IsInWorld": function() { return true; },
| 240| 240| 		});
| 241| 241| 
| 242| 242| 		AddMock(unit + i, IID_UnitMotion, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetWalkSpeed' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 240| 240| 		});
| 241| 241| 
| 242| 242| 		AddMock(unit + i, IID_UnitMotion, {
| 243|    |-			GetWalkSpeed: function() { return 1; },
|    | 243|+			"GetWalkSpeed": function() { return 1; },
| 244| 244| 			MoveToFormationOffset: function(target, x, z) { },
| 245| 245| 			MoveToTargetRange: function(target, min, max) { },
| 246| 246| 			StopMoving: function() { },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'MoveToFormationOffset' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 241| 241| 
| 242| 242| 		AddMock(unit + i, IID_UnitMotion, {
| 243| 243| 			GetWalkSpeed: function() { return 1; },
| 244|    |-			MoveToFormationOffset: function(target, x, z) { },
|    | 244|+			"MoveToFormationOffset": function(target, x, z) { },
| 245| 245| 			MoveToTargetRange: function(target, min, max) { },
| 246| 246| 			StopMoving: function() { },
| 247| 247| 			GetPassabilityClassName: function() { return "default"; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'MoveToTargetRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 242| 242| 		AddMock(unit + i, IID_UnitMotion, {
| 243| 243| 			GetWalkSpeed: function() { return 1; },
| 244| 244| 			MoveToFormationOffset: function(target, x, z) { },
| 245|    |-			MoveToTargetRange: function(target, min, max) { },
|    | 245|+			"MoveToTargetRange": function(target, min, max) { },
| 246| 246| 			StopMoving: function() { },
| 247| 247| 			GetPassabilityClassName: function() { return "default"; },
| 248| 248| 		});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'StopMoving' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 243| 243| 			GetWalkSpeed: function() { return 1; },
| 244| 244| 			MoveToFormationOffset: function(target, x, z) { },
| 245| 245| 			MoveToTargetRange: function(target, min, max) { },
| 246|    |-			StopMoving: function() { },
|    | 246|+			"StopMoving": function() { },
| 247| 247| 			GetPassabilityClassName: function() { return "default"; },
| 248| 248| 		});
| 249| 249| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPassabilityClassName' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 244| 244| 			MoveToFormationOffset: function(target, x, z) { },
| 245| 245| 			MoveToTargetRange: function(target, min, max) { },
| 246| 246| 			StopMoving: function() { },
| 247|    |-			GetPassabilityClassName: function() { return "default"; },
|    | 247|+			"GetPassabilityClassName": function() { return "default"; },
| 248| 248| 		});
| 249| 249| 
| 250| 250| 		AddMock(unit + i, IID_Vision, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 248| 248| 		});
| 249| 249| 
| 250| 250| 		AddMock(unit + i, IID_Vision, {
| 251|    |-			GetRange: function() { return 10; },
|    | 251|+			"GetRange": function() { return 10; },
| 252| 252| 		});
| 253| 253| 
| 254| 254| 		AddMock(unit + i, IID_Attack, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 252| 252| 		});
| 253| 253| 
| 254| 254| 		AddMock(unit + i, IID_Attack, {
| 255|    |-			GetRange: function() { return {"max":10, "min": 0}; },
|    | 255|+			"GetRange": function() { return {"max":10, "min": 0}; },
| 256| 256| 			GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 257| 257| 			GetBestAttackAgainst: function(t) { return "melee"; },
| 258| 258| 			GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 252| 252| 		});
| 253| 253| 
| 254| 254| 		AddMock(unit + i, IID_Attack, {
| 255|    |-			GetRange: function() { return {"max":10, "min": 0}; },
|    | 255|+			GetRange: function() { return { "max":10, "min": 0}; },
| 256| 256| 			GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 257| 257| 			GetBestAttackAgainst: function(t) { return "melee"; },
| 258| 258| 			GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
|    | [NORMAL] ESLintBear (key-spacing):
|    | Missing space before value for key 'max'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 252| 252| 		});
| 253| 253| 
| 254| 254| 		AddMock(unit + i, IID_Attack, {
| 255|    |-			GetRange: function() { return {"max":10, "min": 0}; },
|    | 255|+			GetRange: function() { return {"max": 10, "min": 0}; },
| 256| 256| 			GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 257| 257| 			GetBestAttackAgainst: function(t) { return "melee"; },
| 258| 258| 			GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 252| 252| 		});
| 253| 253| 
| 254| 254| 		AddMock(unit + i, IID_Attack, {
| 255|    |-			GetRange: function() { return {"max":10, "min": 0}; },
|    | 255|+			GetRange: function() { return {"max":10, "min": 0 }; },
| 256| 256| 			GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 257| 257| 			GetBestAttackAgainst: function(t) { return "melee"; },
| 258| 258| 			GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetFullAttackRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 253| 253| 
| 254| 254| 		AddMock(unit + i, IID_Attack, {
| 255| 255| 			GetRange: function() { return {"max":10, "min": 0}; },
| 256|    |-			GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
|    | 256|+			"GetFullAttackRange": function() { return { "max": 40, "min": 0}; },
| 257| 257| 			GetBestAttackAgainst: function(t) { return "melee"; },
| 258| 258| 			GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
| 259| 259| 			CanAttack: function(v) { return true; },
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 253| 253| 
| 254| 254| 		AddMock(unit + i, IID_Attack, {
| 255| 255| 			GetRange: function() { return {"max":10, "min": 0}; },
| 256|    |-			GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
|    | 256|+			GetFullAttackRange: function() { return { "max": 40, "min": 0 }; },
| 257| 257| 			GetBestAttackAgainst: function(t) { return "melee"; },
| 258| 258| 			GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
| 259| 259| 			CanAttack: function(v) { return true; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetBestAttackAgainst' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 254| 254| 		AddMock(unit + i, IID_Attack, {
| 255| 255| 			GetRange: function() { return {"max":10, "min": 0}; },
| 256| 256| 			GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 257|    |-			GetBestAttackAgainst: function(t) { return "melee"; },
|    | 257|+			"GetBestAttackAgainst": function(t) { return "melee"; },
| 258| 258| 			GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
| 259| 259| 			CanAttack: function(v) { return true; },
| 260| 260| 			CompareEntitiesByPreference: function(a, b) { return 0; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetTimers' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 255| 255| 			GetRange: function() { return {"max":10, "min": 0}; },
| 256| 256| 			GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 257| 257| 			GetBestAttackAgainst: function(t) { return "melee"; },
| 258|    |-			GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
|    | 258|+			"GetTimers": function() { return { "prepare": 500, "repeat": 1000 }; },
| 259| 259| 			CanAttack: function(v) { return true; },
| 260| 260| 			CompareEntitiesByPreference: function(a, b) { return 0; },
| 261| 261| 		});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'CanAttack' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 256| 256| 			GetFullAttackRange: function() { return { "max": 40, "min": 0}; },
| 257| 257| 			GetBestAttackAgainst: function(t) { return "melee"; },
| 258| 258| 			GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
| 259|    |-			CanAttack: function(v) { return true; },
|    | 259|+			"CanAttack": function(v) { return true; },
| 260| 260| 			CompareEntitiesByPreference: function(a, b) { return 0; },
| 261| 261| 		});
| 262| 262| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'CompareEntitiesByPreference' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 257| 257| 			GetBestAttackAgainst: function(t) { return "melee"; },
| 258| 258| 			GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
| 259| 259| 			CanAttack: function(v) { return true; },
| 260|    |-			CompareEntitiesByPreference: function(a, b) { return 0; },
|    | 260|+			"CompareEntitiesByPreference": function(a, b) { return 0; },
| 261| 261| 		});
| 262| 262| 
| 263| 263| 		unitAI.OnCreate();
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetHitpoints' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 269| 269| 
| 270| 270| 	// create enemy
| 271| 271| 	AddMock(enemy, IID_Health, {
| 272|    |-		GetHitpoints: function() { return 40; },
|    | 272|+		"GetHitpoints": function() { return 40; },
| 273| 273| 	});
| 274| 274| 
| 275| 275| 	var controllerFormation = ConstructComponent(controller, "Formation", {"FormationName": "Line Closed", "FormationShape": "square", "ShiftRows": "false", "SortingClasses": "", "WidthDepthRatio": 1, "UnitSeparationWidthMultiplier": 1, "UnitSeparationDepthMultiplier": 1, "SpeedMultiplier": 1, "Sloppyness": 0});
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 272| 272| 		GetHitpoints: function() { return 40; },
| 273| 273| 	});
| 274| 274| 
| 275|    |-	var controllerFormation = ConstructComponent(controller, "Formation", {"FormationName": "Line Closed", "FormationShape": "square", "ShiftRows": "false", "SortingClasses": "", "WidthDepthRatio": 1, "UnitSeparationWidthMultiplier": 1, "UnitSeparationDepthMultiplier": 1, "SpeedMultiplier": 1, "Sloppyness": 0});
|    | 275|+	var controllerFormation = ConstructComponent(controller, "Formation", { "FormationName": "Line Closed", "FormationShape": "square", "ShiftRows": "false", "SortingClasses": "", "WidthDepthRatio": 1, "UnitSeparationWidthMultiplier": 1, "UnitSeparationDepthMultiplier": 1, "SpeedMultiplier": 1, "Sloppyness": 0});
| 276| 276| 	var controllerAI = ConstructComponent(controller, "UnitAI", { "FormationController": "true", "DefaultStance": "aggressive" });
| 277| 277| 
| 278| 278| 	AddMock(controller, IID_Position, {
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 272| 272| 		GetHitpoints: function() { return 40; },
| 273| 273| 	});
| 274| 274| 
| 275|    |-	var controllerFormation = ConstructComponent(controller, "Formation", {"FormationName": "Line Closed", "FormationShape": "square", "ShiftRows": "false", "SortingClasses": "", "WidthDepthRatio": 1, "UnitSeparationWidthMultiplier": 1, "UnitSeparationDepthMultiplier": 1, "SpeedMultiplier": 1, "Sloppyness": 0});
|    | 275|+	var controllerFormation = ConstructComponent(controller, "Formation", {"FormationName": "Line Closed", "FormationShape": "square", "ShiftRows": "false", "SortingClasses": "", "WidthDepthRatio": 1, "UnitSeparationWidthMultiplier": 1, "UnitSeparationDepthMultiplier": 1, "SpeedMultiplier": 1, "Sloppyness": 0 });
| 276| 276| 	var controllerAI = ConstructComponent(controller, "UnitAI", { "FormationController": "true", "DefaultStance": "aggressive" });
| 277| 277| 
| 278| 278| 	AddMock(controller, IID_Position, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetTurretParent' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 276| 276| 	var controllerAI = ConstructComponent(controller, "UnitAI", { "FormationController": "true", "DefaultStance": "aggressive" });
| 277| 277| 
| 278| 278| 	AddMock(controller, IID_Position, {
| 279|    |-		GetTurretParent: function() { return INVALID_ENTITY; },
|    | 279|+		"GetTurretParent": function() { return INVALID_ENTITY; },
| 280| 280| 		JumpTo: function(x, z) { this.x = x; this.z = z; },
| 281| 281| 		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
| 282| 282| 		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'JumpTo' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 277| 277| 
| 278| 278| 	AddMock(controller, IID_Position, {
| 279| 279| 		GetTurretParent: function() { return INVALID_ENTITY; },
| 280|    |-		JumpTo: function(x, z) { this.x = x; this.z = z; },
|    | 280|+		"JumpTo": function(x, z) { this.x = x; this.z = z; },
| 281| 281| 		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
| 282| 282| 		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
| 283| 283| 		GetRotation: function() { return { "y": 0 }; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPosition' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 278| 278| 	AddMock(controller, IID_Position, {
| 279| 279| 		GetTurretParent: function() { return INVALID_ENTITY; },
| 280| 280| 		JumpTo: function(x, z) { this.x = x; this.z = z; },
| 281|    |-		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
|    | 281|+		"GetPosition": function() { return new Vector3D(this.x, 0, this.z); },
| 282| 282| 		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
| 283| 283| 		GetRotation: function() { return { "y": 0 }; },
| 284| 284| 		IsInWorld: function() { return true; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPosition2D' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 279| 279| 		GetTurretParent: function() { return INVALID_ENTITY; },
| 280| 280| 		JumpTo: function(x, z) { this.x = x; this.z = z; },
| 281| 281| 		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
| 282|    |-		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
|    | 282|+		"GetPosition2D": function() { return new Vector2D(this.x, this.z); },
| 283| 283| 		GetRotation: function() { return { "y": 0 }; },
| 284| 284| 		IsInWorld: function() { return true; },
| 285| 285| 	});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetRotation' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 280| 280| 		JumpTo: function(x, z) { this.x = x; this.z = z; },
| 281| 281| 		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
| 282| 282| 		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
| 283|    |-		GetRotation: function() { return { "y": 0 }; },
|    | 283|+		"GetRotation": function() { return { "y": 0 }; },
| 284| 284| 		IsInWorld: function() { return true; },
| 285| 285| 	});
| 286| 286| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'IsInWorld' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 281| 281| 		GetPosition: function() { return new Vector3D(this.x, 0, this.z); },
| 282| 282| 		GetPosition2D: function() { return new Vector2D(this.x, this.z); },
| 283| 283| 		GetRotation: function() { return { "y": 0 }; },
| 284|    |-		IsInWorld: function() { return true; },
|    | 284|+		"IsInWorld": function() { return true; },
| 285| 285| 	});
| 286| 286| 
| 287| 287| 	AddMock(controller, IID_UnitMotion, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'SetSpeed' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 285| 285| 	});
| 286| 286| 
| 287| 287| 	AddMock(controller, IID_UnitMotion, {
| 288|    |-		SetSpeed: function(speed) { },
|    | 288|+		"SetSpeed": function(speed) { },
| 289| 289| 		MoveToPointRange: function(x, z, minRange, maxRange) { },
| 290| 290| 		StopMoving: function() { },
| 291| 291| 		GetPassabilityClassName: function() { return "default"; },
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'MoveToPointRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 286| 286| 
| 287| 287| 	AddMock(controller, IID_UnitMotion, {
| 288| 288| 		SetSpeed: function(speed) { },
| 289|    |-		MoveToPointRange: function(x, z, minRange, maxRange) { },
|    | 289|+		"MoveToPointRange": function(x, z, minRange, maxRange) { },
| 290| 290| 		StopMoving: function() { },
| 291| 291| 		GetPassabilityClassName: function() { return "default"; },
| 292| 292| 	});
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'StopMoving' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 287| 287| 	AddMock(controller, IID_UnitMotion, {
| 288| 288| 		SetSpeed: function(speed) { },
| 289| 289| 		MoveToPointRange: function(x, z, minRange, maxRange) { },
| 290|    |-		StopMoving: function() { },
|    | 290|+		"StopMoving": function() { },
| 291| 291| 		GetPassabilityClassName: function() { return "default"; },
| 292| 292| 	});
| 293| 293| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetPassabilityClassName' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 288| 288| 		SetSpeed: function(speed) { },
| 289| 289| 		MoveToPointRange: function(x, z, minRange, maxRange) { },
| 290| 290| 		StopMoving: function() { },
| 291|    |-		GetPassabilityClassName: function() { return "default"; },
|    | 291|+		"GetPassabilityClassName": function() { return "default"; },
| 292| 292| 	});
| 293| 293| 
| 294| 294| 	AddMock(controller, IID_Attack, {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'GetRange' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 292| 292| 	});
| 293| 293| 
| 294| 294| 	AddMock(controller, IID_Attack, {
| 295|    |-		GetRange: function() { return {"max":10, "min": 0}; },
|    | 295|+		"GetRange": function() { return {"max":10, "min": 0}; },
| 296| 296| 		CanAttackAsFormation: function() { return false; },
| 297| 297| 	});
| 298| 298| 
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 292| 292| 	});
| 293| 293| 
| 294| 294| 	AddMock(controller, IID_Attack, {
| 295|    |-		GetRange: function() { return {"max":10, "min": 0}; },
|    | 295|+		GetRange: function() { return { "max":10, "min": 0}; },
| 296| 296| 		CanAttackAsFormation: function() { return false; },
| 297| 297| 	});
| 298| 298| 
|    | [NORMAL] ESLintBear (key-spacing):
|    | Missing space before value for key 'max'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 292| 292| 	});
| 293| 293| 
| 294| 294| 	AddMock(controller, IID_Attack, {
| 295|    |-		GetRange: function() { return {"max":10, "min": 0}; },
|    | 295|+		GetRange: function() { return {"max": 10, "min": 0}; },
| 296| 296| 		CanAttackAsFormation: function() { return false; },
| 297| 297| 	});
| 298| 298| 
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 292| 292| 	});
| 293| 293| 
| 294| 294| 	AddMock(controller, IID_Attack, {
| 295|    |-		GetRange: function() { return {"max":10, "min": 0}; },
|    | 295|+		GetRange: function() { return {"max":10, "min": 0 }; },
| 296| 296| 		CanAttackAsFormation: function() { return false; },
| 297| 297| 	});
| 298| 298| 
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'CanAttackAsFormation' found.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 293| 293| 
| 294| 294| 	AddMock(controller, IID_Attack, {
| 295| 295| 		GetRange: function() { return {"max":10, "min": 0}; },
| 296|    |-		CanAttackAsFormation: function() { return false; },
|    | 296|+		"CanAttackAsFormation": function() { return false; },
| 297| 297| 	});
| 298| 298| 
| 299| 299| 	controllerAI.OnCreate();
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 305| 305| 	for (var ent of unitAIs)
| 306| 306| 		TS_ASSERT_EQUALS(unitAI.fsmStateName, "INDIVIDUAL.COMBAT.ATTACKING");
| 307| 307| 
| 308|    |-	controllerAI.MoveIntoFormation({"name": "Circle"});
|    | 308|+	controllerAI.MoveIntoFormation({ "name": "Circle"});
| 309| 309| 
| 310| 310| 	// let all units be in position
| 311| 311| 	for (var ent of unitAIs)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 305| 305| 	for (var ent of unitAIs)
| 306| 306| 		TS_ASSERT_EQUALS(unitAI.fsmStateName, "INDIVIDUAL.COMBAT.ATTACKING");
| 307| 307| 
| 308|    |-	controllerAI.MoveIntoFormation({"name": "Circle"});
|    | 308|+	controllerAI.MoveIntoFormation({"name": "Circle" });
| 309| 309| 
| 310| 310| 	// let all units be in position
| 311| 311| 	for (var ent of unitAIs)

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
|  46| »   »   ResetActiveQuery:·function(id)·{·if·(mode·==·0)·return·[];·else·return·[enemy];·},
|    | [NORMAL] ESLintBear (brace-rules/brace-on-same-line):
|    | Closing curly brace appears on the same line as the subsequent block.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 220| »   for·(var·i·=·0;·i·<·unitCount;·i++)·{
|    | [NORMAL] ESLintBear (brace-rules/brace-on-same-line):
|    | Opening curly brace appears on the same line as controlling statement.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 311| »   for·(var·ent·of·unitAIs)
|    | [NORMAL] JSHintBear:
|    | 'ent' is already defined.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 314| »   for·(var·ent·of·unitAIs)
|    | [NORMAL] JSHintBear:
|    | 'ent' is already defined.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 306| »   »   TS_ASSERT_EQUALS(unitAI.fsmStateName,·"INDIVIDUAL.COMBAT.ATTACKING");
|    | [NORMAL] JSHintBear:
|    | 'unitAI' used out of scope.

binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
| 315| »   »   TS_ASSERT_EQUALS(unitAI.fsmStateName,·"INDIVIDUAL.COMBAT.ATTACKING");
|    | [NORMAL] JSHintBear:
|    | 'unitAI' used out of scope.
|    | [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
| 228| 228| 		// Move a tile outside the building
| 229| 229| 		let range = 4;
| 230| 230| 		if (this.MoveToTargetRangeExplicit(msg.data.target, range, range))
| 231|    |-		{
|    | 231|+		
| 232| 232| 			// We've started walking to the given point
| 233| 233| 			this.SetNextState("INDIVIDUAL.WALKING");
| 234|    |-		}
|    | 234|+		
| 235| 235| 		else
| 236| 236| 		{
| 237| 237| 			// 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
| 233| 233| 			this.SetNextState("INDIVIDUAL.WALKING");
| 234| 234| 		}
| 235| 235| 		else
| 236|    |-		{
|    | 236|+		
| 237| 237| 			// We are already at the target, or can't move at all
| 238| 238| 			this.FinishOrder();
| 239|    |-		}
|    | 239|+		
| 240| 240| 	},
| 241| 241| 
| 242| 242| 	// 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
| 335| 335| 
| 336| 336| 		var ok = this.MoveToTarget(this.order.data.target);
| 337| 337| 		if (ok)
| 338|    |-		{
|    | 338|+		
| 339| 339| 			// We've started walking to the given point
| 340| 340| 			if (this.IsAnimal())
| 341| 341| 				this.SetNextState("ANIMAL.WALKING");
| 342| 342| 			else
| 343| 343| 				this.SetNextState("INDIVIDUAL.WALKING");
| 344|    |-		}
|    | 344|+		
| 345| 345| 		else
| 346| 346| 		{
| 347| 347| 			// 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
| 363| 363| 		var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
| 364| 364| 		if (this.lastShorelinePosition && cmpPosition && (this.lastShorelinePosition.x == cmpPosition.GetPosition().x)
| 365| 365| 		    && (this.lastShorelinePosition.z == cmpPosition.GetPosition().z))
| 366|    |-		{
|    | 366|+		
| 367| 367| 			// we were already on the shoreline, and have not moved since
| 368| 368| 			if (DistanceBetweenEntities(this.entity, this.order.data.target) < 50)
| 369| 369| 				needToMove = false;
| 370|    |-		}
|    | 370|+		
| 371| 371| 
| 372| 372| 		// TODO: what if the units are on a cliff ? the ship will go below the cliff
| 373| 373| 		// 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
| 361| 361| 		// Check if we need to move     TODO implement a better way to know if we are on the shoreline
| 362| 362| 		var needToMove = true;
| 363| 363| 		var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
| 364|    |-		if (this.lastShorelinePosition && cmpPosition && (this.lastShorelinePosition.x == cmpPosition.GetPosition().x)
| 365|    |-		    && (this.lastShorelinePosition.z == cmpPosition.GetPosition().z))
|    | 364|+		if (this.lastShorelinePosition && cmpPosition && (this.lastShorelinePosition.x == cmpPosition.GetPosition().x) &&
|    | 365|+		    (this.lastShorelinePosition.z == cmpPosition.GetPosition().z))
| 366| 366| 		{
| 367| 367| 			// we were already on the shoreline, and have not moved since
| 368| 368| 			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
| 372| 372| 		// TODO: what if the units are on a cliff ? the ship will go below the cliff
| 373| 373| 		// and the units won't be able to garrison. Should go to the nearest (accessible) shore
| 374| 374| 		if (needToMove && this.MoveToTarget(this.order.data.target))
| 375|    |-		{
|    | 375|+		
| 376| 376| 			this.SetNextState("INDIVIDUAL.PICKUP.APPROACHING");
| 377|    |-		}
|    | 377|+		
| 378| 378| 		else
| 379| 379| 		{
| 380| 380| 			// 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
| 401| 401| 		var distance = DistanceBetweenEntities(this.entity, this.order.data.target) + (+this.template.FleeDistance);
| 402| 402| 		var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion);
| 403| 403| 		if (cmpUnitMotion.MoveToTargetRange(this.order.data.target, distance, -1))
| 404|    |-		{
|    | 404|+		
| 405| 405| 			// We've started fleeing from the given target
| 406| 406| 			if (this.IsAnimal())
| 407| 407| 				this.SetNextState("ANIMAL.FLEEING");
| 408| 408| 			else
| 409| 409| 				this.SetNextState("INDIVIDUAL.FLEEING");
| 410|    |-		}
|    | 410|+		
| 411| 411| 		else
| 412| 412| 		{
| 413| 413| 			// 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
| 448| 448| 			}
| 449| 449| 
| 450| 450| 			if (this.order.data.attackType == this.oldAttackType)
| 451|    |-			{
|    | 451|+			
| 452| 452| 				if (this.IsAnimal())
| 453| 453| 					this.SetNextState("ANIMAL.COMBAT.ATTACKING");
| 454| 454| 				else
| 455| 455| 					this.SetNextState("INDIVIDUAL.COMBAT.ATTACKING");
| 456|    |-			}
|    | 456|+			
| 457| 457| 			else
| 458| 458| 			{
| 459| 459| 				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
| 455| 455| 					this.SetNextState("INDIVIDUAL.COMBAT.ATTACKING");
| 456| 456| 			}
| 457| 457| 			else
| 458|    |-			{
|    | 458|+			
| 459| 459| 				if (this.IsAnimal())
| 460| 460| 					this.SetNextStateAlwaysEntering("ANIMAL.COMBAT.ATTACKING");
| 461| 461| 				else
| 462| 462| 					this.SetNextStateAlwaysEntering("INDIVIDUAL.COMBAT.ATTACKING");
| 463|    |-			}
|    | 463|+			
| 464| 464| 			return;
| 465| 465| 		}
| 466| 466| 
|    | [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
| 580| 580| 					this.PushOrderFront("Walk", this.order.data.lastPos);
| 581| 581| 				}
| 582| 582| 				else
| 583|    |-				{
|    | 583|+				
| 584| 584| 					// We couldn't move there, or the target moved away
| 585| 585| 					this.FinishOrder();
| 586|    |-				}
|    | 586|+				
| 587| 587| 				return;
| 588| 588| 			}
| 589| 589| 
|    | [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
| 593| 593| 
| 594| 594| 		// Try to move within range
| 595| 595| 		if (this.MoveToTargetRange(this.order.data.target, IID_ResourceGatherer))
| 596|    |-		{
|    | 596|+		
| 597| 597| 			// We've started walking to the given point
| 598| 598| 			this.SetNextState("INDIVIDUAL.GATHER.APPROACHING");
| 599|    |-		}
|    | 599|+		
| 600| 600| 		else
| 601| 601| 		{
| 602| 602| 			// 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
| 670| 670| 	"Order.Repair": function(msg) {
| 671| 671| 		// Try to move within range
| 672| 672| 		if (this.MoveToTargetRange(this.order.data.target, IID_Builder))
| 673|    |-		{
|    | 673|+		
| 674| 674| 			// We've started walking to the given point
| 675| 675| 			this.SetNextState("INDIVIDUAL.REPAIR.APPROACHING");
| 676|    |-		}
|    | 676|+		
| 677| 677| 		else
| 678| 678| 		{
| 679| 679| 			// 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
| 706| 706| 		}
| 707| 707| 
| 708| 708| 		if (this.MoveToGarrisonRange(this.order.data.target))
| 709|    |-		{
|    | 709|+		
| 710| 710| 			this.SetNextState("INDIVIDUAL.GARRISON.APPROACHING");
| 711|    |-		}
|    | 711|+		
| 712| 712| 		else
| 713| 713| 		{
| 714| 714| 			// 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
| 834| 834| 			if (!this.CheckTargetAttackRange(target, target))
| 835| 835| 			{
| 836| 836| 				if (this.TargetIsAlive(target) && this.CheckTargetVisible(target))
| 837|    |-				{
|    | 837|+				
| 838| 838| 					if (this.MoveToTargetAttackRange(target, target))
| 839| 839| 					{
| 840| 840| 						this.SetNextState("COMBAT.APPROACHING");
| 841| 841| 						return;
| 842| 842| 					}
| 843|    |-				}
|    | 843|+				
| 844| 844| 				this.FinishOrder();
| 845| 845| 				return;
| 846| 846| 			}
|    | [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
| 859| 859| 			}
| 860| 860| 			// Check if we are already in range, otherwise walk there
| 861| 861| 			if (!this.CheckGarrisonRange(msg.data.target))
| 862|    |-			{
|    | 862|+			
| 863| 863| 				if (!this.CheckTargetVisible(msg.data.target))
| 864| 864| 				{
| 865| 865| 					this.FinishOrder();
| 874| 874| 						return;
| 875| 875| 					}
| 876| 876| 				}
| 877|    |-			}
|    | 877|+			
| 878| 878| 
| 879| 879| 			this.SetNextState("GARRISON.GARRISONING");
| 880| 880| 		},
|    | [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
| 866| 866| 					return;
| 867| 867| 				}
| 868| 868| 				else
| 869|    |-				{
|    | 869|+				
| 870| 870| 					// Out of range; move there in formation
| 871| 871| 					if (this.MoveToGarrisonRange(msg.data.target))
| 872| 872| 					{
| 873| 873| 						this.SetNextState("GARRISON.APPROACHING");
| 874| 874| 						return;
| 875| 875| 					}
| 876|    |-				}
|    | 876|+				
| 877| 877| 			}
| 878| 878| 
| 879| 879| 			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
| 865| 865| 					this.FinishOrder();
| 866| 866| 					return;
| 867| 867| 				}
| 868|    |-				else
| 869|    |-				{
|    | 868|+				
| 870| 869| 					// Out of range; move there in formation
| 871| 870| 					if (this.MoveToGarrisonRange(msg.data.target))
| 872| 871| 					{
| 873| 872| 						this.SetNextState("GARRISON.APPROACHING");
| 874| 873| 						return;
| 875| 874| 					}
| 876|    |-				}
|    | 875|+				
| 877| 876| 			}
| 878| 877| 
| 879| 878| 			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
| 892| 892| 						this.PushOrderFront("Walk", msg.data.lastPos);
| 893| 893| 					}
| 894| 894| 					else
| 895|    |-					{
|    | 895|+					
| 896| 896| 						// We couldn't move there, or the target moved away
| 897| 897| 						this.FinishOrder();
| 898|    |-					}
|    | 898|+					
| 899| 899| 					return;
| 900| 900| 				}
| 901| 901| 
|    | [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
|1113|1113| 			},
|1114|1114| 		},
|1115|1115| 
|1116|    |-		"GARRISON":{
|    |1116|+		"GARRISON": {
|1117|1117| 			"enter": function() {
|1118|1118| 				// If the garrisonholder should pickup, warn it so it can take needed action
|1119|1119| 				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
|1297|1297| 			// If the controller handled an order but some members rejected it,
|1298|1298| 			// they will have no orders and be in the FORMATIONMEMBER.IDLE state.
|1299|1299| 			if (this.orderQueue.length)
|1300|    |-			{
|    |1300|+			
|1301|1301| 				// We're leaving the formation, so stop our FormationWalk order
|1302|1302| 				if (this.FinishOrder())
|1303|1303| 					return;
|1304|    |-			}
|    |1304|+			
|1305|1305| 
|1306|1306| 			// No orders left, we're an individual now
|1307|1307| 			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
|1325|1325| 			// Move a tile outside the building
|1326|1326| 			let range = 4;
|1327|1327| 			if (this.MoveToTargetRangeExplicit(msg.data.target, range, range))
|1328|    |-			{
|    |1328|+			
|1329|1329| 				// We've started walking to the given point
|1330|1330| 				this.SetNextState("WALKINGTOPOINT");
|1331|    |-			}
|    |1331|+			
|1332|1332| 			else
|1333|1333| 			{
|1334|1334| 				// 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
|1330|1330| 				this.SetNextState("WALKINGTOPOINT");
|1331|1331| 			}
|1332|1332| 			else
|1333|    |-			{
|    |1333|+			
|1334|1334| 				// We are already at the target, or can't move at all
|1335|1335| 				this.FinishOrder();
|1336|    |-			}
|    |1336|+			
|1337|1337| 		},
|1338|1338| 
|1339|1339| 
|    | [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
|1531|1531| 
|1532|1532| 			"LosRangeUpdate": function(msg) {
|1533|1533| 				if (this.GetStance().targetVisibleEnemies)
|1534|    |-				{
|    |1534|+				
|1535|1535| 					// Start attacking one of the newly-seen enemy (if any)
|1536|1536| 					this.AttackEntitiesByPreference(msg.data.added);
|1537|    |-				}
|    |1537|+				
|1538|1538| 			},
|1539|1539| 
|1540|1540| 			"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
|1717|1717| 						// if nothing better to do, check if the guarded needs to be healed or repaired
|1718|1718| 						var cmpHealth = Engine.QueryInterface(this.isGuardOf, IID_Health);
|1719|1719| 						if (cmpHealth && (cmpHealth.GetHitpoints() < cmpHealth.GetMaxHitpoints()))
|1720|    |-						{
|    |1720|+						
|1721|1721| 							if (this.CanHeal(this.isGuardOf))
|1722|1722| 								this.PushOrderFront("Heal", { "target": this.isGuardOf, "force": false });
|1723|1723| 							else if (this.CanRepair(this.isGuardOf))
|1724|1724| 								this.PushOrderFront("Repair", { "target": this.isGuardOf, "autocontinue": false, "force": false });
|1725|    |-						}
|    |1725|+						
|1726|1726| 					}
|1727|1727| 				},
|1728|1728| 
|    | [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
|1805|1805| 				"MoveCompleted": function() {
|1806|1806| 
|1807|1807| 					if (this.CheckTargetAttackRange(this.order.data.target, this.order.data.attackType))
|1808|    |-					{
|    |1808|+					
|1809|1809| 						// If the unit needs to unpack, do so
|1810|1810| 						if (this.CanUnpack())
|1811|1811| 						{
|1814|1814| 						}
|1815|1815| 						else
|1816|1816| 							this.SetNextState("ATTACKING");
|1817|    |-					}
|    |1817|+					
|1818|1818| 					else
|1819|1819| 					{
|1820|1820| 						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
|1812|1812| 							this.PushOrderFront("Unpack", { "force": true });
|1813|1813| 							return;
|1814|1814| 						}
|1815|    |-						else
|1816|    |-							this.SetNextState("ATTACKING");
|    |1815|+						this.SetNextState("ATTACKING");
|1817|1816| 					}
|1818|1817| 					else
|1819|1818| 					{
|    | [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
|1816|1816| 							this.SetNextState("ATTACKING");
|1817|1817| 					}
|1818|1818| 					else
|1819|    |-					{
|    |1819|+					
|1820|1820| 						if (this.MoveToTargetAttackRange(this.order.data.target, this.order.data.attackType))
|1821|1821| 						{
|1822|1822| 							this.SetNextState("APPROACHING");
|1826|1826| 							// Give up
|1827|1827| 							this.FinishOrder();
|1828|1828| 						}
|1829|    |-					}
|    |1829|+					
|1830|1830| 				},
|1831|1831| 			},
|1832|1832| 
|    | [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
|1818|1818| 					else
|1819|1819| 					{
|1820|1820| 						if (this.MoveToTargetAttackRange(this.order.data.target, this.order.data.attackType))
|1821|    |-						{
|    |1821|+						
|1822|1822| 							this.SetNextState("APPROACHING");
|1823|    |-						}
|    |1823|+						
|1824|1824| 						else
|1825|1825| 						{
|1826|1826| 							// 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
|1822|1822| 							this.SetNextState("APPROACHING");
|1823|1823| 						}
|1824|1824| 						else
|1825|    |-						{
|    |1825|+						
|1826|1826| 							// Give up
|1827|1827| 							this.FinishOrder();
|1828|    |-						}
|    |1828|+						
|1829|1829| 					}
|1830|1830| 				},
|1831|1831| 			},
|    | [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
|1843|1843| 					}
|1844|1844| 					// Check the target is still alive and attackable
|1845|1845| 					if (this.CanAttack(target) && !this.CheckTargetAttackRange(target, this.order.data.attackType))
|1846|    |-					{
|    |1846|+					
|1847|1847| 						// Can't reach it - try to chase after it
|1848|1848| 						if (this.ShouldChaseTargetedEntity(target, this.order.data.force))
|1849|1849| 						{
|1858|1858| 								return;
|1859|1859| 							}
|1860|1860| 						}
|1861|    |-					}
|    |1861|+					
|1862|1862| 
|1863|1863| 					var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|1864|1864| 					this.attackTimers = cmpAttack.GetTimers(this.order.data.attackType);
|    | [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
|1889|1889| 					// TODO: we should probably only bother syncing projectile attacks, not melee
|1890|1890| 
|1891|1891| 					// If using a non-default prepare time, re-sync the animation when the timer runs.
|1892|    |-					this.resyncAnimation = (prepare != this.attackTimers.prepare) ? true : false;
|    |1892|+					this.resyncAnimation = (prepare != this.attackTimers.prepare);
|1893|1893| 
|1894|1894| 					this.FaceTowardsTarget(this.order.data.target);
|1895|1895| 
|    | [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
|2018|2018| 
|2019|2019| 				"Attacked": function(msg) {
|2020|2020| 					// If we are capturing and are attacked by something that we would not capture, attack that entity instead
|2021|    |-					if (this.order.data.attackType == "Capture" && (this.GetStance().targetAttackersAlways || !this.order.data.force)
|2022|    |-						&& this.order.data.target != msg.data.attacker && this.GetBestAttackAgainst(msg.data.attacker, true) != "Capture")
|    |2021|+					if (this.order.data.attackType == "Capture" && (this.GetStance().targetAttackersAlways || !this.order.data.force) &&
|    |2022|+						this.order.data.target != msg.data.attacker && this.GetBestAttackAgainst(msg.data.attacker, true) != "Capture")
|2023|2023| 						this.RespondToTargetedEntities([msg.data.attacker]);
|2024|2024| 				},
|2025|2025| 			},
|    | [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
|2102|2102| 						// Also don't switch to a different type of huntable animal
|2103|2103| 						var nearby = this.FindNearbyResource(function(ent, type, template) {
|2104|2104| 							return (
|2105|    |-								ent != oldTarget
|2106|    |-								 && ((type.generic == "treasure" && oldType.generic == "treasure")
|    |2105|+								ent != oldTarget &&
|    |2106|+								 ((type.generic == "treasure" && oldType.generic == "treasure")
|2107|2107| 								 || (type.specific == oldType.specific
|2108|2108| 								 && (type.specific != "meat" || oldTemplate == template)))
|2109|2109| 							);
|    | [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
|2103|2103| 						var nearby = this.FindNearbyResource(function(ent, type, template) {
|2104|2104| 							return (
|2105|2105| 								ent != oldTarget
|2106|    |-								 && ((type.generic == "treasure" && oldType.generic == "treasure")
|2107|    |-								 || (type.specific == oldType.specific
|    |2106|+								 && ((type.generic == "treasure" && oldType.generic == "treasure") ||
|    |2107|+								 (type.specific == oldType.specific
|2108|2108| 								 && (type.specific != "meat" || oldTemplate == template)))
|2109|2109| 							);
|2110|2110| 						}, 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
|2104|2104| 							return (
|2105|2105| 								ent != oldTarget
|2106|2106| 								 && ((type.generic == "treasure" && oldType.generic == "treasure")
|2107|    |-								 || (type.specific == oldType.specific
|2108|    |-								 && (type.specific != "meat" || oldTemplate == template)))
|    |2107|+								 || (type.specific == oldType.specific &&
|    |2108|+								 (type.specific != "meat" || oldTemplate == template)))
|2109|2109| 							);
|2110|2110| 						}, oldTarget);
|2111|2111| 						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
|2113|2113| 							this.PerformGather(nearby, false, false);
|2114|2114| 							return true;
|2115|2115| 						}
|2116|    |-						else
|2117|    |-						{
|    |2116|+						
|2118|2117| 							// It's probably better in this case, to avoid units getting stuck around a dropsite
|2119|2118| 							// in a "Target is far away, full, nearby are no good resources, return to dropsite" loop
|2120|2119| 							// to order it to GatherNear the resource position.
|2135|2134| 									return true;
|2136|2135| 								}
|2137|2136| 							}
|2138|    |-						}
|    |2137|+						
|2139|2138| 						return true;
|2140|2139| 					}
|2141|2140| 					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
|2125|2125| 								this.GatherNearPosition(pos.x, pos.z, oldType, oldTemplate);
|2126|2126| 								return true;
|2127|2127| 							}
|2128|    |-							else
|2129|    |-							{
|    |2128|+							
|2130|2129| 								// we're kind of stuck here. Return resource.
|2131|2130| 								var nearby = this.FindNearestDropsite(oldType.generic);
|2132|2131| 								if (nearby)
|2134|2133| 									this.PushOrderFront("ReturnResource", { "target": nearby, "force": false });
|2135|2134| 									return true;
|2136|2135| 								}
|2137|    |-							}
|    |2136|+							
|2138|2137| 						}
|2139|2138| 						return true;
|2140|2139| 					}
|    | [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
|2167|2167| 						// Also don't switch to a different type of huntable animal
|2168|2168| 						var nearby = this.FindNearbyResource(function(ent, type, template) {
|2169|2169| 							return (
|2170|    |-								ent != oldTarget
|2171|    |-								&& ((type.generic == "treasure" && oldType.generic == "treasure")
|    |2170|+								ent != oldTarget &&
|    |2171|+								((type.generic == "treasure" && oldType.generic == "treasure")
|2172|2172| 								|| (type.specific == oldType.specific
|2173|2173| 								&& (type.specific != "meat" || oldTemplate == template)))
|2174|2174| 							);
|    | [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
|2168|2168| 						var nearby = this.FindNearbyResource(function(ent, type, template) {
|2169|2169| 							return (
|2170|2170| 								ent != oldTarget
|2171|    |-								&& ((type.generic == "treasure" && oldType.generic == "treasure")
|2172|    |-								|| (type.specific == oldType.specific
|    |2171|+								&& ((type.generic == "treasure" && oldType.generic == "treasure") ||
|    |2172|+								(type.specific == oldType.specific
|2173|2173| 								&& (type.specific != "meat" || oldTemplate == template)))
|2174|2174| 							);
|2175|2175| 						});
|    | [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
|2169|2169| 							return (
|2170|2170| 								ent != oldTarget
|2171|2171| 								&& ((type.generic == "treasure" && oldType.generic == "treasure")
|2172|    |-								|| (type.specific == oldType.specific
|2173|    |-								&& (type.specific != "meat" || oldTemplate == template)))
|    |2172|+								|| (type.specific == oldType.specific &&
|    |2173|+								(type.specific != "meat" || oldTemplate == template)))
|2174|2174| 							);
|2175|2175| 						});
|2176|2176| 						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
|2214|2214| 					// Also don't switch to a different type of huntable animal
|2215|2215| 					var nearby = this.FindNearbyResource(function(ent, type, template) {
|2216|2216| 						return (
|2217|    |-							(type.generic == "treasure" && resourceType.generic == "treasure")
|2218|    |-							|| (type.specific == resourceType.specific
|    |2217|+							(type.generic == "treasure" && resourceType.generic == "treasure") ||
|    |2218|+							(type.specific == resourceType.specific
|2219|2219| 							&& (type.specific != "meat" || resourceTemplate == template))
|2220|2220| 						);
|2221|2221| 					});
|    | [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
|2215|2215| 					var nearby = this.FindNearbyResource(function(ent, type, template) {
|2216|2216| 						return (
|2217|2217| 							(type.generic == "treasure" && resourceType.generic == "treasure")
|2218|    |-							|| (type.specific == resourceType.specific
|2219|    |-							&& (type.specific != "meat" || resourceTemplate == template))
|    |2218|+							|| (type.specific == resourceType.specific &&
|    |2219|+							(type.specific != "meat" || resourceTemplate == template))
|2220|2220| 						);
|2221|2221| 					});
|2222|2222| 
|    | [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
|2331|2331| 
|2332|2332| 					var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply);
|2333|2333| 					if (cmpSupply && cmpSupply.IsAvailable(cmpOwnership.GetOwner(), this.entity))
|2334|    |-					{
|    |2334|+					
|2335|2335| 						// Check we can still reach and gather from the target
|2336|2336| 						if (this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer) && this.CanGather(this.gatheringTarget))
|2337|2337| 						{
|2397|2397| 								return;
|2398|2398| 							}
|2399|2399| 						}
|2400|    |-					}
|    |2400|+					
|2401|2401| 
|2402|2402| 					// We're already in range, can't get anywhere near it or the target is exhausted.
|2403|2403| 
|    | [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
|2423|2423| 					// Also don't switch to a different type of huntable animal
|2424|2424| 					var nearby = this.FindNearbyResource(function(ent, type, template) {
|2425|2425| 						return (
|2426|    |-							(type.generic == "treasure" && resourceType.generic == "treasure")
|2427|    |-							|| (type.specific == resourceType.specific
|    |2426|+							(type.generic == "treasure" && resourceType.generic == "treasure") ||
|    |2427|+							(type.specific == resourceType.specific
|2428|2428| 							&& (type.specific != "meat" || resourceTemplate == template))
|2429|2429| 						);
|2430|2430| 					});
|    | [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
|2424|2424| 					var nearby = this.FindNearbyResource(function(ent, type, template) {
|2425|2425| 						return (
|2426|2426| 							(type.generic == "treasure" && resourceType.generic == "treasure")
|2427|    |-							|| (type.specific == resourceType.specific
|2428|    |-							&& (type.specific != "meat" || resourceTemplate == template))
|    |2427|+							|| (type.specific == resourceType.specific &&
|    |2428|+							(type.specific != "meat" || resourceTemplate == template))
|2429|2429| 						);
|2430|2430| 					});
|2431|2431| 					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
|2511|2511| 					this.StartTimer(prepare, this.healTimers.repeat);
|2512|2512| 
|2513|2513| 					// If using a non-default prepare time, re-sync the animation when the timer runs.
|2514|    |-					this.resyncAnimation = (prepare != this.healTimers.prepare) ? true : false;
|    |2514|+					this.resyncAnimation = (prepare != this.healTimers.prepare);
|2515|2515| 
|2516|2516| 					this.FaceTowardsTarget(this.order.data.target);
|2517|2517| 				},
|    | [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
|2726|2726| 					{
|2727|2727| 						// The building was already finished/fully repaired before we arrived;
|2728|2728| 						// let the ConstructionFinished handler handle this.
|2729|    |-						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget});
|    |2729|+						this.OnGlobalConstructionFinished({ "entity": this.repairTarget, "newentity": this.repairTarget});
|2730|2730| 						return true;
|2731|2731| 					}
|2732|2732| 
|    | [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
|2726|2726| 					{
|2727|2727| 						// The building was already finished/fully repaired before we arrived;
|2728|2728| 						// let the ConstructionFinished handler handle this.
|2729|    |-						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget});
|    |2729|+						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget });
|2730|2730| 						return true;
|2731|2731| 					}
|2732|2732| 
|    | [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
|2766|2766| 					if (this.MoveToTargetRange(this.repairTarget, IID_Builder))
|2767|2767| 						this.SetNextState("APPROACHING");
|2768|2768| 					else if (!this.CheckTargetRange(this.repairTarget, IID_Builder))
|2769|    |-						this.FinishOrder(); //can't approach and isn't in reach
|    |2769|+						this.FinishOrder(); // can't approach and isn't in reach
|2770|2770| 				},
|2771|2771| 			},
|2772|2772| 
|    | [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
|2853|2853| 
|2854|2854| 				// Unit was approaching and there's nothing to do now, so switch to walking
|2855|2855| 				if (oldState === "INDIVIDUAL.REPAIR.APPROACHING")
|2856|    |-				{
|    |2856|+				
|2857|2857| 					// We're already walking to the given point, so add this as a order.
|2858|2858| 					this.WalkToTarget(msg.data.newentity, true);
|2859|    |-				}
|    |2859|+				
|2860|2860| 			},
|2861|2861| 		},
|2862|2862| 
|    | [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
|2906|2906| 
|2907|2907| 					// Check that we can garrison here
|2908|2908| 					if (this.CanGarrison(target))
|2909|    |-					{
|    |2909|+					
|2910|2910| 						// Check that we're in range of the garrison target
|2911|2911| 						if (this.CheckGarrisonRange(target))
|2912|2912| 						{
|2982|2982| 								return false;
|2983|2983| 							}
|2984|2984| 						}
|2985|    |-					}
|    |2985|+					
|2986|2986| 					// Garrisoning failed for some reason, so finish the order
|2987|2987| 					this.FinishOrder();
|2988|2988| 					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
|3089|3089| 		"Attacked": function(msg) {
|3090|3090| 			if (this.template.NaturalBehaviour == "skittish" ||
|3091|3091| 			    this.template.NaturalBehaviour == "passive")
|3092|    |-			{
|    |3092|+			
|3093|3093| 				this.Flee(msg.data.attacker, false);
|3094|    |-			}
|    |3094|+			
|3095|3095| 			else if (this.IsDangerousAnimal() || this.template.NaturalBehaviour == "defensive")
|3096|3096| 			{
|3097|3097| 				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
|3098|3098| 					this.Attack(msg.data.attacker, false);
|3099|3099| 			}
|3100|3100| 			else if (this.template.NaturalBehaviour == "domestic")
|3101|    |-			{
|    |3101|+			
|3102|3102| 				// Never flee, stop what we were doing
|3103|3103| 				this.SetNextState("IDLE");
|3104|    |-			}
|    |3104|+			
|3105|3105| 		},
|3106|3106| 
|3107|3107| 		"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
|3108|3108| 			// Move a tile outside the building
|3109|3109| 			var range = 4;
|3110|3110| 			if (this.MoveToTargetRangeExplicit(msg.data.target, range, range))
|3111|    |-			{
|    |3111|+			
|3112|3112| 				// We've started walking to the given point
|3113|3113| 				this.SetNextState("WALKING");
|3114|    |-			}
|    |3114|+			
|3115|3115| 			else
|3116|3116| 			{
|3117|3117| 				// 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
|3113|3113| 				this.SetNextState("WALKING");
|3114|3114| 			}
|3115|3115| 			else
|3116|    |-			{
|    |3116|+			
|3117|3117| 				// We are already at the target, or can't move at all
|3118|3118| 				this.FinishOrder();
|3119|    |-			}
|    |3119|+			
|3120|3120| 		},
|3121|3121| 
|3122|3122| 		"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
|3155|3155| 				}
|3156|3156| 				// Start attacking one of the newly-seen enemy (if any)
|3157|3157| 				else if (this.IsDangerousAnimal())
|3158|    |-				{
|    |3158|+				
|3159|3159| 					this.AttackVisibleEntity(msg.data.added);
|3160|    |-				}
|    |3160|+				
|3161|3161| 
|3162|3162| 				// TODO: if two units enter our range together, we'll attack the
|3163|3163| 				// 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
|3198|3198| 				}
|3199|3199| 				// Start attacking one of the newly-seen enemy (if any)
|3200|3200| 				else if (this.template.NaturalBehaviour == "violent")
|3201|    |-				{
|    |3201|+				
|3202|3202| 					this.AttackVisibleEntity(msg.data.added);
|3203|    |-				}
|    |3203|+				
|3204|3204| 			},
|3205|3205| 
|3206|3206| 			"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
|3215|3215| 		"COMBAT": "INDIVIDUAL.COMBAT", // reuse the same combat behaviour for animals
|3216|3216| 
|3217|3217| 		"WALKING": "INDIVIDUAL.WALKING",	// reuse the same walking behaviour for animals
|3218|    |-							// only used for domestic animals
|    |3218|+		// only used for domestic animals
|3219|3219| 	},
|3220|3220| };
|3221|3221| 
|    | [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
|3272|3272| 
|3273|3273| UnitAI.prototype.IsAnimal = function()
|3274|3274| {
|3275|    |-	return (this.template.NaturalBehaviour ? true : false);
|    |3275|+	return (!!this.template.NaturalBehaviour);
|3276|3276| };
|3277|3277| 
|3278|3278| 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
|3310|3310| UnitAI.prototype.GetGarrisonHolder = function()
|3311|3311| {
|3312|3312| 	if (this.IsGarrisoned())
|3313|    |-	{
|    |3313|+	
|3314|3314| 		for (let order of this.orderQueue)
|3315|3315| 			if (order.type == "Garrison")
|3316|3316| 				return order.data.target;
|3317|    |-	}
|    |3317|+	
|3318|3318| 	return INVALID_ENTITY;
|3319|3319| };
|3320|3320| 
|    | [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
|3388|3388| 		{
|3389|3389| 			let index = this.GetCurrentState().indexOf(".");
|3390|3390| 			if (index != -1)
|3391|    |-				this.UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0,index));
|    |3391|+				this.UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0, index));
|3392|3392| 			this.Stop(false);
|3393|3393| 		}
|3394|3394| 
|    | [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
|3444|3444| 		if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity)
|3445|3445| 			continue;
|3446|3446| 		if (i == 0)
|3447|    |-			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg});
|    |3447|+			this.UnitFsm.ProcessMessage(this, { "type": "PickupCanceled", "data": msg});
|3448|3448| 		else
|3449|3449| 			this.orderQueue.splice(i, 1);
|3450|3450| 		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
|3444|3444| 		if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity)
|3445|3445| 			continue;
|3446|3446| 		if (i == 0)
|3447|    |-			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg});
|    |3447|+			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg });
|3448|3448| 		else
|3449|3449| 			this.orderQueue.splice(i, 1);
|3450|3450| 		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
|3528|3528| };
|3529|3529| 
|3530|3530| 
|3531|    |-//// FSM linkage functions ////
|    |3531|+// // FSM linkage functions ////
|3532|3532| 
|3533|3533| UnitAI.prototype.SetNextState = function(state)
|3534|3534| {
|    | [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
|3702|3702| 				continue;
|3703|3703| 			if (this.orderQueue[i].type == type)
|3704|3704| 				continue;
|3705|    |-			this.orderQueue.splice(i, 0, {"type": type, "data": data});
|    |3705|+			this.orderQueue.splice(i, 0, { "type": type, "data": data});
|3706|3706| 			Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|3707|3707| 			return;
|3708|3708| 		}
|    | [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
|3702|3702| 				continue;
|3703|3703| 			if (this.orderQueue[i].type == type)
|3704|3704| 				continue;
|3705|    |-			this.orderQueue.splice(i, 0, {"type": type, "data": data});
|    |3705|+			this.orderQueue.splice(i, 0, {"type": type, "data": data });
|3706|3706| 			Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|3707|3707| 			return;
|3708|3708| 		}
|    | [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
|3716|3716| {
|3717|3717| 	// Remember the previous work orders to be able to go back to them later if required
|3718|3718| 	if (data && data.force)
|3719|    |-	{
|    |3719|+	
|3720|3720| 		if (this.IsFormationController())
|3721|3721| 			this.CallMemberFunction("UpdateWorkOrders", [type]);
|3722|3722| 		else
|3723|3723| 			this.UpdateWorkOrders(type);
|3724|    |-	}
|    |3724|+	
|3725|3725| 
|3726|3726| 	let garrisonHolder = this.IsGarrisoned() && type != "Ungarrison" ? this.GetGarrisonHolder() : null;
|3727|3727| 
|    | [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
|3793|3793| 	{
|3794|3794| 		var cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI);
|3795|3795| 		if (cmpUnitAI)
|3796|    |-		{
|    |3796|+		
|3797|3797| 			for (var i = 0; i < cmpUnitAI.orderQueue.length; ++i)
|3798|3798| 			{
|3799|3799| 				if (isWorkType(cmpUnitAI.orderQueue[i].type))
|3802|3802| 					return;
|3803|3803| 				}
|3804|3804| 			}
|3805|    |-		}
|    |3805|+		
|3806|3806| 	}
|3807|3807| 
|3808|3808| 	// 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
|3795|3795| 		if (cmpUnitAI)
|3796|3796| 		{
|3797|3797| 			for (var i = 0; i < cmpUnitAI.orderQueue.length; ++i)
|3798|    |-			{
|    |3798|+			
|3799|3799| 				if (isWorkType(cmpUnitAI.orderQueue[i].type))
|3800|3800| 				{
|3801|3801| 					this.workOrders = cmpUnitAI.orderQueue.slice(i);
|3802|3802| 					return;
|3803|3803| 				}
|3804|    |-			}
|    |3804|+			
|3805|3805| 		}
|3806|3806| 	}
|3807|3807| 
|    | [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
|3807|3807| 
|3808|3808| 	// If nothing found, take the unit orders
|3809|3809| 	for (var i = 0; i < this.orderQueue.length; ++i)
|3810|    |-	{
|    |3810|+	
|3811|3811| 		if (isWorkType(this.orderQueue[i].type))
|3812|3812| 		{
|3813|3813| 			this.workOrders = this.orderQueue.slice(i);
|3814|3814| 			return;
|3815|3815| 		}
|3816|    |-	}
|    |3816|+	
|3817|3817| };
|3818|3818| 
|3819|3819| 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
|3873|3873| 	if (data.timerRepeat === undefined)
|3874|3874| 		this.timer = undefined;
|3875|3875| 
|3876|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness});
|    |3876|+	this.UnitFsm.ProcessMessage(this, { "type": "Timer", "data": data, "lateness": lateness});
|3877|3877| };
|3878|3878| 
|3879|3879| /**
|    | [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
|3873|3873| 	if (data.timerRepeat === undefined)
|3874|3874| 		this.timer = undefined;
|3875|3875| 
|3876|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness});
|    |3876|+	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness });
|3877|3877| };
|3878|3878| 
|3879|3879| /**
|    | [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
|3908|3908| 	this.timer = undefined;
|3909|3909| };
|3910|3910| 
|3911|    |-//// Message handlers /////
|    |3911|+// // Message handlers /////
|3912|3912| 
|3913|3913| UnitAI.prototype.OnMotionChanged = function(msg)
|3914|3914| {
|    | [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
|3913|3913| UnitAI.prototype.OnMotionChanged = function(msg)
|3914|3914| {
|3915|3915| 	if (msg.starting && !msg.error)
|3916|    |-		this.UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg});
|    |3916|+		this.UnitFsm.ProcessMessage(this, { "type": "MoveStarted", "data": msg});
|3917|3917| 	else if (!msg.starting || msg.error)
|3918|3918| 		this.UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg});
|3919|3919| };
|    | [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
|3913|3913| UnitAI.prototype.OnMotionChanged = function(msg)
|3914|3914| {
|3915|3915| 	if (msg.starting && !msg.error)
|3916|    |-		this.UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg});
|    |3916|+		this.UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg });
|3917|3917| 	else if (!msg.starting || msg.error)
|3918|3918| 		this.UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg});
|3919|3919| };
|    | [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
|3915|3915| 	if (msg.starting && !msg.error)
|3916|3916| 		this.UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg});
|3917|3917| 	else if (!msg.starting || msg.error)
|3918|    |-		this.UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg});
|    |3918|+		this.UnitFsm.ProcessMessage(this, { "type": "MoveCompleted", "data": msg});
|3919|3919| };
|3920|3920| 
|3921|3921| 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
|3915|3915| 	if (msg.starting && !msg.error)
|3916|3916| 		this.UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg});
|3917|3917| 	else if (!msg.starting || msg.error)
|3918|    |-		this.UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg});
|    |3918|+		this.UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg });
|3919|3919| };
|3920|3920| 
|3921|3921| 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
|3923|3923| 	// TODO: This is a bit inefficient since every unit listens to every
|3924|3924| 	// construction message - ideally we could scope it to only the one we're building
|3925|3925| 
|3926|    |-	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg});
|    |3926|+	this.UnitFsm.ProcessMessage(this, { "type": "ConstructionFinished", "data": msg});
|3927|3927| };
|3928|3928| 
|3929|3929| 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
|3923|3923| 	// TODO: This is a bit inefficient since every unit listens to every
|3924|3924| 	// construction message - ideally we could scope it to only the one we're building
|3925|3925| 
|3926|    |-	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg});
|    |3926|+	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg });
|3927|3927| };
|3928|3928| 
|3929|3929| 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
|3948|3948| 
|3949|3949| UnitAI.prototype.OnAttacked = function(msg)
|3950|3950| {
|3951|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
|    |3951|+	this.UnitFsm.ProcessMessage(this, { "type": "Attacked", "data": msg});
|3952|3952| };
|3953|3953| 
|3954|3954| 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
|3948|3948| 
|3949|3949| UnitAI.prototype.OnAttacked = function(msg)
|3950|3950| {
|3951|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
|    |3951|+	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg });
|3952|3952| };
|3953|3953| 
|3954|3954| 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
|3953|3953| 
|3954|3954| UnitAI.prototype.OnGuardedAttacked = function(msg)
|3955|3955| {
|3956|    |-	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data});
|    |3956|+	this.UnitFsm.ProcessMessage(this, { "type": "GuardedAttacked", "data": msg.data});
|3957|3957| };
|3958|3958| 
|3959|3959| 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
|3953|3953| 
|3954|3954| UnitAI.prototype.OnGuardedAttacked = function(msg)
|3955|3955| {
|3956|    |-	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data});
|    |3956|+	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data });
|3957|3957| };
|3958|3958| 
|3959|3959| 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
|3958|3958| 
|3959|3959| UnitAI.prototype.OnHealthChanged = function(msg)
|3960|3960| {
|3961|    |-	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
|    |3961|+	this.UnitFsm.ProcessMessage(this, { "type": "HealthChanged", "from": msg.from, "to": msg.to});
|3962|3962| };
|3963|3963| 
|3964|3964| 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
|3958|3958| 
|3959|3959| UnitAI.prototype.OnHealthChanged = function(msg)
|3960|3960| {
|3961|    |-	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
|    |3961|+	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to });
|3962|3962| };
|3963|3963| 
|3964|3964| 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
|3964|3964| UnitAI.prototype.OnRangeUpdate = function(msg)
|3965|3965| {
|3966|3966| 	if (msg.tag == this.losRangeQuery)
|3967|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|    |3967|+		this.UnitFsm.ProcessMessage(this, { "type": "LosRangeUpdate", "data": msg});
|3968|3968| 	else if (msg.tag == this.losHealRangeQuery)
|3969|3969| 		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|3970|3970| };
|    | [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| UnitAI.prototype.OnRangeUpdate = function(msg)
|3965|3965| {
|3966|3966| 	if (msg.tag == this.losRangeQuery)
|3967|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|    |3967|+		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg });
|3968|3968| 	else if (msg.tag == this.losHealRangeQuery)
|3969|3969| 		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|3970|3970| };
|    | [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
|3966|3966| 	if (msg.tag == this.losRangeQuery)
|3967|3967| 		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|3968|3968| 	else if (msg.tag == this.losHealRangeQuery)
|3969|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|    |3969|+		this.UnitFsm.ProcessMessage(this, { "type": "LosHealRangeUpdate", "data": msg});
|3970|3970| };
|3971|3971| 
|3972|3972| 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
|3966|3966| 	if (msg.tag == this.losRangeQuery)
|3967|3967| 		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|3968|3968| 	else if (msg.tag == this.losHealRangeQuery)
|3969|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|    |3969|+		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg });
|3970|3970| };
|3971|3971| 
|3972|3972| 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
|3971|3971| 
|3972|3972| UnitAI.prototype.OnPackFinished = function(msg)
|3973|3973| {
|3974|    |-	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|    |3974|+	this.UnitFsm.ProcessMessage(this, { "type": "PackFinished", "packed": msg.packed});
|3975|3975| };
|3976|3976| 
|3977|3977| //// 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
|3971|3971| 
|3972|3972| UnitAI.prototype.OnPackFinished = function(msg)
|3973|3973| {
|3974|    |-	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|    |3974|+	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed });
|3975|3975| };
|3976|3976| 
|3977|3977| //// 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
|3974|3974| 	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|3975|3975| };
|3976|3976| 
|3977|    |-//// Helper functions to be called by the FSM ////
|    |3977|+// // Helper functions to be called by the FSM ////
|3978|3978| 
|3979|3979| UnitAI.prototype.GetWalkSpeed = function()
|3980|3980| {
|    | [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
|4078|4078| 	if (!cmpOwnership || cmpOwnership.GetOwner() == INVALID_PLAYER)
|4079|4079| 		return undefined;
|4080|4080| 
|4081|    |-	let cmpPosition = Engine.QueryInterface(this.entity, IID_Position)
|    |4081|+	let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
|4082|4082| 	if (!cmpPosition || !cmpPosition.IsInWorld())
|4083|4083| 		return undefined;
|4084|4084| 
|    | [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
|4163|4163| 			PlaySound(name, member);
|4164|4164| 	}
|4165|4165| 	else
|4166|    |-	{
|    |4166|+	
|4167|4167| 		// Otherwise use our own sounds
|4168|4168| 		PlaySound(name, this.entity);
|4169|    |-	}
|    |4169|+	
|4170|4170| };
|4171|4171| 
|4172|4172| /*
|    | [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
|4332|4332| 	else
|4333|4333| 		// return false? Or hope you come close enough?
|4334|4334| 		var parabolicMaxRange = 0;
|4335|    |-		//return false;
|    |4335|+		// return false;
|4336|4336| 
|4337|4337| 	// the parabole changes while walking, take something in the middle
|4338|4338| 	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
|4397|4397| 	if (this.IsFormationMember())
|4398|4398| 	{
|4399|4399| 		var cmpFormationUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI);
|4400|    |-		if (cmpFormationUnitAI && cmpFormationUnitAI.IsAttackingAsFormation()
|4401|    |-			&& cmpFormationUnitAI.order.data.target == target)
|    |4400|+		if (cmpFormationUnitAI && cmpFormationUnitAI.IsAttackingAsFormation() &&
|    |4401|+			cmpFormationUnitAI.order.data.target == target)
|4402|4402| 			return true;
|4403|4403| 	}
|4404|4404| 
|    | [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
|4565|4565| UnitAI.prototype.AttackEntityInZone = function(ents)
|4566|4566| {
|4567|4567| 	var target = ents.find(target =>
|4568|    |-		this.CanAttack(target)
|4569|    |-		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|    |4568|+		this.CanAttack(target) &&
|    |4569|+		this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|4570|4570| 		&& (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|4571|4571| 	);
|4572|4572| 	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
|4566|4566| {
|4567|4567| 	var target = ents.find(target =>
|4568|4568| 		this.CanAttack(target)
|4569|    |-		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|4570|    |-		&& (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|    |4569|+		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true)) &&
|    |4570|+		(this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|4571|4571| 	);
|4572|4572| 	if (!target)
|4573|4573| 		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
|4630|4630| 	// If we are guarding/escorting, don't abandon as long as the guarded unit is in target range of the attacker
|4631|4631| 	if (this.isGuardOf)
|4632|4632| 	{
|4633|    |-		var cmpUnitAI =  Engine.QueryInterface(target, IID_UnitAI);
|    |4633|+		var cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI);
|4634|4634| 		var cmpAttack = Engine.QueryInterface(target, IID_Attack);
|4635|4635| 		if (cmpUnitAI && cmpAttack &&
|4636|4636| 		    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
|4634|4634| 		var cmpAttack = Engine.QueryInterface(target, IID_Attack);
|4635|4635| 		if (cmpUnitAI && cmpAttack &&
|4636|4636| 		    cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type)))
|4637|    |-				return false;
|    |4637|+			return false;
|4638|4638| 	}
|4639|4639| 
|4640|4640| 	// 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
|4639|4639| 
|4640|4640| 	// Stop if we're in hold-ground mode and it's too far from the holding point
|4641|4641| 	if (this.GetStance().respondHoldGround)
|4642|    |-	{
|    |4642|+	
|4643|4643| 		if (!this.CheckTargetDistanceFromHeldPosition(target, iid, type))
|4644|4644| 			return true;
|4645|    |-	}
|    |4645|+	
|4646|4646| 
|4647|4647| 	// Stop if it's left our vision range, unless we're especially persistent
|4648|4648| 	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
|4646|4646| 
|4647|4647| 	// Stop if it's left our vision range, unless we're especially persistent
|4648|4648| 	if (!this.GetStance().respondChaseBeyondVision)
|4649|    |-	{
|    |4649|+	
|4650|4650| 		if (!this.CheckTargetIsInVisionRange(target))
|4651|4651| 			return true;
|4652|    |-	}
|    |4652|+	
|4653|4653| 
|4654|4654| 	// (Note that CCmpUnitMotion will detect if the target is lost in FoW,
|4655|4655| 	// 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
|4672|4672| 	// If we are guarding/escorting, chase at least as long as the guarded unit is in target range of the attacker
|4673|4673| 	if (this.isGuardOf)
|4674|4674| 	{
|4675|    |-		let cmpUnitAI =  Engine.QueryInterface(target, IID_UnitAI);
|    |4675|+		let cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI);
|4676|4676| 		let cmpAttack = Engine.QueryInterface(target, IID_Attack);
|4677|4677| 		if (cmpUnitAI && cmpAttack &&
|4678|4678| 		    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
|4685|4685| 	return false;
|4686|4686| };
|4687|4687| 
|4688|    |-//// External interface functions ////
|    |4688|+// // External interface functions ////
|4689|4689| 
|4690|4690| UnitAI.prototype.SetFormationController = function(ent)
|4691|4691| {
|    | [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
|4695|4695| 	// of our own formation (or ourself if not in formation)
|4696|4696| 	var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction);
|4697|4697| 	if (cmpObstruction)
|4698|    |-	{
|    |4698|+	
|4699|4699| 		if (ent == INVALID_ENTITY)
|4700|4700| 			cmpObstruction.SetControlGroup(this.entity);
|4701|4701| 		else
|4702|4702| 			cmpObstruction.SetControlGroup(ent);
|4703|    |-	}
|    |4703|+	
|4704|4704| 
|4705|4705| 	// If we were removed from a formation, let the FSM switch back to INDIVIDUAL
|4706|4706| 	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
|4838|4838| 	// if we already had an old guard order, do nothing if the target is the same
|4839|4839| 	// and the order is running, otherwise remove the previous order
|4840|4840| 	if (this.isGuardOf)
|4841|    |-	{
|    |4841|+	
|4842|4842| 		if (this.isGuardOf == target && this.order && this.order.type == "Guard")
|4843|4843| 			return;
|4844|4844| 		else
|4845|4845| 			this.RemoveGuard();
|4846|    |-	}
|    |4846|+	
|4847|4847| 
|4848|4848| 	this.AddOrder("Guard", { "target": target, "force": false }, queued);
|4849|4849| };
|    | [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
|4841|4841| 	{
|4842|4842| 		if (this.isGuardOf == target && this.order && this.order.type == "Guard")
|4843|4843| 			return;
|4844|    |-		else
|4845|    |-			this.RemoveGuard();
|    |4844|+		this.RemoveGuard();
|4846|4845| 	}
|4847|4846| 
|4848|4847| 	this.AddOrder("Guard", { "target": target, "force": false }, queued);
|    | [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
|5012|5012| 			this.WalkToTarget(target, queued);
|5013|5013| 		return;
|5014|5014| 	}
|5015|    |-	this.AddOrder("Attack", { "target": target, "force": true, "allowCapture": allowCapture}, queued);
|    |5015|+	this.AddOrder("Attack", { "target": target, "force": true, "allowCapture": allowCapture }, queued);
|5016|5016| };
|5017|5017| 
|5018|5018| /**
|    | [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
|5161|5161| 	    this.workOrders.length && this.workOrders[0].type == "Trade")
|5162|5162| 	{
|5163|5163| 		let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader);
|5164|    |-		if (cmpTrader.HasBothMarkets() && 
|    |5164|+		if (cmpTrader.HasBothMarkets() &&
|5165|5165| 		   (cmpTrader.GetFirstMarket() == target && cmpTrader.GetSecondMarket() == source ||
|5166|5166| 		    cmpTrader.GetFirstMarket() == source && cmpTrader.GetSecondMarket() == target))
|5167|5167| 		{
|    | [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
|5442|5442| 				{
|5443|5443| 					var cmpIdentity = Engine.QueryInterface(targ, IID_Identity);
|5444|5444| 					var targetClasses = this.order.data.targetClasses;
|5445|    |-					if (targetClasses.attack && cmpIdentity
|5446|    |-						&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|    |5445|+					if (targetClasses.attack && cmpIdentity &&
|    |5446|+						!MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5447|5447| 						continue;
|5448|5448| 					if (targetClasses.avoid && cmpIdentity
|5449|5449| 						&& 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
|5445|5445| 					if (targetClasses.attack && cmpIdentity
|5446|5446| 						&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5447|5447| 						continue;
|5448|    |-					if (targetClasses.avoid && cmpIdentity
|5449|    |-						&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    |5448|+					if (targetClasses.avoid && cmpIdentity &&
|    |5449|+						MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|5450|5450| 						continue;
|5451|5451| 					// Only used by the AIs to prevent some choices of targets
|5452|5452| 					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
|5468|5468| 		{
|5469|5469| 			var cmpIdentity = Engine.QueryInterface(targ, IID_Identity);
|5470|5470| 			var targetClasses = this.order.data.targetClasses;
|5471|    |-			if (cmpIdentity && targetClasses.attack
|5472|    |-				&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|    |5471|+			if (cmpIdentity && targetClasses.attack &&
|    |5472|+				!MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5473|5473| 				continue;
|5474|5474| 			if (cmpIdentity && targetClasses.avoid
|5475|5475| 				&& 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
|5471|5471| 			if (cmpIdentity && targetClasses.attack
|5472|5472| 				&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5473|5473| 				continue;
|5474|    |-			if (cmpIdentity && targetClasses.avoid
|5475|    |-				&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    |5474|+			if (cmpIdentity && targetClasses.avoid &&
|    |5475|+				MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|5476|5476| 				continue;
|5477|5477| 			// Only used by the AIs to prevent some choices of targets
|5478|5478| 			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
|5604|5604| 
|5605|5605| UnitAI.prototype.SetHeldPosition = function(x, z)
|5606|5606| {
|5607|    |-	this.heldPosition = {"x": x, "z": z};
|    |5607|+	this.heldPosition = { "x": x, "z": z};
|5608|5608| };
|5609|5609| 
|5610|5610| 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
|5604|5604| 
|5605|5605| UnitAI.prototype.SetHeldPosition = function(x, z)
|5606|5606| {
|5607|    |-	this.heldPosition = {"x": x, "z": z};
|    |5607|+	this.heldPosition = {"x": x, "z": z };
|5608|5608| };
|5609|5609| 
|5610|5610| 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
|5631|5631| 	return false;
|5632|5632| };
|5633|5633| 
|5634|    |-//// Helper functions ////
|    |5634|+// // Helper functions ////
|5635|5635| 
|5636|5636| UnitAI.prototype.CanAttack = function(target)
|5637|5637| {
|    | [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
|5835|5835| 	return cmpPack && cmpPack.IsPacking();
|5836|5836| };
|5837|5837| 
|5838|    |-//// Formation specific functions ////
|    |5838|+// // Formation specific functions ////
|5839|5839| 
|5840|5840| UnitAI.prototype.IsAttackingAsFormation = function()
|5841|5841| {
|    | [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
|5840|5840| UnitAI.prototype.IsAttackingAsFormation = function()
|5841|5841| {
|5842|5842| 	var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|5843|    |-	return cmpAttack && cmpAttack.CanAttackAsFormation()
|5844|    |-		&& this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|    |5843|+	return cmpAttack && cmpAttack.CanAttackAsFormation() &&
|    |5844|+		this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|5845|5845| };
|5846|5846| 
|5847|5847| //// 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
|5844|5844| 		&& this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|5845|5845| };
|5846|5846| 
|5847|    |-//// Animal specific functions ////
|    |5847|+// // Animal specific functions ////
|5848|5848| 
|5849|5849| UnitAI.prototype.MoveRandomly = function(distance)
|5850|5850| {

binaries/data/mods/public/simulation/components/UnitAI.js
|2413| »   »   »   »   »   »   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
|3778| »   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
|4552| »   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
|4567| »   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
|4613| »   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
|4636| »   »   ····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
|5092| »   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
| 365| »   »   ····&&·(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
|1881| »   »   »   »   »   »   var·cmpFormation·=·Engine.QueryInterface(this.formationController,·IID_Formation);
|    | [NORMAL] JSHintBear:
|    | 'cmpFormation' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2022| »   »   »   »   »   »   &&·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
|2106| »   »   »   »   »   »   »   »   ·&&·((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
|2107| »   »   »   »   »   »   »   »   ·||·(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
|2108| »   »   »   »   »   »   »   »   ·&&·(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
|2131| »   »   »   »   »   »   »   »   var·nearby·=·this.FindNearestDropsite(oldType.generic);
|    | [NORMAL] JSHintBear:
|    | 'nearby' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|2171| »   »   »   »   »   »   »   »   &&·((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
|2172| »   »   »   »   »   »   »   »   ||·(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
|2173| »   »   »   »   »   »   »   »   &&·(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
|2218| »   »   »   »   »   »   »   ||·(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
|2219| »   »   »   »   »   »   »   &&·(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
|2235| »   »   »   »   »   var·nearby·=·this.FindNearestDropsite(resourceType.generic);
|    | [NORMAL] JSHintBear:
|    | 'nearby' is already defined.

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

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

binaries/data/mods/public/simulation/components/UnitAI.js
|2427| »   »   »   »   »   »   »   ||·(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
|2428| »   »   »   »   »   »   »   &&·(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
|2448| »   »   »   »   »   var·nearby·=·this.FindNearestDropsite(resourceType.generic);
|    | [NORMAL] JSHintBear:
|    | 'nearby' is already defined.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

binaries/data/mods/public/simulation/components/UnitAI.js
|4345| »   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
|4401| »   »   »   &&·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
|4569| »   »   &&·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
|4570| »   »   &&·(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
|5092| »   var·lastPos·=·undefined;
|    | [NORMAL] JSHintBear:
|    | It's not necessary to initialize 'lastPos' to 'undefined'.

binaries/data/mods/public/simulation/components/UnitAI.js
|5446| »   »   »   »   »   »   &&·!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
|5449| »   »   »   »   »   »   &&·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
|5462| »   var·targets·=·this.GetTargetsFromUnit();
|    | [NORMAL] JSHintBear:
|    | 'targets' is already defined.

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

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

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

binaries/data/mods/public/simulation/components/UnitAI.js
|5472| »   »   »   »   &&·!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
|5475| »   »   »   »   &&·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
|5550| »   »   var·cmpVision·=·Engine.QueryInterface(this.entity,·IID_Vision);
|    | [NORMAL] JSHintBear:
|    | 'cmpVision' is already defined.

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

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

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

binaries/data/mods/public/simulation/components/UnitAI.js
|5561| »   »   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/669/display/redirect

@bb Does this still use farthest/farthest ?
I've re-read the above discussion and I'm changing my mind, I think closest-closest makes the most sense given our current game design. If we were to implement realistically what 'min-range' is supposed to be, we'd do a whole different thing.

In which case this can be committed.

wraitii requested changes to this revision.Jan 2 2019, 6:52 PM

This ends up crashing because it sends unitAI in an infinite loop... From example in commands:


In some cases (such as Formation Order.Attack), unitAI first does a range check using the obstructionManager, then asks to move in-range, but UnitMotion's MoveToTargetRange goes through its 'circle approximation' and the results between ObstructionManager and UnitMotion are contradictory, so unitAI doesn't know how to answer and this triggers an infinite recursion and the stack bails.

I think UnitAI is buggy in this case regardless since it expects CheckTargetAttackRange and MoveToTargetAttackRange to always return coherent results (which they don't - probably ought to but guaranteeing that is hard), but I'm asking for input.

This revision now requires changes to proceed.Jan 2 2019, 6:52 PM

I fix this issue in D13 by never having MoveToFooRange return 'false', since UnitAI never handles it correctly and it makes no sense anyways - if unitAI wants to do nothing when in range it should just do a range check (which it does anyways so really…).