Page MenuHomeWildfire Games

Adds snapping to edges for buildings
Needs ReviewPublic

Authored by vladislavbelov on Jul 15 2019, 12:20 AM.
Tags
None
Tokens
"Orange Medal" token, awarded by Krinkle."Party Time" token, awarded by asterix."Party Time" token, awarded by nani."Orange Medal" token, awarded by elexis.

Details

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

The patch allows place buildings faster and more perfect aligned. Also it might help to find nearest placeable position in some cases (for ex on the GIF you might see when a preview is inside CC the snapping tries to place it outside without collision).

How it works (GIF, ~10MB):

Test Plan
  1. Apply the patch
  2. Run the game
  3. Make sure that snapping works with Shift key pressed

Diff Detail

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

Event Timeline

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

Linter detected issues:
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/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.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
| 415| 415| 			ret.attack[type].elevationBonus = range.elevationBonus;
| 416| 416| 
| 417| 417| 			if (cmpUnitAI && cmpPosition && cmpPosition.IsInWorld())
| 418|    |-			{
|    | 418|+			
| 419| 419| 				// For units, take the range in front of it, no spread. So angle = 0
| 420| 420| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 0);
| 421|    |-			}
|    | 421|+			
| 422| 422| 			else if(cmpPosition && cmpPosition.IsInWorld())
| 423| 423| 			{
| 424| 424| 				// For buildings, take the average elevation around it. So angle = 2*pi
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
| 420| 420| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 0);
| 421| 421| 			}
| 422| 422| 			else if(cmpPosition && cmpPosition.IsInWorld())
| 423|    |-			{
|    | 423|+			
| 424| 424| 				// For buildings, take the average elevation around it. So angle = 2*pi
| 425| 425| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 2*Math.PI);
| 426|    |-			}
|    | 426|+			
| 427| 427| 			else
| 428| 428| 			{
| 429| 429| 				// not in world, set a default?
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
| 425| 425| 				ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 2*Math.PI);
| 426| 426| 			}
| 427| 427| 			else
| 428|    |-			{
|    | 428|+			
| 429| 429| 				// not in world, set a default?
| 430| 430| 				ret.attack[type].elevationAdaptedRange = ret.attack.maxRange;
| 431|    |-			}
|    | 431|+			
| 432| 432| 		}
| 433| 433| 	}
| 434| 434| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
| 796| 796| 		updateEntityColor(data.showAllStatusBars && (i == player || player == -1) ?
| 797| 797| 			[IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer, IID_StatusBars] :
| 798| 798| 			[IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer],
| 799|    |-			cmpRangeManager.GetEntitiesByPlayer(i));
|    | 799|+		cmpRangeManager.GetEntitiesByPlayer(i));
| 800| 800| 	}
| 801| 801| 	updateEntityColor([IID_Selectable, IID_StatusBars], data.selected);
| 802| 802| 	Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager).UpdateColors();
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1315|1315| 		}
|1316|1316| 	}
|1317|1317| 	else
|1318|    |-	{
|    |1318|+	
|1319|1319| 		// Didn't snap to an existing entity, add the starting tower manually. To prevent odd-looking rotation jumps
|1320|1320| 		// when shift-clicking to build a wall, reuse the placement angle that was last seen on a validly positioned
|1321|1321| 		// wall piece.
|1336|1336| 			"pos": start.pos,
|1337|1337| 			"angle": previewEntities.length > 0 ? previewEntities[0].angle : this.placementWallLastAngle
|1338|1338| 		});
|1339|    |-	}
|    |1339|+	
|1340|1340| 
|1341|1341| 	if (end.pos)
|1342|1342| 	{
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1339|1339| 	}
|1340|1340| 
|1341|1341| 	if (end.pos)
|1342|    |-	{
|    |1342|+	
|1343|1343| 		// Analogous to the starting side case above
|1344|1344| 		if (end.snappedEnt && end.snappedEnt != INVALID_ENTITY)
|1345|1345| 		{
|1377|1377| 				"pos": end.pos,
|1378|1378| 				"angle": previewEntities.length > 0 ? previewEntities[previewEntities.length-1].angle : this.placementWallLastAngle
|1379|1379| 			});
|1380|    |-	}
|    |1380|+	
|1381|1381| 
|1382|1382| 	let cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
|1383|1383| 	if (!cmpTerrain)
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1555|1555| 
|1556|1556| 		let cmpVisual = Engine.QueryInterface(ent, IID_Visual);
|1557|1557| 		if (cmpVisual)
|1558|    |-		{
|    |1558|+		
|1559|1559| 			if (!allPiecesValid || !canAfford)
|1560|1560| 				cmpVisual.SetShadingColor(1.4, 0.4, 0.4, 1);
|1561|1561| 			else
|1562|1562| 				cmpVisual.SetShadingColor(1, 1, 1, 1);
|1563|    |-		}
|    |1563|+		
|1564|1564| 
|1565|1565| 		++entPool.numUsed;
|1566|1566| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1629|1629| 			{
|1630|1630| 				minDist2 = dist2;
|1631|1631| 				minDistEntitySnapData = {
|1632|    |-						"x": pos.x,
|    |1632|+					"x": pos.x,
|1633|1633| 						"z": pos.z,
|1634|1634| 						"angle": cmpPosition.GetRotation().y,
|1635|1635| 						"ent": ent
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1630|1630| 				minDist2 = dist2;
|1631|1631| 				minDistEntitySnapData = {
|1632|1632| 						"x": pos.x,
|1633|    |-						"z": pos.z,
|    |1633|+					"z": pos.z,
|1634|1634| 						"angle": cmpPosition.GetRotation().y,
|1635|1635| 						"ent": ent
|1636|1636| 				};
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1631|1631| 				minDistEntitySnapData = {
|1632|1632| 						"x": pos.x,
|1633|1633| 						"z": pos.z,
|1634|    |-						"angle": cmpPosition.GetRotation().y,
|    |1634|+					"angle": cmpPosition.GetRotation().y,
|1635|1635| 						"ent": ent
|1636|1636| 				};
|1637|1637| 			}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1632|1632| 						"x": pos.x,
|1633|1633| 						"z": pos.z,
|1634|1634| 						"angle": cmpPosition.GetRotation().y,
|1635|    |-						"ent": ent
|    |1635|+					"ent": ent
|1636|1636| 				};
|1637|1637| 			}
|1638|1638| 		}
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1682|1682| 				edges.push(edge);
|1683|1683| 			}
|1684|1684| 			return edges;
|1685|    |-		}
|    |1685|+		};
|1686|1686| 
|1687|1687| 		let edges = getValidEdges(allEdges, templatePos);
|1688|1688| 		if (edges.length)
|    | [NORMAL] ESLintBear (no-else-return):
|    | Unnecessary 'else' after 'return'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1703|1703| 						return behindA - behindB;
|1704|1704| 					if (!behindA)
|1705|1705| 						return a.offsetDistance - b.offsetDistance;
|1706|    |-					else
|1707|    |-						return -a.signedDistance - -b.signedDistance;
|    |1706|+					return -a.signedDistance - -b.signedDistance;
|1708|1707| 				}
|1709|1708| 				return scoreA - scoreB;
|1710|1709| 			};
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1920|1920| 			result.gain = cmpEntityTrader.GetGoods().amount;
|1921|1921| 	}
|1922|1922| 	else if (data.target === secondMarket)
|1923|    |-	{
|    |1923|+	
|1924|1924| 		result = {
|1925|1925| 			"type": "is second",
|1926|1926| 			"gain": cmpEntityTrader.GetGoods().amount,
|1927|1927| 		};
|1928|    |-	}
|    |1928|+	
|1929|1929| 	else if (!firstMarket)
|1930|1930| 	{
|1931|1931| 		result = { "type": "set first" };
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1927|1927| 		};
|1928|1928| 	}
|1929|1929| 	else if (!firstMarket)
|1930|    |-	{
|    |1930|+	
|1931|1931| 		result = { "type": "set first" };
|1932|    |-	}
|    |1932|+	
|1933|1933| 	else if (!secondMarket)
|1934|1934| 	{
|1935|1935| 		result = {
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1931|1931| 		result = { "type": "set first" };
|1932|1932| 	}
|1933|1933| 	else if (!secondMarket)
|1934|    |-	{
|    |1934|+	
|1935|1935| 		result = {
|1936|1936| 			"type": "set second",
|1937|1937| 			"gain": cmpEntityTrader.CalculateGain(firstMarket, data.target),
|1938|1938| 		};
|1939|    |-	}
|    |1939|+	
|1940|1940| 	else
|1941|1941| 	{
|1942|1942| 		// Else both markets are not null and target is different from them
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
|1938|1938| 		};
|1939|1939| 	}
|1940|1940| 	else
|1941|    |-	{
|    |1941|+	
|1942|1942| 		// Else both markets are not null and target is different from them
|1943|1943| 		result = { "type": "set first" };
|1944|    |-	}
|    |1944|+	
|1945|1945| 	return result;
|1946|1946| };
|1947|1947| 

binaries/data/mods/public/simulation/components/GuiInterface.js
|1657| »   »   const·getValidEdges·=·(allEdges,·position)·=>·{
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'allEdges' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/GuiInterface.js
|1775| »   »   »   »   »   let·distance·=·secondEdge.normal.dot(templatePos)·-·secondEdge.normal.dot(secondEdge.begin);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'distance' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/GuiInterface.js
|1685| »   »   }
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.

binaries/data/mods/public/simulation/components/GuiInterface.js
|1707| »   »   »   »   »   »   return·-a.signedDistance·-·-b.signedDistance;
|    | [NORMAL] JSHintBear:
|    | Confusing minuses.
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 181| 181| 		}
| 182| 182| 	}
| 183| 183| 	else if (placementSupport.mode === "wall")
| 184|    |-	{
|    | 184|+	
| 185| 185| 		if (placementSupport.wallSet && placementSupport.position)
| 186| 186| 		{
| 187| 187| 			// Fetch an updated list of snapping candidate entities
| 199| 199| 				"snapEntities": placementSupport.wallSnapEntities,	// snapping entities (towers) for starting a wall segment
| 200| 200| 			});
| 201| 201| 		}
| 202|    |-	}
|    | 202|+	
| 203| 203| 
| 204| 204| 	return false;
| 205| 205| }
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 288| 288| 	}
| 289| 289| 
| 290| 290| 	if (!updateBuildingPlacementPreview())
| 291|    |-	{
|    | 291|+	
| 292| 292| 		// invalid location - don't build it
| 293| 293| 		// TODO: play a sound?
| 294| 294| 		return false;
| 295|    |-	}
|    | 295|+	
| 296| 296| 
| 297| 297| 	var selection = g_Selection.toList();
| 298| 298| 
|    | [NORMAL] ESLintBear (space-unary-ops):
|    | Unary word operator 'typeof' must be followed by whitespace.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 327| 327| 	}
| 328| 328| 
| 329| 329| 	var wallPlacementInfo = updateBuildingPlacementPreview(); // entities making up the wall (wall segments, towers, ...)
| 330|    |-	if (!(wallPlacementInfo === false || typeof(wallPlacementInfo) === "object"))
|    | 330|+	if (!(wallPlacementInfo === false || typeof (wallPlacementInfo) === "object"))
| 331| 331| 	{
| 332| 332| 		error("Invalid updateBuildingPlacementPreview return value: " + uneval(wallPlacementInfo));
| 333| 333| 		return false;
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'for-of'.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 354| 354| 	// (this is somewhat non-ideal and hardcode-ish)
| 355| 355| 	var hasWallSegment = false;
| 356| 356| 	for (let piece of cmd.pieces)
| 357|    |-	{
|    | 357|+	
| 358| 358| 		if (piece.template != cmd.wallSet.templates.tower) // TODO: hardcode-ish :(
| 359| 359| 		{
| 360| 360| 			hasWallSegment = true;
| 361| 361| 			break;
| 362| 362| 		}
| 363|    |-	}
|    | 363|+	
| 364| 364| 
| 365| 365| 	if (hasWallSegment)
| 366| 366| 	{
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 477| 477| 	mouseIsOverObject = (hoveredObject != null);
| 478| 478| 
| 479| 479| 	// Close the menu when interacting with the game world
| 480|    |-	if (!mouseIsOverObject && (ev.type =="mousebuttonup" || ev.type == "mousebuttondown")
| 481|    |-		&& (ev.button == SDL_BUTTON_LEFT || ev.button == SDL_BUTTON_RIGHT))
|    | 480|+	if (!mouseIsOverObject && (ev.type =="mousebuttonup" || ev.type == "mousebuttondown") &&
|    | 481|+		(ev.button == SDL_BUTTON_LEFT || ev.button == SDL_BUTTON_RIGHT))
| 482| 482| 		closeMenu();
| 483| 483| 
| 484| 484| 	// State-machine processing:
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 518| 518| 
| 519| 519| 				// Update the list of selected units
| 520| 520| 				if (Engine.HotkeyIsPressed("selection.add"))
| 521|    |-				{
|    | 521|+				
| 522| 522| 					g_Selection.addList(ents);
| 523|    |-				}
|    | 523|+				
| 524| 524| 				else if (Engine.HotkeyIsPressed("selection.remove"))
| 525| 525| 				{
| 526| 526| 					g_Selection.removeList(ents);
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 522| 522| 					g_Selection.addList(ents);
| 523| 523| 				}
| 524| 524| 				else if (Engine.HotkeyIsPressed("selection.remove"))
| 525|    |-				{
|    | 525|+				
| 526| 526| 					g_Selection.removeList(ents);
| 527|    |-				}
|    | 527|+				
| 528| 528| 				else
| 529| 529| 				{
| 530| 530| 					g_Selection.reset();
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 578| 578| 				// If shift is down, let the player continue placing another of the same building
| 579| 579| 				var queued = Engine.HotkeyIsPressed("session.queue");
| 580| 580| 				if (tryPlaceBuilding(queued))
| 581|    |-				{
|    | 581|+				
| 582| 582| 					if (queued)
| 583| 583| 						inputState = INPUT_BUILDING_PLACEMENT;
| 584| 584| 					else
| 585| 585| 						inputState = INPUT_NORMAL;
| 586|    |-				}
|    | 586|+				
| 587| 587| 				else
| 588| 588| 				{
| 589| 589| 					inputState = INPUT_BUILDING_PLACEMENT;
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 585| 585| 						inputState = INPUT_NORMAL;
| 586| 586| 				}
| 587| 587| 				else
| 588|    |-				{
|    | 588|+				
| 589| 589| 					inputState = INPUT_BUILDING_PLACEMENT;
| 590|    |-				}
|    | 590|+				
| 591| 591| 				return true;
| 592| 592| 			}
| 593| 593| 			break;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 638| 638| 		// user to continue building walls.
| 639| 639| 		switch (ev.type)
| 640| 640| 		{
| 641|    |-			case "mousemotion":
|    | 641|+		case "mousemotion":
| 642| 642| 				placementSupport.wallEndPosition = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
| 643| 643| 
| 644| 644| 				// Update the building placement preview, and by extension, the list of snapping candidate entities for both (!)
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 639| 639| 		switch (ev.type)
| 640| 640| 		{
| 641| 641| 			case "mousemotion":
| 642|    |-				placementSupport.wallEndPosition = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
|    | 642|+			placementSupport.wallEndPosition = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
| 643| 643| 
| 644| 644| 				// Update the building placement preview, and by extension, the list of snapping candidate entities for both (!)
| 645| 645| 				// the ending point and the starting point to snap to.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 641| 641| 			case "mousemotion":
| 642| 642| 				placementSupport.wallEndPosition = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
| 643| 643| 
| 644|    |-				// Update the building placement preview, and by extension, the list of snapping candidate entities for both (!)
|    | 644|+			// Update the building placement preview, and by extension, the list of snapping candidate entities for both (!)
| 645| 645| 				// the ending point and the starting point to snap to.
| 646| 646| 				//
| 647| 647| 				// TODO: Note that here, we need to fetch all similar entities, including any offscreen ones, to support the case
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 642| 642| 				placementSupport.wallEndPosition = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
| 643| 643| 
| 644| 644| 				// Update the building placement preview, and by extension, the list of snapping candidate entities for both (!)
| 645|    |-				// the ending point and the starting point to snap to.
|    | 645|+			// the ending point and the starting point to snap to.
| 646| 646| 				//
| 647| 647| 				// TODO: Note that here, we need to fetch all similar entities, including any offscreen ones, to support the case
| 648| 648| 				// where the snap entity for the starting point has moved offscreen, or has been deleted/destroyed, or was a
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 643| 643| 
| 644| 644| 				// Update the building placement preview, and by extension, the list of snapping candidate entities for both (!)
| 645| 645| 				// the ending point and the starting point to snap to.
| 646|    |-				//
|    | 646|+			//
| 647| 647| 				// TODO: Note that here, we need to fetch all similar entities, including any offscreen ones, to support the case
| 648| 648| 				// where the snap entity for the starting point has moved offscreen, or has been deleted/destroyed, or was a
| 649| 649| 				// foundation and has been replaced with a completed entity since the user first chose it. Fetching all towers on
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 644| 644| 				// Update the building placement preview, and by extension, the list of snapping candidate entities for both (!)
| 645| 645| 				// the ending point and the starting point to snap to.
| 646| 646| 				//
| 647|    |-				// TODO: Note that here, we need to fetch all similar entities, including any offscreen ones, to support the case
|    | 647|+			// TODO: Note that here, we need to fetch all similar entities, including any offscreen ones, to support the case
| 648| 648| 				// where the snap entity for the starting point has moved offscreen, or has been deleted/destroyed, or was a
| 649| 649| 				// foundation and has been replaced with a completed entity since the user first chose it. Fetching all towers on
| 650| 650| 				// the entire map instead of only the current screen might get expensive fast since walls all have a ton of towers
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 645| 645| 				// the ending point and the starting point to snap to.
| 646| 646| 				//
| 647| 647| 				// TODO: Note that here, we need to fetch all similar entities, including any offscreen ones, to support the case
| 648|    |-				// where the snap entity for the starting point has moved offscreen, or has been deleted/destroyed, or was a
|    | 648|+			// where the snap entity for the starting point has moved offscreen, or has been deleted/destroyed, or was a
| 649| 649| 				// foundation and has been replaced with a completed entity since the user first chose it. Fetching all towers on
| 650| 650| 				// the entire map instead of only the current screen might get expensive fast since walls all have a ton of towers
| 651| 651| 				// in them. Might be useful to query only for entities within a certain range around the starting point and ending
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 646| 646| 				//
| 647| 647| 				// TODO: Note that here, we need to fetch all similar entities, including any offscreen ones, to support the case
| 648| 648| 				// where the snap entity for the starting point has moved offscreen, or has been deleted/destroyed, or was a
| 649|    |-				// foundation and has been replaced with a completed entity since the user first chose it. Fetching all towers on
|    | 649|+			// foundation and has been replaced with a completed entity since the user first chose it. Fetching all towers on
| 650| 650| 				// the entire map instead of only the current screen might get expensive fast since walls all have a ton of towers
| 651| 651| 				// in them. Might be useful to query only for entities within a certain range around the starting point and ending
| 652| 652| 				// points.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 647| 647| 				// TODO: Note that here, we need to fetch all similar entities, including any offscreen ones, to support the case
| 648| 648| 				// where the snap entity for the starting point has moved offscreen, or has been deleted/destroyed, or was a
| 649| 649| 				// foundation and has been replaced with a completed entity since the user first chose it. Fetching all towers on
| 650|    |-				// the entire map instead of only the current screen might get expensive fast since walls all have a ton of towers
|    | 650|+			// the entire map instead of only the current screen might get expensive fast since walls all have a ton of towers
| 651| 651| 				// in them. Might be useful to query only for entities within a certain range around the starting point and ending
| 652| 652| 				// points.
| 653| 653| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 648| 648| 				// where the snap entity for the starting point has moved offscreen, or has been deleted/destroyed, or was a
| 649| 649| 				// foundation and has been replaced with a completed entity since the user first chose it. Fetching all towers on
| 650| 650| 				// the entire map instead of only the current screen might get expensive fast since walls all have a ton of towers
| 651|    |-				// in them. Might be useful to query only for entities within a certain range around the starting point and ending
|    | 651|+			// in them. Might be useful to query only for entities within a certain range around the starting point and ending
| 652| 652| 				// points.
| 653| 653| 
| 654| 654| 				placementSupport.wallSnapEntitiesIncludeOffscreen = true;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 649| 649| 				// foundation and has been replaced with a completed entity since the user first chose it. Fetching all towers on
| 650| 650| 				// the entire map instead of only the current screen might get expensive fast since walls all have a ton of towers
| 651| 651| 				// in them. Might be useful to query only for entities within a certain range around the starting point and ending
| 652|    |-				// points.
|    | 652|+			// points.
| 653| 653| 
| 654| 654| 				placementSupport.wallSnapEntitiesIncludeOffscreen = true;
| 655| 655| 				var result = updateBuildingPlacementPreview(); // includes an update of the snap entity candidates
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 651| 651| 				// in them. Might be useful to query only for entities within a certain range around the starting point and ending
| 652| 652| 				// points.
| 653| 653| 
| 654|    |-				placementSupport.wallSnapEntitiesIncludeOffscreen = true;
|    | 654|+			placementSupport.wallSnapEntitiesIncludeOffscreen = true;
| 655| 655| 				var result = updateBuildingPlacementPreview(); // includes an update of the snap entity candidates
| 656| 656| 
| 657| 657| 				if (result && result.cost)
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 652| 652| 				// points.
| 653| 653| 
| 654| 654| 				placementSupport.wallSnapEntitiesIncludeOffscreen = true;
| 655|    |-				var result = updateBuildingPlacementPreview(); // includes an update of the snap entity candidates
|    | 655|+			var result = updateBuildingPlacementPreview(); // includes an update of the snap entity candidates
| 656| 656| 
| 657| 657| 				if (result && result.cost)
| 658| 658| 				{
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 654| 654| 				placementSupport.wallSnapEntitiesIncludeOffscreen = true;
| 655| 655| 				var result = updateBuildingPlacementPreview(); // includes an update of the snap entity candidates
| 656| 656| 
| 657|    |-				if (result && result.cost)
|    | 657|+			if (result && result.cost)
| 658| 658| 				{
| 659| 659| 					var neededResources = Engine.GuiInterfaceCall("GetNeededResources", { "cost": result.cost });
| 660| 660| 					placementSupport.tooltipMessage = [
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 655| 655| 				var result = updateBuildingPlacementPreview(); // includes an update of the snap entity candidates
| 656| 656| 
| 657| 657| 				if (result && result.cost)
| 658|    |-				{
|    | 658|+			{
| 659| 659| 					var neededResources = Engine.GuiInterfaceCall("GetNeededResources", { "cost": result.cost });
| 660| 660| 					placementSupport.tooltipMessage = [
| 661| 661| 						getEntityCostTooltip(result),
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 656| 656| 
| 657| 657| 				if (result && result.cost)
| 658| 658| 				{
| 659|    |-					var neededResources = Engine.GuiInterfaceCall("GetNeededResources", { "cost": result.cost });
|    | 659|+				var neededResources = Engine.GuiInterfaceCall("GetNeededResources", { "cost": result.cost });
| 660| 660| 					placementSupport.tooltipMessage = [
| 661| 661| 						getEntityCostTooltip(result),
| 662| 662| 						getNeededResourcesTooltip(neededResources)
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 657| 657| 				if (result && result.cost)
| 658| 658| 				{
| 659| 659| 					var neededResources = Engine.GuiInterfaceCall("GetNeededResources", { "cost": result.cost });
| 660|    |-					placementSupport.tooltipMessage = [
|    | 660|+				placementSupport.tooltipMessage = [
| 661| 661| 						getEntityCostTooltip(result),
| 662| 662| 						getNeededResourcesTooltip(neededResources)
| 663| 663| 					].filter(tip => tip).join("\n");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 658| 658| 				{
| 659| 659| 					var neededResources = Engine.GuiInterfaceCall("GetNeededResources", { "cost": result.cost });
| 660| 660| 					placementSupport.tooltipMessage = [
| 661|    |-						getEntityCostTooltip(result),
|    | 661|+					getEntityCostTooltip(result),
| 662| 662| 						getNeededResourcesTooltip(neededResources)
| 663| 663| 					].filter(tip => tip).join("\n");
| 664| 664| 				}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 659| 659| 					var neededResources = Engine.GuiInterfaceCall("GetNeededResources", { "cost": result.cost });
| 660| 660| 					placementSupport.tooltipMessage = [
| 661| 661| 						getEntityCostTooltip(result),
| 662|    |-						getNeededResourcesTooltip(neededResources)
|    | 662|+					getNeededResourcesTooltip(neededResources)
| 663| 663| 					].filter(tip => tip).join("\n");
| 664| 664| 				}
| 665| 665| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 660| 660| 					placementSupport.tooltipMessage = [
| 661| 661| 						getEntityCostTooltip(result),
| 662| 662| 						getNeededResourcesTooltip(neededResources)
| 663|    |-					].filter(tip => tip).join("\n");
|    | 663|+				].filter(tip => tip).join("\n");
| 664| 664| 				}
| 665| 665| 
| 666| 666| 				break;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 661| 661| 						getEntityCostTooltip(result),
| 662| 662| 						getNeededResourcesTooltip(neededResources)
| 663| 663| 					].filter(tip => tip).join("\n");
| 664|    |-				}
|    | 664|+			}
| 665| 665| 
| 666| 666| 				break;
| 667| 667| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 663| 663| 					].filter(tip => tip).join("\n");
| 664| 664| 				}
| 665| 665| 
| 666|    |-				break;
|    | 666|+			break;
| 667| 667| 
| 668| 668| 			case "mousebuttondown":
| 669| 669| 				if (ev.button == SDL_BUTTON_LEFT)
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 665| 665| 
| 666| 666| 				break;
| 667| 667| 
| 668|    |-			case "mousebuttondown":
|    | 668|+		case "mousebuttondown":
| 669| 669| 				if (ev.button == SDL_BUTTON_LEFT)
| 670| 670| 				{
| 671| 671| 					var queued = Engine.HotkeyIsPressed("session.queue");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 666| 666| 				break;
| 667| 667| 
| 668| 668| 			case "mousebuttondown":
| 669|    |-				if (ev.button == SDL_BUTTON_LEFT)
|    | 669|+			if (ev.button == SDL_BUTTON_LEFT)
| 670| 670| 				{
| 671| 671| 					var queued = Engine.HotkeyIsPressed("session.queue");
| 672| 672| 					if (tryPlaceWall(queued))
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 667| 667| 
| 668| 668| 			case "mousebuttondown":
| 669| 669| 				if (ev.button == SDL_BUTTON_LEFT)
| 670|    |-				{
|    | 670|+			{
| 671| 671| 					var queued = Engine.HotkeyIsPressed("session.queue");
| 672| 672| 					if (tryPlaceWall(queued))
| 673| 673| 					{
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 668| 668| 			case "mousebuttondown":
| 669| 669| 				if (ev.button == SDL_BUTTON_LEFT)
| 670| 670| 				{
| 671|    |-					var queued = Engine.HotkeyIsPressed("session.queue");
|    | 671|+				var queued = Engine.HotkeyIsPressed("session.queue");
| 672| 672| 					if (tryPlaceWall(queued))
| 673| 673| 					{
| 674| 674| 						if (queued)
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 669| 669| 				if (ev.button == SDL_BUTTON_LEFT)
| 670| 670| 				{
| 671| 671| 					var queued = Engine.HotkeyIsPressed("session.queue");
| 672|    |-					if (tryPlaceWall(queued))
|    | 672|+				if (tryPlaceWall(queued))
| 673| 673| 					{
| 674| 674| 						if (queued)
| 675| 675| 						{
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 670| 670| 				{
| 671| 671| 					var queued = Engine.HotkeyIsPressed("session.queue");
| 672| 672| 					if (tryPlaceWall(queued))
| 673|    |-					{
|    | 673|+					
| 674| 674| 						if (queued)
| 675| 675| 						{
| 676| 676| 							// continue building, just set a new starting position where we left off
| 684| 684| 							placementSupport.Reset();
| 685| 685| 							inputState = INPUT_NORMAL;
| 686| 686| 						}
| 687|    |-					}
|    | 687|+					
| 688| 688| 					else
| 689| 689| 						placementSupport.tooltipMessage = translate("Cannot build wall here!");
| 690| 690| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 670| 670| 				{
| 671| 671| 					var queued = Engine.HotkeyIsPressed("session.queue");
| 672| 672| 					if (tryPlaceWall(queued))
| 673|    |-					{
|    | 673|+				{
| 674| 674| 						if (queued)
| 675| 675| 						{
| 676| 676| 							// continue building, just set a new starting position where we left off
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 671| 671| 					var queued = Engine.HotkeyIsPressed("session.queue");
| 672| 672| 					if (tryPlaceWall(queued))
| 673| 673| 					{
| 674|    |-						if (queued)
|    | 674|+					if (queued)
| 675| 675| 						{
| 676| 676| 							// continue building, just set a new starting position where we left off
| 677| 677| 							placementSupport.position = placementSupport.wallEndPosition;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 672| 672| 					if (tryPlaceWall(queued))
| 673| 673| 					{
| 674| 674| 						if (queued)
| 675|    |-						{
|    | 675|+					{
| 676| 676| 							// continue building, just set a new starting position where we left off
| 677| 677| 							placementSupport.position = placementSupport.wallEndPosition;
| 678| 678| 							placementSupport.wallEndPosition = undefined;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 7.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 673| 673| 					{
| 674| 674| 						if (queued)
| 675| 675| 						{
| 676|    |-							// continue building, just set a new starting position where we left off
|    | 676|+						// continue building, just set a new starting position where we left off
| 677| 677| 							placementSupport.position = placementSupport.wallEndPosition;
| 678| 678| 							placementSupport.wallEndPosition = undefined;
| 679| 679| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 7.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 674| 674| 						if (queued)
| 675| 675| 						{
| 676| 676| 							// continue building, just set a new starting position where we left off
| 677|    |-							placementSupport.position = placementSupport.wallEndPosition;
|    | 677|+						placementSupport.position = placementSupport.wallEndPosition;
| 678| 678| 							placementSupport.wallEndPosition = undefined;
| 679| 679| 
| 680| 680| 							inputState = INPUT_BUILDING_WALL_CLICK;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 7.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 675| 675| 						{
| 676| 676| 							// continue building, just set a new starting position where we left off
| 677| 677| 							placementSupport.position = placementSupport.wallEndPosition;
| 678|    |-							placementSupport.wallEndPosition = undefined;
|    | 678|+						placementSupport.wallEndPosition = undefined;
| 679| 679| 
| 680| 680| 							inputState = INPUT_BUILDING_WALL_CLICK;
| 681| 681| 						}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 7.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 677| 677| 							placementSupport.position = placementSupport.wallEndPosition;
| 678| 678| 							placementSupport.wallEndPosition = undefined;
| 679| 679| 
| 680|    |-							inputState = INPUT_BUILDING_WALL_CLICK;
|    | 680|+						inputState = INPUT_BUILDING_WALL_CLICK;
| 681| 681| 						}
| 682| 682| 						else
| 683| 683| 						{
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 678| 678| 							placementSupport.wallEndPosition = undefined;
| 679| 679| 
| 680| 680| 							inputState = INPUT_BUILDING_WALL_CLICK;
| 681|    |-						}
|    | 681|+					}
| 682| 682| 						else
| 683| 683| 						{
| 684| 684| 							placementSupport.Reset();
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 679| 679| 
| 680| 680| 							inputState = INPUT_BUILDING_WALL_CLICK;
| 681| 681| 						}
| 682|    |-						else
|    | 682|+					else
| 683| 683| 						{
| 684| 684| 							placementSupport.Reset();
| 685| 685| 							inputState = INPUT_NORMAL;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 680| 680| 							inputState = INPUT_BUILDING_WALL_CLICK;
| 681| 681| 						}
| 682| 682| 						else
| 683|    |-						{
|    | 683|+					{
| 684| 684| 							placementSupport.Reset();
| 685| 685| 							inputState = INPUT_NORMAL;
| 686| 686| 						}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 7.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 681| 681| 						}
| 682| 682| 						else
| 683| 683| 						{
| 684|    |-							placementSupport.Reset();
|    | 684|+						placementSupport.Reset();
| 685| 685| 							inputState = INPUT_NORMAL;
| 686| 686| 						}
| 687| 687| 					}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 7.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 682| 682| 						else
| 683| 683| 						{
| 684| 684| 							placementSupport.Reset();
| 685|    |-							inputState = INPUT_NORMAL;
|    | 685|+						inputState = INPUT_NORMAL;
| 686| 686| 						}
| 687| 687| 					}
| 688| 688| 					else
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 683| 683| 						{
| 684| 684| 							placementSupport.Reset();
| 685| 685| 							inputState = INPUT_NORMAL;
| 686|    |-						}
|    | 686|+					}
| 687| 687| 					}
| 688| 688| 					else
| 689| 689| 						placementSupport.tooltipMessage = translate("Cannot build wall here!");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 684| 684| 							placementSupport.Reset();
| 685| 685| 							inputState = INPUT_NORMAL;
| 686| 686| 						}
| 687|    |-					}
|    | 687|+				}
| 688| 688| 					else
| 689| 689| 						placementSupport.tooltipMessage = translate("Cannot build wall here!");
| 690| 690| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 685| 685| 							inputState = INPUT_NORMAL;
| 686| 686| 						}
| 687| 687| 					}
| 688|    |-					else
|    | 688|+				else
| 689| 689| 						placementSupport.tooltipMessage = translate("Cannot build wall here!");
| 690| 690| 
| 691| 691| 					updateBuildingPlacementPreview();
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 686| 686| 						}
| 687| 687| 					}
| 688| 688| 					else
| 689|    |-						placementSupport.tooltipMessage = translate("Cannot build wall here!");
|    | 689|+					placementSupport.tooltipMessage = translate("Cannot build wall here!");
| 690| 690| 
| 691| 691| 					updateBuildingPlacementPreview();
| 692| 692| 					return true;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 688| 688| 					else
| 689| 689| 						placementSupport.tooltipMessage = translate("Cannot build wall here!");
| 690| 690| 
| 691|    |-					updateBuildingPlacementPreview();
|    | 691|+				updateBuildingPlacementPreview();
| 692| 692| 					return true;
| 693| 693| 				}
| 694| 694| 				else if (ev.button == SDL_BUTTON_RIGHT)
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 689| 689| 						placementSupport.tooltipMessage = translate("Cannot build wall here!");
| 690| 690| 
| 691| 691| 					updateBuildingPlacementPreview();
| 692|    |-					return true;
|    | 692|+				return true;
| 693| 693| 				}
| 694| 694| 				else if (ev.button == SDL_BUTTON_RIGHT)
| 695| 695| 				{
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 690| 690| 
| 691| 691| 					updateBuildingPlacementPreview();
| 692| 692| 					return true;
| 693|    |-				}
|    | 693|+			}
| 694| 694| 				else if (ev.button == SDL_BUTTON_RIGHT)
| 695| 695| 				{
| 696| 696| 					// reset to normal input mode
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 691| 691| 					updateBuildingPlacementPreview();
| 692| 692| 					return true;
| 693| 693| 				}
| 694|    |-				else if (ev.button == SDL_BUTTON_RIGHT)
|    | 694|+			else if (ev.button == SDL_BUTTON_RIGHT)
| 695| 695| 				{
| 696| 696| 					// reset to normal input mode
| 697| 697| 					placementSupport.Reset();
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 692| 692| 					return true;
| 693| 693| 				}
| 694| 694| 				else if (ev.button == SDL_BUTTON_RIGHT)
| 695|    |-				{
|    | 695|+			{
| 696| 696| 					// reset to normal input mode
| 697| 697| 					placementSupport.Reset();
| 698| 698| 					updateBuildingPlacementPreview();
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 693| 693| 				}
| 694| 694| 				else if (ev.button == SDL_BUTTON_RIGHT)
| 695| 695| 				{
| 696|    |-					// reset to normal input mode
|    | 696|+				// reset to normal input mode
| 697| 697| 					placementSupport.Reset();
| 698| 698| 					updateBuildingPlacementPreview();
| 699| 699| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 694| 694| 				else if (ev.button == SDL_BUTTON_RIGHT)
| 695| 695| 				{
| 696| 696| 					// reset to normal input mode
| 697|    |-					placementSupport.Reset();
|    | 697|+				placementSupport.Reset();
| 698| 698| 					updateBuildingPlacementPreview();
| 699| 699| 
| 700| 700| 					inputState = INPUT_NORMAL;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 695| 695| 				{
| 696| 696| 					// reset to normal input mode
| 697| 697| 					placementSupport.Reset();
| 698|    |-					updateBuildingPlacementPreview();
|    | 698|+				updateBuildingPlacementPreview();
| 699| 699| 
| 700| 700| 					inputState = INPUT_NORMAL;
| 701| 701| 					return true;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 697| 697| 					placementSupport.Reset();
| 698| 698| 					updateBuildingPlacementPreview();
| 699| 699| 
| 700|    |-					inputState = INPUT_NORMAL;
|    | 700|+				inputState = INPUT_NORMAL;
| 701| 701| 					return true;
| 702| 702| 				}
| 703| 703| 				break;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 698| 698| 					updateBuildingPlacementPreview();
| 699| 699| 
| 700| 700| 					inputState = INPUT_NORMAL;
| 701|    |-					return true;
|    | 701|+				return true;
| 702| 702| 				}
| 703| 703| 				break;
| 704| 704| 		}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 699| 699| 
| 700| 700| 					inputState = INPUT_NORMAL;
| 701| 701| 					return true;
| 702|    |-				}
|    | 702|+			}
| 703| 703| 				break;
| 704| 704| 		}
| 705| 705| 		break;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 700| 700| 					inputState = INPUT_NORMAL;
| 701| 701| 					return true;
| 702| 702| 				}
| 703|    |-				break;
|    | 703|+			break;
| 704| 704| 		}
| 705| 705| 		break;
| 706| 706| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 710| 710| 		case "mousemotion":
| 711| 711| 			let maxDragDelta = 16;
| 712| 712| 			if (g_DragStart.distanceTo(ev) >= maxDragDelta)
| 713|    |-			{
|    | 713|+			
| 714| 714| 				// Rotate in the direction of the mouse
| 715| 715| 				placementSupport.angle = placementSupport.position.horizAngleTo(Engine.GetTerrainAtScreenPoint(ev.x, ev.y));
| 716|    |-			}
|    | 716|+			
| 717| 717| 			else
| 718| 718| 			{
| 719| 719| 				// If the mouse is near the center, snap back to the default orientation
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 715| 715| 				placementSupport.angle = placementSupport.position.horizAngleTo(Engine.GetTerrainAtScreenPoint(ev.x, ev.y));
| 716| 716| 			}
| 717| 717| 			else
| 718|    |-			{
|    | 718|+			
| 719| 719| 				// If the mouse is near the center, snap back to the default orientation
| 720| 720| 				placementSupport.SetDefaultAngle();
| 721|    |-			}
|    | 721|+			
| 722| 722| 
| 723| 723| 			var snapToEdge = Engine.HotkeyIsPressed("session.snaptoedge");
| 724| 724| 			var snapData = Engine.GuiInterfaceCall("GetFoundationSnapData", {
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 744| 744| 				// If shift is down, let the player continue placing another of the same building
| 745| 745| 				var queued = Engine.HotkeyIsPressed("session.queue");
| 746| 746| 				if (tryPlaceBuilding(queued))
| 747|    |-				{
|    | 747|+				
| 748| 748| 					if (queued)
| 749| 749| 						inputState = INPUT_BUILDING_PLACEMENT;
| 750| 750| 					else
| 751| 751| 						inputState = INPUT_NORMAL;
| 752|    |-				}
|    | 752|+				
| 753| 753| 				else
| 754| 754| 				{
| 755| 755| 					inputState = INPUT_BUILDING_PLACEMENT;
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'else'.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 751| 751| 						inputState = INPUT_NORMAL;
| 752| 752| 				}
| 753| 753| 				else
| 754|    |-				{
|    | 754|+				
| 755| 755| 					inputState = INPUT_BUILDING_PLACEMENT;
| 756|    |-				}
|    | 756|+				
| 757| 757| 				return true;
| 758| 758| 			}
| 759| 759| 			break;
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 800| 800| 
| 801| 801| 	// Handle the time-warp testing features, restricted to single-player
| 802| 802| 	if (!g_IsNetworked && g_DeveloperOverlay.isTimeWarpEnabled())
| 803|    |-	{
|    | 803|+	
| 804| 804| 		if (ev.type == "hotkeydown" && ev.hotkey == "session.timewarp.fastforward")
| 805| 805| 			Engine.SetSimRate(20.0);
| 806| 806| 		else if (ev.type == "hotkeyup" && ev.hotkey == "session.timewarp.fastforward")
| 807| 807| 			Engine.SetSimRate(1.0);
| 808| 808| 		else if (ev.type == "hotkeyup" && ev.hotkey == "session.timewarp.rewind")
| 809| 809| 			Engine.RewindTimeWarp();
| 810|    |-	}
|    | 810|+	
| 811| 811| 
| 812| 812| 	if (ev.hotkey == "session.highlightguarding")
| 813| 813| 	{
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 859| 859| 			break;
| 860| 860| 
| 861| 861| 		case "hotkeydown":
| 862|    |-				if (ev.hotkey.indexOf("selection.group.") == 0)
|    | 862|+			if (ev.hotkey.indexOf("selection.group.") == 0)
| 863| 863| 				{
| 864| 864| 					let now = Date.now();
| 865| 865| 					if (now - doublePressTimer < doublePressTime && ev.hotkey == prevHotkey)
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 860| 860| 
| 861| 861| 		case "hotkeydown":
| 862| 862| 				if (ev.hotkey.indexOf("selection.group.") == 0)
| 863|    |-				{
|    | 863|+			{
| 864| 864| 					let now = Date.now();
| 865| 865| 					if (now - doublePressTimer < doublePressTime && ev.hotkey == prevHotkey)
| 866| 866| 					{
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 861| 861| 		case "hotkeydown":
| 862| 862| 				if (ev.hotkey.indexOf("selection.group.") == 0)
| 863| 863| 				{
| 864|    |-					let now = Date.now();
|    | 864|+				let now = Date.now();
| 865| 865| 					if (now - doublePressTimer < doublePressTime && ev.hotkey == prevHotkey)
| 866| 866| 					{
| 867| 867| 						if (ev.hotkey.indexOf("selection.group.select.") == 0)
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 862| 862| 				if (ev.hotkey.indexOf("selection.group.") == 0)
| 863| 863| 				{
| 864| 864| 					let now = Date.now();
| 865|    |-					if (now - doublePressTimer < doublePressTime && ev.hotkey == prevHotkey)
|    | 865|+				if (now - doublePressTimer < doublePressTime && ev.hotkey == prevHotkey)
| 866| 866| 					{
| 867| 867| 						if (ev.hotkey.indexOf("selection.group.select.") == 0)
| 868| 868| 						{
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 863| 863| 				{
| 864| 864| 					let now = Date.now();
| 865| 865| 					if (now - doublePressTimer < doublePressTime && ev.hotkey == prevHotkey)
| 866|    |-					{
|    | 866|+				{
| 867| 867| 						if (ev.hotkey.indexOf("selection.group.select.") == 0)
| 868| 868| 						{
| 869| 869| 							var sptr = ev.hotkey.split(".");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 864| 864| 					let now = Date.now();
| 865| 865| 					if (now - doublePressTimer < doublePressTime && ev.hotkey == prevHotkey)
| 866| 866| 					{
| 867|    |-						if (ev.hotkey.indexOf("selection.group.select.") == 0)
|    | 867|+					if (ev.hotkey.indexOf("selection.group.select.") == 0)
| 868| 868| 						{
| 869| 869| 							var sptr = ev.hotkey.split(".");
| 870| 870| 							performGroup("snap", sptr[3]);
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 865| 865| 					if (now - doublePressTimer < doublePressTime && ev.hotkey == prevHotkey)
| 866| 866| 					{
| 867| 867| 						if (ev.hotkey.indexOf("selection.group.select.") == 0)
| 868|    |-						{
|    | 868|+					{
| 869| 869| 							var sptr = ev.hotkey.split(".");
| 870| 870| 							performGroup("snap", sptr[3]);
| 871| 871| 						}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 7.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 866| 866| 					{
| 867| 867| 						if (ev.hotkey.indexOf("selection.group.select.") == 0)
| 868| 868| 						{
| 869|    |-							var sptr = ev.hotkey.split(".");
|    | 869|+						var sptr = ev.hotkey.split(".");
| 870| 870| 							performGroup("snap", sptr[3]);
| 871| 871| 						}
| 872| 872| 					}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 7.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 867| 867| 						if (ev.hotkey.indexOf("selection.group.select.") == 0)
| 868| 868| 						{
| 869| 869| 							var sptr = ev.hotkey.split(".");
| 870|    |-							performGroup("snap", sptr[3]);
|    | 870|+						performGroup("snap", sptr[3]);
| 871| 871| 						}
| 872| 872| 					}
| 873| 873| 					else
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 868| 868| 						{
| 869| 869| 							var sptr = ev.hotkey.split(".");
| 870| 870| 							performGroup("snap", sptr[3]);
| 871|    |-						}
|    | 871|+					}
| 872| 872| 					}
| 873| 873| 					else
| 874| 874| 					{
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 869| 869| 							var sptr = ev.hotkey.split(".");
| 870| 870| 							performGroup("snap", sptr[3]);
| 871| 871| 						}
| 872|    |-					}
|    | 872|+				}
| 873| 873| 					else
| 874| 874| 					{
| 875| 875| 						var sptr = ev.hotkey.split(".");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 870| 870| 							performGroup("snap", sptr[3]);
| 871| 871| 						}
| 872| 872| 					}
| 873|    |-					else
|    | 873|+				else
| 874| 874| 					{
| 875| 875| 						var sptr = ev.hotkey.split(".");
| 876| 876| 						performGroup(sptr[2], sptr[3]);
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 871| 871| 						}
| 872| 872| 					}
| 873| 873| 					else
| 874|    |-					{
|    | 874|+				{
| 875| 875| 						var sptr = ev.hotkey.split(".");
| 876| 876| 						performGroup(sptr[2], sptr[3]);
| 877| 877| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 872| 872| 					}
| 873| 873| 					else
| 874| 874| 					{
| 875|    |-						var sptr = ev.hotkey.split(".");
|    | 875|+					var sptr = ev.hotkey.split(".");
| 876| 876| 						performGroup(sptr[2], sptr[3]);
| 877| 877| 
| 878| 878| 						doublePressTimer = now;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 873| 873| 					else
| 874| 874| 					{
| 875| 875| 						var sptr = ev.hotkey.split(".");
| 876|    |-						performGroup(sptr[2], sptr[3]);
|    | 876|+					performGroup(sptr[2], sptr[3]);
| 877| 877| 
| 878| 878| 						doublePressTimer = now;
| 879| 879| 						prevHotkey = ev.hotkey;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 875| 875| 						var sptr = ev.hotkey.split(".");
| 876| 876| 						performGroup(sptr[2], sptr[3]);
| 877| 877| 
| 878|    |-						doublePressTimer = now;
|    | 878|+					doublePressTimer = now;
| 879| 879| 						prevHotkey = ev.hotkey;
| 880| 880| 					}
| 881| 881| 				}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 6.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 876| 876| 						performGroup(sptr[2], sptr[3]);
| 877| 877| 
| 878| 878| 						doublePressTimer = now;
| 879|    |-						prevHotkey = ev.hotkey;
|    | 879|+					prevHotkey = ev.hotkey;
| 880| 880| 					}
| 881| 881| 				}
| 882| 882| 				break;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 877| 877| 
| 878| 878| 						doublePressTimer = now;
| 879| 879| 						prevHotkey = ev.hotkey;
| 880|    |-					}
|    | 880|+				}
| 881| 881| 				}
| 882| 882| 				break;
| 883| 883| 		}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 878| 878| 						doublePressTimer = now;
| 879| 879| 						prevHotkey = ev.hotkey;
| 880| 880| 					}
| 881|    |-				}
|    | 881|+			}
| 882| 882| 				break;
| 883| 883| 		}
| 884| 884| 		break;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
| 879| 879| 						prevHotkey = ev.hotkey;
| 880| 880| 					}
| 881| 881| 				}
| 882|    |-				break;
|    | 882|+			break;
| 883| 883| 		}
| 884| 884| 		break;
| 885| 885| 
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|1047|1047| 			placementSupport.position = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
|1048|1048| 
|1049|1049| 			if (placementSupport.mode === "wall")
|1050|    |-			{
|    |1050|+			
|1051|1051| 				// Including only the on-screen towers in the next snap candidate list is sufficient here, since the user is
|1052|1052| 				// still selecting a starting point (which must necessarily be on-screen). (The update of the snap entities
|1053|1053| 				// itself happens in the call to updateBuildingPlacementPreview below).
|1054|1054| 				placementSupport.wallSnapEntitiesIncludeOffscreen = false;
|1055|    |-			}
|    |1055|+			
|1056|1056| 			else
|1057|1057| 			{
|1058|1058| 				// cancel if not enough resources
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|1339|1339| 	if (templateData.attack &&
|1340|1340| 		templateData.attack.Ranged &&
|1341|1341| 		templateData.attack.Ranged.maxRange)
|1342|    |-	{
|    |1342|+	
|1343|1343| 		// add attack information to display a good tooltip
|1344|1344| 		placementSupport.attack = templateData.attack;
|1345|    |-	}
|    |1345|+	
|1346|1346| }
|1347|1347| 
|1348|1348| // Batch training:
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'if' condition.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|1427|1427| 	if (Engine.HotkeyIsPressed("session.batchtrain") && (canBeAddedCount == undefined || canBeAddedCount > 1))
|1428|1428| 	{
|1429|1429| 		if (inputState == INPUT_BATCHTRAINING)
|1430|    |-		{
|    |1430|+		
|1431|1431| 			// Check if we are training in the same building(s) as the last batch
|1432|1432| 			// NOTE: We just check if the arrays are the same and if the order is the same
|1433|1433| 			// If the order changed, we have a new selection and we should create a new batch.
|1460|1460| 			else if (!decrement)
|1461|1461| 				flushTrainingBatch();
|1462|1462| 				// fall through to create the new batch
|1463|    |-		}
|    |1463|+		
|1464|1464| 
|1465|1465| 		// Don't start a new batch if decrementing or unable to afford it.
|1466|1466| 		if (decrement || Engine.GuiInterfaceCall("GetNeededResources", { "cost":
|    | [NORMAL] ESLintBear (space-in-parens):
|    | There should be no spaces inside this paren.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|1537|1537| 		g_BatchTrainingEntityAllowedCount < batchedSize * appropriateBuildings.length)
|1538|1538| 	{
|1539|1539| 		// Train as many full batches as we can
|1540|    |-		let buildingsCountToTrainFullBatch = Math.floor( g_BatchTrainingEntityAllowedCount / batchedSize);
|    |1540|+		let buildingsCountToTrainFullBatch = Math.floor(g_BatchTrainingEntityAllowedCount / batchedSize);
|1541|1541| 		Engine.PostNetworkCommand({
|1542|1542| 			"type": "train",
|1543|1543| 			"entities": appropriateBuildings.slice(0, buildingsCountToTrainFullBatch),
|    | [NORMAL] ESLintBear (comma-spacing):
|    | A space is required after ','.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/input.js
|1616|1616| 	var selectall = Engine.HotkeyIsPressed("selection.offscreen");
|1617|1617| 
|1618|1618| 	// Reset the last idle unit, etc., if the selection type has changed.
|1619|    |-	if (selectall || classes.length != lastIdleClasses.length || !classes.every((v,i) => v === lastIdleClasses[i]))
|    |1619|+	if (selectall || classes.length != lastIdleClasses.length || !classes.every((v, i) => v === lastIdleClasses[i]))
|1620|1620| 		resetIdleUnit();
|1621|1621| 	lastIdleClasses = classes;
|1622|1622| 

binaries/data/mods/public/gui/session/input.js
| 228| »   »   var·entState·=·GetEntityState(ent);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'entState' is already declared in the upper scope.

binaries/data/mods/public/gui/session/input.js
| 235| »   var·target·=·undefined;
|    | [NORMAL] ESLintBear (no-undef-init):
|    | It's not necessary to initialize 'target' to undefined.

binaries/data/mods/public/gui/session/input.js
| 249| »   var·actionInfo·=·undefined;
|    | [NORMAL] ESLintBear (no-undef-init):
|    | It's not necessary to initialize 'actionInfo' to undefined.

binaries/data/mods/public/gui/session/input.js
| 466| »   switch·(ev.type)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

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

binaries/data/mods/public/gui/session/input.js
| 497| »   »   switch·(ev.type)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/input.js
| 552| »   »   switch·(ev.type)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/input.js
| 562| »   »   switch·(ev.type)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/input.js
| 610| »   »   switch·(ev.type)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/input.js
| 639| »   »   switch·(ev.type)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/input.js
| 708| »   »   switch·(ev.type)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

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

binaries/data/mods/public/gui/session/input.js
| 831| »   »   switch·(ev.type)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/input.js
| 931| »   »   switch·(ev.type)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/input.js
|1020| »   »   switch·(ev.type)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/input.js
|1034| »   »   »   »   let·action·=·determineAction(ev.x,·ev.y);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'action' is already declared in the upper scope.

binaries/data/mods/public/gui/session/input.js
|1043| »   »   switch·(ev.type)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

binaries/data/mods/public/gui/session/input.js
|1132| »   »   »   switch·(ev.hotkey)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.

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

binaries/data/mods/public/gui/session/input.js
| 235| »   var·target·=·undefined;
|    | [NORMAL] JSHintBear:
|    | It's not necessary to initialize 'target' to 'undefined'.

binaries/data/mods/public/gui/session/input.js
| 249| »   var·actionInfo·=·undefined;
|    | [NORMAL] JSHintBear:
|    | It's not necessary to initialize 'actionInfo' to 'undefined'.

binaries/data/mods/public/gui/session/input.js
| 263| »   for·(var·action·of·actions)
|    | [NORMAL] JSHintBear:
|    | 'action' is already defined.

binaries/data/mods/public/gui/session/input.js
| 266| »   »   »   var·r·=·g_UnitActions[action].hotkeyActionCheck(target,·selection);
|    | [NORMAL] JSHintBear:
|    | 'r' is already defined.

binaries/data/mods/public/gui/session/input.js
| 271| »   for·(var·action·of·actions)
|    | [NORMAL] JSHintBear:
|    | 'action' is already defined.

binaries/data/mods/public/gui/session/input.js
| 274| »   »   »   var·r·=·g_UnitActions[action].actionCheck(target,·selection);
|    | [NORMAL] JSHintBear:
|    | 'r' is already defined.

binaries/data/mods/public/gui/session/input.js
| 481| »   »   &&·(ev.button·==·SDL_BUTTON_LEFT·||·ev.button·==·SDL_BUTTON_RIGHT))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/gui/session/input.js
| 511| »   »   »   »   var·rect·=·updateBandbox(bandbox,·ev,·true);
|    | [NORMAL] JSHintBear:
|    | 'rect' is already defined.

binaries/data/mods/public/gui/session/input.js
| 514| »   »   »   »   var·ents·=·getPreferredEntities(Engine.PickPlayerEntitiesInRect(rect[0],·rect[1],·rect[2],·rect[3],·g_ViewedPlayer));
|    | [NORMAL] JSHintBear:
|    | 'ents' is already defined.

binaries/data/mods/public/gui/session/input.js
| 671| »   »   »   »   »   var·queued·=·Engine.HotkeyIsPressed("session.queue");
|    | [NORMAL] JSHintBear:
|    | 'queued' is already defined.

binaries/data/mods/public/gui/session/input.js
| 745| »   »   »   »   var·queued·=·Engine.HotkeyIsPressed("session.queue");
|    | [NORMAL] JSHintBear:
|    | 'queued' is already defined.

binaries/data/mods/public/gui/session/input.js
| 875| »   »   »   »   »   »   var·sptr·=·ev.hotkey.split(".");
|    | [NORMAL] JSHintBear:
|    | 'sptr' is already defined.

binaries/data/mods/public/gui/session/input.js
| 891| »   »   »   var·ent·=·Engine.PickEntityAtPoint(ev.x,·ev.y);
|    | [NORMAL] JSHintBear:
|    | 'ent' is already defined.

binaries/data/mods/public/gui/session/input.js
| 917| »   »   »   }
|    | [NORMAL] JSHintBear:
|    | Expected a 'break' statement before 'default'.

binaries/data/mods/public/gui/session/input.js
| 941| »   »   »   var·ent·=·Engine.PickEntityAtPoint(ev.x,·ev.y);
|    | [NORMAL] JSHintBear:
|    | 'ent' is already defined.

binaries/data/mods/public/gui/session/input.js
|1097| »   »   »   »   »   var·snapToEdge·=·Engine.HotkeyIsPressed("session.snaptoedge");
|    | [NORMAL] JSHintBear:
|    | 'snapToEdge' is already defined.

binaries/data/mods/public/gui/session/input.js
|1100| »   »   »   »   »   »   var·snapData·=·Engine.GuiInterfaceCall("GetFoundationSnapData",·{
|    | [NORMAL] JSHintBear:
|    | 'snapData' is already defined.
Executing section cli...

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/80/display/redirect

elexis added a subscriber: elexis.Jul 15 2019, 12:51 AM

Very nice feature! From testing, feels perfect!

(12:37:10 AM) Vladislav: Also a question: should it be on the JS side or on the C++ side?

The rationale is to have things in C++ that are ncessary for performance, and the rest in JS for convenience.
One can do some worst case measurements to decide.

Either way I suggest to minimize JS object creation, it can add up when done inside of loops. If you read the words "new Vector2D" it should be considered something similar to an error, because in most cases one can get away with modiying an iterator,.
(Perhaps it's possible here as well to only operate on found edges, rather than discovering all edges, then sorting them, I didn't check, just brainstorm)

binaries/data/mods/public/gui/session/input.js
1097

let where possible

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

This function is already way too large, move it into a separate function. (Perhaps it would be better in a different file as well, since GUIInterface is getting cramped a bit. I understand there is already related code here.)

1650

0.0 -> 0
new Vector2D(data.x, data.z) -> Vector2D.from3D
data.angle || 0

1655
1668

clone and new Vector2D call can be at least moved out of the loop to avoid re-creation of objects.
let iterator = new Vector2D(); outside of the loop, and iterator.setTo(someVector) inside the loop.

1747

(perhaps an early return once this hunk is in a function, or moving this into a new function as well)

binaries/data/mods/public/simulation/helpers/Placement.js
37

(In theory this could be cached until PositionChanged, which should only happen on destruction or for mods, didn't check if reasonable)

elexis added inline comments.Jul 15 2019, 12:57 AM
binaries/data/config/default.cfg
316

Intro.txt

binaries/data/mods/public/gui/session/input.js
1104

(there is also a method for screen slices, perhaps the area can be reduced, maybe not, it doesnt account for the footprint of buildings as you mentioned on irc)

binaries/data/mods/public/simulation/helpers/Placement.js
1

(some overlap with getObstructionSize from library.js and EntitiesObstructionPlacer.js, but too little to demand deduplication)

nani awarded a token.Jul 15 2019, 12:59 AM
Krinkle added inline comments.
binaries/data/mods/public/simulation/components/GuiInterface.js
1655

In either case, would recommend going for push() instead of concat() so as to not create and discard many intermediate array objects.

I assume the reason one would pick concat() here is because one needs to push several at once. There's ways to do that:

ES5 JavaScript
allEdges.push.apply(allEdges, GetObstructionEdges())
ES2015 JavaScript (ES6)
allEdges.push(...GetObstructionEdges())
Krinkle added inline comments.Jul 15 2019, 1:07 AM
binaries/data/mods/public/simulation/components/GuiInterface.js
1702

Unless type coercion is expected/desired, should probably use !== instead.

Why put this behind a hotkey? This seems to me like desirable default placement behavior.

wraitii added a subscriber: wraitii.EditedJul 15 2019, 8:42 AM

Feature looks pretty good from the gif and making it optional is good imo (I like leaving "natural" placement as default behaviour because the engine can handle it and it's beautiful)

Have to say from looking at the code that this feels like a c++ feature - there's not only the matter of speed vs convenience but also correctness and modulability - I'm not sure mods would ever want to change this (perhaps some constants?), and correctness would be easier to assert in a typed system.
Given that it's driven by user-input, I guess lag is less of a concern, but what if you have hundreds of player entities on screen? Definitely needs to be profiled with profiler2 calls imo (I'll do it unless someone else does it first)

This seems to me like desirable default placement behavior.

Being able to opt out with a hotkey?

On performance, there are some low hanging fruit optimizations, secondly some functions or loops may be particularly slower than the rest (so perhaps it could be half cpp half js), thirdly one can measure the performance with Engine.GetMicroseconds()` and a loop over some functions to get accurate numbers (ingame or offgrid in a JS testfile). In case it turns out that it should be in C++, it's quicker to implement if one has the blueprint in JS.

nani added a subscriber: nani.Jul 15 2019, 1:45 PM
nani added inline comments.
binaries/data/mods/public/gui/session/input.js
1104

IMO Engine.PickPlayerEntitiesOnScreen(g_ViewedPlayer) will be the decisive factor to make this feature fast.
Given the snapping placing constrains, an object should (at worse case) have 15~20 other buildings near it that affect this tool behavior.

As elexis said, something like screen slices would help.
I think a screen slice is not what it really needs but instead a radius nearness (taking into account the footprint) from the current mouse position in global space coordinates would be helpful.

This would make the others possible optimizations marginal given that the possible snapping candidates should be minimal.

Nescio added a subscriber: Nescio.Jul 15 2019, 8:10 PM
Nescio added inline comments.
binaries/data/config/default.cfg
316

Shift is already used for many things (see above), so it might be a good idea to select a different key.
How about CapsLock?

There's some oddities to the snapping

.

However after testing it feels really natural and the fact that you still free-place when not near buildings is very nice - I would agree with Josh above that this might be made the default case and a hotkey to opt out, rather than the current situation.

I would agree with committing this in JS anyways - just saying it might be worth rewriting in C++ at some point anyways. Also agreed that picking entities to compare to will be key.

Nescio removed a subscriber: Nescio.Jul 15 2019, 8:23 PM

Thank you for working on this @vladislavbelov .

Why put this behind a hotkey?

Because it's new behaviour and it has own restrictions.

This seems to me like desirable default placement behavior.

However after testing it feels really natural and the fact that you still free-place when not near buildings is very nice - I would agree with Josh above that this might be made the default case and a hotkey to opt out, rather than the current situation.
I would agree with committing this in JS anyways - just saying it might be worth rewriting in C++ at some point anyways. Also agreed that picking entities to compare to will be key.

I'd prefer to add it as option and test on a meaningful number of matches, including community players.

As far as I can see it has a bit different idea: remove free placement completely.

binaries/data/config/default.cfg
316

Number of actions is much more than number of available handy keys. So that situation is expected. All these keys are context-sensitive. CapsLock changes a context, it means you won't be able to start typing immediately, you need to remember/see and disable it.

binaries/data/mods/public/gui/session/input.js
1104

Currently we don't have a correct implementation of such methods, we don't account obstructions. I may suggest to add it as optional and test it within a bunch of matches.

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

Why? We compare two bools.

elexis added inline comments.Jul 17 2019, 5:53 PM
binaries/data/mods/public/gui/session/input.js
1104

Should this only pick the players entities or also the ones of allies?
I wonder about the worst case performance - what about skipping units (non-static obstructions)? Order of magnitude of units to consider would be 1000+ units in a 4v4 fight, but the function returns all of them, even copied to the GUIInterface. If done correctly, it will contribute to the true 0ad experience.

Some profiling (on Kushites sandbox) showed GetObstructionEdges to be the slowest part of the function, taking around 60% of the runtime.
Maybe move that to c++ ?

Stan added a subscriber: Stan.Mon, Sep 23, 12:42 PM
Stan added inline comments.
binaries/data/mods/public/simulation/helpers/Placement.js
1

Shouldn't that be in foundation or something ?

vladislavbelov added inline comments.Mon, Sep 23, 1:15 PM
binaries/data/mods/public/simulation/helpers/Placement.js
1

We don't use any foundation in the code. We work only with the obstruction component.

Stan added inline comments.Wed, Oct 9, 4:05 PM
binaries/data/mods/public/gui/session/input.js
723

let

1066

let maybe reduce the duplication wile at it