Files
goon-game/app/src/main/java/com/projectsacrifice/game/GameStrings.java
T

329 lines
17 KiB
Java

package com.projectsacrifice.game;
/** All player-facing copy behind one typed, Android-independent interface. */
public final class GameStrings {
private final GameLanguage language;
private GameStrings(GameLanguage language) {
this.language = language == null ? GameLanguage.EN : language;
}
public static GameStrings forLanguage(GameLanguage language) {
return new GameStrings(language);
}
public GameLanguage language() {
return language;
}
private boolean russian() {
return language == GameLanguage.RU;
}
public String appContentDescription() {
return russian()
? "Project Sacrifice. Платформенная головоломка из десяти уровней."
: "Project Sacrifice. Ten-level puzzle platform game.";
}
public String projectTitle() { return "PROJECT SACRIFICE"; }
public String tagline() {
return russian() ? "Каждый конец оставляет путь вперёд"
: "Every ending leaves a way forward";
}
public String locked() { return russian() ? "ЗАКРЫТО" : "LOCKED"; }
public String tapToEnter() { return russian() ? "Нажмите, чтобы войти" : "Tap to enter"; }
public String levelSelectFooter() {
return russian()
? "Альбомная ориентация · мультитач · прогресс сохраняется автоматически"
: "Landscape · multitouch · progress saves automatically";
}
public String settingsButton() {
return russian() ? "Настройки" : "Settings";
}
public String settingsTitle() { return russian() ? "НАСТРОЙКИ" : "SETTINGS"; }
public String settingsInstruction() {
return russian() ? "Нажмите на строку, чтобы изменить. Всё сохраняется автоматически."
: "Tap a row to change it. Changes save automatically.";
}
public String controlSizeSetting() { return russian() ? "Размер управления" : "Control size"; }
public String controlOpacitySetting() { return russian() ? "Прозрачность управления" : "Control opacity"; }
public String vibrationSetting() { return russian() ? "Вибрация" : "Vibration"; }
public String languageSetting() { return russian() ? "Язык" : "Language"; }
public String languageName() { return russian() ? "Русский" : "English"; }
public String controlSizeValue(int index) {
String[] values = russian()
? new String[]{"Маленький", "Средний", "Большой"}
: new String[]{"Small", "Medium", "Large"};
return values[validPreset(index)];
}
public String controlOpacityValue(int index) {
String[] values = russian()
? new String[]{"Низкая", "Средняя", "Высокая"}
: new String[]{"Low", "Medium", "High"};
return values[validPreset(index)];
}
public String hapticsValue(boolean enabled) {
if (russian()) return enabled ? "Вкл." : "Выкл.";
return enabled ? "On" : "Off";
}
public String accessibilityTitle() { return russian() ? "ДОСТУПНОСТЬ" : "ACCESSIBILITY"; }
public String textSizeSetting() { return russian() ? "Размер текста" : "Text size"; }
public String textSizeValue(float scale) {
return scale > 1f ? (russian() ? "Крупный" : "Large")
: (russian() ? "Обычный" : "Standard");
}
public String highContrastSetting() { return russian() ? "Контраст" : "High contrast"; }
public String highContrastValue(boolean enabled) {
return hapticsValue(enabled);
}
public String reducedMotionSetting() { return russian() ? "Меньше движения" : "Reduced motion"; }
public String reducedMotionValue(boolean enabled) { return hapticsValue(enabled); }
public String audioTitle() { return russian() ? "ЗВУК" : "Audio"; }
public String musicSetting() { return russian() ? "Музыка" : "Music"; }
public String effectsSetting() { return russian() ? "Эффекты" : "Effects"; }
public String voiceSetting() { return russian() ? "Голоса" : "Voice"; }
public String volumeValue(AudioSettings settings, int preset) {
return settings.volumeLabel(preset);
}
public String back() { return russian() ? "Назад" : "Back"; }
public String hudStats(int deaths, long elapsedMilliseconds) {
if (russian()) {
return "Добровольцы " + deaths + " Время " + GameMath.formatTime(elapsedMilliseconds);
}
return "Volunteers " + deaths + " Time " + GameMath.formatTime(elapsedMilliseconds);
}
public String restart() { return russian() ? "Заново" : "Restart"; }
public String respawning() {
return russian() ? "Следующий доброволец уже в пути…"
: "Another volunteer is on the way…";
}
public String levelBestStats(int deaths, long elapsedMilliseconds) {
return "✓ " + deaths + " " + volunteerWord(deaths) + " · "
+ GameMath.formatTime(elapsedMilliseconds);
}
public String relicClaimed() { return russian() ? "РЕЛИКВИЯ ПОЛУЧЕНА" : "RELIC CLAIMED"; }
public String completion() { return russian() ? "Завершение ★" : "Completion ★"; }
public String completionDeaths(boolean earned, int deaths, int targetDeaths) {
return (earned ? "★" : "☆") + " " + deaths + " / " + targetDeaths + " "
+ volunteerWord(deaths);
}
public String completionTime(boolean earned, long elapsedMilliseconds, long targetMilliseconds) {
return (earned ? "★" : "☆") + " " + GameMath.formatTime(elapsedMilliseconds)
+ " / " + GameMath.formatTime(targetMilliseconds);
}
public String levelSelect() { return russian() ? "Выбор уровня" : "Level select"; }
public String replay() { return russian() ? "Повторить" : "Replay"; }
public String nextLevel() { return russian() ? "Следующий уровень" : "Next level"; }
public String paused() { return russian() ? "ПАУЗА" : "PAUSED"; }
public String resume() { return russian() ? "Продолжить" : "Resume"; }
// Result-flow hooks used by the Stage 3 result screen.
public String currentResult() { return russian() ? "Текущий результат" : "Current result"; }
public String bestResult() { return russian() ? "Лучший результат" : "Best result"; }
public String deathsStat() { return russian() ? "Добровольцы" : "Volunteers"; }
public String timeStat() { return russian() ? "Время" : "Time"; }
public String newBest() { return russian() ? "НОВЫЙ РЕКОРД" : "NEW BEST"; }
public String currentResultLine(int deaths, long timeMs) {
return currentResult() + " · " + deaths + " " + volunteerWord(deaths)
+ " · " + GameMath.formatTime(timeMs);
}
public String bestResultLine(int deaths, long timeMs) {
return bestResult() + " · " + deaths + " " + volunteerWord(deaths)
+ " · " + GameMath.formatTime(timeMs);
}
public String targetsResultLine(int deaths, long timeMs) {
String label = russian() ? "Цели" : "Targets";
return label + " · " + deaths + " " + volunteerWord(deaths)
+ " · " + GameMath.formatTime(timeMs);
}
public String nextGoalDeaths(long deaths) {
return russian()
? "Следующая цель · пройти с " + deaths + " добровольцами"
: "Next goal · finish with " + deaths + " volunteers";
}
public String nextGoalTime(long timeMs) {
return (russian() ? "Следующая цель · пройти за " : "Next goal · finish in ")
+ GameMath.formatTime(timeMs);
}
public String nextGoalLevel(long level) {
return (russian() ? "Следующая цель · перейти на уровень "
: "Next goal · enter level ") + level;
}
public String nextGoalPersonalBest() {
return russian() ? "Следующая цель · улучшить личный рекорд"
: "Next goal · improve your personal best";
}
// Onboarding hooks keep new tutorial Canvas copy out of GameView conditionals.
public String tutorialWelcomeTitle() {
return russian() ? "Смерть — это инструмент" : "Death is a tool";
}
public String tutorialWelcomeBody() {
return russian()
? "Двигайтесь стрелками и прыгайте кнопкой с крылом. Доберитесь до реликвии."
: "Move with the arrows and jump with the winged button. Reach the relic.";
}
public String tutorialSacrificeTitle() {
return russian() ? "Оставьте путь вперёд" : "Leave a way forward";
}
public String tutorialSacrificeBody() {
return russian()
? "После смерти тело остаётся в мире: закрывает шипы, держит плиты и становится ступенью."
: "A body stays in the world after death: cover spikes, hold plates, and make a step.";
}
public String tutorialSkip() { return russian() ? "Пропустить" : "Skip"; }
public String tutorialNext() { return russian() ? "Далее" : "Next"; }
public String tutorialStart() { return russian() ? "Начать" : "Start"; }
public String tutorialDone() { return russian() ? "Готово" : "Done"; }
public String tutorialMovementTitle() { return russian() ? "ДВИЖЕНИЕ" : "MOVE"; }
public String tutorialMovementBody() {
return russian() ? "Удерживайте левую или правую стрелку, чтобы двигаться."
: "Hold the left or right arrow to explore.";
}
public String tutorialJumpTitle() { return russian() ? "ДВИЖЕНИЕ + ПРЫЖОК" : "MOVE + JUMP"; }
public String tutorialJumpBody() {
return russian() ? "Используйте два пальца: держите направление и нажмите Прыжок."
: "Use two fingers: hold a direction and tap Jump.";
}
public String tutorialCorpseTitle() {
return russian() ? "СМЕРТЬ ОСТАВЛЯЕТ ИНСТРУМЕНТ" : "DEATH LEAVES A TOOL";
}
public String tutorialCorpseBody() {
return russian() ? "Павший доброволец остаётся. Используйте тело, чтобы открыть путь."
: "A fallen volunteer remains. Use the body to open a path.";
}
public String tutorialProgress(int step, int total) {
return step + " / " + total;
}
public String accessibilityStatus(int activeSignals, int totalSignals,
int openDoors, int totalDoors, boolean playerAlive) {
if (russian()) {
return "Сигналы " + activeSignals + "/" + totalSignals
+ " · Двери " + openDoors + "/" + totalDoors
+ " · Доброволец " + (playerAlive ? "активен" : "возрождается");
}
return "Signals " + activeSignals + "/" + totalSignals
+ " · Doors " + openDoors + "/" + totalDoors
+ " · Volunteer " + (playerAlive ? "active" : "respawning");
}
public String levelSelectDescription(int unlocked, int total) {
if (russian()) {
return "Выбор уровня. Открыто " + unlocked + " из " + total
+ ". Выберите открытый уровень или Настройки.";
}
return "Level select. " + unlocked + " of " + total
+ " unlocked. Choose an unlocked level or open Settings.";
}
public String settingsDescription(ControlSettings controls,
AccessibilitySettings accessibility) {
return settingsDescription(controls, accessibility, AudioSettings.defaults());
}
public String settingsDescription(ControlSettings controls,
AccessibilitySettings accessibility,
AudioSettings audio) {
if (russian()) {
return "Настройки. Размер управления "
+ controlSizeValue(controls.controlSizeIndex())
+ ". Прозрачность управления "
+ controlOpacityValue(controls.controlOpacityIndex())
+ ". Вибрация " + hapticsValue(controls.hapticsEnabled())
+ ". Размер текста " + textSizeValue(accessibility.textScale())
+ ". Контраст " + highContrastValue(accessibility.highContrastEnabled())
+ ". Меньше движения "
+ reducedMotionValue(accessibility.reducedMotionEnabled())
+ ". Музыка " + volumeValue(audio, audio.musicPreset())
+ ". Эффекты " + volumeValue(audio, audio.effectsPreset())
+ ". Голоса " + volumeValue(audio, audio.voicePreset())
+ ". Назад.";
}
return "Settings. Control size " + controls.controlSizeLabel()
+ ". Control opacity " + controls.controlOpacityLabel()
+ ". Vibration " + controls.hapticsLabel()
+ ". Text size " + accessibility.textSizeLabel()
+ ". High contrast " + accessibility.highContrastLabel()
+ ". Reduced motion " + accessibility.reducedMotionLabel()
+ ". Music " + volumeValue(audio, audio.musicPreset())
+ ". Effects " + volumeValue(audio, audio.effectsPreset())
+ ". Voice " + volumeValue(audio, audio.voicePreset())
+ ". Back.";
}
public String playingDescription(int levelNumber, int deaths, String elapsed,
String criticalState, boolean paused) {
if (paused) {
return russian()
? "Пауза на уровне " + levelNumber + ", " + levelTitle(levelNumber)
+ ". Продолжить или вернуться к выбору уровня."
: "Paused on level " + levelNumber + ", " + levelTitle(levelNumber)
+ ". Resume or return to level select.";
}
if (russian()) {
return "Идёт уровень " + levelNumber + ", " + levelTitle(levelNumber)
+ ". Добровольцы " + deaths + ". Время " + elapsed + ". "
+ criticalState + ". Движение влево и вправо, прыжок, заново, пауза.";
}
return "Playing level " + levelNumber + ", " + levelTitle(levelNumber)
+ ". " + deaths + " volunteers. Time " + elapsed + ". " + criticalState
+ ". Move left, move right, jump, restart, pause.";
}
public String completeDescription(int levelNumber, int deaths, String elapsed,
boolean hasNextLevel) {
if (russian()) {
return "Уровень завершён. " + levelTitle(levelNumber) + ". Добровольцы "
+ deaths + ". Время " + elapsed
+ ". Выбор уровня. Повторить."
+ (hasNextLevel ? " Следующий уровень." : "");
}
return "Level complete. " + levelTitle(levelNumber) + ". " + deaths
+ " volunteers. Time " + elapsed + ". Level select. Replay."
+ (hasNextLevel ? " Next level." : "");
}
public String levelTitle(int oneBasedLevelNumber) {
LevelDefinition level = level(oneBasedLevelNumber);
return russian() ? level.titleRu : level.title;
}
public String levelHint(int oneBasedLevelNumber) {
LevelDefinition level = level(oneBasedLevelNumber);
return russian() ? level.hintRu : level.hint;
}
private String volunteerWord(int count) {
if (!russian()) return count == 1 ? "volunteer" : "volunteers";
int mod100 = Math.abs(count) % 100;
int mod10 = Math.abs(count) % 10;
if (mod100 >= 11 && mod100 <= 14) return "добровольцев";
if (mod10 == 1) return "доброволец";
if (mod10 >= 2 && mod10 <= 4) return "добровольца";
return "добровольцев";
}
private static int validPreset(int index) {
return index >= 0 && index <= 2 ? index : 1;
}
private static LevelDefinition level(int oneBasedLevelNumber) {
int index = oneBasedLevelNumber - 1;
if (index < 0 || index >= LevelCatalog.all().size()) index = 0;
return LevelCatalog.get(index);
}
}