starOfWords/Assets/Scripts/4.0/game/ParagraphTrueFalse25Mod.cs
portakal ecb1c9edea Initial commit: Star of Words Unity project
Snapshot of the existing Unity 6 language-learning word game before any
refactoring. Adds Unity .gitignore and .gitattributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 15:31:20 +03:00

1109 lines
30 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.SceneManagement;
using System.Collections;
using System.Collections.Generic;
public class ParagraphTrueFalse25Mod : MonoBehaviour
{
[Header("DATA")]
public TextAsset wordFile;
public string wordsResourcePath = "Mod25Words";
[Header("MAIN TEXTS")]
[Tooltip("Paragraf burada gösterilecek.")]
public TMP_Text paragraphText;
[Tooltip("Doğru / yanlış kontrol edilecek ifade burada gösterilecek.")]
public TMP_Text statementText;
[Header("TEXTS")]
public TMP_Text titleText;
public TMP_Text languageText;
public TMP_Text feedbackText;
public TMP_Text scoreText;
public TMP_Text comboText;
public TMP_Text timerText;
[Header("TRUE / FALSE BUTTONS")]
[Tooltip("En az 2 buton bağla. 0 = TRUE, 1 = FALSE. 3. ve 4. varsa otomatik kapatılır.")]
public Button[] answerButtons;
public TMP_Text[] answerTexts;
[Header("MAIN BUTTONS")]
public Button submitButton;
public Button backButton;
[Header("EXTRA BUTTONS")]
public Button extraTimeButton;
public Button extraHintButton;
public Button extraSkipButton;
public TMP_Text extraTimeCooldownText;
public TMP_Text extraHintCooldownText;
public TMP_Text extraSkipCooldownText;
[Header("SCENES")]
public string backSceneName = "modsec 25";
public string resultSceneName = "modres 25";
[Header("LANGUAGE TEST")]
[Tooltip("-1 otomatik. 0 TR, 1 EN, 2 ES, 3 DE, 4 FR, 5 PT | QuestionLangID = paragraf ve ifade dili")]
public int forcedQuestionLanguageIndex = -1;
[Tooltip("-1 otomatik. 0 TR, 1 EN, 2 ES, 3 DE, 4 FR, 5 PT | AnswerLangID = TRUE / FALSE yazı dili")]
public int forcedAnswerLanguageIndex = -1;
[Header("GAME SETTINGS")]
public float startTime = 60f;
public int basePoints = 50;
public int wrongPenalty = 50;
public float correctTimeBonus = 2f;
public float nextQuestionDelay = 1.25f;
[Header("EXTRA SETTINGS")]
public float extraTimeAmount = 5f;
public float cooldownDuration = 5f;
[Header("COMBO MULTIPLIERS")]
public float mult_1to2 = 1f;
public float mult_3to4 = 1.15f;
public float mult_5to7 = 1.3f;
public float mult_8plus = 1.5f;
[Header("COLORS")]
public Color normalButtonColor = new Color32(120, 70, 220, 255);
public Color selectedButtonColor = new Color32(155, 105, 255, 255);
public Color correctButtonColor = new Color32(70, 240, 130, 255);
public Color wrongButtonColor = new Color32(255, 80, 95, 255);
public Color disabledButtonColor = new Color32(90, 75, 120, 255);
readonly string[] langNames = { "Türkçe", "English", "Español", "Deutsch", "Français", "Português" };
const string modKey = "Mod25";
class TrueFalseEntry
{
public string[] paragraphs = new string[6];
public string[] statements = new string[6];
public bool isTrue;
}
readonly List<TrueFalseEntry> allQuestions = new List<TrueFalseEntry>();
readonly List<TrueFalseEntry> questionPool = new List<TrueFalseEntry>();
TrueFalseEntry currentQuestion;
int paragraphLangIndex = 1;
int optionLangIndex = 0;
int selectedAnswer = -1;
int correctAnswerIndex = -1; // 0 = TRUE, 1 = FALSE
int score = 0;
int combo = 0;
int correctCount = 0;
int wrongCount = 0;
int bestComboThisRun = 0;
float timeLeft;
bool gameOver = false;
bool waitingNextQuestion = false;
bool extraTimeReady = true;
bool extraHintReady = true;
bool extraSkipReady = true;
Vector3[] originalButtonScales;
Vector3[] originalButtonPositions;
void Awake()
{
LoadQuestions();
}
void Start()
{
ResolveLanguages();
timeLeft = PlayerPrefs.GetFloat("SelectedGameTime", startTime);
if (timeLeft <= 0f)
timeLeft = startTime;
if (allQuestions.Count < 1)
{
Debug.LogError("Mod25: En az 1 geçerli TXT satırı gerekli. Yüklenen soru sayısı: " + allQuestions.Count);
enabled = false;
return;
}
if (paragraphText == null)
{
Debug.LogError("Mod25: paragraphText atanmadı.");
enabled = false;
return;
}
if (statementText == null)
{
Debug.LogError("Mod25: statementText atanmadı.");
enabled = false;
return;
}
if (answerButtons == null || answerButtons.Length < 2 || answerTexts == null || answerTexts.Length < 2)
{
Debug.LogError("Mod25: En az 2 answerButtons ve 2 answerTexts atanmalı. 0 TRUE, 1 FALSE.");
enabled = false;
return;
}
PrepareUI();
BindButtons();
ResetQuestionPool();
UpdateLanguageUI();
UpdateScoreUI();
UpdateComboUI();
UpdateTimerUI();
NextQuestion();
Debug.Log("Mod25 Paragraf Dili: " + paragraphLangIndex + " / " + langNames[paragraphLangIndex]);
Debug.Log("Mod25 TRUE/FALSE Dili: " + optionLangIndex + " / " + langNames[optionLangIndex]);
}
void Update()
{
if (gameOver)
return;
timeLeft -= Time.deltaTime;
if (timeLeft <= 0f)
{
timeLeft = 0f;
UpdateTimerUI();
GameOver();
return;
}
UpdateTimerUI();
}
// TXT FORMAT:
// 0-5 paragraf:
// trParagraph|enParagraph|esParagraph|deParagraph|frParagraph|ptParagraph
//
// 6-11 ifade:
// trStatement|enStatement|esStatement|deStatement|frStatement|ptStatement
//
// 12 cevap:
// true veya false
void LoadQuestions()
{
allQuestions.Clear();
TextAsset txt = wordFile;
if (txt == null)
txt = Resources.Load<TextAsset>(wordsResourcePath);
if (txt == null)
{
Debug.LogError("Mod25: TXT bulunamadı. Şuraya koy: Assets/Resources/" + wordsResourcePath + ".txt");
return;
}
string[] lines = txt.text.Split(
new[] { '\n', '\r' },
System.StringSplitOptions.RemoveEmptyEntries
);
for (int i = 0; i < lines.Length; i++)
{
string line = lines[i].Trim();
if (string.IsNullOrWhiteSpace(line))
continue;
if (line.StartsWith("#"))
continue;
string[] p = SplitLineSmart(line);
if (p.Length < 13)
{
Debug.LogWarning("Mod25 TXT eksik satır atlandı. Satır: " + (i + 1) + " Alan sayısı: " + p.Length);
continue;
}
TrueFalseEntry entry = new TrueFalseEntry();
bool valid = true;
for (int l = 0; l < 6; l++)
{
entry.paragraphs[l] = CleanField(p[l]);
if (string.IsNullOrWhiteSpace(entry.paragraphs[l]))
valid = false;
}
for (int l = 0; l < 6; l++)
{
entry.statements[l] = CleanField(p[6 + l]);
if (string.IsNullOrWhiteSpace(entry.statements[l]))
valid = false;
}
string answer = CleanField(p[12]).ToLowerInvariant();
if (answer == "true" || answer == "1" || answer == "yes" || answer == "doğru" || answer == "dogru")
entry.isTrue = true;
else if (answer == "false" || answer == "0" || answer == "no" || answer == "yanlış" || answer == "yanlis")
entry.isTrue = false;
else
{
Debug.LogWarning("Mod25 TXT cevap alanı true/false değil. Satır: " + (i + 1) + " Cevap: " + p[12]);
valid = false;
}
if (valid)
allQuestions.Add(entry);
}
Debug.Log("Mod25 yüklenen soru sayısı: " + allQuestions.Count);
}
string[] SplitLineSmart(string line)
{
if (line.Contains("|"))
return line.Split('|');
if (line.Contains("\t"))
return line.Split('\t');
return line.Split(',');
}
string CleanField(string s)
{
if (string.IsNullOrEmpty(s))
return "";
return s.Trim().Trim('"').Trim().Replace("\\n", "\n").Replace("[blank]", "____");
}
void ResolveLanguages()
{
// QuestionLangID = ekrandaki paragraf ve ifade dili
// AnswerLangID = TRUE / FALSE buton yazılarının dili
if (forcedQuestionLanguageIndex >= 0 && forcedQuestionLanguageIndex <= 5)
paragraphLangIndex = forcedQuestionLanguageIndex;
else
paragraphLangIndex = PlayerPrefs.GetInt("QuestionLangID", 1);
if (forcedAnswerLanguageIndex >= 0 && forcedAnswerLanguageIndex <= 5)
optionLangIndex = forcedAnswerLanguageIndex;
else
optionLangIndex = PlayerPrefs.GetInt("AnswerLangID", 0);
paragraphLangIndex = ClampLanguage(paragraphLangIndex, 1);
optionLangIndex = ClampLanguage(optionLangIndex, 0);
}
int ClampLanguage(int value, int fallback)
{
if (value < 0 || value > 5)
return fallback;
return value;
}
public void RefreshLanguagesFromPrefs()
{
ResolveLanguages();
UpdateLanguageUI();
if (currentQuestion != null && !gameOver)
RefreshCurrentQuestion();
}
public void SetQuestionLanguage(int id)
{
if (id < 0 || id > 5)
return;
paragraphLangIndex = id;
PlayerPrefs.SetInt("QuestionLangID", id);
PlayerPrefs.SetString("QuestionLangCode", ToCode(id));
PlayerPrefs.Save();
UpdateLanguageUI();
RefreshCurrentQuestion();
}
public void SetAnswerLanguage(int id)
{
if (id < 0 || id > 5)
return;
optionLangIndex = id;
PlayerPrefs.SetInt("AnswerLangID", id);
PlayerPrefs.SetString("AnswerLangCode", ToCode(id));
PlayerPrefs.Save();
UpdateLanguageUI();
RefreshCurrentQuestion();
}
string ToCode(int id)
{
switch (id)
{
case 0: return "tr";
case 1: return "en";
case 2: return "es";
case 3: return "de";
case 4: return "fr";
case 5: return "pt";
default: return "en";
}
}
void UpdateLanguageUI()
{
if (languageText != null)
{
languageText.text =
"PARAGRAF: " + langNames[paragraphLangIndex] +
" | SEÇİM: " + langNames[optionLangIndex];
}
if (titleText != null)
titleText.text = GetTitleText();
}
string GetTitleText()
{
switch (optionLangIndex)
{
case 0: return "Doğru mu Yanlış mı?";
case 1: return "True or False?";
case 2: return "¿Verdadero o falso?";
case 3: return "Richtig oder falsch?";
case 4: return "Vrai ou faux ?";
case 5: return "Verdadeiro ou falso?";
default: return "True or False?";
}
}
string GetText(string key)
{
int lang = optionLangIndex;
if (key == "choose")
{
if (lang == 0) return "DOĞRU VEYA YANLIŞ SEÇ";
if (lang == 1) return "CHOOSE TRUE OR FALSE";
if (lang == 2) return "ELIGE VERDADERO O FALSO";
if (lang == 3) return "WÄHLE RICHTIG ODER FALSCH";
if (lang == 4) return "CHOISIS VRAI OU FAUX";
if (lang == 5) return "ESCOLHA VERDADEIRO OU FALSO";
}
if (key == "correct")
{
if (lang == 0) return "DOĞRU";
if (lang == 1) return "CORRECT";
if (lang == 2) return "CORRECTO";
if (lang == 3) return "RICHTIG";
if (lang == 4) return "CORRECT";
if (lang == 5) return "CORRETO";
}
if (key == "wrong")
{
if (lang == 0) return "YANLIŞ";
if (lang == 1) return "WRONG";
if (lang == 2) return "INCORRECTO";
if (lang == 3) return "FALSCH";
if (lang == 4) return "FAUX";
if (lang == 5) return "ERRADO";
}
if (key == "correctAnswer")
{
if (lang == 0) return "Doğru cevap";
if (lang == 1) return "Correct answer";
if (lang == 2) return "Respuesta correcta";
if (lang == 3) return "Richtige Antwort";
if (lang == 4) return "Bonne réponse";
if (lang == 5) return "Resposta correta";
}
if (key == "trueButton")
{
if (lang == 0) return "DOĞRU";
if (lang == 1) return "TRUE";
if (lang == 2) return "VERDADERO";
if (lang == 3) return "RICHTIG";
if (lang == 4) return "VRAI";
if (lang == 5) return "VERDADEIRO";
}
if (key == "falseButton")
{
if (lang == 0) return "YANLIŞ";
if (lang == 1) return "FALSE";
if (lang == 2) return "FALSO";
if (lang == 3) return "FALSCH";
if (lang == 4) return "FAUX";
if (lang == 5) return "FALSO";
}
if (key == "paragraphLabel")
{
if (paragraphLangIndex == 0) return "Paragraf";
if (paragraphLangIndex == 1) return "Paragraph";
if (paragraphLangIndex == 2) return "Párrafo";
if (paragraphLangIndex == 3) return "Absatz";
if (paragraphLangIndex == 4) return "Paragraphe";
if (paragraphLangIndex == 5) return "Parágrafo";
}
if (key == "statementLabel")
{
if (paragraphLangIndex == 0) return "İfade";
if (paragraphLangIndex == 1) return "Statement";
if (paragraphLangIndex == 2) return "Afirmación";
if (paragraphLangIndex == 3) return "Aussage";
if (paragraphLangIndex == 4) return "Phrase";
if (paragraphLangIndex == 5) return "Afirmação";
}
if (key == "skipped")
{
if (lang == 0) return "GEÇİLDİ";
if (lang == 1) return "SKIPPED";
if (lang == 2) return "SALTADO";
if (lang == 3) return "ÜBERSPRUNGEN";
if (lang == 4) return "PASSÉ";
if (lang == 5) return "PULADO";
}
return key;
}
void PrepareUI()
{
if (paragraphText != null)
{
paragraphText.alignment = TextAlignmentOptions.Center;
paragraphText.textWrappingMode = TextWrappingModes.Normal;
}
if (statementText != null)
{
statementText.alignment = TextAlignmentOptions.Center;
statementText.textWrappingMode = TextWrappingModes.Normal;
}
if (feedbackText != null)
{
feedbackText.text = "";
feedbackText.alignment = TextAlignmentOptions.Center;
feedbackText.textWrappingMode = TextWrappingModes.Normal;
}
originalButtonScales = new Vector3[answerButtons.Length];
originalButtonPositions = new Vector3[answerButtons.Length];
for (int i = 0; i < answerButtons.Length; i++)
{
if (answerButtons[i] == null)
continue;
originalButtonScales[i] = answerButtons[i].transform.localScale;
originalButtonPositions[i] = answerButtons[i].transform.localPosition;
answerButtons[i].transition = Selectable.Transition.None;
if (answerButtons[i].image != null)
answerButtons[i].image.color = FullAlpha(normalButtonColor);
if (i > 1)
answerButtons[i].gameObject.SetActive(false);
}
HideCooldownTexts();
}
void HideCooldownTexts()
{
if (extraTimeCooldownText != null)
extraTimeCooldownText.gameObject.SetActive(false);
if (extraHintCooldownText != null)
extraHintCooldownText.gameObject.SetActive(false);
if (extraSkipCooldownText != null)
extraSkipCooldownText.gameObject.SetActive(false);
}
void BindButtons()
{
if (submitButton != null)
{
submitButton.onClick.RemoveAllListeners();
submitButton.onClick.AddListener(OnSubmit);
}
if (backButton != null)
{
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(() =>
{
SaveProgressOnly();
SceneManager.LoadScene(backSceneName);
});
}
if (extraTimeButton != null)
{
extraTimeButton.onClick.RemoveAllListeners();
extraTimeButton.onClick.AddListener(OnExtraTime);
}
if (extraHintButton != null)
{
extraHintButton.onClick.RemoveAllListeners();
extraHintButton.onClick.AddListener(OnExtraHint);
}
if (extraSkipButton != null)
{
extraSkipButton.onClick.RemoveAllListeners();
extraSkipButton.onClick.AddListener(OnExtraSkip);
}
for (int i = 0; i < answerButtons.Length; i++)
{
int index = i;
if (answerButtons[i] == null)
continue;
answerButtons[i].onClick.RemoveAllListeners();
answerButtons[i].onClick.AddListener(() => SelectAnswer(index));
}
}
void ResetQuestionPool()
{
questionPool.Clear();
questionPool.AddRange(allQuestions);
Shuffle(questionPool);
}
void NextQuestion()
{
if (gameOver)
return;
if (questionPool.Count <= 0)
ResetQuestionPool();
currentQuestion = questionPool[0];
questionPool.RemoveAt(0);
RefreshCurrentQuestion();
}
void RefreshCurrentQuestion()
{
if (currentQuestion == null)
return;
waitingNextQuestion = false;
selectedAnswer = -1;
correctAnswerIndex = currentQuestion.isTrue ? 0 : 1;
ResetButtons();
if (paragraphText != null)
paragraphText.text = GetText("paragraphLabel") + ":\n" + currentQuestion.paragraphs[paragraphLangIndex];
if (statementText != null)
statementText.text = GetText("statementLabel") + ":\n" + currentQuestion.statements[paragraphLangIndex];
if (answerTexts != null && answerTexts.Length > 0 && answerTexts[0] != null)
answerTexts[0].text = GetText("trueButton");
if (answerTexts != null && answerTexts.Length > 1 && answerTexts[1] != null)
answerTexts[1].text = GetText("falseButton");
for (int i = 2; i < answerTexts.Length; i++)
{
if (answerTexts[i] != null)
answerTexts[i].text = "";
}
if (feedbackText != null)
feedbackText.text = "";
if (submitButton != null)
submitButton.interactable = true;
StartCoroutine(MainTextPopAnim());
}
void ResetButtons()
{
for (int i = 0; i < answerButtons.Length; i++)
{
if (answerButtons[i] == null)
continue;
bool active = i < 2;
answerButtons[i].gameObject.SetActive(active);
if (!active)
continue;
answerButtons[i].interactable = true;
answerButtons[i].transform.localScale = originalButtonScales[i];
answerButtons[i].transform.localPosition = originalButtonPositions[i];
if (answerButtons[i].image != null)
answerButtons[i].image.color = FullAlpha(normalButtonColor);
}
}
void SelectAnswer(int index)
{
if (gameOver || waitingNextQuestion)
return;
if (index < 0 || index > 1)
return;
selectedAnswer = index;
for (int i = 0; i < 2; i++)
{
if (answerButtons[i] == null)
continue;
if (answerButtons[i].image != null)
answerButtons[i].image.color = FullAlpha(normalButtonColor);
answerButtons[i].transform.localScale = originalButtonScales[i];
}
if (answerButtons[index].image != null)
answerButtons[index].image.color = FullAlpha(selectedButtonColor);
answerButtons[index].transform.localScale = originalButtonScales[index] * 0.94f;
}
void OnSubmit()
{
if (gameOver || waitingNextQuestion)
return;
if (selectedAnswer < 0)
{
ShowFeedback(GetText("choose"), wrongButtonColor);
return;
}
waitingNextQuestion = true;
if (submitButton != null)
submitButton.interactable = false;
for (int i = 0; i < 2; i++)
{
if (answerButtons[i] != null)
answerButtons[i].interactable = false;
}
if (selectedAnswer == correctAnswerIndex)
CorrectAnswer();
else
WrongAnswer();
UpdateScoreUI();
UpdateComboUI();
SaveProgressOnly();
StartCoroutine(NextQuestionDelay());
}
void CorrectAnswer()
{
if (answerButtons[selectedAnswer].image != null)
answerButtons[selectedAnswer].image.color = FullAlpha(correctButtonColor);
combo++;
correctCount++;
if (combo > bestComboThisRun)
bestComboThisRun = combo;
int earned = Mathf.RoundToInt(basePoints * GetComboMultiplier(combo));
score += earned;
timeLeft += correctTimeBonus;
ShowFeedback(GetText("correct") + " +" + earned, correctButtonColor);
StartCoroutine(ButtonPop(answerButtons[selectedAnswer]));
}
void WrongAnswer()
{
if (answerButtons[selectedAnswer].image != null)
answerButtons[selectedAnswer].image.color = FullAlpha(wrongButtonColor);
if (correctAnswerIndex >= 0 && correctAnswerIndex < 2)
{
if (answerButtons[correctAnswerIndex].image != null)
answerButtons[correctAnswerIndex].image.color = FullAlpha(correctButtonColor);
}
wrongCount++;
combo = 0;
score -= wrongPenalty;
if (score < 0)
score = 0;
string correctText = correctAnswerIndex == 0 ? GetText("trueButton") : GetText("falseButton");
ShowFeedback(GetText("wrong") + "\n" + GetText("correctAnswer") + ": " + correctText, wrongButtonColor);
}
IEnumerator NextQuestionDelay()
{
yield return new WaitForSeconds(nextQuestionDelay);
if (!gameOver)
NextQuestion();
}
void OnExtraTime()
{
if (!extraTimeReady || gameOver)
return;
timeLeft += extraTimeAmount;
extraTimeReady = false;
if (extraTimeButton != null)
extraTimeButton.interactable = false;
StartCoroutine(Cooldown(extraTimeCooldownText, extraTimeButton, () => extraTimeReady = true));
}
void OnExtraHint()
{
if (!extraHintReady || gameOver || waitingNextQuestion)
return;
int wrongIndex = correctAnswerIndex == 0 ? 1 : 0;
if (wrongIndex == selectedAnswer)
selectedAnswer = -1;
if (answerButtons[wrongIndex] != null)
{
answerButtons[wrongIndex].interactable = false;
if (answerButtons[wrongIndex].image != null)
answerButtons[wrongIndex].image.color = FullAlpha(disabledButtonColor);
if (answerTexts != null && wrongIndex < answerTexts.Length && answerTexts[wrongIndex] != null)
answerTexts[wrongIndex].text = "—";
}
extraHintReady = false;
if (extraHintButton != null)
extraHintButton.interactable = false;
StartCoroutine(Cooldown(extraHintCooldownText, extraHintButton, () => extraHintReady = true));
}
void OnExtraSkip()
{
if (!extraSkipReady || gameOver || waitingNextQuestion)
return;
combo = 0;
UpdateComboUI();
ShowFeedback(GetText("skipped"), Color.white);
NextQuestion();
extraSkipReady = false;
if (extraSkipButton != null)
extraSkipButton.interactable = false;
StartCoroutine(Cooldown(extraSkipCooldownText, extraSkipButton, () => extraSkipReady = true));
}
IEnumerator Cooldown(TMP_Text label, Button button, System.Action done)
{
float t = cooldownDuration;
if (label != null)
label.gameObject.SetActive(true);
while (t > 0)
{
if (label != null)
label.text = Mathf.CeilToInt(t).ToString();
t -= Time.deltaTime;
yield return null;
}
if (label != null)
{
label.text = "";
label.gameObject.SetActive(false);
}
if (button != null)
button.interactable = true;
done?.Invoke();
}
void SaveProgressOnly()
{
PlayerPrefs.SetInt("Mod25Skor", score);
PlayerPrefs.SetInt("Mod25Score", score);
PlayerPrefs.SetInt("Mod25Correct", correctCount);
PlayerPrefs.SetInt("Mod25Wrong", wrongCount);
PlayerPrefs.SetInt(modKey + "_LastScore", score);
PlayerPrefs.SetInt(modKey + "_Correct", correctCount);
PlayerPrefs.SetInt(modKey + "_Wrong", wrongCount);
PlayerPrefs.SetInt(modKey + "_LastCombo", combo);
PlayerPrefs.SetInt(modKey + "_BestComboRun", bestComboThisRun);
PlayerPrefs.SetInt(modKey + "_LastTimeLeft", Mathf.CeilToInt(timeLeft));
int total = correctCount + wrongCount;
int accuracy = total > 0 ? Mathf.RoundToInt((correctCount / (float)total) * 100f) : 0;
PlayerPrefs.SetInt(modKey + "_LastAccuracy", accuracy);
if (score > PlayerPrefs.GetInt(modKey + "_MaxScore", 0))
PlayerPrefs.SetInt(modKey + "_MaxScore", score);
if (score > PlayerPrefs.GetInt("Mod25LeaderScore", 0))
PlayerPrefs.SetInt("Mod25LeaderScore", score);
if (score > PlayerPrefs.GetInt("Mod25BestScore", 0))
PlayerPrefs.SetInt("Mod25BestScore", score);
if (bestComboThisRun > PlayerPrefs.GetInt(modKey + "_BestCombo", 0))
PlayerPrefs.SetInt(modKey + "_BestCombo", bestComboThisRun);
PlayerPrefs.Save();
}
void GameOver()
{
if (gameOver)
return;
gameOver = true;
SaveProgressOnly();
PlayerPrefs.SetString("LastPlayedMod", modKey);
PlayerPrefs.SetInt(modKey + "_TotalCorrect", PlayerPrefs.GetInt(modKey + "_TotalCorrect", 0) + correctCount);
PlayerPrefs.SetInt(modKey + "_TotalWrong", PlayerPrefs.GetInt(modKey + "_TotalWrong", 0) + wrongCount);
PlayerPrefs.SetInt(modKey + "_PlayCount", PlayerPrefs.GetInt(modKey + "_PlayCount", 0) + 1);
PlayerPrefs.SetInt("TotalScore", PlayerPrefs.GetInt("TotalScore", 0) + score);
PlayerPrefs.Save();
SceneManager.LoadScene(resultSceneName);
}
void UpdateScoreUI()
{
if (scoreText != null)
scoreText.text = score.ToString();
}
void UpdateComboUI()
{
if (comboText != null)
comboText.text = combo + "x";
}
void UpdateTimerUI()
{
if (timerText == null)
return;
timerText.text = Mathf.CeilToInt(timeLeft).ToString();
if (timeLeft <= 10f)
timerText.color = Color.red;
else
timerText.color = Color.white;
}
void ShowFeedback(string msg, Color color)
{
if (feedbackText == null)
return;
feedbackText.text = msg;
feedbackText.color = FullAlpha(color);
StopCoroutine(nameof(FeedbackAnim));
StartCoroutine(nameof(FeedbackAnim));
}
float GetComboMultiplier(int c)
{
if (c >= 8)
return mult_8plus;
if (c >= 5)
return mult_5to7;
if (c >= 3)
return mult_3to4;
return mult_1to2;
}
IEnumerator FeedbackAnim()
{
if (feedbackText == null)
yield break;
Vector3 normal = Vector3.one;
Vector3 big = Vector3.one * 1.15f;
feedbackText.transform.localScale = normal;
float t = 0;
while (t < 1)
{
t += Time.deltaTime / 0.15f;
feedbackText.transform.localScale = Vector3.Lerp(normal, big, t);
yield return null;
}
t = 0;
while (t < 1)
{
t += Time.deltaTime / 0.15f;
feedbackText.transform.localScale = Vector3.Lerp(big, normal, t);
yield return null;
}
feedbackText.transform.localScale = normal;
}
IEnumerator ButtonPop(Button btn)
{
if (btn == null)
yield break;
Vector3 normal = btn.transform.localScale;
Vector3 big = normal * 1.12f;
float t = 0;
while (t < 1)
{
t += Time.deltaTime / 0.12f;
btn.transform.localScale = Vector3.Lerp(normal, big, t);
yield return null;
}
t = 0;
while (t < 1)
{
t += Time.deltaTime / 0.12f;
btn.transform.localScale = Vector3.Lerp(big, normal, t);
yield return null;
}
btn.transform.localScale = normal;
}
IEnumerator MainTextPopAnim()
{
if (paragraphText == null)
yield break;
Vector3 normal = Vector3.one;
Vector3 small = Vector3.one * 0.92f;
paragraphText.transform.localScale = small;
if (statementText != null)
statementText.transform.localScale = small;
float t = 0;
while (t < 1)
{
t += Time.deltaTime / 0.18f;
paragraphText.transform.localScale = Vector3.Lerp(small, normal, t);
if (statementText != null)
statementText.transform.localScale = Vector3.Lerp(small, normal, t);
yield return null;
}
paragraphText.transform.localScale = normal;
if (statementText != null)
statementText.transform.localScale = normal;
}
Color FullAlpha(Color c)
{
c.a = 1f;
return c;
}
void Shuffle<T>(List<T> list)
{
for (int i = 0; i < list.Count; i++)
{
int rnd = Random.Range(i, list.Count);
T temp = list[i];
list[i] = list[rnd];
list[rnd] = temp;
}
}
}