Page MenuHomeWildfire Games

Hard-counter tooltips
Needs RevisionPublic

Authored by Stan on Dec 28 2018, 9:21 AM.

Details

Reviewers
elexis
Feldfeld
wraitii
Trac Tickets
#4130
Summary

This adds units counter information in unit tooltip in structure tree and in game, for each types of attack a unit can have (currently no units have multiple counters for different attack types but just in case).
Adds a new line for each counter an attack can have.

Test Plan
  • Check that the tooltips for counters are displayed correctly
  • Check that after researching sentries (tower_watch.json) the ship bonus goes from 2 to 7

Diff Detail

Repository
rP 0 A.D. Public Repository
Lint
Lint Skipped
Unit
Unit Tests Skipped
Build Status
Buildable 7827
Build 12731: Vulcan BuildJenkins

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

But if it's generated by script, then only the language-specific part has to be translated, right? E.g. for the Pikeman: "3.0× vs Cavalry", the "vs Cavalry" is English and has to be translated, but the "3.0×" part is probably the same in all languages.

How could you tell the probability without the knowledge about all languages?

Feldfeld updated this revision to Diff 7109.Dec 29 2018, 12:44 PM

Now it works like it should. Here are the screenshots (where i didn't bother putting my game in english). First one in vanilla, second one in Delenda Est where we can have multiple counters.



There i separate counters with ", ", i could use new lines too but that might take too much space.
Also I didn't understand for the translate calls. I know that unit classes should be translated separately (which I did in first version) since they are already translated, but then how do I do ? I suppose that putting the translate call in the object argument of sprintf is not good because it would get retranslated after (I suppose ?), and concatenating strings with sprintf is would not be good too ?

Also for the if(bonus.Classes) code, I put it there because before i saw it in DamageBonus.js code in simulation, but didn't understand why it was there, if there are Bonuses in the template there should always be at least a bonus, which should always contain Classes and Multiplier, so maybe it can just be removed, didn't try it.

Thanks for the screenshots. Perhaps you could put the counters line directly below the attack line, thus above the armour line?

The python translation script (somewhere in source/tools/l10n or i18n) scans through all source files, extracts all english strings that are marked with translate() or markForTranslation(), uploads them to transifex.com, then another script downloads the translations from transifex again and puts them into l10n/*.po files, they are loaded via C++ and the JS translate() function can then lookup the translations when the function is called for a given string. A bit more information here https://trac.wildfiregames.com/wiki/Implementation_of_Internationalization_and_Localization.
Anyhow, so, yes you can use translate(template.identity.VisibleClasses[0]) and so forth. The VisibleClasses should be translated already, so you can see if your diff got it right if they appear in french.

if there are Bonuses in the template there should always be at least a bonus

Whether an empty list of bonuses is allowed is determined by the Schema in the according simulation component. Check the first 5 lines of Attack.js, it says "zeroOrMore", so that should become 1+ (whatever syntax) if we want to change that.

Feldfeld updated this revision to Diff 7115.Dec 29 2018, 3:35 PM

Here is how it looks after moving the line down attack :


Perhaps if we want to keep it in this location we can remove word against and write unit classes in yellow ?
In Attack.js zeroOrMore applies for each bonus but i get the bonus by iterating on it so there should be no problem in removing that test, and "<element name='Classes' in Attack.js to me looks like this part is not optional if we get there in the hierarchy. So i removed the if and tried with a template that had <Bonuses></Bonuses> and it seemed to be just fine.
For translation what worried me the way I did is if translaters won't get semi-translated strings after ?

  • translateWithContext("separator for damage bonuses", ", ")
  • I suspect the "\n" ternary and the first variable can be avoided by creating an array and join() each. Array functions can be neat for this (someArray.map(item => someStringUsing(item)).join(separator)), but that's code fiddling which can be done when everything else works as intended.

About counters in general, I guess this will impact the effectiveness of petra AI...

Feldfeld updated this revision to Diff 7132.Dec 30 2018, 8:55 AM

What do you prefer ? As done in first 2 screenshots, or in these :



Or I try to mix with attack type stats, or other proposal ?

I didn't notice the difference in the two screenshots (it would help if they're in english btw).
I only noticed that the unitFont/color should only be used for units (like seconds, meters), not for Unit types.

binaries/data/mods/public/simulation/components/GuiInterface.js
412

missing semicolon
-1 tab

This is the default way, and the right way to do it assuming that auras/techs can change the counters, also the way I explained.
(The GetEntiyState function is a significant performance bottleneck, last addressed in #4322, in particular when selecting as many units as allowed (currently capped at 200)).
But perhaps one could also load the template data from the EntityState in tooltips.js to avoid this copy? Then again not sure which of the two variants will turn out to be the faster / feasible / cleaner mechanism. (So maybe we end up with this GUIInterface diff as is.)

elexis retitled this revision from Automatically updates unit tooltip to include hard counter information to Hard-counter tooltips.Dec 30 2018, 2:21 PM

Yes, classes and other texts ought to be white, not orange.

Feldfeld updated this revision to Diff 7165.Dec 31 2018, 9:14 AM

By the first 2 screenshots, i meant overall in this differential. I posted 5 in total.
If unit classes are not in yellow wouldn't it look weird if line is inbetween attack and armor tooltip, with nothing other than digits in white ? The first 2 screenshot show the result if i put it on the top, where i would say white font looks less weird but putting counters here is also not logically pertinent. In the third screenshot the line is after attack tooltip and in white(but with "against" that is unnecessary and removed now)
I didn't find the missing semi-colon.
For effectiveness of petra, true it would reduce it but it can be possible to make him train counters to his opponent units (AoM AI does it IIRC). Of course, that AI train units well doesn't mean it would use those units well. (also i think AI has a big room for improvement)
And now i just noticed i removed sprintf where i shouldn't

smiley added a subscriber: smiley.Dec 31 2018, 10:02 AM

Re: AI
With current behavior, not sure how such a thing could be done in an acceptable way. The quick and easy fix could end up being too unfair. People could attack the AI only to find it having the perfect army. An alternative option is to rely on past attack compositions. Which would of course allow people to “play” the AI. I guess the only sane option is to finally implement scouting.

Could also consider to delay reaction of the AI by a multiple of AI difficulty, with 0 for the very hard one

elexis added a subscriber: borg-.Dec 31 2018, 11:25 AM
  • The counters tooltip should be right below the attack stats probably, since it modifies the attack stats. I suppose the icons arent right to the thumbnail anymore and that's why you put it there? By the way if @borg- has an opinion he might voice it here too.
  • The word "Counters:" should be bold like the other captions.
In D1707#68254, @smiley wrote:

Re: AI

Not sure what you mean with the AI being to good, the problem I was refering to is that the AI has no maintainer anymore and won't take counters into account.

binaries/data/mods/public/globalscripts/Templates.js
220

{} can be removed since it contains only one statement
still mising semicolon x = y; (check what Vulcan posts or paste code to www.jshint.com for syntax checks (we use ES6 btw)))

binaries/data/mods/public/gui/common/tooltips.js
851

Looks nicer without the first and other variables, right?
Try map https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/map

let bonusBody = template.attack[attackType].bonuses.map(bonus => bodyFont(...) + " " + ...)

(The bonus variable could be ommitted by using template.attack[attackType].bonuses[key] twice and adding a newline. The string variable can be inlined too with some \n and indentation).

multiplier + " " + classes should use a sprintf too I think, languages might reverse that or add characters somewhere, or more space or whatever.

The proposal is about adding a tooltip to something existing. If I was in position to attribute adjectives, I would qualify that of nice and desired (#4130).
I wonder what is the link between an AI and a tooltip.
Did the new AI read tooltip?

AI talk is about the eventuality that more hard counters are added
But the proposal itself doesn't affect AI yes

Feldfeld added inline comments.Dec 31 2018, 1:30 PM
binaries/data/mods/public/gui/common/tooltips.js
851

If I try map it fails (it says it's not a function), may it be because template.attack[attackType].bonuses is an object (not array) or i failed the syntax ?

elexis added inline comments.Dec 31 2018, 1:51 PM
binaries/data/mods/public/gui/common/tooltips.js
851

Oh, right, sorry for the wasted time. It is an object, not an array. One could use Object.keys(bonuses).map(bonusType => bonuses[bonusType].bla) but that will mean more objects are created, making this slower than your current function, so screw that array function.

elexis updated the Trac tickets for this revision.Dec 31 2018, 1:51 PM
Feldfeld updated this revision to Diff 7167.Dec 31 2018, 2:06 PM

Here's how it looks now :


Please remove the space before the colon.

Also, there is nothing between the value and the class. I'd prefer "3.0× vs Cavalry" instead of "3.0 Cavalry".

And how does it look like if you click on the tooltip "to view more information"?

There was a space in french translation so I missed it
In more information tooltip :

elexis accepted this revision.Jan 3 2019, 10:45 AM

The minimum number of bonuses should be 1, not 0, as you mentioned in the lobby. Can be done separately, but the patch implicitly relies on that change already.
I guess the evidence and me witnissing it force me to accept this and thank you for serving.

binaries/data/mods/public/gui/common/tooltips.js
838

-1 space

851

", " still needs a translateWithContext, but that can be fixed at committing stage too.
string variable can be inlined. Also makes it easier to change "Counters %(attackType)s : " to "Counters %(attackType)s : %(counters)s"

binaries/data/mods/public/simulation/components/GuiInterface.js
412

Given that we have cmpAttavck.GetBonusTemplate already, passing it through the GUIInterface is justified, despite the unfortunate performance impact. (The cmpAttack function may change the bonuses, if not now then in the future or for mods)

This revision is now accepted and ready to land.Jan 3 2019, 10:45 AM
Nescio added inline comments.Jan 12 2019, 3:19 PM
binaries/data/mods/public/gui/common/tooltips.js
838
let string = headerFont(sprintf(translate("%(attackType)s Counters: "), {
845
bonusesBody.push(sprintf(translate("%(multiplier)s× vs %(classes)s"), {
Feldfeld updated this revision to Diff 7514.Mar 3 2019, 9:03 PM

Tried to fix compatibility problem with tech but i didn't test it, also for some reasons the decimals .0 will not show up when the multiplier is an integer and this is not the unit card for some reasons

Stan added a subscriber: Stan.Mar 3 2019, 9:44 PM
Stan added inline comments.
binaries/data/mods/public/globalscripts/Templates.js
11

I didn't manage to get it work, can you try whether it works for you ?

binaries/data/mods/public/simulation/components/Attack.js
476

You forgot that change :)

Angen added a subscriber: Angen.Mar 17 2019, 5:28 PM
Angen added inline comments.
binaries/data/mods/public/simulation/components/Attack.js
476

let bonus creates local variable which is changed and forgot after every loop iteration. You are not changing nothing in template.Bonuses which you are returning later

Stan requested changes to this revision.May 10 2019, 8:44 AM

The change in Attack.js shouldn't be there.

This revision now requires changes to proceed.May 10 2019, 8:44 AM
smiley added inline comments.May 10 2019, 9:33 AM
binaries/data/mods/public/simulation/components/Attack.js
476

let bonus creates local variable which is changed and forgot after every loop iteration.

Not necessarily.

var a = [{"a": 4, "b": 7}, {"a": 5, "b": 8}
for (let obj of a) obj.b += 10;
warn(uneval(a));

Objects are passed by reference. This would have been correct if you were not iterating the keys. If you print out bonus in the loop, you would only see the key names in the first object. Not the object the key corresponds to.
I have no clue about the semantics of this change. (Is this needed or not?)

Stan added inline comments.May 10 2019, 9:37 AM
binaries/data/mods/public/simulation/components/Attack.js
476

Change is from another diff of mine :)
It allows bonus modifications from tech.

smiley added inline comments.May 10 2019, 10:13 AM
binaries/data/mods/public/simulation/components/Attack.js
476

Ah, I see.

Stan added inline comments.May 10 2019, 3:17 PM
binaries/data/mods/public/simulation/components/Attack.js
474

{ on new line.

476

Actually I was wrong, this is not from my patch, but it is indeed the reason why my patch and this one are not compatible. Since the multiplier do not get applied correctly here, the tooltip is always wrong.
This should do the trick I think.

if (template.Bonuses) 
{
	for (let bonusKey in template.Bonuses)
	{
		let bonus = template.Bonuses[bonusKey];
		bonus.Multiplier = ApplyValueModificationsToEntity("Attack/" + type + "/Bonuses/" + bonusKey + "/Multiplier", +bonus.Multiplier, this.entity);
	}

}
Stan commandeered this revision.Jun 6 2019, 10:45 PM
Stan edited reviewers, added: Feldfeld; removed: Stan.
Stan added a reviewer: wraitii.
This revision is now accepted and ready to land.Jun 6 2019, 10:45 PM
Stan updated this revision to Diff 8356.EditedJun 6 2019, 10:50 PM
Stan edited the test plan for this revision. (Show Details)

Now works with bonuses changed via tech following rP22346

  • tower_watch.json and athen_defense_tower are just here for testing they won't be committed.
  • Kept the credit for @Feldfeld as he wrote most of the patch.
Stan updated this revision to Diff 8357.Jun 6 2019, 10:56 PM
Stan marked 13 inline comments as done.
  • Fix the remaining comments.

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

Linter detected issues:
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
| 526| 526| 
| 527| 527| 		let horizSpeed = +this.template[type].Projectile.Speed;
| 528| 528| 		let gravity = +this.template[type].Projectile.Gravity;
| 529|    |-		//horizSpeed /= 2; gravity /= 2; // slow it down for testing
|    | 529|+		// horizSpeed /= 2; gravity /= 2; // slow it down for testing
| 530| 530| 
| 531| 531| 		let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
| 532| 532| 		if (!cmpPosition || !cmpPosition.IsInWorld())
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
| 645| 645| 			});
| 646| 646| 	}
| 647| 647| 	else
| 648|    |-	{
|    | 648|+	
| 649| 649| 		// Melee attack - hurt the target immediately
| 650| 650| 		cmpDamage.CauseDamage({
| 651| 651| 			"strengths": this.GetAttackStrengths(type),
| 655| 655| 			"type": type,
| 656| 656| 			"attackerOwner": attackerOwner
| 657| 657| 		});
| 658|    |-	}
|    | 658|+	
| 659| 659| };
| 660| 660| 
| 661| 661| /**

binaries/data/mods/public/simulation/components/Attack.js
| 516| ·»   let·cmpDamage·=·Engine.QueryInterface(SYSTEM_ENTITY,·IID_Damage);
|    | [NORMAL] ESLintBear (no-mixed-spaces-and-tabs):
|    | Mixed spaces and tabs.

binaries/data/mods/public/simulation/components/Attack.js
| 620| »   »   cmpTimer.SetTimeout(SYSTEM_ENTITY,·IID_Damage,·"MissileHit",·timeToTarget·*·1000·+·+this.template[type].Delay,·data);
|    | [NORMAL] JSHintBear:
|    | Confusing plusses.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 393| 393| function getRepairTimeTooltip(entState)
| 394| 394| {
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396|    |-			"label": headerFont(translate("Number of repairers:")),
|    | 396|+		"label": headerFont(translate("Number of repairers:")),
| 397| 397| 			"details": entState.repairable.numBuilders
| 398| 398| 		}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 394| 394| {
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396| 396| 			"label": headerFont(translate("Number of repairers:")),
| 397|    |-			"details": entState.repairable.numBuilders
|    | 397|+		"details": entState.repairable.numBuilders
| 398| 398| 		}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
| 400| 400| 			"Add another worker to speed up the repairs by %(second)s second.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396| 396| 			"label": headerFont(translate("Number of repairers:")),
| 397| 397| 			"details": entState.repairable.numBuilders
| 398|    |-		}) + "\n" + (entState.repairable.numBuilders ?
|    | 398|+	}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
| 400| 400| 			"Add another worker to speed up the repairs by %(second)s second.",
| 401| 401| 			"Add another worker to speed up the repairs by %(second)s seconds.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 415| 415| function getBuildTimeTooltip(entState)
| 416| 416| {
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418|    |-			"label": headerFont(translate("Number of builders:")),
|    | 418|+		"label": headerFont(translate("Number of builders:")),
| 419| 419| 			"details": entState.foundation.numBuilders
| 420| 420| 		}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 416| 416| {
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418| 418| 			"label": headerFont(translate("Number of builders:")),
| 419|    |-			"details": entState.foundation.numBuilders
|    | 419|+		"details": entState.foundation.numBuilders
| 420| 420| 		}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
| 422| 422| 			"Add another worker to speed up the construction by %(second)s second.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418| 418| 			"label": headerFont(translate("Number of builders:")),
| 419| 419| 			"details": entState.foundation.numBuilders
| 420|    |-		}) + "\n" + (entState.foundation.numBuilders ?
|    | 420|+	}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
| 422| 422| 			"Add another worker to speed up the construction by %(second)s second.",
| 423| 423| 			"Add another worker to speed up the construction by %(second)s seconds.",
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 825| 825| 
| 826| 826| function getCountersTooltip(template)
| 827| 827| {
| 828|    |-	
|    | 828|+
| 829| 829| 	if (!template.attack)
| 830| 830| 		return "";
| 831| 831| 
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 834| 834| 	{
| 835| 835| 		if (!template.attack[attackType].bonuses)
| 836| 836| 			continue;
| 837|    |-			
|    | 837|+
| 838| 838| 		let string = headerFont(sprintf(translate("Counters %(attackType)s : "), {
| 839| 839| 			"attackType": translate(attackType)
| 840| 840| 		}));
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|  66|  66| 		let phase = "";
|  67|  67| 		let cmpTechnologyManager = QueryPlayerIDInterface(i, IID_TechnologyManager);
|  68|  68| 		if (cmpTechnologyManager)
|  69|    |-		{
|    |  69|+		
|  70|  70| 			if (cmpTechnologyManager.IsTechnologyResearched("phase_city"))
|  71|  71| 				phase = "city";
|  72|  72| 			else if (cmpTechnologyManager.IsTechnologyResearched("phase_town"))
|  73|  73| 				phase = "town";
|  74|  74| 			else if (cmpTechnologyManager.IsTechnologyResearched("phase_village"))
|  75|  75| 				phase = "village";
|  76|    |-		}
|    |  76|+		
|  77|  77| 
|  78|  78| 		// store player ally/neutral/enemy data as arrays
|  79|  79| 		let allies = [];
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 398| 398| 			let timers = cmpAttack.GetTimers(type);
| 399| 399| 			ret.attack[type].prepareTime = timers.prepare;
| 400| 400| 			ret.attack[type].repeatTime = timers.repeat;
| 401|    |-			
|    | 401|+
| 402| 402| 			let bonuses = cmpAttack.GetBonusTemplate(type);
| 403| 403| 			if (bonuses)
| 404| 404| 			{
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 421| 421| 			ret.attack[type].elevationBonus = range.elevationBonus;
| 422| 422| 
| 423| 423| 			if (cmpUnitAI && cmpPosition && cmpPosition.IsInWorld())
| 424|    |-			{
|    | 424|+			
| 425| 425| 				// For units, take the range in front of it, no spread. So angle = 0
| 426| 426| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 0);
| 427|    |-			}
|    | 427|+			
| 428| 428| 			else if(cmpPosition && cmpPosition.IsInWorld())
| 429| 429| 			{
| 430| 430| 				// For buildings, take the average elevation around it. So angle = 2*pi
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 426| 426| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 0);
| 427| 427| 			}
| 428| 428| 			else if(cmpPosition && cmpPosition.IsInWorld())
| 429|    |-			{
|    | 429|+			
| 430| 430| 				// For buildings, take the average elevation around it. So angle = 2*pi
| 431| 431| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 2*Math.PI);
| 432|    |-			}
|    | 432|+			
| 433| 433| 			else
| 434| 434| 			{
| 435| 435| 				// not in world, set a default?
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 431| 431| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 2*Math.PI);
| 432| 432| 			}
| 433| 433| 			else
| 434|    |-			{
|    | 434|+			
| 435| 435| 				// not in world, set a default?
| 436| 436| 				ret.attack[type].elevationAdaptedRange = ret.attack.maxRange;
| 437|    |-			}
|    | 437|+			
| 438| 438| 		}
| 439| 439| 	}
| 440| 440| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 802| 802| 		updateEntityColor(data.showAllStatusBars && (i == player || player == -1) ?
| 803| 803| 			[IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer, IID_StatusBars] :
| 804| 804| 			[IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer],
| 805|    |-			cmpRangeManager.GetEntitiesByPlayer(i));
|    | 805|+		cmpRangeManager.GetEntitiesByPlayer(i));
| 806| 806| 	}
| 807| 807| 	updateEntityColor([IID_Selectable, IID_StatusBars], data.selected);
| 808| 808| 	Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager).UpdateColors();
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1321|1321| 		}
|1322|1322| 	}
|1323|1323| 	else
|1324|    |-	{
|    |1324|+	
|1325|1325| 		// Didn't snap to an existing entity, add the starting tower manually. To prevent odd-looking rotation jumps
|1326|1326| 		// when shift-clicking to build a wall, reuse the placement angle that was last seen on a validly positioned
|1327|1327| 		// wall piece.
|1342|1342| 			"pos": start.pos,
|1343|1343| 			"angle": previewEntities.length > 0 ? previewEntities[0].angle : this.placementWallLastAngle
|1344|1344| 		});
|1345|    |-	}
|    |1345|+	
|1346|1346| 
|1347|1347| 	if (end.pos)
|1348|1348| 	{
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1345|1345| 	}
|1346|1346| 
|1347|1347| 	if (end.pos)
|1348|    |-	{
|    |1348|+	
|1349|1349| 		// Analogous to the starting side case above
|1350|1350| 		if (end.snappedEnt && end.snappedEnt != INVALID_ENTITY)
|1351|1351| 		{
|1383|1383| 				"pos": end.pos,
|1384|1384| 				"angle": previewEntities.length > 0 ? previewEntities[previewEntities.length-1].angle : this.placementWallLastAngle
|1385|1385| 			});
|1386|    |-	}
|    |1386|+	
|1387|1387| 
|1388|1388| 	let cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
|1389|1389| 	if (!cmpTerrain)
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1561|1561| 
|1562|1562| 		let cmpVisual = Engine.QueryInterface(ent, IID_Visual);
|1563|1563| 		if (cmpVisual)
|1564|    |-		{
|    |1564|+		
|1565|1565| 			if (!allPiecesValid || !canAfford)
|1566|1566| 				cmpVisual.SetShadingColor(1.4, 0.4, 0.4, 1);
|1567|1567| 			else
|1568|1568| 				cmpVisual.SetShadingColor(1, 1, 1, 1);
|1569|    |-		}
|    |1569|+		
|1570|1570| 
|1571|1571| 		++entPool.numUsed;
|1572|1572| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1635|1635| 			{
|1636|1636| 				minDist2 = dist2;
|1637|1637| 				minDistEntitySnapData = {
|1638|    |-						"x": pos.x,
|    |1638|+					"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1636|1636| 				minDist2 = dist2;
|1637|1637| 				minDistEntitySnapData = {
|1638|1638| 						"x": pos.x,
|1639|    |-						"z": pos.z,
|    |1639|+					"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|1642|1642| 				};
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1637|1637| 				minDistEntitySnapData = {
|1638|1638| 						"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|    |-						"angle": cmpPosition.GetRotation().y,
|    |1640|+					"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|1642|1642| 				};
|1643|1643| 			}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1638|1638| 						"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|    |-						"ent": ent
|    |1641|+					"ent": ent
|1642|1642| 				};
|1643|1643| 			}
|1644|1644| 		}
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1783|1783| 			result.gain = cmpEntityTrader.GetGoods().amount;
|1784|1784| 	}
|1785|1785| 	else if (data.target === secondMarket)
|1786|    |-	{
|    |1786|+	
|1787|1787| 		result = {
|1788|1788| 			"type": "is second",
|1789|1789| 			"gain": cmpEntityTrader.GetGoods().amount,
|1790|1790| 		};
|1791|    |-	}
|    |1791|+	
|1792|1792| 	else if (!firstMarket)
|1793|1793| 	{
|1794|1794| 		result = { "type": "set first" };
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1790|1790| 		};
|1791|1791| 	}
|1792|1792| 	else if (!firstMarket)
|1793|    |-	{
|    |1793|+	
|1794|1794| 		result = { "type": "set first" };
|1795|    |-	}
|    |1795|+	
|1796|1796| 	else if (!secondMarket)
|1797|1797| 	{
|1798|1798| 		result = {
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1794|1794| 		result = { "type": "set first" };
|1795|1795| 	}
|1796|1796| 	else if (!secondMarket)
|1797|    |-	{
|    |1797|+	
|1798|1798| 		result = {
|1799|1799| 			"type": "set second",
|1800|1800| 			"gain": cmpEntityTrader.CalculateGain(firstMarket, data.target),
|1801|1801| 		};
|1802|    |-	}
|    |1802|+	
|1803|1803| 	else
|1804|1804| 	{
|1805|1805| 		// Else both markets are not null and target is different from them
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1801|1801| 		};
|1802|1802| 	}
|1803|1803| 	else
|1804|    |-	{
|    |1804|+	
|1805|1805| 		// Else both markets are not null and target is different from them
|1806|1806| 		result = { "type": "set first" };
|1807|    |-	}
|    |1807|+	
|1808|1808| 	return result;
|1809|1809| };
|1810|1810| 
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '||' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|  87|  87| 		// If the elements are still strings, split them by space or by '+'
|  88|  88| 		if (typeof sublist == "string")
|  89|  89| 			sublist = sublist.split(/[+\s]+/);
|  90|    |-		if (sublist.every(c => (c[0] == "!" && classes.indexOf(c.substr(1)) == -1)
|  91|    |-		                    || (c[0] != "!" && classes.indexOf(c) != -1)))
|    |  90|+		if (sublist.every(c => (c[0] == "!" && classes.indexOf(c.substr(1)) == -1) ||
|    |  91|+		                    (c[0] != "!" && classes.indexOf(c) != -1)))
|  92|  92| 			return true;
|  93|  93| 	}
|  94|  94| 
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 207| 207| 				for (let damageType of damageTypes.GetTypes())
| 208| 208| 					ret.attack[type].splash[damageType] = getAttackStat("Splash/" + damageType);
| 209| 209| 			}
| 210|    |-			
|    | 210|+
| 211| 211| 			if (template.Attack[type].Bonuses)
| 212| 212| 			{
| 213| 213| 				ret.attack[type].bonuses = {};
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'for-in'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 211| 211| 			if (template.Attack[type].Bonuses)
| 212| 212| 			{
| 213| 213| 				ret.attack[type].bonuses = {};
| 214|    |-				for (let bonus in template.Attack[type].Bonuses) {
|    | 214|+				for (let bonus in template.Attack[type].Bonuses) 
| 215| 215| 					ret.attack[type].bonuses[bonus] = {
| 216| 216| 						"classes": template.Attack[type].Bonuses[bonus].Classes,
| 217| 217| 						"multiplier": getAttackStat("Bonuses/" + bonus + "/Multiplier")
| 218| 218| 					};
| 219|    |-				}
|    | 219|+				
| 220| 220| 			}
| 221| 221| 		}
| 222| 222| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 237| 237| 		{
| 238| 238| 			let aura = auraTemplates[auraID];
| 239| 239| 			ret.auras[auraID] = {
| 240|    |-					"name": aura.auraName,
|    | 240|+				"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243| 243| 				};
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 238| 238| 			let aura = auraTemplates[auraID];
| 239| 239| 			ret.auras[auraID] = {
| 240| 240| 					"name": aura.auraName,
| 241|    |-					"description": aura.auraDescription || null,
|    | 241|+				"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243| 243| 				};
| 244| 244| 		}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 239| 239| 			ret.auras[auraID] = {
| 240| 240| 					"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242|    |-					"radius": aura.radius || null
|    | 242|+				"radius": aura.radius || null
| 243| 243| 				};
| 244| 244| 		}
| 245| 245| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 240| 240| 					"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243|    |-				};
|    | 243|+			};
| 244| 244| 		}
| 245| 245| 	}
| 246| 246| 

binaries/data/mods/public/globalscripts/Templates.js
| 214| »   »   »   »   for·(let·bonus·in·template.Attack[type].Bonuses)·{
|    | [NORMAL] ESLintBear (brace-rules/brace-on-same-line):
|    | Opening curly brace appears on the same line as controlling statement.

binaries/data/mods/public/globalscripts/Templates.js
|  91| »   »   ····················||·(c[0]·!=·"!"·&&·classes.indexOf(c)·!=·-1)))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '||'; readers may interpret this as an expression boundary.
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 452| 452| 				continue;
| 453| 453| 
| 454| 454| 			if (state.pack.progress == 0)
| 455|    |-			{
|    | 455|+			
| 456| 456| 				if (state.pack.packed)
| 457| 457| 					checks.unpackButton = true;
| 458| 458| 				else
| 459| 459| 					checks.packButton = true;
| 460|    |-			}
|    | 460|+			
| 461| 461| 			else if (state.pack.packed)
| 462| 462| 				checks.unpackCancelButton = true;
| 463| 463| 			else
|    | [NORMAL] ESLintBear (space-before-function-paren):
|    | Unexpected space before function parentheses.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 763| 763| 				addResearchToQueue(data.item.researchFacilityId, t);
| 764| 764| 			})(tech);
| 765| 765| 
| 766|    |-			button.onPressRight = (t => function () {
|    | 766|+			button.onPressRight = (t => function() {
| 767| 767| 				showTemplateDetails(
| 768| 768| 					t,
| 769| 769| 					GetTemplateData(data.unitEntStates.find(state => state.id == data.item.researchFacilityId).template).nativeCiv);
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 941| 941| 			"player": data.player
| 942| 942| 		});
| 943| 943| 
| 944|    |-		let unitIds = data.unitEntStates.map(status => status.id)
|    | 944|+		let unitIds = data.unitEntStates.map(status => status.id);
| 945| 945| 		let [buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch] =
| 946| 946| 			getTrainingStatus(unitIds, data.item, data.playerState);
| 947| 947| 

binaries/data/mods/public/gui/session/selection_panels.js
|  48| »   »   »   switch·(data.item)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
|  59| »   »   switch·(data.item)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
| 731| »   »   »   »   »   »   switch·(entity.check)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
| 944| »   »   let·unitIds·=·data.unitEntStates.map(status·=>·status.id)
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.
Executing section cli...

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

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

Linter detected issues:
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '||' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|  87|  87| 		// If the elements are still strings, split them by space or by '+'
|  88|  88| 		if (typeof sublist == "string")
|  89|  89| 			sublist = sublist.split(/[+\s]+/);
|  90|    |-		if (sublist.every(c => (c[0] == "!" && classes.indexOf(c.substr(1)) == -1)
|  91|    |-		                    || (c[0] != "!" && classes.indexOf(c) != -1)))
|    |  90|+		if (sublist.every(c => (c[0] == "!" && classes.indexOf(c.substr(1)) == -1) ||
|    |  91|+		                    (c[0] != "!" && classes.indexOf(c) != -1)))
|  92|  92| 			return true;
|  93|  93| 	}
|  94|  94| 
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 207| 207| 				for (let damageType of damageTypes.GetTypes())
| 208| 208| 					ret.attack[type].splash[damageType] = getAttackStat("Splash/" + damageType);
| 209| 209| 			}
| 210|    |-			
|    | 210|+
| 211| 211| 			if (template.Attack[type].Bonuses)
| 212| 212| 			{
| 213| 213| 				ret.attack[type].bonuses = {};
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'for-in'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 211| 211| 			if (template.Attack[type].Bonuses)
| 212| 212| 			{
| 213| 213| 				ret.attack[type].bonuses = {};
| 214|    |-				for (let bonus in template.Attack[type].Bonuses) {
|    | 214|+				for (let bonus in template.Attack[type].Bonuses) 
| 215| 215| 					ret.attack[type].bonuses[bonus] = {
| 216| 216| 						"classes": template.Attack[type].Bonuses[bonus].Classes,
| 217| 217| 						"multiplier": getAttackStat("Bonuses/" + bonus + "/Multiplier")
| 218| 218| 					};
| 219|    |-				}
|    | 219|+				
| 220| 220| 			}
| 221| 221| 		}
| 222| 222| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 237| 237| 		{
| 238| 238| 			let aura = auraTemplates[auraID];
| 239| 239| 			ret.auras[auraID] = {
| 240|    |-					"name": aura.auraName,
|    | 240|+				"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243| 243| 				};
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 238| 238| 			let aura = auraTemplates[auraID];
| 239| 239| 			ret.auras[auraID] = {
| 240| 240| 					"name": aura.auraName,
| 241|    |-					"description": aura.auraDescription || null,
|    | 241|+				"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243| 243| 				};
| 244| 244| 		}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 239| 239| 			ret.auras[auraID] = {
| 240| 240| 					"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242|    |-					"radius": aura.radius || null
|    | 242|+				"radius": aura.radius || null
| 243| 243| 				};
| 244| 244| 		}
| 245| 245| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 240| 240| 					"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243|    |-				};
|    | 243|+			};
| 244| 244| 		}
| 245| 245| 	}
| 246| 246| 

binaries/data/mods/public/globalscripts/Templates.js
| 214| »   »   »   »   for·(let·bonus·in·template.Attack[type].Bonuses)·{
|    | [NORMAL] ESLintBear (brace-rules/brace-on-same-line):
|    | Opening curly brace appears on the same line as controlling statement.

binaries/data/mods/public/globalscripts/Templates.js
|  91| »   »   ····················||·(c[0]·!=·"!"·&&·classes.indexOf(c)·!=·-1)))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '||'; readers may interpret this as an expression boundary.
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
| 526| 526| 
| 527| 527| 		let horizSpeed = +this.template[type].Projectile.Speed;
| 528| 528| 		let gravity = +this.template[type].Projectile.Gravity;
| 529|    |-		//horizSpeed /= 2; gravity /= 2; // slow it down for testing
|    | 529|+		// horizSpeed /= 2; gravity /= 2; // slow it down for testing
| 530| 530| 
| 531| 531| 		let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
| 532| 532| 		if (!cmpPosition || !cmpPosition.IsInWorld())
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
| 645| 645| 			});
| 646| 646| 	}
| 647| 647| 	else
| 648|    |-	{
|    | 648|+	
| 649| 649| 		// Melee attack - hurt the target immediately
| 650| 650| 		cmpDamage.CauseDamage({
| 651| 651| 			"strengths": this.GetAttackStrengths(type),
| 655| 655| 			"type": type,
| 656| 656| 			"attackerOwner": attackerOwner
| 657| 657| 		});
| 658|    |-	}
|    | 658|+	
| 659| 659| };
| 660| 660| 
| 661| 661| /**

binaries/data/mods/public/simulation/components/Attack.js
| 516| ·»   let·cmpDamage·=·Engine.QueryInterface(SYSTEM_ENTITY,·IID_Damage);
|    | [NORMAL] ESLintBear (no-mixed-spaces-and-tabs):
|    | Mixed spaces and tabs.

binaries/data/mods/public/simulation/components/Attack.js
| 620| »   »   cmpTimer.SetTimeout(SYSTEM_ENTITY,·IID_Damage,·"MissileHit",·timeToTarget·*·1000·+·+this.template[type].Delay,·data);
|    | [NORMAL] JSHintBear:
|    | Confusing plusses.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 393| 393| function getRepairTimeTooltip(entState)
| 394| 394| {
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396|    |-			"label": headerFont(translate("Number of repairers:")),
|    | 396|+		"label": headerFont(translate("Number of repairers:")),
| 397| 397| 			"details": entState.repairable.numBuilders
| 398| 398| 		}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 394| 394| {
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396| 396| 			"label": headerFont(translate("Number of repairers:")),
| 397|    |-			"details": entState.repairable.numBuilders
|    | 397|+		"details": entState.repairable.numBuilders
| 398| 398| 		}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
| 400| 400| 			"Add another worker to speed up the repairs by %(second)s second.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396| 396| 			"label": headerFont(translate("Number of repairers:")),
| 397| 397| 			"details": entState.repairable.numBuilders
| 398|    |-		}) + "\n" + (entState.repairable.numBuilders ?
|    | 398|+	}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
| 400| 400| 			"Add another worker to speed up the repairs by %(second)s second.",
| 401| 401| 			"Add another worker to speed up the repairs by %(second)s seconds.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 415| 415| function getBuildTimeTooltip(entState)
| 416| 416| {
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418|    |-			"label": headerFont(translate("Number of builders:")),
|    | 418|+		"label": headerFont(translate("Number of builders:")),
| 419| 419| 			"details": entState.foundation.numBuilders
| 420| 420| 		}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 416| 416| {
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418| 418| 			"label": headerFont(translate("Number of builders:")),
| 419|    |-			"details": entState.foundation.numBuilders
|    | 419|+		"details": entState.foundation.numBuilders
| 420| 420| 		}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
| 422| 422| 			"Add another worker to speed up the construction by %(second)s second.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418| 418| 			"label": headerFont(translate("Number of builders:")),
| 419| 419| 			"details": entState.foundation.numBuilders
| 420|    |-		}) + "\n" + (entState.foundation.numBuilders ?
|    | 420|+	}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
| 422| 422| 			"Add another worker to speed up the construction by %(second)s second.",
| 423| 423| 			"Add another worker to speed up the construction by %(second)s seconds.",
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 452| 452| 				continue;
| 453| 453| 
| 454| 454| 			if (state.pack.progress == 0)
| 455|    |-			{
|    | 455|+			
| 456| 456| 				if (state.pack.packed)
| 457| 457| 					checks.unpackButton = true;
| 458| 458| 				else
| 459| 459| 					checks.packButton = true;
| 460|    |-			}
|    | 460|+			
| 461| 461| 			else if (state.pack.packed)
| 462| 462| 				checks.unpackCancelButton = true;
| 463| 463| 			else
|    | [NORMAL] ESLintBear (space-before-function-paren):
|    | Unexpected space before function parentheses.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 763| 763| 				addResearchToQueue(data.item.researchFacilityId, t);
| 764| 764| 			})(tech);
| 765| 765| 
| 766|    |-			button.onPressRight = (t => function () {
|    | 766|+			button.onPressRight = (t => function() {
| 767| 767| 				showTemplateDetails(
| 768| 768| 					t,
| 769| 769| 					GetTemplateData(data.unitEntStates.find(state => state.id == data.item.researchFacilityId).template).nativeCiv);
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 941| 941| 			"player": data.player
| 942| 942| 		});
| 943| 943| 
| 944|    |-		let unitIds = data.unitEntStates.map(status => status.id)
|    | 944|+		let unitIds = data.unitEntStates.map(status => status.id);
| 945| 945| 		let [buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch] =
| 946| 946| 			getTrainingStatus(unitIds, data.item, data.playerState);
| 947| 947| 

binaries/data/mods/public/gui/session/selection_panels.js
|  48| »   »   »   switch·(data.item)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
|  59| »   »   switch·(data.item)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
| 731| »   »   »   »   »   »   switch·(entity.check)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
| 944| »   »   let·unitIds·=·data.unitEntStates.map(status·=>·status.id)
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|  66|  66| 		let phase = "";
|  67|  67| 		let cmpTechnologyManager = QueryPlayerIDInterface(i, IID_TechnologyManager);
|  68|  68| 		if (cmpTechnologyManager)
|  69|    |-		{
|    |  69|+		
|  70|  70| 			if (cmpTechnologyManager.IsTechnologyResearched("phase_city"))
|  71|  71| 				phase = "city";
|  72|  72| 			else if (cmpTechnologyManager.IsTechnologyResearched("phase_town"))
|  73|  73| 				phase = "town";
|  74|  74| 			else if (cmpTechnologyManager.IsTechnologyResearched("phase_village"))
|  75|  75| 				phase = "village";
|  76|    |-		}
|    |  76|+		
|  77|  77| 
|  78|  78| 		// store player ally/neutral/enemy data as arrays
|  79|  79| 		let allies = [];
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 421| 421| 			ret.attack[type].elevationBonus = range.elevationBonus;
| 422| 422| 
| 423| 423| 			if (cmpUnitAI && cmpPosition && cmpPosition.IsInWorld())
| 424|    |-			{
|    | 424|+			
| 425| 425| 				// For units, take the range in front of it, no spread. So angle = 0
| 426| 426| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 0);
| 427|    |-			}
|    | 427|+			
| 428| 428| 			else if(cmpPosition && cmpPosition.IsInWorld())
| 429| 429| 			{
| 430| 430| 				// For buildings, take the average elevation around it. So angle = 2*pi
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 426| 426| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 0);
| 427| 427| 			}
| 428| 428| 			else if(cmpPosition && cmpPosition.IsInWorld())
| 429|    |-			{
|    | 429|+			
| 430| 430| 				// For buildings, take the average elevation around it. So angle = 2*pi
| 431| 431| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 2*Math.PI);
| 432|    |-			}
|    | 432|+			
| 433| 433| 			else
| 434| 434| 			{
| 435| 435| 				// not in world, set a default?
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 431| 431| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 2*Math.PI);
| 432| 432| 			}
| 433| 433| 			else
| 434|    |-			{
|    | 434|+			
| 435| 435| 				// not in world, set a default?
| 436| 436| 				ret.attack[type].elevationAdaptedRange = ret.attack.maxRange;
| 437|    |-			}
|    | 437|+			
| 438| 438| 		}
| 439| 439| 	}
| 440| 440| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 802| 802| 		updateEntityColor(data.showAllStatusBars && (i == player || player == -1) ?
| 803| 803| 			[IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer, IID_StatusBars] :
| 804| 804| 			[IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer],
| 805|    |-			cmpRangeManager.GetEntitiesByPlayer(i));
|    | 805|+		cmpRangeManager.GetEntitiesByPlayer(i));
| 806| 806| 	}
| 807| 807| 	updateEntityColor([IID_Selectable, IID_StatusBars], data.selected);
| 808| 808| 	Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager).UpdateColors();
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1321|1321| 		}
|1322|1322| 	}
|1323|1323| 	else
|1324|    |-	{
|    |1324|+	
|1325|1325| 		// Didn't snap to an existing entity, add the starting tower manually. To prevent odd-looking rotation jumps
|1326|1326| 		// when shift-clicking to build a wall, reuse the placement angle that was last seen on a validly positioned
|1327|1327| 		// wall piece.
|1342|1342| 			"pos": start.pos,
|1343|1343| 			"angle": previewEntities.length > 0 ? previewEntities[0].angle : this.placementWallLastAngle
|1344|1344| 		});
|1345|    |-	}
|    |1345|+	
|1346|1346| 
|1347|1347| 	if (end.pos)
|1348|1348| 	{
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1345|1345| 	}
|1346|1346| 
|1347|1347| 	if (end.pos)
|1348|    |-	{
|    |1348|+	
|1349|1349| 		// Analogous to the starting side case above
|1350|1350| 		if (end.snappedEnt && end.snappedEnt != INVALID_ENTITY)
|1351|1351| 		{
|1383|1383| 				"pos": end.pos,
|1384|1384| 				"angle": previewEntities.length > 0 ? previewEntities[previewEntities.length-1].angle : this.placementWallLastAngle
|1385|1385| 			});
|1386|    |-	}
|    |1386|+	
|1387|1387| 
|1388|1388| 	let cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
|1389|1389| 	if (!cmpTerrain)
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1561|1561| 
|1562|1562| 		let cmpVisual = Engine.QueryInterface(ent, IID_Visual);
|1563|1563| 		if (cmpVisual)
|1564|    |-		{
|    |1564|+		
|1565|1565| 			if (!allPiecesValid || !canAfford)
|1566|1566| 				cmpVisual.SetShadingColor(1.4, 0.4, 0.4, 1);
|1567|1567| 			else
|1568|1568| 				cmpVisual.SetShadingColor(1, 1, 1, 1);
|1569|    |-		}
|    |1569|+		
|1570|1570| 
|1571|1571| 		++entPool.numUsed;
|1572|1572| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1635|1635| 			{
|1636|1636| 				minDist2 = dist2;
|1637|1637| 				minDistEntitySnapData = {
|1638|    |-						"x": pos.x,
|    |1638|+					"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1636|1636| 				minDist2 = dist2;
|1637|1637| 				minDistEntitySnapData = {
|1638|1638| 						"x": pos.x,
|1639|    |-						"z": pos.z,
|    |1639|+					"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|1642|1642| 				};
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1637|1637| 				minDistEntitySnapData = {
|1638|1638| 						"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|    |-						"angle": cmpPosition.GetRotation().y,
|    |1640|+					"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|1642|1642| 				};
|1643|1643| 			}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1638|1638| 						"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|    |-						"ent": ent
|    |1641|+					"ent": ent
|1642|1642| 				};
|1643|1643| 			}
|1644|1644| 		}
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1783|1783| 			result.gain = cmpEntityTrader.GetGoods().amount;
|1784|1784| 	}
|1785|1785| 	else if (data.target === secondMarket)
|1786|    |-	{
|    |1786|+	
|1787|1787| 		result = {
|1788|1788| 			"type": "is second",
|1789|1789| 			"gain": cmpEntityTrader.GetGoods().amount,
|1790|1790| 		};
|1791|    |-	}
|    |1791|+	
|1792|1792| 	else if (!firstMarket)
|1793|1793| 	{
|1794|1794| 		result = { "type": "set first" };
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1790|1790| 		};
|1791|1791| 	}
|1792|1792| 	else if (!firstMarket)
|1793|    |-	{
|    |1793|+	
|1794|1794| 		result = { "type": "set first" };
|1795|    |-	}
|    |1795|+	
|1796|1796| 	else if (!secondMarket)
|1797|1797| 	{
|1798|1798| 		result = {
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1794|1794| 		result = { "type": "set first" };
|1795|1795| 	}
|1796|1796| 	else if (!secondMarket)
|1797|    |-	{
|    |1797|+	
|1798|1798| 		result = {
|1799|1799| 			"type": "set second",
|1800|1800| 			"gain": cmpEntityTrader.CalculateGain(firstMarket, data.target),
|1801|1801| 		};
|1802|    |-	}
|    |1802|+	
|1803|1803| 	else
|1804|1804| 	{
|1805|1805| 		// Else both markets are not null and target is different from them
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1801|1801| 		};
|1802|1802| 	}
|1803|1803| 	else
|1804|    |-	{
|    |1804|+	
|1805|1805| 		// Else both markets are not null and target is different from them
|1806|1806| 		result = { "type": "set first" };
|1807|    |-	}
|    |1807|+	
|1808|1808| 	return result;
|1809|1809| };
|1810|1810| 
Executing section cli...

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

Stan updated this revision to Diff 8358.Jun 7 2019, 11:33 AM

Do not display bonuses equal to 1

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

Linter detected issues:
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 393| 393| function getRepairTimeTooltip(entState)
| 394| 394| {
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396|    |-			"label": headerFont(translate("Number of repairers:")),
|    | 396|+		"label": headerFont(translate("Number of repairers:")),
| 397| 397| 			"details": entState.repairable.numBuilders
| 398| 398| 		}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 394| 394| {
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396| 396| 			"label": headerFont(translate("Number of repairers:")),
| 397|    |-			"details": entState.repairable.numBuilders
|    | 397|+		"details": entState.repairable.numBuilders
| 398| 398| 		}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
| 400| 400| 			"Add another worker to speed up the repairs by %(second)s second.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396| 396| 			"label": headerFont(translate("Number of repairers:")),
| 397| 397| 			"details": entState.repairable.numBuilders
| 398|    |-		}) + "\n" + (entState.repairable.numBuilders ?
|    | 398|+	}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
| 400| 400| 			"Add another worker to speed up the repairs by %(second)s second.",
| 401| 401| 			"Add another worker to speed up the repairs by %(second)s seconds.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 415| 415| function getBuildTimeTooltip(entState)
| 416| 416| {
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418|    |-			"label": headerFont(translate("Number of builders:")),
|    | 418|+		"label": headerFont(translate("Number of builders:")),
| 419| 419| 			"details": entState.foundation.numBuilders
| 420| 420| 		}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 416| 416| {
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418| 418| 			"label": headerFont(translate("Number of builders:")),
| 419|    |-			"details": entState.foundation.numBuilders
|    | 419|+		"details": entState.foundation.numBuilders
| 420| 420| 		}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
| 422| 422| 			"Add another worker to speed up the construction by %(second)s second.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418| 418| 			"label": headerFont(translate("Number of builders:")),
| 419| 419| 			"details": entState.foundation.numBuilders
| 420|    |-		}) + "\n" + (entState.foundation.numBuilders ?
|    | 420|+	}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
| 422| 422| 			"Add another worker to speed up the construction by %(second)s second.",
| 423| 423| 			"Add another worker to speed up the construction by %(second)s seconds.",
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 452| 452| 				continue;
| 453| 453| 
| 454| 454| 			if (state.pack.progress == 0)
| 455|    |-			{
|    | 455|+			
| 456| 456| 				if (state.pack.packed)
| 457| 457| 					checks.unpackButton = true;
| 458| 458| 				else
| 459| 459| 					checks.packButton = true;
| 460|    |-			}
|    | 460|+			
| 461| 461| 			else if (state.pack.packed)
| 462| 462| 				checks.unpackCancelButton = true;
| 463| 463| 			else
|    | [NORMAL] ESLintBear (space-before-function-paren):
|    | Unexpected space before function parentheses.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 763| 763| 				addResearchToQueue(data.item.researchFacilityId, t);
| 764| 764| 			})(tech);
| 765| 765| 
| 766|    |-			button.onPressRight = (t => function () {
|    | 766|+			button.onPressRight = (t => function() {
| 767| 767| 				showTemplateDetails(
| 768| 768| 					t,
| 769| 769| 					GetTemplateData(data.unitEntStates.find(state => state.id == data.item.researchFacilityId).template).nativeCiv);
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 941| 941| 			"player": data.player
| 942| 942| 		});
| 943| 943| 
| 944|    |-		let unitIds = data.unitEntStates.map(status => status.id)
|    | 944|+		let unitIds = data.unitEntStates.map(status => status.id);
| 945| 945| 		let [buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch] =
| 946| 946| 			getTrainingStatus(unitIds, data.item, data.playerState);
| 947| 947| 

binaries/data/mods/public/gui/session/selection_panels.js
|  48| »   »   »   switch·(data.item)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
|  59| »   »   switch·(data.item)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
| 731| »   »   »   »   »   »   switch·(entity.check)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
| 944| »   »   let·unitIds·=·data.unitEntStates.map(status·=>·status.id)
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|  66|  66| 		let phase = "";
|  67|  67| 		let cmpTechnologyManager = QueryPlayerIDInterface(i, IID_TechnologyManager);
|  68|  68| 		if (cmpTechnologyManager)
|  69|    |-		{
|    |  69|+		
|  70|  70| 			if (cmpTechnologyManager.IsTechnologyResearched("phase_city"))
|  71|  71| 				phase = "city";
|  72|  72| 			else if (cmpTechnologyManager.IsTechnologyResearched("phase_town"))
|  73|  73| 				phase = "town";
|  74|  74| 			else if (cmpTechnologyManager.IsTechnologyResearched("phase_village"))
|  75|  75| 				phase = "village";
|  76|    |-		}
|    |  76|+		
|  77|  77| 
|  78|  78| 		// store player ally/neutral/enemy data as arrays
|  79|  79| 		let allies = [];
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 421| 421| 			ret.attack[type].elevationBonus = range.elevationBonus;
| 422| 422| 
| 423| 423| 			if (cmpUnitAI && cmpPosition && cmpPosition.IsInWorld())
| 424|    |-			{
|    | 424|+			
| 425| 425| 				// For units, take the range in front of it, no spread. So angle = 0
| 426| 426| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 0);
| 427|    |-			}
|    | 427|+			
| 428| 428| 			else if(cmpPosition && cmpPosition.IsInWorld())
| 429| 429| 			{
| 430| 430| 				// For buildings, take the average elevation around it. So angle = 2*pi
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 426| 426| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 0);
| 427| 427| 			}
| 428| 428| 			else if(cmpPosition && cmpPosition.IsInWorld())
| 429|    |-			{
|    | 429|+			
| 430| 430| 				// For buildings, take the average elevation around it. So angle = 2*pi
| 431| 431| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 2*Math.PI);
| 432|    |-			}
|    | 432|+			
| 433| 433| 			else
| 434| 434| 			{
| 435| 435| 				// not in world, set a default?
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 431| 431| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 2*Math.PI);
| 432| 432| 			}
| 433| 433| 			else
| 434|    |-			{
|    | 434|+			
| 435| 435| 				// not in world, set a default?
| 436| 436| 				ret.attack[type].elevationAdaptedRange = ret.attack.maxRange;
| 437|    |-			}
|    | 437|+			
| 438| 438| 		}
| 439| 439| 	}
| 440| 440| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 802| 802| 		updateEntityColor(data.showAllStatusBars && (i == player || player == -1) ?
| 803| 803| 			[IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer, IID_StatusBars] :
| 804| 804| 			[IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer],
| 805|    |-			cmpRangeManager.GetEntitiesByPlayer(i));
|    | 805|+		cmpRangeManager.GetEntitiesByPlayer(i));
| 806| 806| 	}
| 807| 807| 	updateEntityColor([IID_Selectable, IID_StatusBars], data.selected);
| 808| 808| 	Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager).UpdateColors();
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1321|1321| 		}
|1322|1322| 	}
|1323|1323| 	else
|1324|    |-	{
|    |1324|+	
|1325|1325| 		// Didn't snap to an existing entity, add the starting tower manually. To prevent odd-looking rotation jumps
|1326|1326| 		// when shift-clicking to build a wall, reuse the placement angle that was last seen on a validly positioned
|1327|1327| 		// wall piece.
|1342|1342| 			"pos": start.pos,
|1343|1343| 			"angle": previewEntities.length > 0 ? previewEntities[0].angle : this.placementWallLastAngle
|1344|1344| 		});
|1345|    |-	}
|    |1345|+	
|1346|1346| 
|1347|1347| 	if (end.pos)
|1348|1348| 	{
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1345|1345| 	}
|1346|1346| 
|1347|1347| 	if (end.pos)
|1348|    |-	{
|    |1348|+	
|1349|1349| 		// Analogous to the starting side case above
|1350|1350| 		if (end.snappedEnt && end.snappedEnt != INVALID_ENTITY)
|1351|1351| 		{
|1383|1383| 				"pos": end.pos,
|1384|1384| 				"angle": previewEntities.length > 0 ? previewEntities[previewEntities.length-1].angle : this.placementWallLastAngle
|1385|1385| 			});
|1386|    |-	}
|    |1386|+	
|1387|1387| 
|1388|1388| 	let cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
|1389|1389| 	if (!cmpTerrain)
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1561|1561| 
|1562|1562| 		let cmpVisual = Engine.QueryInterface(ent, IID_Visual);
|1563|1563| 		if (cmpVisual)
|1564|    |-		{
|    |1564|+		
|1565|1565| 			if (!allPiecesValid || !canAfford)
|1566|1566| 				cmpVisual.SetShadingColor(1.4, 0.4, 0.4, 1);
|1567|1567| 			else
|1568|1568| 				cmpVisual.SetShadingColor(1, 1, 1, 1);
|1569|    |-		}
|    |1569|+		
|1570|1570| 
|1571|1571| 		++entPool.numUsed;
|1572|1572| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1635|1635| 			{
|1636|1636| 				minDist2 = dist2;
|1637|1637| 				minDistEntitySnapData = {
|1638|    |-						"x": pos.x,
|    |1638|+					"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1636|1636| 				minDist2 = dist2;
|1637|1637| 				minDistEntitySnapData = {
|1638|1638| 						"x": pos.x,
|1639|    |-						"z": pos.z,
|    |1639|+					"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|1642|1642| 				};
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1637|1637| 				minDistEntitySnapData = {
|1638|1638| 						"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|    |-						"angle": cmpPosition.GetRotation().y,
|    |1640|+					"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|1642|1642| 				};
|1643|1643| 			}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1638|1638| 						"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|    |-						"ent": ent
|    |1641|+					"ent": ent
|1642|1642| 				};
|1643|1643| 			}
|1644|1644| 		}
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1783|1783| 			result.gain = cmpEntityTrader.GetGoods().amount;
|1784|1784| 	}
|1785|1785| 	else if (data.target === secondMarket)
|1786|    |-	{
|    |1786|+	
|1787|1787| 		result = {
|1788|1788| 			"type": "is second",
|1789|1789| 			"gain": cmpEntityTrader.GetGoods().amount,
|1790|1790| 		};
|1791|    |-	}
|    |1791|+	
|1792|1792| 	else if (!firstMarket)
|1793|1793| 	{
|1794|1794| 		result = { "type": "set first" };
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1790|1790| 		};
|1791|1791| 	}
|1792|1792| 	else if (!firstMarket)
|1793|    |-	{
|    |1793|+	
|1794|1794| 		result = { "type": "set first" };
|1795|    |-	}
|    |1795|+	
|1796|1796| 	else if (!secondMarket)
|1797|1797| 	{
|1798|1798| 		result = {
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1794|1794| 		result = { "type": "set first" };
|1795|1795| 	}
|1796|1796| 	else if (!secondMarket)
|1797|    |-	{
|    |1797|+	
|1798|1798| 		result = {
|1799|1799| 			"type": "set second",
|1800|1800| 			"gain": cmpEntityTrader.CalculateGain(firstMarket, data.target),
|1801|1801| 		};
|1802|    |-	}
|    |1802|+	
|1803|1803| 	else
|1804|1804| 	{
|1805|1805| 		// Else both markets are not null and target is different from them
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1801|1801| 		};
|1802|1802| 	}
|1803|1803| 	else
|1804|    |-	{
|    |1804|+	
|1805|1805| 		// Else both markets are not null and target is different from them
|1806|1806| 		result = { "type": "set first" };
|1807|    |-	}
|    |1807|+	
|1808|1808| 	return result;
|1809|1809| };
|1810|1810| 
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '||' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|  87|  87| 		// If the elements are still strings, split them by space or by '+'
|  88|  88| 		if (typeof sublist == "string")
|  89|  89| 			sublist = sublist.split(/[+\s]+/);
|  90|    |-		if (sublist.every(c => (c[0] == "!" && classes.indexOf(c.substr(1)) == -1)
|  91|    |-		                    || (c[0] != "!" && classes.indexOf(c) != -1)))
|    |  90|+		if (sublist.every(c => (c[0] == "!" && classes.indexOf(c.substr(1)) == -1) ||
|    |  91|+		                    (c[0] != "!" && classes.indexOf(c) != -1)))
|  92|  92| 			return true;
|  93|  93| 	}
|  94|  94| 
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 207| 207| 				for (let damageType of damageTypes.GetTypes())
| 208| 208| 					ret.attack[type].splash[damageType] = getAttackStat("Splash/" + damageType);
| 209| 209| 			}
| 210|    |-			
|    | 210|+
| 211| 211| 			if (template.Attack[type].Bonuses)
| 212| 212| 			{
| 213| 213| 				ret.attack[type].bonuses = {};
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'for-in'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 211| 211| 			if (template.Attack[type].Bonuses)
| 212| 212| 			{
| 213| 213| 				ret.attack[type].bonuses = {};
| 214|    |-				for (let bonus in template.Attack[type].Bonuses) {
|    | 214|+				for (let bonus in template.Attack[type].Bonuses) 
| 215| 215| 					ret.attack[type].bonuses[bonus] = {
| 216| 216| 						"classes": template.Attack[type].Bonuses[bonus].Classes,
| 217| 217| 						"multiplier": getAttackStat("Bonuses/" + bonus + "/Multiplier")
| 218| 218| 					};
| 219|    |-				}
|    | 219|+				
| 220| 220| 			}
| 221| 221| 		}
| 222| 222| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 237| 237| 		{
| 238| 238| 			let aura = auraTemplates[auraID];
| 239| 239| 			ret.auras[auraID] = {
| 240|    |-					"name": aura.auraName,
|    | 240|+				"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243| 243| 				};
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 238| 238| 			let aura = auraTemplates[auraID];
| 239| 239| 			ret.auras[auraID] = {
| 240| 240| 					"name": aura.auraName,
| 241|    |-					"description": aura.auraDescription || null,
|    | 241|+				"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243| 243| 				};
| 244| 244| 		}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 239| 239| 			ret.auras[auraID] = {
| 240| 240| 					"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242|    |-					"radius": aura.radius || null
|    | 242|+				"radius": aura.radius || null
| 243| 243| 				};
| 244| 244| 		}
| 245| 245| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 240| 240| 					"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243|    |-				};
|    | 243|+			};
| 244| 244| 		}
| 245| 245| 	}
| 246| 246| 

binaries/data/mods/public/globalscripts/Templates.js
| 214| »   »   »   »   for·(let·bonus·in·template.Attack[type].Bonuses)·{
|    | [NORMAL] ESLintBear (brace-rules/brace-on-same-line):
|    | Opening curly brace appears on the same line as controlling statement.

binaries/data/mods/public/globalscripts/Templates.js
|  91| »   »   ····················||·(c[0]·!=·"!"·&&·classes.indexOf(c)·!=·-1)))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '||'; readers may interpret this as an expression boundary.
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
| 526| 526| 
| 527| 527| 		let horizSpeed = +this.template[type].Projectile.Speed;
| 528| 528| 		let gravity = +this.template[type].Projectile.Gravity;
| 529|    |-		//horizSpeed /= 2; gravity /= 2; // slow it down for testing
|    | 529|+		// horizSpeed /= 2; gravity /= 2; // slow it down for testing
| 530| 530| 
| 531| 531| 		let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
| 532| 532| 		if (!cmpPosition || !cmpPosition.IsInWorld())
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
| 645| 645| 			});
| 646| 646| 	}
| 647| 647| 	else
| 648|    |-	{
|    | 648|+	
| 649| 649| 		// Melee attack - hurt the target immediately
| 650| 650| 		cmpDamage.CauseDamage({
| 651| 651| 			"strengths": this.GetAttackStrengths(type),
| 655| 655| 			"type": type,
| 656| 656| 			"attackerOwner": attackerOwner
| 657| 657| 		});
| 658|    |-	}
|    | 658|+	
| 659| 659| };
| 660| 660| 
| 661| 661| /**

binaries/data/mods/public/simulation/components/Attack.js
| 516| ·»   let·cmpDamage·=·Engine.QueryInterface(SYSTEM_ENTITY,·IID_Damage);
|    | [NORMAL] ESLintBear (no-mixed-spaces-and-tabs):
|    | Mixed spaces and tabs.

binaries/data/mods/public/simulation/components/Attack.js
| 620| »   »   cmpTimer.SetTimeout(SYSTEM_ENTITY,·IID_Damage,·"MissileHit",·timeToTarget·*·1000·+·+this.template[type].Delay,·data);
|    | [NORMAL] JSHintBear:
|    | Confusing plusses.
Executing section cli...

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

smiley added inline comments.Jun 7 2019, 11:46 AM
binaries/data/mods/public/gui/common/tooltips.js
838

Shouldn't that be .every() == 1?
If something isn't one, they should not be skipped over?

Stan added inline comments.Jun 7 2019, 11:49 AM
binaries/data/mods/public/gui/common/tooltips.js
838

Could work as well, as I understand it, !some != 1 = every = 1 no ?

smiley added inline comments.Jun 7 2019, 11:53 AM
binaries/data/mods/public/gui/common/tooltips.js
838

I did not see that negation.
Why a double negative though?
I didn’t not see a bird
Vs
I saw a bird.
Is how this reads to me.

Stan added inline comments.Jun 7 2019, 12:07 PM
binaries/data/mods/public/gui/common/tooltips.js
838

Yeah I didn't remember the every function. I'll fix it later it makes more sense to me :)

elexis added inline comments.Jun 7 2019, 4:37 PM
binaries/data/mods/public/gui/common/tooltips.js
838

(having all quantors in a formula first = https://en.wikipedia.org/wiki/Prenex_normal_form)

Stan updated this revision to Diff 8366.Jun 7 2019, 6:03 PM
Stan marked 3 inline comments as done.

Use every instead of some.

Vulcan added a comment.Jun 7 2019, 6:05 PM

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

Linter detected issues:
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
| 526| 526| 
| 527| 527| 		let horizSpeed = +this.template[type].Projectile.Speed;
| 528| 528| 		let gravity = +this.template[type].Projectile.Gravity;
| 529|    |-		//horizSpeed /= 2; gravity /= 2; // slow it down for testing
|    | 529|+		// horizSpeed /= 2; gravity /= 2; // slow it down for testing
| 530| 530| 
| 531| 531| 		let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
| 532| 532| 		if (!cmpPosition || !cmpPosition.IsInWorld())
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/Attack.js
| 645| 645| 			});
| 646| 646| 	}
| 647| 647| 	else
| 648|    |-	{
|    | 648|+	
| 649| 649| 		// Melee attack - hurt the target immediately
| 650| 650| 		cmpDamage.CauseDamage({
| 651| 651| 			"strengths": this.GetAttackStrengths(type),
| 655| 655| 			"type": type,
| 656| 656| 			"attackerOwner": attackerOwner
| 657| 657| 		});
| 658|    |-	}
|    | 658|+	
| 659| 659| };
| 660| 660| 
| 661| 661| /**

binaries/data/mods/public/simulation/components/Attack.js
| 516| ·»   let·cmpDamage·=·Engine.QueryInterface(SYSTEM_ENTITY,·IID_Damage);
|    | [NORMAL] ESLintBear (no-mixed-spaces-and-tabs):
|    | Mixed spaces and tabs.

binaries/data/mods/public/simulation/components/Attack.js
| 620| »   »   cmpTimer.SetTimeout(SYSTEM_ENTITY,·IID_Damage,·"MissileHit",·timeToTarget·*·1000·+·+this.template[type].Delay,·data);
|    | [NORMAL] JSHintBear:
|    | Confusing plusses.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 393| 393| function getRepairTimeTooltip(entState)
| 394| 394| {
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396|    |-			"label": headerFont(translate("Number of repairers:")),
|    | 396|+		"label": headerFont(translate("Number of repairers:")),
| 397| 397| 			"details": entState.repairable.numBuilders
| 398| 398| 		}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 394| 394| {
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396| 396| 			"label": headerFont(translate("Number of repairers:")),
| 397|    |-			"details": entState.repairable.numBuilders
|    | 397|+		"details": entState.repairable.numBuilders
| 398| 398| 		}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
| 400| 400| 			"Add another worker to speed up the repairs by %(second)s second.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 395| 395| 	return sprintf(translate("%(label)s %(details)s"), {
| 396| 396| 			"label": headerFont(translate("Number of repairers:")),
| 397| 397| 			"details": entState.repairable.numBuilders
| 398|    |-		}) + "\n" + (entState.repairable.numBuilders ?
|    | 398|+	}) + "\n" + (entState.repairable.numBuilders ?
| 399| 399| 		sprintf(translatePlural(
| 400| 400| 			"Add another worker to speed up the repairs by %(second)s second.",
| 401| 401| 			"Add another worker to speed up the repairs by %(second)s seconds.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 415| 415| function getBuildTimeTooltip(entState)
| 416| 416| {
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418|    |-			"label": headerFont(translate("Number of builders:")),
|    | 418|+		"label": headerFont(translate("Number of builders:")),
| 419| 419| 			"details": entState.foundation.numBuilders
| 420| 420| 		}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 416| 416| {
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418| 418| 			"label": headerFont(translate("Number of builders:")),
| 419|    |-			"details": entState.foundation.numBuilders
|    | 419|+		"details": entState.foundation.numBuilders
| 420| 420| 		}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
| 422| 422| 			"Add another worker to speed up the construction by %(second)s second.",
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/common/tooltips.js
| 417| 417| 	return sprintf(translate("%(label)s %(details)s"), {
| 418| 418| 			"label": headerFont(translate("Number of builders:")),
| 419| 419| 			"details": entState.foundation.numBuilders
| 420|    |-		}) + "\n" + (entState.foundation.numBuilders ?
|    | 420|+	}) + "\n" + (entState.foundation.numBuilders ?
| 421| 421| 		sprintf(translatePlural(
| 422| 422| 			"Add another worker to speed up the construction by %(second)s second.",
| 423| 423| 			"Add another worker to speed up the construction by %(second)s seconds.",
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|  66|  66| 		let phase = "";
|  67|  67| 		let cmpTechnologyManager = QueryPlayerIDInterface(i, IID_TechnologyManager);
|  68|  68| 		if (cmpTechnologyManager)
|  69|    |-		{
|    |  69|+		
|  70|  70| 			if (cmpTechnologyManager.IsTechnologyResearched("phase_city"))
|  71|  71| 				phase = "city";
|  72|  72| 			else if (cmpTechnologyManager.IsTechnologyResearched("phase_town"))
|  73|  73| 				phase = "town";
|  74|  74| 			else if (cmpTechnologyManager.IsTechnologyResearched("phase_village"))
|  75|  75| 				phase = "village";
|  76|    |-		}
|    |  76|+		
|  77|  77| 
|  78|  78| 		// store player ally/neutral/enemy data as arrays
|  79|  79| 		let allies = [];
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 421| 421| 			ret.attack[type].elevationBonus = range.elevationBonus;
| 422| 422| 
| 423| 423| 			if (cmpUnitAI && cmpPosition && cmpPosition.IsInWorld())
| 424|    |-			{
|    | 424|+			
| 425| 425| 				// For units, take the range in front of it, no spread. So angle = 0
| 426| 426| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 0);
| 427|    |-			}
|    | 427|+			
| 428| 428| 			else if(cmpPosition && cmpPosition.IsInWorld())
| 429| 429| 			{
| 430| 430| 				// For buildings, take the average elevation around it. So angle = 2*pi
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 426| 426| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 0);
| 427| 427| 			}
| 428| 428| 			else if(cmpPosition && cmpPosition.IsInWorld())
| 429|    |-			{
|    | 429|+			
| 430| 430| 				// For buildings, take the average elevation around it. So angle = 2*pi
| 431| 431| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 2*Math.PI);
| 432|    |-			}
|    | 432|+			
| 433| 433| 			else
| 434| 434| 			{
| 435| 435| 				// not in world, set a default?
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 431| 431| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 2*Math.PI);
| 432| 432| 			}
| 433| 433| 			else
| 434|    |-			{
|    | 434|+			
| 435| 435| 				// not in world, set a default?
| 436| 436| 				ret.attack[type].elevationAdaptedRange = ret.attack.maxRange;
| 437|    |-			}
|    | 437|+			
| 438| 438| 		}
| 439| 439| 	}
| 440| 440| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
| 802| 802| 		updateEntityColor(data.showAllStatusBars && (i == player || player == -1) ?
| 803| 803| 			[IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer, IID_StatusBars] :
| 804| 804| 			[IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer],
| 805|    |-			cmpRangeManager.GetEntitiesByPlayer(i));
|    | 805|+		cmpRangeManager.GetEntitiesByPlayer(i));
| 806| 806| 	}
| 807| 807| 	updateEntityColor([IID_Selectable, IID_StatusBars], data.selected);
| 808| 808| 	Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager).UpdateColors();
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1321|1321| 		}
|1322|1322| 	}
|1323|1323| 	else
|1324|    |-	{
|    |1324|+	
|1325|1325| 		// Didn't snap to an existing entity, add the starting tower manually. To prevent odd-looking rotation jumps
|1326|1326| 		// when shift-clicking to build a wall, reuse the placement angle that was last seen on a validly positioned
|1327|1327| 		// wall piece.
|1342|1342| 			"pos": start.pos,
|1343|1343| 			"angle": previewEntities.length > 0 ? previewEntities[0].angle : this.placementWallLastAngle
|1344|1344| 		});
|1345|    |-	}
|    |1345|+	
|1346|1346| 
|1347|1347| 	if (end.pos)
|1348|1348| 	{
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1345|1345| 	}
|1346|1346| 
|1347|1347| 	if (end.pos)
|1348|    |-	{
|    |1348|+	
|1349|1349| 		// Analogous to the starting side case above
|1350|1350| 		if (end.snappedEnt && end.snappedEnt != INVALID_ENTITY)
|1351|1351| 		{
|1383|1383| 				"pos": end.pos,
|1384|1384| 				"angle": previewEntities.length > 0 ? previewEntities[previewEntities.length-1].angle : this.placementWallLastAngle
|1385|1385| 			});
|1386|    |-	}
|    |1386|+	
|1387|1387| 
|1388|1388| 	let cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
|1389|1389| 	if (!cmpTerrain)
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1561|1561| 
|1562|1562| 		let cmpVisual = Engine.QueryInterface(ent, IID_Visual);
|1563|1563| 		if (cmpVisual)
|1564|    |-		{
|    |1564|+		
|1565|1565| 			if (!allPiecesValid || !canAfford)
|1566|1566| 				cmpVisual.SetShadingColor(1.4, 0.4, 0.4, 1);
|1567|1567| 			else
|1568|1568| 				cmpVisual.SetShadingColor(1, 1, 1, 1);
|1569|    |-		}
|    |1569|+		
|1570|1570| 
|1571|1571| 		++entPool.numUsed;
|1572|1572| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1635|1635| 			{
|1636|1636| 				minDist2 = dist2;
|1637|1637| 				minDistEntitySnapData = {
|1638|    |-						"x": pos.x,
|    |1638|+					"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1636|1636| 				minDist2 = dist2;
|1637|1637| 				minDistEntitySnapData = {
|1638|1638| 						"x": pos.x,
|1639|    |-						"z": pos.z,
|    |1639|+					"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|1642|1642| 				};
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1637|1637| 				minDistEntitySnapData = {
|1638|1638| 						"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|    |-						"angle": cmpPosition.GetRotation().y,
|    |1640|+					"angle": cmpPosition.GetRotation().y,
|1641|1641| 						"ent": ent
|1642|1642| 				};
|1643|1643| 			}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1638|1638| 						"x": pos.x,
|1639|1639| 						"z": pos.z,
|1640|1640| 						"angle": cmpPosition.GetRotation().y,
|1641|    |-						"ent": ent
|    |1641|+					"ent": ent
|1642|1642| 				};
|1643|1643| 			}
|1644|1644| 		}
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1783|1783| 			result.gain = cmpEntityTrader.GetGoods().amount;
|1784|1784| 	}
|1785|1785| 	else if (data.target === secondMarket)
|1786|    |-	{
|    |1786|+	
|1787|1787| 		result = {
|1788|1788| 			"type": "is second",
|1789|1789| 			"gain": cmpEntityTrader.GetGoods().amount,
|1790|1790| 		};
|1791|    |-	}
|    |1791|+	
|1792|1792| 	else if (!firstMarket)
|1793|1793| 	{
|1794|1794| 		result = { "type": "set first" };
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1790|1790| 		};
|1791|1791| 	}
|1792|1792| 	else if (!firstMarket)
|1793|    |-	{
|    |1793|+	
|1794|1794| 		result = { "type": "set first" };
|1795|    |-	}
|    |1795|+	
|1796|1796| 	else if (!secondMarket)
|1797|1797| 	{
|1798|1798| 		result = {
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1794|1794| 		result = { "type": "set first" };
|1795|1795| 	}
|1796|1796| 	else if (!secondMarket)
|1797|    |-	{
|    |1797|+	
|1798|1798| 		result = {
|1799|1799| 			"type": "set second",
|1800|1800| 			"gain": cmpEntityTrader.CalculateGain(firstMarket, data.target),
|1801|1801| 		};
|1802|    |-	}
|    |1802|+	
|1803|1803| 	else
|1804|1804| 	{
|1805|1805| 		// Else both markets are not null and target is different from them
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/simulation/components/GuiInterface.js
|1801|1801| 		};
|1802|1802| 	}
|1803|1803| 	else
|1804|    |-	{
|    |1804|+	
|1805|1805| 		// Else both markets are not null and target is different from them
|1806|1806| 		result = { "type": "set first" };
|1807|    |-	}
|    |1807|+	
|1808|1808| 	return result;
|1809|1809| };
|1810|1810| 
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '||' should be placed at the end of the line.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|  87|  87| 		// If the elements are still strings, split them by space or by '+'
|  88|  88| 		if (typeof sublist == "string")
|  89|  89| 			sublist = sublist.split(/[+\s]+/);
|  90|    |-		if (sublist.every(c => (c[0] == "!" && classes.indexOf(c.substr(1)) == -1)
|  91|    |-		                    || (c[0] != "!" && classes.indexOf(c) != -1)))
|    |  90|+		if (sublist.every(c => (c[0] == "!" && classes.indexOf(c.substr(1)) == -1) ||
|    |  91|+		                    (c[0] != "!" && classes.indexOf(c) != -1)))
|  92|  92| 			return true;
|  93|  93| 	}
|  94|  94| 
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 207| 207| 				for (let damageType of damageTypes.GetTypes())
| 208| 208| 					ret.attack[type].splash[damageType] = getAttackStat("Splash/" + damageType);
| 209| 209| 			}
| 210|    |-			
|    | 210|+
| 211| 211| 			if (template.Attack[type].Bonuses)
| 212| 212| 			{
| 213| 213| 				ret.attack[type].bonuses = {};
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'for-in'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 211| 211| 			if (template.Attack[type].Bonuses)
| 212| 212| 			{
| 213| 213| 				ret.attack[type].bonuses = {};
| 214|    |-				for (let bonus in template.Attack[type].Bonuses) {
|    | 214|+				for (let bonus in template.Attack[type].Bonuses) 
| 215| 215| 					ret.attack[type].bonuses[bonus] = {
| 216| 216| 						"classes": template.Attack[type].Bonuses[bonus].Classes,
| 217| 217| 						"multiplier": getAttackStat("Bonuses/" + bonus + "/Multiplier")
| 218| 218| 					};
| 219|    |-				}
|    | 219|+				
| 220| 220| 			}
| 221| 221| 		}
| 222| 222| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 237| 237| 		{
| 238| 238| 			let aura = auraTemplates[auraID];
| 239| 239| 			ret.auras[auraID] = {
| 240|    |-					"name": aura.auraName,
|    | 240|+				"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243| 243| 				};
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 238| 238| 			let aura = auraTemplates[auraID];
| 239| 239| 			ret.auras[auraID] = {
| 240| 240| 					"name": aura.auraName,
| 241|    |-					"description": aura.auraDescription || null,
|    | 241|+				"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243| 243| 				};
| 244| 244| 		}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 239| 239| 			ret.auras[auraID] = {
| 240| 240| 					"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242|    |-					"radius": aura.radius || null
|    | 242|+				"radius": aura.radius || null
| 243| 243| 				};
| 244| 244| 		}
| 245| 245| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/globalscripts/Templates.js
| 240| 240| 					"name": aura.auraName,
| 241| 241| 					"description": aura.auraDescription || null,
| 242| 242| 					"radius": aura.radius || null
| 243|    |-				};
|    | 243|+			};
| 244| 244| 		}
| 245| 245| 	}
| 246| 246| 

binaries/data/mods/public/globalscripts/Templates.js
| 214| »   »   »   »   for·(let·bonus·in·template.Attack[type].Bonuses)·{
|    | [NORMAL] ESLintBear (brace-rules/brace-on-same-line):
|    | Opening curly brace appears on the same line as controlling statement.

binaries/data/mods/public/globalscripts/Templates.js
|  91| »   »   ····················||·(c[0]·!=·"!"·&&·classes.indexOf(c)·!=·-1)))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '||'; readers may interpret this as an expression boundary.
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 452| 452| 				continue;
| 453| 453| 
| 454| 454| 			if (state.pack.progress == 0)
| 455|    |-			{
|    | 455|+			
| 456| 456| 				if (state.pack.packed)
| 457| 457| 					checks.unpackButton = true;
| 458| 458| 				else
| 459| 459| 					checks.packButton = true;
| 460|    |-			}
|    | 460|+			
| 461| 461| 			else if (state.pack.packed)
| 462| 462| 				checks.unpackCancelButton = true;
| 463| 463| 			else
|    | [NORMAL] ESLintBear (space-before-function-paren):
|    | Unexpected space before function parentheses.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 763| 763| 				addResearchToQueue(data.item.researchFacilityId, t);
| 764| 764| 			})(tech);
| 765| 765| 
| 766|    |-			button.onPressRight = (t => function () {
|    | 766|+			button.onPressRight = (t => function() {
| 767| 767| 				showTemplateDetails(
| 768| 768| 					t,
| 769| 769| 					GetTemplateData(data.unitEntStates.find(state => state.id == data.item.researchFacilityId).template).nativeCiv);
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/selection_panels.js
| 941| 941| 			"player": data.player
| 942| 942| 		});
| 943| 943| 
| 944|    |-		let unitIds = data.unitEntStates.map(status => status.id)
|    | 944|+		let unitIds = data.unitEntStates.map(status => status.id);
| 945| 945| 		let [buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch] =
| 946| 946| 			getTrainingStatus(unitIds, data.item, data.playerState);
| 947| 947| 

binaries/data/mods/public/gui/session/selection_panels.js
|  48| »   »   »   switch·(data.item)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
|  59| »   »   switch·(data.item)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
| 731| »   »   »   »   »   »   switch·(entity.check)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/selection_panels.js
| 944| »   »   let·unitIds·=·data.unitEntStates.map(status·=>·status.id)
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.
Executing section cli...

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

elexis requested changes to this revision.Sun, Jul 14, 1:49 PM

Reading my old recommendation to use arrays and array functions and knowing that this function is at least called once per turn, once per selection, it's probably better to put this under scrutiny for performance issues.


On the multiplier == -1 checks:
The first thing I noticed was this:
if (Object.keys(template.attack[attackType].bonuses).every(key => template.attack[attackType].bonuses[key].multiplier == 1))

The Object.keys call creates a new array just in order to loop over it (which can also be done without array construction using for-in).
If that happens only once in a while (like in many if not most parts of the UI) thats not an issue, but here such little things might add up.
(I know, I recommended this style for consistency with the other tooltip functions where I introduced that style for consistency with consistency for areas where performance wasnt relevant)

There is another if (bonus.multiplier == 1).
So I wonder if we actually need to test for this case, whether one could just display it as usual, or whether one could perhaps even rule it out in the template validation stage (probably not cleanly implementable).
But since it's desired to be able to change the multiplier with technologies, I suppose there may be a use case to set it back to 1 upon some trigger, or to start with 1 and increase it.

So I suppose one can still remove the .every thing altogether, not only the array construction but the entire loop, since one can just create the list of "%(multiplier)s vs %(classes)s" strings and then preprend Counters: thing if it's non-empty.


Two more templates have counter tooltips:

  • kush_champion_infantry_apedemak.xml has <Tooltip>Armor-piercing Axes: Counters 1.3x vs. Champions and Heroes.</Tooltip> (from rP21477)
  • template_unit_hero_cavalry_spearman.xml from rP21284

On the GuiInterface.js call, that part is even more performance criticial, since it is performed for every unit selected at least once per turn, so one should avoid doing work there as possible.


As mentioned by Stan above, the tech changes were implemented in rP22346, and as mentioned in D1782, the AI already takes counters into account.

On the phrasing "Counters Melee:" perhaps it should be "Melee Counters:"? (In the first case Counters comes over as a verb, so it sounds like a counter against specific classes of melee units)

So all in all:

  • Two templates missing, some garbage characters, every 1 check sounds avoidable, array construction I recommended may be avoided

I click on request changes as the diff needs a revision, but I'm willing to perform the changes in case you prefer that (FeldFeld).

binaries/data/mods/public/gui/common/tooltips.js
853

The heck happened here

binaries/data/mods/public/simulation/components/Attack.js
492

(offtopic, but above line sounds like a hack)

503

The clone call could be avoided by constructing the output object in place (would also look a bit cleaner).
Secondly this is called often (each attack, each guiinterface call) but changed rarely, perhaps its better to cache it (even if it means one more variable to be stored memory - and even serialized unless explicitly removed from the Serialize function and recreated in the Deserialize function)

binaries/data/mods/public/simulation/components/GuiInterface.js
412

This function is a mess performance-wise, way too much object creation which could be cached in the components at least, even if it makes it harder to read the output. But reading the function again, it seems like 85% of the variables change so often that caching wouldn't be possible for many properties. I guess the object creation itself may be avoided however (only setting the properties). That would be probably thousands of JS Objects less per turn or something (200 units * 20 objects less recreated?).

I really wonder if it makes sense to modify the counters with techs and auras, aren't they something that the player should remember well? I guess I can't argue against the freedom to modify it, especially the modders freedom so whatever, let's go with it.

This revision now requires changes to proceed.Sun, Jul 14, 1:49 PM
nani awarded a token.Mon, Jul 15, 2:39 PM