[QoL] Adding challenge arrows (#4048)
Arrows allow for dynamic placement based on language --------- Co-authored-by: MokaStitcher <54149968+MokaStitcher@users.noreply.github.com> Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>
This commit is contained in:
parent
c387f498c8
commit
6626df27ba
|
@ -172,11 +172,9 @@ export abstract class Challenge {
|
||||||
* @param overrideValue {@link integer} The value to check for. If undefined, gets the current value.
|
* @param overrideValue {@link integer} The value to check for. If undefined, gets the current value.
|
||||||
* @returns {@link string} The localised name for the current value.
|
* @returns {@link string} The localised name for the current value.
|
||||||
*/
|
*/
|
||||||
getValue(overrideValue?: integer): string {
|
getValue(overrideValue?: number): string {
|
||||||
if (overrideValue === undefined) {
|
const value = overrideValue ?? this.value;
|
||||||
overrideValue = this.value;
|
return i18next.t(`challenges:${this.geti18nKey()}.value.${value}`);
|
||||||
}
|
|
||||||
return i18next.t(`challenges:${this.geti18nKey()}.value.${this.value}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,11 +182,9 @@ export abstract class Challenge {
|
||||||
* @param overrideValue {@link integer} The value to check for. If undefined, gets the current value.
|
* @param overrideValue {@link integer} The value to check for. If undefined, gets the current value.
|
||||||
* @returns {@link string} The localised description for the current value.
|
* @returns {@link string} The localised description for the current value.
|
||||||
*/
|
*/
|
||||||
getDescription(overrideValue?: integer): string {
|
getDescription(overrideValue?: number): string {
|
||||||
if (overrideValue === undefined) {
|
const value = overrideValue ?? this.value;
|
||||||
overrideValue = this.value;
|
return `${i18next.t([`challenges:${this.geti18nKey()}.desc.${value}`, `challenges:${this.geti18nKey()}.desc`])}`;
|
||||||
}
|
|
||||||
return `${i18next.t([`challenges:${this.geti18nKey()}.desc.${this.value}`, `challenges:${this.geti18nKey()}.desc`])}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -511,14 +507,12 @@ export class SingleGenerationChallenge extends Challenge {
|
||||||
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
||||||
* @returns {string} The localised name for the current value.
|
* @returns {string} The localised name for the current value.
|
||||||
*/
|
*/
|
||||||
getValue(overrideValue?: integer): string {
|
getValue(overrideValue?: number): string {
|
||||||
if (overrideValue === undefined) {
|
const value = overrideValue ?? this.value;
|
||||||
overrideValue = this.value;
|
if (value === 0) {
|
||||||
}
|
|
||||||
if (this.value === 0) {
|
|
||||||
return i18next.t("settings:off");
|
return i18next.t("settings:off");
|
||||||
}
|
}
|
||||||
return i18next.t(`starterSelectUiHandler:gen${this.value}`);
|
return i18next.t(`starterSelectUiHandler:gen${value}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -526,14 +520,12 @@ export class SingleGenerationChallenge extends Challenge {
|
||||||
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
||||||
* @returns {string} The localised description for the current value.
|
* @returns {string} The localised description for the current value.
|
||||||
*/
|
*/
|
||||||
getDescription(overrideValue?: integer): string {
|
getDescription(overrideValue?: number): string {
|
||||||
if (overrideValue === undefined) {
|
const value = overrideValue ?? this.value;
|
||||||
overrideValue = this.value;
|
if (value === 0) {
|
||||||
}
|
|
||||||
if (this.value === 0) {
|
|
||||||
return i18next.t("challenges:singleGeneration.desc_default");
|
return i18next.t("challenges:singleGeneration.desc_default");
|
||||||
}
|
}
|
||||||
return i18next.t("challenges:singleGeneration.desc", { gen: i18next.t(`challenges:singleGeneration.gen_${this.value}`) });
|
return i18next.t("challenges:singleGeneration.desc", { gen: i18next.t(`challenges:singleGeneration.gen_${value}`) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ export default class GameChallengesUiHandler extends UiHandler {
|
||||||
|
|
||||||
private descriptionText: BBCodeText;
|
private descriptionText: BBCodeText;
|
||||||
|
|
||||||
private challengeLabels: Array<{ label: Phaser.GameObjects.Text, value: Phaser.GameObjects.Text }>;
|
private challengeLabels: Array<{ label: Phaser.GameObjects.Text, value: Phaser.GameObjects.Text, leftArrow: Phaser.GameObjects.Image, rightArrow: Phaser.GameObjects.Image }>;
|
||||||
private monoTypeValue: Phaser.GameObjects.Sprite;
|
private monoTypeValue: Phaser.GameObjects.Sprite;
|
||||||
|
|
||||||
private cursorObj: Phaser.GameObjects.NineSlice | null;
|
private cursorObj: Phaser.GameObjects.NineSlice | null;
|
||||||
|
@ -40,6 +40,11 @@ export default class GameChallengesUiHandler extends UiHandler {
|
||||||
|
|
||||||
private optionsWidth: number;
|
private optionsWidth: number;
|
||||||
|
|
||||||
|
private widestTextBox: number;
|
||||||
|
|
||||||
|
private readonly leftArrowGap: number = 90; // distance from the label to the left arrow
|
||||||
|
private readonly arrowSpacing: number = 3; // distance between the arrows and the value area
|
||||||
|
|
||||||
constructor(scene: BattleScene, mode: Mode | null = null) {
|
constructor(scene: BattleScene, mode: Mode | null = null) {
|
||||||
super(scene, mode);
|
super(scene, mode);
|
||||||
}
|
}
|
||||||
|
@ -47,6 +52,8 @@ export default class GameChallengesUiHandler extends UiHandler {
|
||||||
setup() {
|
setup() {
|
||||||
const ui = this.getUi();
|
const ui = this.getUi();
|
||||||
|
|
||||||
|
this.widestTextBox = 0;
|
||||||
|
|
||||||
this.challengesContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1);
|
this.challengesContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1);
|
||||||
this.challengesContainer.setName("challenges");
|
this.challengesContainer.setName("challenges");
|
||||||
|
|
||||||
|
@ -135,6 +142,20 @@ export default class GameChallengesUiHandler extends UiHandler {
|
||||||
|
|
||||||
this.valuesContainer.add(label);
|
this.valuesContainer.add(label);
|
||||||
|
|
||||||
|
const leftArrow = this.scene.add.image(0, 0, "cursor_reverse");
|
||||||
|
leftArrow.setName(`challenge-left-arrow-${i}`);
|
||||||
|
leftArrow.setOrigin(0, 0);
|
||||||
|
leftArrow.setVisible(false);
|
||||||
|
leftArrow.setScale(0.75);
|
||||||
|
this.valuesContainer.add(leftArrow);
|
||||||
|
|
||||||
|
const rightArrow = this.scene.add.image(0, 0, "cursor");
|
||||||
|
rightArrow.setName(`challenge-right-arrow-${i}`);
|
||||||
|
rightArrow.setOrigin(0, 0);
|
||||||
|
rightArrow.setScale(0.75);
|
||||||
|
rightArrow.setVisible(false);
|
||||||
|
this.valuesContainer.add(rightArrow);
|
||||||
|
|
||||||
const value = addTextObject(this.scene, 0, 28 + i * 16, "", TextStyle.SETTINGS_LABEL);
|
const value = addTextObject(this.scene, 0, 28 + i * 16, "", TextStyle.SETTINGS_LABEL);
|
||||||
value.setName(`challenge-value-text-${i}`);
|
value.setName(`challenge-value-text-${i}`);
|
||||||
value.setPositionRelative(label, 100, 0);
|
value.setPositionRelative(label, 100, 0);
|
||||||
|
@ -142,7 +163,9 @@ export default class GameChallengesUiHandler extends UiHandler {
|
||||||
|
|
||||||
this.challengeLabels[i] = {
|
this.challengeLabels[i] = {
|
||||||
label: label,
|
label: label,
|
||||||
value: value
|
value: value,
|
||||||
|
leftArrow: leftArrow,
|
||||||
|
rightArrow: rightArrow
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,10 +210,26 @@ export default class GameChallengesUiHandler extends UiHandler {
|
||||||
*/
|
*/
|
||||||
initLabels(): void {
|
initLabels(): void {
|
||||||
this.setDescription(this.scene.gameMode.challenges[0].getDescription());
|
this.setDescription(this.scene.gameMode.challenges[0].getDescription());
|
||||||
|
this.widestTextBox = 0;
|
||||||
for (let i = 0; i < 9; i++) {
|
for (let i = 0; i < 9; i++) {
|
||||||
if (i < this.scene.gameMode.challenges.length) {
|
if (i < this.scene.gameMode.challenges.length) {
|
||||||
this.challengeLabels[i].label.setVisible(true);
|
this.challengeLabels[i].label.setVisible(true);
|
||||||
this.challengeLabels[i].value.setVisible(true);
|
this.challengeLabels[i].value.setVisible(true);
|
||||||
|
this.challengeLabels[i].leftArrow.setVisible(true);
|
||||||
|
this.challengeLabels[i].rightArrow.setVisible(true);
|
||||||
|
|
||||||
|
const tempText = addTextObject(this.scene, 0, 0, "", TextStyle.SETTINGS_LABEL); // this is added here to get the widest text object for this language, which will be used for the arrow placement
|
||||||
|
|
||||||
|
for (let j = 0; j <= this.scene.gameMode.challenges[i].maxValue; j++) { // this goes through each challenge's value to find out what the max width will be
|
||||||
|
if (this.scene.gameMode.challenges[i].id !== Challenges.SINGLE_TYPE) {
|
||||||
|
tempText.setText(this.scene.gameMode.challenges[i].getValue(j));
|
||||||
|
if (tempText.displayWidth > this.widestTextBox) {
|
||||||
|
this.widestTextBox = tempText.displayWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tempText.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,16 +242,33 @@ export default class GameChallengesUiHandler extends UiHandler {
|
||||||
let monoTypeVisible = false;
|
let monoTypeVisible = false;
|
||||||
for (let i = 0; i < Math.min(9, this.scene.gameMode.challenges.length); i++) {
|
for (let i = 0; i < Math.min(9, this.scene.gameMode.challenges.length); i++) {
|
||||||
const challenge = this.scene.gameMode.challenges[this.scrollCursor + i];
|
const challenge = this.scene.gameMode.challenges[this.scrollCursor + i];
|
||||||
this.challengeLabels[i].label.setText(challenge.getName());
|
const challengeLabel = this.challengeLabels[i];
|
||||||
|
challengeLabel.label.setText(challenge.getName());
|
||||||
|
challengeLabel.leftArrow.setPositionRelative(challengeLabel.label, this.leftArrowGap, 4.5);
|
||||||
|
challengeLabel.leftArrow.setVisible(challenge.value !== 0);
|
||||||
|
challengeLabel.rightArrow.setPositionRelative(challengeLabel.leftArrow, Math.max(this.monoTypeValue.width, this.widestTextBox) + challengeLabel.leftArrow.displayWidth + 2 * this.arrowSpacing, 0);
|
||||||
|
challengeLabel.rightArrow.setVisible(challenge.value !== challenge.maxValue);
|
||||||
|
|
||||||
|
// this check looks to make sure that the arrows and value textbox don't take up too much space that they'll clip the right edge of the options background
|
||||||
|
if (challengeLabel.rightArrow.x + challengeLabel.rightArrow.width + this.optionsBg.rightWidth + this.arrowSpacing > this.optionsWidth) {
|
||||||
|
// if we go out of bounds of the box, set the x position as far right as we can without going past the box, with this.arrowSpacing to allow a small gap between the arrow and border
|
||||||
|
challengeLabel.rightArrow.setX(this.optionsWidth - this.arrowSpacing - this.optionsBg.rightWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this line of code gets the center point between the left and right arrows from their left side (Arrow.x gives middle point), taking into account the width of the arrows
|
||||||
|
const xLocation = Math.round((challengeLabel.leftArrow.x + challengeLabel.rightArrow.x + challengeLabel.leftArrow.displayWidth) / 2);
|
||||||
if (challenge.id === Challenges.SINGLE_TYPE) {
|
if (challenge.id === Challenges.SINGLE_TYPE) {
|
||||||
this.monoTypeValue.setPositionRelative(this.challengeLabels[i].label, 113, 8);
|
this.monoTypeValue.setX(xLocation);
|
||||||
|
this.monoTypeValue.setY(challengeLabel.label.y + 8);
|
||||||
this.monoTypeValue.setFrame(challenge.getValue());
|
this.monoTypeValue.setFrame(challenge.getValue());
|
||||||
this.monoTypeValue.setVisible(true);
|
this.monoTypeValue.setVisible(true);
|
||||||
this.challengeLabels[i].value.setVisible(false);
|
challengeLabel.value.setVisible(false);
|
||||||
monoTypeVisible = true;
|
monoTypeVisible = true;
|
||||||
} else {
|
} else {
|
||||||
this.challengeLabels[i].value.setText(challenge.getValue());
|
challengeLabel.value.setText(challenge.getValue());
|
||||||
this.challengeLabels[i].value.setVisible(true);
|
challengeLabel.value.setX(xLocation);
|
||||||
|
challengeLabel.value.setOrigin(0.5, 0);
|
||||||
|
challengeLabel.value.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!monoTypeVisible) {
|
if (!monoTypeVisible) {
|
||||||
|
@ -244,6 +300,7 @@ export default class GameChallengesUiHandler extends UiHandler {
|
||||||
super.show(args);
|
super.show(args);
|
||||||
|
|
||||||
this.startCursor.setVisible(false);
|
this.startCursor.setVisible(false);
|
||||||
|
this.updateChallengeArrows(false);
|
||||||
this.challengesContainer.setVisible(true);
|
this.challengesContainer.setVisible(true);
|
||||||
// Should always be false at the start
|
// Should always be false at the start
|
||||||
this.hasSelectedChallenge = this.scene.gameMode.challenges.some(c => c.value !== 0);
|
this.hasSelectedChallenge = this.scene.gameMode.challenges.some(c => c.value !== 0);
|
||||||
|
@ -259,6 +316,21 @@ export default class GameChallengesUiHandler extends UiHandler {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This code updates the challenge starter arrows to be tinted/not tinted when the start button is selected to show they can't be changed
|
||||||
|
*/
|
||||||
|
updateChallengeArrows(tinted: boolean) {
|
||||||
|
for (let i = 0; i < Math.min(9, this.scene.gameMode.challenges.length); i++) {
|
||||||
|
const challengeLabel = this.challengeLabels[i];
|
||||||
|
if (tinted) {
|
||||||
|
challengeLabel.leftArrow.setTint(0x808080);
|
||||||
|
challengeLabel.rightArrow.setTint(0x808080);
|
||||||
|
} else {
|
||||||
|
challengeLabel.leftArrow.clearTint();
|
||||||
|
challengeLabel.rightArrow.clearTint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes input from a specified button.
|
* Processes input from a specified button.
|
||||||
* This method handles navigation through a UI menu, including movement through menu items
|
* This method handles navigation through a UI menu, including movement through menu items
|
||||||
|
@ -280,6 +352,7 @@ export default class GameChallengesUiHandler extends UiHandler {
|
||||||
// If the user presses cancel when the start cursor has been activated, the game deactivates the start cursor and allows typical challenge selection behavior
|
// If the user presses cancel when the start cursor has been activated, the game deactivates the start cursor and allows typical challenge selection behavior
|
||||||
this.startCursor.setVisible(false);
|
this.startCursor.setVisible(false);
|
||||||
this.cursorObj?.setVisible(true);
|
this.cursorObj?.setVisible(true);
|
||||||
|
this.updateChallengeArrows(this.startCursor.visible);
|
||||||
} else {
|
} else {
|
||||||
this.scene.clearPhaseQueue();
|
this.scene.clearPhaseQueue();
|
||||||
this.scene.pushPhase(new TitlePhase(this.scene));
|
this.scene.pushPhase(new TitlePhase(this.scene));
|
||||||
|
@ -294,6 +367,7 @@ export default class GameChallengesUiHandler extends UiHandler {
|
||||||
} else {
|
} else {
|
||||||
this.startCursor.setVisible(true);
|
this.startCursor.setVisible(true);
|
||||||
this.cursorObj?.setVisible(false);
|
this.cursorObj?.setVisible(false);
|
||||||
|
this.updateChallengeArrows(this.startCursor.visible);
|
||||||
}
|
}
|
||||||
success = true;
|
success = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue