Page MenuHomeWildfire Games

Implement Single-Player (SP) campaign interface
Needs ReviewPublic

Authored by wraitii on Dec 26 2016, 3:32 PM.

Details

Reviewers
leper
elexis
Stan
Group Reviewers
Restricted Owners Package(Owns No Changed Paths)
Trac Tickets
#4387
Summary

Campaign implementation for Single Player.
Provides a basic architecture for creating campaigns, loading them, and running them via scenarios that get enabled "façon Age of Empires 1".

These campaign scripts should be somewhat SP/MP agnostic, though they're using the SP gamesetup for now.


Structure

Campaign-specific GUI files reside in /gui/campaigns
Campaign templates in /campaigns
Some common files have been put in /gui/common/campaigns, to avoid /common becoming too large. These are included in the main menu and in session.
There is a custom session file in /gui/session/campaigns for convenience.


Side effects

  • The load/save game page has been extended slightly to support showing/hiding campaign games.
  • some tweaks in gamesetup, though nothing major.

TODOs:

Further work on the gamesetup is probably required. I would like campaigns to have their own subfolder in "maps", ideally, or perhaps in "campaigns/[yourcampaignname]"


Possibly for a V2 implementation:

  • Letting campaigns also hook in the "loading" screen, to show videos or whatever.
  • Letting campaigns freeze gamesetup settings and not others/implement a custom simplified gamesetting for campaign (difficulties...)

Many other things I'm probably forgetting now.


Screenshots (bear in mind, this is ugly & functional on purpose. I do think a v2 nicer version could be worked on after this is committed).


Also for reference the AoE 1 screen -> https://www.mobygames.com/images/shots/l/585805-age-of-empires-the-rise-of-rome-demo-version-windows-screenshot.png .

Test Plan

Code reviews, other pitfalls.

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
elexis added inline comments.Jan 6 2019, 3:53 PM
binaries/data/mods/public/campaigns/example.json
2

This sounds like a candidate for the hypothetic pyrogenesis-examples mod #5366. Otherwise I'd recommend not to commit this as it will be translated. Otherwise, campaign authors can also take an example at the tutorial map.

4

"This shows map authors how to create campaign" or similar

14

Something nonempty

binaries/data/mods/public/campaigns/tutorial.json
10

Wondering if it's good that one can load arbitrary maptypes here and not only campaign maps.
Makes me also wonder whether we want players to be able to select campaign maps in the regular gamesetup menu in SP and MP, and
whether there are other hard distinctions between campaign and the other maptypes.

21

If Levels is an array, the order is implied. Not so important however. I still have a campaign screen in my mind that is a graphical map, not a list table, in which case the order would be ignored.

binaries/data/mods/public/gui/campaign/campaign_io.js
11 ↗(On Diff #7277)

listFiles

66 ↗(On Diff #7277)

||

117 ↗(On Diff #7277)

That (and possibly related variables) are not a filenames

124 ↗(On Diff #7277)

;;

binaries/data/mods/public/gui/campaign/load.js
23 ↗(On Diff #7277)

Looks like it could become one line using Math.min, Math.max (here and in the place it was copied from)

31 ↗(On Diff #7277)

Perhaps it's easier to just use the actual filenames as keys (if list and list_data are not easily avoidable by JS)

37 ↗(On Diff #7277)

crime against transifex

55 ↗(On Diff #7277)

When you’re riding a dead horse, the best strategy is to get off

binaries/data/mods/public/gui/campaign/load.xml
9 ↗(On Diff #7277)

same

binaries/data/mods/public/gui/campaign/newcampaign_modal.js
32 ↗(On Diff #7277)

===, !== only if the type is relevant (for consistency)

54 ↗(On Diff #7277)

assigning object properties on a separate line each arranges it more cleanly

binaries/data/mods/public/gui/campaign/simple_campaign/mainmenu.js
1 ↗(On Diff #7277)

Good that campaigns can come with custom GUi pages.
Maybe simple -> default.
Interface -> GUIPage?

source/ps/scripting/JSInterface_VFS.cpp
1

9 and so on

276

(OT: Because we already own FromJSVal<Path>, all JSInterface files should be registered with VfsPath directly instead of receiving a string and converting that (possibly incorrectly).)

291

??

Answers to some comments.

binaries/data/mods/public/campaigns/tutorial.json
10

One argument for "arbitrary maps in campaign" is making a Rise of Nations like campaign, where the 'campaign map' is a thing and the actual games are regular maps.

21

This is tied to the interface one chooses above, in this case simple_campaign. Another interface might do something completely different.

binaries/data/mods/public/gui/campaign/load.js
55 ↗(On Diff #7277)

I think this is supposed to update the GUI elements but I believe I've not implemented that yet.

44 ↗(On Diff #4508)

Not done yet.

binaries/data/mods/public/gui/campaign/simple_campaign/mainmenu.js
1 ↗(On Diff #7277)

I'm not sure we want the list interface to be the default one. I had an AOE-2 like campaign map in mind for the default.

binaries/data/mods/public/gui/session/session.js
537

I believe (been a while) this data can come from the campaign metadata itself, so keeping it separate makes sense imo. For example a campaign might keep track of how well you are doing, but that's not really 'Sim Data' to me.

binaries/data/mods/public/gui/session/session.xml
22

I'll check if it's needed at all. Don't remember why I added it a solid 2 years ago.

23

These are needed to pass the end game data.

binaries/data/mods/public/gui/summary/summary.xml
10 ↗(On Diff #7277)

Not sure what you mean here?
This is so Summary.xml brings you back to the campaign interface. I guess I should just PopPage ?

binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
336

Is this still broken?

source/ps/scripting/JSInterface_VFS.cpp
223

We did. Haven't implemented said restriction when rebasing since it's more work and honestly this patch is already almost too big to grok.

291

Same, not sure when that got here.

As a reminder of what we're trying to achieve here: the goal (to me) is not to provide something beautiful, or even something complete, but rather a necessary, minimal, and well-architectured stepping stone for other code. As the patch stands, it is usable for a very basic campaign, though it's missing plenty of things one would want, but I think that's fine, we can add those on top of this core stuff, so long as the general direction of the core stuff isn't stupid.

elexis added inline comments.Jan 6 2019, 11:03 PM
binaries/data/mods/public/campaigns/example.json
3

Did someone say messages.json? (Also some exotic transifex file if new directory IIRC)

binaries/data/mods/public/campaigns/tutorial.json
10

I'm sure there are important arguments for both sides. But that can be decided later as it doesn't invalidate any of the existing code I suppose.
But it should be decided before people make campaigns, as the maptype decision can invalidate campaign implementation.

The tutorial maptype already exists, so I guess it should be figured out by wise men whether that type should be migrated, nuked or kept separate.

binaries/data/mods/public/gui/pregame/mainmenu.js
57 ↗(On Diff #7277)

(I didn't leave one of these "I have a patch since 2 years that rewrites this entire file" comments yet)

binaries/data/mods/public/gui/session/session.js
537

That data comes from Engine.GetInitAttributes() but that should only contain the gamesettings which determine the simulation.
That's in particular relevant because GUI data is non-deterministic and per client, but simulation data is. So if you have someone spectating the campaign playyer or watching a replay, the GUI data must be irrelevant, nonpresent.
Savegames also have a sim/gui data bipartition IIRC.

binaries/data/mods/public/gui/session/session.xml
23

The io remark was about the name. I/O typically describes hardware.

binaries/data/mods/public/gui/summary/summary.xml
10 ↗(On Diff #7277)

gui/common/ or gui/campaign/common/.
(Heads up: any/common/ (by definition) should not contain code that is only valid on one page)

source/ps/scripting/JSInterface_VFS.cpp
223

Apparently JS is agnostic of the .0adsave suffix, so SavedGames::DeleteSavedGame can't be replaced without hardcoding the suffic in JS.

One could also examine the position that everything that this function could delete could already be deleted otherwise (config system) or be a valid user-triggered deletion (screenshots? but that would require displaying them in 0ad. So perhaps make it safe until then. Should be two lines, one of them defining a path, the other calling PathRestrictionMet)

wraitii updated this revision to Diff 11963.May 21 2020, 10:36 PM

Complete rewrite of the patch (bar the simulation/session bit which I haven't looked at yet).

This introduces a similar OOP style as the rest of the code, moves files around in new folders, renames plenty of things.
I reckon the OG patch had pretty poor separation of concerns.

Most of the above comments are now irrelevant.


This also introduces a super-magical way to do rendering updates, because I like being lazy and magic.


At this point, I also need to look harder at the new gamesetup.

wraitii edited the summary of this revision. (Show Details)May 21 2020, 10:38 PM
wraitii edited the test plan for this revision. (Show Details)
wraitii edited the summary of this revision. (Show Details)

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

Linter detected issues:
Executing section Source...

source/ps/scripting/JSInterface_VFS.h
|   1| /*·Copyright·(C)·2018·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2018"

source/ps/scripting/JSInterface_VFS.h
|  23| namespace·JSI_VFS
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'namespaceJSI_VFS{' is invalid C code. Use --std or --language to configure the language.

source/ps/scripting/JSInterface_VFS.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"
Executing section JS...
|    | [NORMAL] ESLintBear (key-spacing):
|    | Extra space after key 'campaignData'.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
| 539| 539| 			"replayDirectory": !g_HasRejoined && replayDirectory,
| 540| 540| 			"replaySelectionData": g_ReplaySelectionData
| 541| 541| 		},
| 542|    |-		"campaignData" : campaignData
|    | 542|+		"campaignData": campaignData
| 543| 543| 	});
| 544| 544| }
| 545| 545| 

binaries/data/mods/public/gui/session/session.js
| 700| »   »   button.onPress·=·(function(i)·{·return·function()·{·performGroup((Engine.HotkeyIsPressed("selection.add")·?·"add"·:·"select"),·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
| 701| »   »   button.onDoublePress·=·(function(i)·{·return·function()·{·performGroup("snap",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
| 702| »   »   button.onPressRight·=·(function(i)·{·return·function()·{·performGroup("breakUp",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 490| 490| 	Engine.GetGUIObjectByName("summaryText").caption =
| 491| 491| 		g_GameData.gui.isInGame ?
| 492| 492| 			translate("Current Scores") :
| 493|    |-		g_GameData.gui.isReplay ?
|    | 493|+			g_GameData.gui.isReplay ?
| 494| 494| 			translate("Scores at the end of the game.") :
| 495| 495| 		g_GameData.gui.disconnected ?
| 496| 496| 			translate("You have been disconnected.") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 491| 491| 		g_GameData.gui.isInGame ?
| 492| 492| 			translate("Current Scores") :
| 493| 493| 		g_GameData.gui.isReplay ?
| 494|    |-			translate("Scores at the end of the game.") :
|    | 494|+				translate("Scores at the end of the game.") :
| 495| 495| 		g_GameData.gui.disconnected ?
| 496| 496| 			translate("You have been disconnected.") :
| 497| 497| 		!assignedState ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 492| 492| 			translate("Current Scores") :
| 493| 493| 		g_GameData.gui.isReplay ?
| 494| 494| 			translate("Scores at the end of the game.") :
| 495|    |-		g_GameData.gui.disconnected ?
|    | 495|+				g_GameData.gui.disconnected ?
| 496| 496| 			translate("You have been disconnected.") :
| 497| 497| 		!assignedState ?
| 498| 498| 			translate("You have left the game.") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 493| 493| 		g_GameData.gui.isReplay ?
| 494| 494| 			translate("Scores at the end of the game.") :
| 495| 495| 		g_GameData.gui.disconnected ?
| 496|    |-			translate("You have been disconnected.") :
|    | 496|+					translate("You have been disconnected.") :
| 497| 497| 		!assignedState ?
| 498| 498| 			translate("You have left the game.") :
| 499| 499| 		assignedState.state == "won" ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 494| 494| 			translate("Scores at the end of the game.") :
| 495| 495| 		g_GameData.gui.disconnected ?
| 496| 496| 			translate("You have been disconnected.") :
| 497|    |-		!assignedState ?
|    | 497|+					!assignedState ?
| 498| 498| 			translate("You have left the game.") :
| 499| 499| 		assignedState.state == "won" ?
| 500| 500| 			translate("You have won the battle!") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 495| 495| 		g_GameData.gui.disconnected ?
| 496| 496| 			translate("You have been disconnected.") :
| 497| 497| 		!assignedState ?
| 498|    |-			translate("You have left the game.") :
|    | 498|+						translate("You have left the game.") :
| 499| 499| 		assignedState.state == "won" ?
| 500| 500| 			translate("You have won the battle!") :
| 501| 501| 		assignedState.state == "defeated" ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 496| 496| 			translate("You have been disconnected.") :
| 497| 497| 		!assignedState ?
| 498| 498| 			translate("You have left the game.") :
| 499|    |-		assignedState.state == "won" ?
|    | 499|+						assignedState.state == "won" ?
| 500| 500| 			translate("You have won the battle!") :
| 501| 501| 		assignedState.state == "defeated" ?
| 502| 502| 			translate("You have been defeated…") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 497| 497| 		!assignedState ?
| 498| 498| 			translate("You have left the game.") :
| 499| 499| 		assignedState.state == "won" ?
| 500|    |-			translate("You have won the battle!") :
|    | 500|+							translate("You have won the battle!") :
| 501| 501| 		assignedState.state == "defeated" ?
| 502| 502| 			translate("You have been defeated…") :
| 503| 503| 			translate("You have abandoned the game.");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 498| 498| 			translate("You have left the game.") :
| 499| 499| 		assignedState.state == "won" ?
| 500| 500| 			translate("You have won the battle!") :
| 501|    |-		assignedState.state == "defeated" ?
|    | 501|+							assignedState.state == "defeated" ?
| 502| 502| 			translate("You have been defeated…") :
| 503| 503| 			translate("You have abandoned the game.");
| 504| 504| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 499| 499| 		assignedState.state == "won" ?
| 500| 500| 			translate("You have won the battle!") :
| 501| 501| 		assignedState.state == "defeated" ?
| 502|    |-			translate("You have been defeated…") :
|    | 502|+								translate("You have been defeated…") :
| 503| 503| 			translate("You have abandoned the game.");
| 504| 504| 
| 505| 505| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 500| 500| 			translate("You have won the battle!") :
| 501| 501| 		assignedState.state == "defeated" ?
| 502| 502| 			translate("You have been defeated…") :
| 503|    |-			translate("You have abandoned the game.");
|    | 503|+								translate("You have abandoned the game.");
| 504| 504| 
| 505| 505| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
| 506| 506| 		translate("Game time elapsed: %(time)s"), {
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 1.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 505| 505| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
| 506| 506| 		translate("Game time elapsed: %(time)s"), {
| 507| 507| 			"time": timeToString(g_GameData.sim.timeElapsed)
| 508|    |-	});
|    | 508|+		});
| 509| 509| 
| 510| 510| 	let mapType = g_Settings.MapTypes.find(type => type.Name == g_GameData.sim.mapSettings.mapType);
| 511| 511| 	let mapSize = g_Settings.MapSizes.find(size => size.Tiles == g_GameData.sim.mapSettings.Size || 0);
|    | [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
| 210| 210| 	return {
| 211| 211| 		"status": QueryPlayerIDInterface(player, IID_Player).GetState()
| 212| 212| 	};
| 213|    |-}
|    | 213|+};
| 214| 214| 
| 215| 215| GuiInterface.prototype.GetRenamedEntities = function(player)
| 216| 216| {

binaries/data/mods/public/simulation/components/GuiInterface.js
| 213| }
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.
Executing section cli...

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

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/macos-differential/777/display/redirect

wraitii updated this revision to Diff 11964.May 22 2020, 12:05 AM
wraitii edited the summary of this revision. (Show Details)

This implements some basic handling of game ends via a common file in session/campaigns.

Campaigns may or may not autostart (Ideally, most settings would then be frozen). Campaigns may skip the summary.

The campaigns now register that the player has won a scenario.
Bunch of other tweaks.


See TODO above for list of things to do.

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/macos-differential/778/display/redirect

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

Linter detected issues:
Executing section Source...

source/ps/scripting/JSInterface_VFS.h
|   1| /*·Copyright·(C)·2018·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2018"

source/ps/scripting/JSInterface_VFS.h
|  23| namespace·JSI_VFS
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'namespaceJSI_VFS{' is invalid C code. Use --std or --language to configure the language.

source/ps/scripting/JSInterface_VFS.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"
Executing section JS...
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
| 385| 385| 	let position = Engine.QueryInterface(target, IID_Position).GetPosition2D();
| 386| 386| 
| 387| 387| 	this.attackers = cmpRangeManager.GetEntitiesByPlayer(this.enemyID).filter(e =>
| 388|    |-			Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
|    | 388|+		Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
| 389| 389| 			Engine.QueryInterface(e, IID_Identity).HasClass("CitizenSoldier")
| 390| 390| 		);
| 391| 391| 	this.attackers.forEach(e => { Engine.QueryInterface(e, IID_UnitAI).WalkAndFight(position.x, position.y, { "attack": ["Unit"] }, false); });
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
| 387| 387| 	this.attackers = cmpRangeManager.GetEntitiesByPlayer(this.enemyID).filter(e =>
| 388| 388| 			Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
| 389| 389| 			Engine.QueryInterface(e, IID_Identity).HasClass("CitizenSoldier")
| 390|    |-		);
|    | 390|+	);
| 391| 391| 	this.attackers.forEach(e => { Engine.QueryInterface(e, IID_UnitAI).WalkAndFight(position.x, position.y, { "attack": ["Unit"] }, false); });
| 392| 392| };
| 393| 393| 

binaries/data/mods/public/gui/session/session.js
| 709| »   »   button.onPress·=·(function(i)·{·return·function()·{·performGroup((Engine.HotkeyIsPressed("selection.add")·?·"add"·:·"select"),·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
| 710| »   »   button.onDoublePress·=·(function(i)·{·return·function()·{·performGroup("snap",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
| 711| »   »   button.onPressRight·=·(function(i)·{·return·function()·{·performGroup("breakUp",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.
|    | [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
| 210| 210| 	return {
| 211| 211| 		"status": QueryPlayerIDInterface(player, IID_Player).GetState()
| 212| 212| 	};
| 213|    |-}
|    | 213|+};
| 214| 214| 
| 215| 215| GuiInterface.prototype.GetRenamedEntities = function(player)
| 216| 216| {

binaries/data/mods/public/simulation/components/GuiInterface.js
| 213| }
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 491| 491| 	Engine.GetGUIObjectByName("summaryText").caption =
| 492| 492| 		g_GameData.gui.isInGame ?
| 493| 493| 			translate("Current Scores") :
| 494|    |-		g_GameData.gui.isReplay ?
|    | 494|+			g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 492| 492| 		g_GameData.gui.isInGame ?
| 493| 493| 			translate("Current Scores") :
| 494| 494| 		g_GameData.gui.isReplay ?
| 495|    |-			translate("Scores at the end of the game.") :
|    | 495|+				translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 493| 493| 			translate("Current Scores") :
| 494| 494| 		g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496|    |-		g_GameData.gui.disconnected ?
|    | 496|+				g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 494| 494| 		g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497|    |-			translate("You have been disconnected.") :
|    | 497|+					translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498|    |-		!assignedState ?
|    | 498|+					!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499|    |-			translate("You have left the game.") :
|    | 499|+						translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500|    |-		assignedState.state == "won" ?
|    | 500|+						assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501|    |-			translate("You have won the battle!") :
|    | 501|+							translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502|    |-		assignedState.state == "defeated" ?
|    | 502|+							assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
| 505| 505| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503|    |-			translate("You have been defeated…") :
|    | 503|+								translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
| 505| 505| 
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504|    |-			translate("You have abandoned the game.");
|    | 504|+								translate("You have abandoned the game.");
| 505| 505| 
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
| 507| 507| 		translate("Game time elapsed: %(time)s"), {
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 1.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
| 507| 507| 		translate("Game time elapsed: %(time)s"), {
| 508| 508| 			"time": timeToString(g_GameData.sim.timeElapsed)
| 509|    |-	});
|    | 509|+		});
| 510| 510| 
| 511| 511| 	let mapType = g_Settings.MapTypes.find(type => type.Name == g_GameData.sim.mapSettings.mapType);
| 512| 512| 	let mapSize = g_Settings.MapSizes.find(size => size.Tiles == g_GameData.sim.mapSettings.Size || 0);
Executing section cli...

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

wraitii updated this revision to Diff 11967.May 22 2020, 9:56 AM
wraitii edited the summary of this revision. (Show Details)

Update with:

  • i18n support
  • Triggers can define a custom "OnCampaignGameEnd" trigger that processes custom user data
  • Moving some files around to clean up the interface.

I need to do a small cleanup pass on my this.identifier/this.filename business.

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/macos-differential/781/display/redirect

wraitii edited the summary of this revision. (Show Details)May 22 2020, 10:02 AM
wraitii added inline comments.
binaries/data/mods/mod/gui/common/modern/styles.xml
33

This should probably be committed regardless.

binaries/data/mods/public/gui/common/settings.js
204 ↗(On Diff #11967)

I'm not a fan of this hardcoding tbh. Can you so easily extend it with mods, even?

binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
429

the above is obviously only to show that it works.

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

The reason why I'm not using CallEvents is:

  • that doesn't return the value
  • I don't care about multiple handlers.

I can change this to CallEvent if we agree that CallEvent should return the value of the trigger.

wraitii updated this revision to Diff 11968.May 22 2020, 10:13 AM

Add the missing .tx file.

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

Linter detected issues:
Executing section Source...

source/ps/scripting/JSInterface_VFS.h
|   1| /*·Copyright·(C)·2018·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2018"

source/ps/scripting/JSInterface_VFS.h
|  23| namespace·JSI_VFS
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'namespaceJSI_VFS{' is invalid C code. Use --std or --language to configure the language.

source/ps/scripting/JSInterface_VFS.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"
Executing section JS...
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 491| 491| 	Engine.GetGUIObjectByName("summaryText").caption =
| 492| 492| 		g_GameData.gui.isInGame ?
| 493| 493| 			translate("Current Scores") :
| 494|    |-		g_GameData.gui.isReplay ?
|    | 494|+			g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 492| 492| 		g_GameData.gui.isInGame ?
| 493| 493| 			translate("Current Scores") :
| 494| 494| 		g_GameData.gui.isReplay ?
| 495|    |-			translate("Scores at the end of the game.") :
|    | 495|+				translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 493| 493| 			translate("Current Scores") :
| 494| 494| 		g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496|    |-		g_GameData.gui.disconnected ?
|    | 496|+				g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 494| 494| 		g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497|    |-			translate("You have been disconnected.") :
|    | 497|+					translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498|    |-		!assignedState ?
|    | 498|+					!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499|    |-			translate("You have left the game.") :
|    | 499|+						translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500|    |-		assignedState.state == "won" ?
|    | 500|+						assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501|    |-			translate("You have won the battle!") :
|    | 501|+							translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502|    |-		assignedState.state == "defeated" ?
|    | 502|+							assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
| 505| 505| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503|    |-			translate("You have been defeated…") :
|    | 503|+								translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
| 505| 505| 
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504|    |-			translate("You have abandoned the game.");
|    | 504|+								translate("You have abandoned the game.");
| 505| 505| 
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
| 507| 507| 		translate("Game time elapsed: %(time)s"), {
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 1.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
| 507| 507| 		translate("Game time elapsed: %(time)s"), {
| 508| 508| 			"time": timeToString(g_GameData.sim.timeElapsed)
| 509|    |-	});
|    | 509|+		});
| 510| 510| 
| 511| 511| 	let mapType = g_Settings.MapTypes.find(type => type.Name == g_GameData.sim.mapSettings.mapType);
| 512| 512| 	let mapSize = g_Settings.MapSizes.find(size => size.Tiles == g_GameData.sim.mapSettings.Size || 0);

binaries/data/mods/public/gui/loadgame/SavegameList.js
|  98| »   »   »   switch·(sortKey)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
| 385| 385| 	let position = Engine.QueryInterface(target, IID_Position).GetPosition2D();
| 386| 386| 
| 387| 387| 	this.attackers = cmpRangeManager.GetEntitiesByPlayer(this.enemyID).filter(e =>
| 388|    |-			Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
|    | 388|+		Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
| 389| 389| 			Engine.QueryInterface(e, IID_Identity).HasClass("CitizenSoldier")
| 390| 390| 		);
| 391| 391| 	this.attackers.forEach(e => { Engine.QueryInterface(e, IID_UnitAI).WalkAndFight(position.x, position.y, { "attack": ["Unit"] }, false); });
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
| 387| 387| 	this.attackers = cmpRangeManager.GetEntitiesByPlayer(this.enemyID).filter(e =>
| 388| 388| 			Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
| 389| 389| 			Engine.QueryInterface(e, IID_Identity).HasClass("CitizenSoldier")
| 390|    |-		);
|    | 390|+	);
| 391| 391| 	this.attackers.forEach(e => { Engine.QueryInterface(e, IID_UnitAI).WalkAndFight(position.x, position.y, { "attack": ["Unit"] }, false); });
| 392| 392| };
| 393| 393| 

binaries/data/mods/public/gui/session/session.js
| 709| »   »   button.onPress·=·(function(i)·{·return·function()·{·performGroup((Engine.HotkeyIsPressed("selection.add")·?·"add"·:·"select"),·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
| 710| »   »   button.onDoublePress·=·(function(i)·{·return·function()·{·performGroup("snap",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
| 711| »   »   button.onPressRight·=·(function(i)·{·return·function()·{·performGroup("breakUp",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/loadgame/SavegamePage.js
|   9| »   g_SavegamePage·=·new·SavegamePage(data);
|    | [MAJOR] ESLintBear (no-use-before-define):
|    | 'SavegamePage' was used before it was defined.

binaries/data/mods/public/gui/loadgame/SavegamePage.js
|  16| class·SavegamePage
|    | [NORMAL] JSHintBear:
|    | 'SavegamePage' was used before it was defined.
Executing section cli...

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

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

Linter detected issues:
Executing section Source...

source/ps/scripting/JSInterface_VFS.h
|   1| /*·Copyright·(C)·2018·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2018"

source/ps/scripting/JSInterface_VFS.h
|  23| namespace·JSI_VFS
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'namespaceJSI_VFS{' is invalid C code. Use --std or --language to configure the language.

source/ps/scripting/JSInterface_VFS.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"
Executing section JS...

binaries/data/mods/public/gui/loadgame/SavegamePage.js
|   9| »   g_SavegamePage·=·new·SavegamePage(data);
|    | [MAJOR] ESLintBear (no-use-before-define):
|    | 'SavegamePage' was used before it was defined.

binaries/data/mods/public/gui/loadgame/SavegamePage.js
|  16| class·SavegamePage
|    | [NORMAL] JSHintBear:
|    | 'SavegamePage' was used before it was defined.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 491| 491| 	Engine.GetGUIObjectByName("summaryText").caption =
| 492| 492| 		g_GameData.gui.isInGame ?
| 493| 493| 			translate("Current Scores") :
| 494|    |-		g_GameData.gui.isReplay ?
|    | 494|+			g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 492| 492| 		g_GameData.gui.isInGame ?
| 493| 493| 			translate("Current Scores") :
| 494| 494| 		g_GameData.gui.isReplay ?
| 495|    |-			translate("Scores at the end of the game.") :
|    | 495|+				translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 493| 493| 			translate("Current Scores") :
| 494| 494| 		g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496|    |-		g_GameData.gui.disconnected ?
|    | 496|+				g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 494| 494| 		g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497|    |-			translate("You have been disconnected.") :
|    | 497|+					translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498|    |-		!assignedState ?
|    | 498|+					!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499|    |-			translate("You have left the game.") :
|    | 499|+						translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500|    |-		assignedState.state == "won" ?
|    | 500|+						assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501|    |-			translate("You have won the battle!") :
|    | 501|+							translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502|    |-		assignedState.state == "defeated" ?
|    | 502|+							assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
| 505| 505| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503|    |-			translate("You have been defeated…") :
|    | 503|+								translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
| 505| 505| 
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504|    |-			translate("You have abandoned the game.");
|    | 504|+								translate("You have abandoned the game.");
| 505| 505| 
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
| 507| 507| 		translate("Game time elapsed: %(time)s"), {
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 1.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
| 507| 507| 		translate("Game time elapsed: %(time)s"), {
| 508| 508| 			"time": timeToString(g_GameData.sim.timeElapsed)
| 509|    |-	});
|    | 509|+		});
| 510| 510| 
| 511| 511| 	let mapType = g_Settings.MapTypes.find(type => type.Name == g_GameData.sim.mapSettings.mapType);
| 512| 512| 	let mapSize = g_Settings.MapSizes.find(size => size.Tiles == g_GameData.sim.mapSettings.Size || 0);

binaries/data/mods/public/gui/session/session.js
| 709| »   »   button.onPress·=·(function(i)·{·return·function()·{·performGroup((Engine.HotkeyIsPressed("selection.add")·?·"add"·:·"select"),·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
| 710| »   »   button.onDoublePress·=·(function(i)·{·return·function()·{·performGroup("snap",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
| 711| »   »   button.onPressRight·=·(function(i)·{·return·function()·{·performGroup("breakUp",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/loadgame/SavegameList.js
|  98| »   »   »   switch·(sortKey)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
| 385| 385| 	let position = Engine.QueryInterface(target, IID_Position).GetPosition2D();
| 386| 386| 
| 387| 387| 	this.attackers = cmpRangeManager.GetEntitiesByPlayer(this.enemyID).filter(e =>
| 388|    |-			Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
|    | 388|+		Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
| 389| 389| 			Engine.QueryInterface(e, IID_Identity).HasClass("CitizenSoldier")
| 390| 390| 		);
| 391| 391| 	this.attackers.forEach(e => { Engine.QueryInterface(e, IID_UnitAI).WalkAndFight(position.x, position.y, { "attack": ["Unit"] }, false); });
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
| 387| 387| 	this.attackers = cmpRangeManager.GetEntitiesByPlayer(this.enemyID).filter(e =>
| 388| 388| 			Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
| 389| 389| 			Engine.QueryInterface(e, IID_Identity).HasClass("CitizenSoldier")
| 390|    |-		);
|    | 390|+	);
| 391| 391| 	this.attackers.forEach(e => { Engine.QueryInterface(e, IID_UnitAI).WalkAndFight(position.x, position.y, { "attack": ["Unit"] }, false); });
| 392| 392| };
| 393| 393| 
Executing section cli...

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

wraitii updated this revision to Diff 12046.May 29 2020, 7:41 PM
wraitii edited the summary of this revision. (Show Details)

Fix a few issues, and bump years.

Add some screenshots of the very basic interface to the summary.

Build failure - The Moirai have given mortals hearts that can endure.

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

Stan requested changes to this revision.May 30 2020, 10:50 AM
Stan added a subscriber: Stan.

Okay, so the normal campaign is currently broken. (So that obviously needs to be fixed)
https://upload.jabberfr.org/qmJ8LfmtvdhWLl1h/Bureau.mp4

ERROR: JavaScript error: gui/common/MapCache.js line 18 TypeError: g_Settings.MapTypes.find(...) is undefined getMapData@gui/common/MapCache.js:18:18 updateGameAttributes@gui/gamesetup/Controls/GameSettingsControl.js:184:18 onLoad@gui/gamesetup/Controls/GameSettingsControl.js:120:4 SetupWindow@gui/gamesetup/SetupWindow.js:58:4 init@gui/gamesetup/gamesetup.js:44:18 startScenario@gui/campaigns/default_menu/CampaignMenu.js:46:1 @gui/campaigns/default_menu/CampaignMenu.js:20:36

ERROR: GUI page 'page_gamesetup.xml': Failed to call init() function

ERROR: GL error GL_INVALID_VALUE (0x0501) occurred

WARNING: JavaScript warning: gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerCiv.js line 113 reference to undefined property pData.Civ

ERROR: JavaScript error: gui/common/MapCache.js line 18 TypeError: g_Settings.MapTypes.find(...) is undefined getMapData@gui/common/MapCache.js:18:18 onGameAttributesFinalize@gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapSelection.js:126:17 onLaunchGame@gui/gamesetup/Controls/GameSettingsControl.js:256:4 launchGame@gui/gamesetup/Controls/StartGameControl.js:35:4 onPress@gui/gamesetup/Pages/GameSetupPage/Panels/Buttons/StartGameButton.js:60:3

ERROR: JavaScript error: Errors executing script event "Press"

I tested the normal introductory one, it seems to work, you win quickly and then it unlocks the next mission. Quicksaving seemed to work there (No reason why it would not)
Saving however is a bit strange, since you don't see the other savegames when in the campaign menu, but you do see them when in game, probably needs some code there if that savegame hidness is intended

The campaign menu is a bit crowded see

The first popup feels a bit strange, as you don't know what you are expected to do, if it is to stay there should be a nice description

The quit popup is pretty scary, how can it dare saving all my campaigns 🗡

The scenario unlocking seemed to work. It'd be nicer if it was a map, but I guess that's harder to do.

Some warnings popped up as well

WARNING: ({})
WARNING: ({somearbitrarydata:4})
This revision now requires changes to proceed.May 30 2020, 10:50 AM
wraitii updated this revision to Diff 12058.May 30 2020, 11:40 AM

Fix Stan's remark & also prevent starting any scenario by double clicking on them :p

Owners added a subscriber: Restricted Owners Package.May 30 2020, 11:40 AM
wraitii added inline comments.May 30 2020, 11:41 AM
binaries/data/mods/public/gui/common/settings.js
204 ↗(On Diff #11967)

Er, this actually seems to simply define the Filter names in the gamesetup, but on can start a "scenario" from a different folder.
Probably needs some tweaking but it's OK from my end so far.

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

Linter detected issues:
Executing section Source...

source/ps/scripting/JSInterface_VFS.h
|  23| namespace·JSI_VFS
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'namespaceJSI_VFS{' is invalid C code. Use --std or --language to configure the language.
Executing section JS...

binaries/data/mods/public/gui/session/session.js
| 709| »   »   button.onPress·=·(function(i)·{·return·function()·{·performGroup((Engine.HotkeyIsPressed("selection.add")·?·"add"·:·"select"),·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
| 710| »   »   button.onDoublePress·=·(function(i)·{·return·function()·{·performGroup("snap",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
| 711| »   »   button.onPressRight·=·(function(i)·{·return·function()·{·performGroup("breakUp",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/loadgame/SavegamePage.js
|   9| »   g_SavegamePage·=·new·SavegamePage(data);
|    | [MAJOR] ESLintBear (no-use-before-define):
|    | 'SavegamePage' was used before it was defined.

binaries/data/mods/public/gui/loadgame/SavegamePage.js
|  16| class·SavegamePage
|    | [NORMAL] JSHintBear:
|    | 'SavegamePage' was used before it was defined.

binaries/data/mods/public/gui/loadgame/SavegameList.js
|  98| »   »   »   switch·(sortKey)
|    | [NORMAL] ESLintBear (default-case):
|    | Expected a default case.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
| 385| 385| 	let position = Engine.QueryInterface(target, IID_Position).GetPosition2D();
| 386| 386| 
| 387| 387| 	this.attackers = cmpRangeManager.GetEntitiesByPlayer(this.enemyID).filter(e =>
| 388|    |-			Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
|    | 388|+		Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
| 389| 389| 			Engine.QueryInterface(e, IID_Identity).HasClass("CitizenSoldier")
| 390| 390| 		);
| 391| 391| 	this.attackers.forEach(e => { Engine.QueryInterface(e, IID_UnitAI).WalkAndFight(position.x, position.y, { "attack": ["Unit"] }, false); });
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.js
| 387| 387| 	this.attackers = cmpRangeManager.GetEntitiesByPlayer(this.enemyID).filter(e =>
| 388| 388| 			Engine.QueryInterface(e, IID_Identity) && Engine.QueryInterface(e, IID_UnitAI) &&
| 389| 389| 			Engine.QueryInterface(e, IID_Identity).HasClass("CitizenSoldier")
| 390|    |-		);
|    | 390|+	);
| 391| 391| 	this.attackers.forEach(e => { Engine.QueryInterface(e, IID_UnitAI).WalkAndFight(position.x, position.y, { "attack": ["Unit"] }, false); });
| 392| 392| };
| 393| 393| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 491| 491| 	Engine.GetGUIObjectByName("summaryText").caption =
| 492| 492| 		g_GameData.gui.isInGame ?
| 493| 493| 			translate("Current Scores") :
| 494|    |-		g_GameData.gui.isReplay ?
|    | 494|+			g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 492| 492| 		g_GameData.gui.isInGame ?
| 493| 493| 			translate("Current Scores") :
| 494| 494| 		g_GameData.gui.isReplay ?
| 495|    |-			translate("Scores at the end of the game.") :
|    | 495|+				translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 493| 493| 			translate("Current Scores") :
| 494| 494| 		g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496|    |-		g_GameData.gui.disconnected ?
|    | 496|+				g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 494| 494| 		g_GameData.gui.isReplay ?
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497|    |-			translate("You have been disconnected.") :
|    | 497|+					translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 495| 495| 			translate("Scores at the end of the game.") :
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498|    |-		!assignedState ?
|    | 498|+					!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 496| 496| 		g_GameData.gui.disconnected ?
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499|    |-			translate("You have left the game.") :
|    | 499|+						translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 497| 497| 			translate("You have been disconnected.") :
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500|    |-		assignedState.state == "won" ?
|    | 500|+						assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 498| 498| 		!assignedState ?
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501|    |-			translate("You have won the battle!") :
|    | 501|+							translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 499| 499| 			translate("You have left the game.") :
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502|    |-		assignedState.state == "defeated" ?
|    | 502|+							assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
| 505| 505| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 500| 500| 		assignedState.state == "won" ?
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503|    |-			translate("You have been defeated…") :
|    | 503|+								translate("You have been defeated…") :
| 504| 504| 			translate("You have abandoned the game.");
| 505| 505| 
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 501| 501| 			translate("You have won the battle!") :
| 502| 502| 		assignedState.state == "defeated" ?
| 503| 503| 			translate("You have been defeated…") :
| 504|    |-			translate("You have abandoned the game.");
|    | 504|+								translate("You have abandoned the game.");
| 505| 505| 
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
| 507| 507| 		translate("Game time elapsed: %(time)s"), {
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 1.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/summary/summary.js
| 506| 506| 	Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
| 507| 507| 		translate("Game time elapsed: %(time)s"), {
| 508| 508| 			"time": timeToString(g_GameData.sim.timeElapsed)
| 509|    |-	});
|    | 509|+		});
| 510| 510| 
| 511| 511| 	let mapType = g_Settings.MapTypes.find(type => type.Name == g_GameData.sim.mapSettings.mapType);
| 512| 512| 	let mapSize = g_Settings.MapSizes.find(size => size.Tiles == g_GameData.sim.mapSettings.Size || 0);
Executing section cli...

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

Freagarach added inline comments.
binaries/data/mods/public/gui/campaigns/default_menu/CampaignMenu.js
20
In D11#116393, @wraitii wrote:

This also introduces a super-magical way to do rendering updates, because I like being lazy and magic.

This?

binaries/data/mods/public/gui/pregame/MainMenuItems.js
68

Should be the top most button, before Single-Player at least. And then not in the SP menu.

wraitii added inline comments.Aug 17 2020, 9:24 AM
binaries/data/mods/public/gui/campaigns/default_menu/CampaignMenu.js
20

No, it's actually the inheritance from DefaultPage which uses a Proxy to call Render when a property is set. This is just shorthand for "getGUiObjectByName" or whatever it's called.

binaries/data/mods/public/gui/pregame/MainMenuItems.js
68

Why do you think it would be better in first position?

Freagarach added inline comments.Aug 17 2020, 9:35 AM
binaries/data/mods/public/gui/pregame/MainMenuItems.js
68

Because for SP-people this is probably the most important button. If you're knee-deep into some nice campaign but have to do other stuff and come back it would be nice if this is the very first button. (See e.g. some other RTS games.)
I mean, it doesn't *have* to be the first, but I would certainly be in favour ;)