starOfWords/Assets/Scripts/4.0/game/ParagraphOrder27Mod.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

1258 lines
No EOL
33 KiB
C#
Raw 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 ParagraphOrder27Mod : MonoBehaviour
{
[Header("DATA")]
public TextAsset wordFile;
public string wordsResourcePath = "Mod27Words";
[Header("MAIN TEXTS")]
public TMP_Text instructionText;
[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("SENTENCE BUTTONS")]
public Button[] sentenceButtons;
public TMP_Text[] sentenceTexts;
[Header("MAIN BUTTONS")]
public Button submitButton;
public Button resetButton;
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 27";
public string resultSceneName = "modres 27";
[Header("LANGUAGE TEST")]
[Tooltip("-1 otomatik. 0 TR, 1 EN, 2 ES, 3 DE, 4 FR, 5 PT")]
public int forcedQuestionLanguageIndex = -1;
[Header("GAME SETTINGS")]
public float startTime = 60f;
public int basePoints = 60;
public int wrongPenalty = 50;
public float correctTimeBonus = 3f;
public float nextQuestionDelay = 1.5f;
[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 = "Mod27";
class ParagraphOrderEntry
{
public string[] sentences = new string[24];
}
class SentenceOption
{
public string text;
public int correctOrder;
}
readonly List<ParagraphOrderEntry> allQuestions = new List<ParagraphOrderEntry>();
readonly List<ParagraphOrderEntry> questionPool = new List<ParagraphOrderEntry>();
readonly List<SentenceOption> currentOptions = new List<SentenceOption>();
ParagraphOrderEntry currentQuestion;
ParagraphOrderEntry lastQuestion;
int sentenceLangIndex = 1;
int[] selectedOrderByButton;
int selectedCount = 0;
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;
string[] baseButtonTexts;
void Awake()
{
LoadQuestions();
}
void Start()
{
ResolveLanguage();
timeLeft = PlayerPrefs.GetFloat("SelectedGameTime", startTime);
if (timeLeft <= 0f)
timeLeft = startTime;
if (allQuestions.Count < 1)
{
Debug.LogError("Mod27: En az 1 geçerli TXT satırı gerekli. Yüklenen soru sayısı: " + allQuestions.Count);
enabled = false;
return;
}
if (allQuestions.Count == 1)
{
Debug.LogWarning("Mod27: Sadece 1 geçerli TXT satırı var. Bu yüzden aynı soru tekrar gelir. Random için TXT satır sayısını artır.");
}
if (sentenceButtons == null || sentenceButtons.Length < 4)
{
Debug.LogError("Mod27: 4 sentenceButtons atanmalı.");
enabled = false;
return;
}
if (sentenceTexts == null || sentenceTexts.Length < 4)
{
Debug.LogError("Mod27: 4 sentenceTexts atanmalı.");
enabled = false;
return;
}
PrepareUI();
BindButtons();
ResetQuestionPool();
UpdateLanguageUI();
UpdateScoreUI();
UpdateComboUI();
UpdateTimerUI();
NextQuestion();
Debug.Log("Mod27 aktif dil: " + sentenceLangIndex + " / " + langNames[sentenceLangIndex]);
}
void Update()
{
if (gameOver)
return;
timeLeft -= Time.deltaTime;
if (timeLeft <= 0f)
{
timeLeft = 0f;
UpdateTimerUI();
GameOver();
return;
}
UpdateTimerUI();
}
/*
TXT FORMAT:
Her satır 24 alan olmalı.
tr1|tr2|tr3|tr4|
en1|en2|en3|en4|
es1|es2|es3|es4|
de1|de2|de3|de4|
fr1|fr2|fr3|fr4|
pt1|pt2|pt3|pt4
TXT içindeki cümleler doğru sırayla yazılır.
Script ekranda otomatik karıştırır.
*/
void LoadQuestions()
{
allQuestions.Clear();
TextAsset txt = wordFile;
if (txt == null)
txt = Resources.Load<TextAsset>(wordsResourcePath);
if (txt == null)
{
Debug.LogError("Mod27: TXT bulunamadı. Dosya yolu: 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[] parts = SplitLineSmart(line);
if (parts.Length < 24)
{
Debug.LogWarning("Mod27 TXT eksik satır atlandı. Satır: " + (i + 1) + " / Alan sayısı: " + parts.Length);
continue;
}
ParagraphOrderEntry entry = new ParagraphOrderEntry();
bool valid = true;
for (int s = 0; s < 24; s++)
{
entry.sentences[s] = CleanField(parts[s]);
if (string.IsNullOrWhiteSpace(entry.sentences[s]))
valid = false;
}
if (valid)
allQuestions.Add(entry);
}
Debug.Log("Mod27 yüklenen soru sayısı: " + allQuestions.Count);
if (allQuestions.Count <= 1)
{
Debug.LogWarning("Mod27 UYARI: TXT içinden sadece " + allQuestions.Count + " soru yüklendi. Random düzgün görünmesi için Mod27Words.txt içine daha fazla geçerli satır ekle.");
}
}
string[] SplitLineSmart(string line)
{
if (line.Contains("|"))
return line.Split('|');
if (line.Contains("\t"))
return line.Split('\t');
return line.Split(',');
}
string CleanField(string value)
{
if (string.IsNullOrEmpty(value))
return "";
return value.Trim().Trim('"').Trim().Replace("\\n", "\n");
}
void ResolveLanguage()
{
if (forcedQuestionLanguageIndex >= 0 && forcedQuestionLanguageIndex <= 5)
sentenceLangIndex = forcedQuestionLanguageIndex;
else
sentenceLangIndex = PlayerPrefs.GetInt("QuestionLangID", 1);
sentenceLangIndex = ClampLanguage(sentenceLangIndex, 1);
}
int ClampLanguage(int value, int fallback)
{
if (value < 0 || value > 5)
return fallback;
return value;
}
public void RefreshLanguagesFromPrefs()
{
ResolveLanguage();
UpdateLanguageUI();
if (currentQuestion != null && !gameOver)
RefreshCurrentQuestion();
}
public void SetQuestionLanguage(int id)
{
if (id < 0 || id > 5)
return;
sentenceLangIndex = id;
PlayerPrefs.SetInt("QuestionLangID", id);
PlayerPrefs.SetString("QuestionLangCode", 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 = GetText("language") + ": " + langNames[sentenceLangIndex];
if (titleText != null)
titleText.text = GetTitleText();
if (instructionText != null)
instructionText.text = GetText("instruction");
}
string GetTitleText()
{
switch (sentenceLangIndex)
{
case 0: return "Paragrafı Sırala";
case 1: return "Order the Paragraph";
case 2: return "Ordena el párrafo";
case 3: return "Ordne den Absatz";
case 4: return "Remets le paragraphe dans l'ordre";
case 5: return "Ordene o parágrafo";
default: return "Order the Paragraph";
}
}
string GetText(string key)
{
int lang = sentenceLangIndex;
if (key == "language")
{
if (lang == 0) return "DİL";
if (lang == 1) return "LANGUAGE";
if (lang == 2) return "IDIOMA";
if (lang == 3) return "SPRACHE";
if (lang == 4) return "LANGUE";
if (lang == 5) return "IDIOMA";
}
if (key == "instruction")
{
if (lang == 0) return "Cümlelere doğru sırayla dokun. Sonra SUBMIT'e bas.";
if (lang == 1) return "Tap the sentences in the correct order. Then press SUBMIT.";
if (lang == 2) return "Toca las oraciones en el orden correcto. Luego pulsa SUBMIT.";
if (lang == 3) return "Tippe die Sätze in der richtigen Reihenfolge an. Dann drücke SUBMIT.";
if (lang == 4) return "Touche les phrases dans le bon ordre. Puis appuie sur SUBMIT.";
if (lang == 5) return "Toque nas frases na ordem correta. Depois aperte SUBMIT.";
}
if (key == "chooseAll")
{
if (lang == 0) return "4 CÜMLENİN HEPSİNİ SIRALA";
if (lang == 1) return "ORDER ALL 4 SENTENCES";
if (lang == 2) return "ORDENA LAS 4 ORACIONES";
if (lang == 3) return "ORDNE ALLE 4 SÄTZE";
if (lang == 4) return "ORDONNE LES 4 PHRASES";
if (lang == 5) return "ORDENE AS 4 FRASES";
}
if (key == "correct")
{
if (lang == 0) return "DOĞRU SIRALAMA";
if (lang == 1) return "CORRECT ORDER";
if (lang == 2) return "ORDEN CORRECTO";
if (lang == 3) return "RICHTIGE REIHENFOLGE";
if (lang == 4) return "BON ORDRE";
if (lang == 5) return "ORDEM CORRETA";
}
if (key == "wrong")
{
if (lang == 0) return "SIRALAMA YANLIŞ";
if (lang == 1) return "WRONG ORDER";
if (lang == 2) return "ORDEN INCORRECTO";
if (lang == 3) return "FALSCHE REIHENFOLGE";
if (lang == 4) return "MAUVAIS ORDRE";
if (lang == 5) return "ORDEM ERRADA";
}
if (key == "hint")
{
if (lang == 0) return "İPUCU: SIRADAKİ DOĞRU CÜMLE SEÇİLDİ";
if (lang == 1) return "HINT: THE NEXT CORRECT SENTENCE WAS SELECTED";
if (lang == 2) return "PISTA: SE SELECCIONÓ LA SIGUIENTE ORACIÓN CORRECTA";
if (lang == 3) return "HINWEIS: DER NÄCHSTE RICHTIGE SATZ WURDE GEWÄHLT";
if (lang == 4) return "INDICE : LA PROCHAINE PHRASE CORRECTE A ÉTÉ CHOISIE";
if (lang == 5) return "DICA: A PRÓXIMA FRASE CORRETA FOI SELECIONADA";
}
if (key == "hintReset")
{
if (lang == 0) return "İPUCU İÇİN ÖNCE SEÇİMİ RESETLE";
if (lang == 1) return "RESET YOUR ORDER BEFORE USING HINT";
if (lang == 2) return "REINICIA TU ORDEN ANTES DE USAR LA PISTA";
if (lang == 3) return "SETZE DEINE REIHENFOLGE ZURÜCK, BEVOR DU DEN HINWEIS NUTZT";
if (lang == 4) return "RÉINITIALISE TON ORDRE AVANT L'INDICE";
if (lang == 5) return "REDEFINA SUA ORDEM ANTES DE USAR A DICA";
}
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 (instructionText != null)
{
instructionText.alignment = TextAlignmentOptions.Center;
instructionText.textWrappingMode = TextWrappingModes.Normal;
}
if (feedbackText != null)
{
feedbackText.text = "";
feedbackText.alignment = TextAlignmentOptions.Center;
feedbackText.textWrappingMode = TextWrappingModes.Normal;
}
originalButtonScales = new Vector3[sentenceButtons.Length];
originalButtonPositions = new Vector3[sentenceButtons.Length];
selectedOrderByButton = new int[sentenceButtons.Length];
baseButtonTexts = new string[sentenceButtons.Length];
for (int i = 0; i < sentenceButtons.Length; i++)
{
if (sentenceButtons[i] == null)
continue;
originalButtonScales[i] = sentenceButtons[i].transform.localScale;
originalButtonPositions[i] = sentenceButtons[i].transform.localPosition;
sentenceButtons[i].transition = Selectable.Transition.None;
if (sentenceButtons[i].image != null)
sentenceButtons[i].image.color = FullAlpha(normalButtonColor);
}
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 (resetButton != null)
{
resetButton.onClick.RemoveAllListeners();
resetButton.onClick.AddListener(ResetCurrentSelection);
}
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 < sentenceButtons.Length; i++)
{
int index = i;
if (sentenceButtons[i] == null)
continue;
sentenceButtons[i].onClick.RemoveAllListeners();
sentenceButtons[i].onClick.AddListener(() => SelectSentence(index));
}
}
void ResetQuestionPool()
{
questionPool.Clear();
questionPool.AddRange(allQuestions);
Shuffle(questionPool);
if (questionPool.Count > 1 && lastQuestion != null && questionPool[0] == lastQuestion)
{
int swapIndex = Random.Range(1, questionPool.Count);
ParagraphOrderEntry temp = questionPool[0];
questionPool[0] = questionPool[swapIndex];
questionPool[swapIndex] = temp;
}
}
void NextQuestion()
{
if (gameOver)
return;
if (allQuestions.Count <= 0)
return;
if (questionPool.Count <= 0)
ResetQuestionPool();
if (questionPool.Count <= 0)
return;
currentQuestion = questionPool[0];
questionPool.RemoveAt(0);
lastQuestion = currentQuestion;
RefreshCurrentQuestion();
}
void RefreshCurrentQuestion()
{
if (currentQuestion == null)
return;
waitingNextQuestion = false;
selectedCount = 0;
currentOptions.Clear();
for (int i = 0; i < 4; i++)
{
SentenceOption option = new SentenceOption();
option.text = GetSentence(currentQuestion, sentenceLangIndex, i);
option.correctOrder = i;
currentOptions.Add(option);
}
ShuffleSentenceOptions();
ResetButtonsForNewQuestion();
for (int i = 0; i < 4; i++)
{
baseButtonTexts[i] = currentOptions[i].text;
if (sentenceTexts[i] != null)
sentenceTexts[i].text = baseButtonTexts[i];
}
if (feedbackText != null)
feedbackText.text = "";
if (submitButton != null)
submitButton.interactable = true;
if (resetButton != null)
resetButton.interactable = true;
StartCoroutine(SentencesPopAnim());
}
void ShuffleSentenceOptions()
{
if (currentOptions.Count <= 1)
return;
int safety = 0;
do
{
Shuffle(currentOptions);
safety++;
}
while (IsOptionsInCorrectOrder() && safety < 20);
}
bool IsOptionsInCorrectOrder()
{
for (int i = 0; i < currentOptions.Count; i++)
{
if (currentOptions[i].correctOrder != i)
return false;
}
return true;
}
string GetSentence(ParagraphOrderEntry entry, int langIndex, int sentenceIndex)
{
int index = langIndex * 4 + sentenceIndex;
if (index < 0 || index >= entry.sentences.Length)
return "";
return entry.sentences[index];
}
void ResetButtonsForNewQuestion()
{
selectedCount = 0;
for (int i = 0; i < sentenceButtons.Length; i++)
{
selectedOrderByButton[i] = 0;
if (sentenceButtons[i] == null)
continue;
bool active = i < 4;
sentenceButtons[i].gameObject.SetActive(active);
sentenceButtons[i].interactable = active;
sentenceButtons[i].transform.localScale = originalButtonScales[i];
sentenceButtons[i].transform.localPosition = originalButtonPositions[i];
if (sentenceButtons[i].image != null)
sentenceButtons[i].image.color = FullAlpha(normalButtonColor);
}
}
void ResetCurrentSelection()
{
if (gameOver || waitingNextQuestion)
return;
selectedCount = 0;
for (int i = 0; i < 4; i++)
{
selectedOrderByButton[i] = 0;
if (sentenceButtons[i] != null)
{
sentenceButtons[i].interactable = true;
sentenceButtons[i].transform.localScale = originalButtonScales[i];
if (sentenceButtons[i].image != null)
sentenceButtons[i].image.color = FullAlpha(normalButtonColor);
}
if (sentenceTexts[i] != null)
sentenceTexts[i].text = baseButtonTexts[i];
}
if (feedbackText != null)
feedbackText.text = "";
}
void SelectSentence(int index)
{
if (gameOver || waitingNextQuestion)
return;
if (index < 0 || index >= 4)
return;
if (selectedOrderByButton[index] > 0)
{
RemoveSelection(index);
return;
}
if (selectedCount >= 4)
return;
selectedCount++;
selectedOrderByButton[index] = selectedCount;
ApplySelectedVisual(index);
}
void ForceSelectSentence(int index)
{
if (index < 0 || index >= 4)
return;
if (selectedOrderByButton[index] > 0)
return;
if (selectedCount >= 4)
return;
selectedCount++;
selectedOrderByButton[index] = selectedCount;
ApplySelectedVisual(index);
}
void RemoveSelection(int index)
{
int removedOrder = selectedOrderByButton[index];
if (removedOrder <= 0)
return;
selectedOrderByButton[index] = 0;
selectedCount--;
for (int i = 0; i < 4; i++)
{
if (selectedOrderByButton[i] > removedOrder)
selectedOrderByButton[i]--;
}
RefreshSelectionVisuals();
}
void RefreshSelectionVisuals()
{
for (int i = 0; i < 4; i++)
{
if (sentenceButtons[i] == null)
continue;
sentenceButtons[i].transform.localScale = originalButtonScales[i];
if (sentenceButtons[i].image != null)
sentenceButtons[i].image.color = FullAlpha(normalButtonColor);
if (sentenceTexts[i] != null)
sentenceTexts[i].text = baseButtonTexts[i];
if (selectedOrderByButton[i] > 0)
ApplySelectedVisual(i);
}
}
void ApplySelectedVisual(int index)
{
if (sentenceButtons[index] != null)
{
if (sentenceButtons[index].image != null)
sentenceButtons[index].image.color = FullAlpha(selectedButtonColor);
sentenceButtons[index].transform.localScale = originalButtonScales[index] * 0.94f;
}
if (sentenceTexts[index] != null)
sentenceTexts[index].text = selectedOrderByButton[index] + ". " + baseButtonTexts[index];
}
void OnSubmit()
{
if (gameOver || waitingNextQuestion)
return;
if (selectedCount < 4)
{
ShowFeedback(GetText("chooseAll"), wrongButtonColor);
return;
}
waitingNextQuestion = true;
if (submitButton != null)
submitButton.interactable = false;
if (resetButton != null)
resetButton.interactable = false;
for (int i = 0; i < 4; i++)
{
if (sentenceButtons[i] != null)
sentenceButtons[i].interactable = false;
}
if (IsCorrectOrder())
CorrectAnswer();
else
WrongAnswer();
UpdateScoreUI();
UpdateComboUI();
SaveProgressOnly();
StartCoroutine(NextQuestionDelay());
}
bool IsCorrectOrder()
{
for (int i = 0; i < 4; i++)
{
int correctOrderNumber = currentOptions[i].correctOrder + 1;
if (selectedOrderByButton[i] != correctOrderNumber)
return false;
}
return true;
}
void CorrectAnswer()
{
for (int i = 0; i < 4; i++)
{
if (sentenceButtons[i] != null && sentenceButtons[i].image != null)
sentenceButtons[i].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);
for (int i = 0; i < 4; i++)
StartCoroutine(ButtonPop(sentenceButtons[i]));
}
void WrongAnswer()
{
for (int i = 0; i < 4; i++)
{
int correctOrderNumber = currentOptions[i].correctOrder + 1;
bool thisButtonCorrect = selectedOrderByButton[i] == correctOrderNumber;
if (sentenceButtons[i] != null && sentenceButtons[i].image != null)
sentenceButtons[i].image.color = FullAlpha(thisButtonCorrect ? correctButtonColor : wrongButtonColor);
if (sentenceTexts[i] != null)
sentenceTexts[i].text = correctOrderNumber + ". " + baseButtonTexts[i];
}
wrongCount++;
combo = 0;
score -= wrongPenalty;
if (score < 0)
score = 0;
ShowFeedback(GetText("wrong"), 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;
for (int i = 0; i < 4; i++)
{
if (selectedOrderByButton[i] <= 0)
continue;
int correctOrderNumber = currentOptions[i].correctOrder + 1;
if (selectedOrderByButton[i] != correctOrderNumber)
{
ShowFeedback(GetText("hintReset"), wrongButtonColor);
return;
}
}
if (selectedCount < 4)
{
int neededCorrectOrder = selectedCount;
for (int i = 0; i < 4; i++)
{
if (currentOptions[i].correctOrder == neededCorrectOrder && selectedOrderByButton[i] == 0)
{
ForceSelectSentence(i);
ShowFeedback(GetText("hint"), Color.white);
break;
}
}
}
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("Mod27Skor", score);
PlayerPrefs.SetInt("Mod27Score", score);
PlayerPrefs.SetInt("Mod27Correct", correctCount);
PlayerPrefs.SetInt("Mod27Wrong", 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("Mod27LeaderScore", 0))
PlayerPrefs.SetInt("Mod27LeaderScore", score);
if (score > PlayerPrefs.GetInt("Mod27BestScore", 0))
PlayerPrefs.SetInt("Mod27BestScore", 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 = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.15f;
feedbackText.transform.localScale = Vector3.Lerp(normal, big, t);
yield return null;
}
t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.15f;
feedbackText.transform.localScale = Vector3.Lerp(big, normal, t);
yield return null;
}
feedbackText.transform.localScale = normal;
}
IEnumerator ButtonPop(Button button)
{
if (button == null)
yield break;
Vector3 normal = button.transform.localScale;
Vector3 big = normal * 1.12f;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.12f;
button.transform.localScale = Vector3.Lerp(normal, big, t);
yield return null;
}
t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.12f;
button.transform.localScale = Vector3.Lerp(big, normal, t);
yield return null;
}
button.transform.localScale = normal;
}
IEnumerator SentencesPopAnim()
{
for (int i = 0; i < 4; i++)
{
if (sentenceButtons[i] == null)
continue;
sentenceButtons[i].transform.localScale = originalButtonScales[i] * 0.92f;
}
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.18f;
for (int i = 0; i < 4; i++)
{
if (sentenceButtons[i] == null)
continue;
sentenceButtons[i].transform.localScale =
Vector3.Lerp(originalButtonScales[i] * 0.92f, originalButtonScales[i], t);
}
yield return null;
}
for (int i = 0; i < 4; i++)
{
if (sentenceButtons[i] != null)
sentenceButtons[i].transform.localScale = originalButtonScales[i];
}
}
Color FullAlpha(Color color)
{
color.a = 1f;
return color;
}
void Shuffle<T>(List<T> list)
{
for (int i = 0; i < list.Count; i++)
{
int randomIndex = Random.Range(i, list.Count);
T temp = list[i];
list[i] = list[randomIndex];
list[randomIndex] = temp;
}
}
}