Feedback
This commit is contained in:
parent
fde0d8f908
commit
33aeb3b742
@ -246,3 +246,33 @@ MonoBehaviour:
|
|||||||
\u0627\u0644\u0648\u0627\u0636\u062D\u0629 \u064A\u0645\u0643\u0646 \u0623\u0646
|
\u0627\u0644\u0648\u0627\u0636\u062D\u0629 \u064A\u0645\u0643\u0646 \u0623\u0646
|
||||||
\u062A\u0643\u0648\u0646 \u0639\u0644\u0627\u0645\u0629 \u0639\u0644\u0649
|
\u062A\u0643\u0648\u0646 \u0639\u0644\u0627\u0645\u0629 \u0639\u0644\u0649
|
||||||
\u0645\u062D\u0627\u0648\u0644\u0629 \u062A\u0635\u064A\u062F \u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A.\r\n"
|
\u0645\u062D\u0627\u0648\u0644\u0629 \u062A\u0635\u064A\u062F \u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A.\r\n"
|
||||||
|
- key: mission_intro
|
||||||
|
english: 'Your mission: Analyze incoming emails for phishing threats'
|
||||||
|
arabic: "\u0645\u0647\u0645\u062A\u0643: \u062A\u062D\u0644\u064A\u0644 \u0631\u0633\u0627\u0626\u0644
|
||||||
|
\u0627\u0644\u0628\u0631\u064A\u062F \u0627\u0644\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A
|
||||||
|
\u0627\u0644\u0648\u0627\u0631\u062F\u0629 \u0628\u062D\u062B\u064B\u0627 \u0639\u0646
|
||||||
|
\u0645\u062D\u0627\u0648\u0644\u0627\u062A \u062A\u0635\u064A\u062F"
|
||||||
|
- key: click_to_open
|
||||||
|
english: Click to open your inbox
|
||||||
|
arabic: "\u0627\u0636\u063A\u0637 \u0644\u0641\u062A\u062D \u0628\u0631\u064A\u062F\u0643"
|
||||||
|
- key: click_and_hold
|
||||||
|
english: Click and hold to scan the email
|
||||||
|
arabic: "\u0627\u0646\u0642\u0631 \u0645\u0639 \u0627\u0644\u0627\u0633\u062A\u0645\u0631\u0627\u0631
|
||||||
|
\u0644\u0645\u0633\u062D \u0627\u0644\u0628\u0631\u064A\u062F \u0627\u0644\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A"
|
||||||
|
- key: review_email_content
|
||||||
|
english: Review the email content carefully
|
||||||
|
arabic: "\u0631\u0627\u062C\u0639 \u0645\u062D\u062A\u0648\u0649 \u0627\u0644\u0628\u0631\u064A\u062F
|
||||||
|
\u0628\u0639\u0646\u0627\u064A\u0629"
|
||||||
|
- key: correct_choice
|
||||||
|
english: Correct choice!
|
||||||
|
arabic: " \u0627\u062E\u062A\u064A\u0627\u0631 \u0635\u062D\u064A\u062D!"
|
||||||
|
- key: start
|
||||||
|
english: START
|
||||||
|
arabic: "\u0627\u0628\u062F\u0623"
|
||||||
|
- key: phishingawareness
|
||||||
|
english: PHISHING AWARENESS SIMULATION
|
||||||
|
arabic: "\u0645\u062D\u0627\u0643\u0627\u0629 \u0627\u0644\u062A\u0648\u0639\u064A\u0629
|
||||||
|
\u0628\u0627\u0644\u062A\u0635\u064A\u062F \u0627\u0644\u0627\u062D\u062A\u064A\u0627\u0644\u064A"
|
||||||
|
- key: poweredby
|
||||||
|
english: Powered by CyberCompanion
|
||||||
|
arabic: "\u0628\u062F\u0639\u0645 \u0645\u0646 CyberCompanion"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -54,6 +54,7 @@ public class CharacterMovement : MonoBehaviour
|
|||||||
{
|
{
|
||||||
animator.SetTrigger("StartWalking");
|
animator.SetTrigger("StartWalking");
|
||||||
isStarted = true;
|
isStarted = true;
|
||||||
|
InstructionManager.Instance?.ShowScreenInstruction("mission_intro");
|
||||||
}
|
}
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
@ -163,6 +164,7 @@ public class CharacterMovement : MonoBehaviour
|
|||||||
.OnComplete(() =>
|
.OnComplete(() =>
|
||||||
{
|
{
|
||||||
state = MovementState.Finished;
|
state = MovementState.Finished;
|
||||||
|
InstructionManager.Instance?.ShowScreenInstruction("click_to_open");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
public class CursorManager : MonoBehaviour
|
public class CursorManager : MonoBehaviour
|
||||||
{
|
{
|
||||||
@ -10,12 +13,33 @@ public class CursorManager : MonoBehaviour
|
|||||||
|
|
||||||
[Header("Cursor Hotspot")]
|
[Header("Cursor Hotspot")]
|
||||||
public Vector2 hotspot = Vector2.zero;
|
public Vector2 hotspot = Vector2.zero;
|
||||||
|
public GraphicRaycaster raycaster;
|
||||||
|
public EventSystem eventSystem;
|
||||||
|
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
SetDefaultCursor();
|
SetDefaultCursor();
|
||||||
}
|
}
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (Input.GetMouseButtonDown(0))
|
||||||
|
{
|
||||||
|
PointerEventData pointerData = new PointerEventData(eventSystem)
|
||||||
|
{
|
||||||
|
position = Input.mousePosition
|
||||||
|
};
|
||||||
|
|
||||||
|
List<RaycastResult> results = new List<RaycastResult>();
|
||||||
|
raycaster.Raycast(pointerData, results);
|
||||||
|
|
||||||
|
foreach (RaycastResult result in results)
|
||||||
|
{
|
||||||
|
Debug.Log("Clicked UI: " + result.gameObject.name,result.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SetDefaultCursor()
|
public void SetDefaultCursor()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -50,6 +50,16 @@ public class EmailOpenPanel : MonoBehaviour
|
|||||||
string summary = $"{action.ToUpper()} clicked on email from '{emailData.senderName}' with subject '{emailData.subject}'";
|
string summary = $"{action.ToUpper()} clicked on email from '{emailData.senderName}' with subject '{emailData.subject}'";
|
||||||
UserActionLogger.Instance?.Log(summary);
|
UserActionLogger.Instance?.Log(summary);
|
||||||
|
|
||||||
|
bool isCorrect =
|
||||||
|
(action == "report" && emailData.isPhishing) ||
|
||||||
|
(action == "ignore" && !emailData.isPhishing);
|
||||||
|
|
||||||
|
if (isCorrect)
|
||||||
|
{
|
||||||
|
// ✅ Correct choice → Show instruction
|
||||||
|
InstructionManager.Instance?.ShowScreenInstruction("correct_choice", 3f);
|
||||||
|
}
|
||||||
|
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case "report":
|
case "report":
|
||||||
|
|||||||
106
Assets/Scripts/InstructionManager.cs
Normal file
106
Assets/Scripts/InstructionManager.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using DG.Tweening;
|
||||||
|
|
||||||
|
public class InstructionManager : MonoBehaviour
|
||||||
|
{
|
||||||
|
public static InstructionManager Instance;
|
||||||
|
|
||||||
|
[Header("Screen Instruction (HUD)")]
|
||||||
|
public GameObject instructionBG; // The background image object
|
||||||
|
public TextMeshProUGUI instructionText; // The TMP text inside the background
|
||||||
|
|
||||||
|
[Header("Speech Bubble UI")]
|
||||||
|
public GameObject speechBubbleObj; // The bubble GameObject (inside its own canvas)
|
||||||
|
public TextMeshProUGUI speechText; // The TMP text inside the speech bubble
|
||||||
|
public Vector3 offset = new Vector3(0, 2f, 0); // Offset from followTarget
|
||||||
|
|
||||||
|
private Transform followTarget; // Target the speech bubble follows
|
||||||
|
private Camera mainCam;
|
||||||
|
|
||||||
|
[Header("Optional Settings")]
|
||||||
|
public float fadeDuration = 0.5f; // Not used unless you want to add tween effects later
|
||||||
|
|
||||||
|
void Awake()
|
||||||
|
{
|
||||||
|
if (Instance != null && Instance != this)
|
||||||
|
{
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance = this;
|
||||||
|
mainCam = Camera.main;
|
||||||
|
|
||||||
|
if (instructionBG != null)
|
||||||
|
instructionBG.SetActive(false);
|
||||||
|
|
||||||
|
if (speechBubbleObj != null)
|
||||||
|
speechBubbleObj.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LateUpdate()
|
||||||
|
{
|
||||||
|
// Reposition speech bubble to follow world target
|
||||||
|
if (speechBubbleObj != null && followTarget != null)
|
||||||
|
{
|
||||||
|
Vector3 screenPos = mainCam.WorldToScreenPoint(followTarget.position + offset);
|
||||||
|
speechBubbleObj.transform.position = screenPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show screen HUD instruction with localization key
|
||||||
|
public void ShowScreenInstruction(string key, float autoHideDelay = -1f)
|
||||||
|
{
|
||||||
|
if (LanguageManager.Instance == null || instructionText == null || instructionBG == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string localized = LanguageManager.Instance.GetLocalizedText(key);
|
||||||
|
bool isArabic = LanguageManager.Instance.currentLanguage == "Arabic";
|
||||||
|
|
||||||
|
instructionText.text = isArabic
|
||||||
|
? ArabicFixerHelper.FixPreservingTags(localized)
|
||||||
|
: localized;
|
||||||
|
|
||||||
|
instructionText.font = LanguageManager.Instance.GetCurrentFont();
|
||||||
|
|
||||||
|
instructionBG.SetActive(true);
|
||||||
|
|
||||||
|
if (autoHideDelay > 0)
|
||||||
|
Invoke(nameof(HideScreenInstruction), autoHideDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HideScreenInstruction()
|
||||||
|
{
|
||||||
|
if (instructionBG != null)
|
||||||
|
instructionBG.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show speech bubble above a world target (e.g., teacher's head)
|
||||||
|
public void ShowSpeechBubble(string key, Transform target, float autoHideDelay = -1f)
|
||||||
|
{
|
||||||
|
if (LanguageManager.Instance == null || speechText == null || speechBubbleObj == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string localized = LanguageManager.Instance.GetLocalizedText(key);
|
||||||
|
bool isArabic = LanguageManager.Instance.currentLanguage == "Arabic";
|
||||||
|
|
||||||
|
speechText.text = isArabic
|
||||||
|
? ArabicFixerHelper.FixPreservingTags(localized)
|
||||||
|
: localized;
|
||||||
|
|
||||||
|
speechText.font = LanguageManager.Instance.GetCurrentFont();
|
||||||
|
|
||||||
|
followTarget = target;
|
||||||
|
speechBubbleObj.SetActive(true);
|
||||||
|
|
||||||
|
if (autoHideDelay > 0)
|
||||||
|
Invoke(nameof(HideSpeechBubble), autoHideDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HideSpeechBubble()
|
||||||
|
{
|
||||||
|
speechBubbleObj.SetActive(false);
|
||||||
|
followTarget = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Assets/Scripts/InstructionManager.cs.meta
Normal file
11
Assets/Scripts/InstructionManager.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 354e60420595cea4e80f051df74d201a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -1,5 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
public class SceneOutcomeManager : MonoBehaviour
|
public class SceneOutcomeManager : MonoBehaviour
|
||||||
{
|
{
|
||||||
@ -67,7 +68,10 @@ public class SceneOutcomeManager : MonoBehaviour
|
|||||||
Debug.Log("Ignored a safe email. No feedback triggered.");
|
Debug.Log("Ignored a safe email. No feedback triggered.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void Restarter()
|
||||||
|
{
|
||||||
|
SceneManager.LoadScene(0);
|
||||||
|
}
|
||||||
private IEnumerator MoveCameraToDebrief()
|
private IEnumerator MoveCameraToDebrief()
|
||||||
{
|
{
|
||||||
DebriefObj.SetActive(true);
|
DebriefObj.SetActive(true);
|
||||||
|
|||||||
5063
Assets/TextMesh Pro/Fonts/NotoNaskhArabic-Regular SDF.asset
Normal file
5063
Assets/TextMesh Pro/Fonts/NotoNaskhArabic-Regular SDF.asset
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 59bbd8cc5c5f37e4c8d25cd9eb892134
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Assets/TextMesh Pro/Fonts/NotoNaskhArabic-Regular.ttf
Normal file
BIN
Assets/TextMesh Pro/Fonts/NotoNaskhArabic-Regular.ttf
Normal file
Binary file not shown.
21
Assets/TextMesh Pro/Fonts/NotoNaskhArabic-Regular.ttf.meta
Normal file
21
Assets/TextMesh Pro/Fonts/NotoNaskhArabic-Regular.ttf.meta
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: cfb623675ebe37b4abbb6fbcbf32166a
|
||||||
|
TrueTypeFontImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 4
|
||||||
|
fontSize: 16
|
||||||
|
forceTextureCase: -2
|
||||||
|
characterSpacing: 0
|
||||||
|
characterPadding: 1
|
||||||
|
includeFontData: 1
|
||||||
|
fontNames:
|
||||||
|
- Noto Naskh Arabic
|
||||||
|
fallbackFontReferences: []
|
||||||
|
customCharacters:
|
||||||
|
fontRenderingMode: 0
|
||||||
|
ascentCalculationMode: 1
|
||||||
|
useLegacyBoundsCalculation: 0
|
||||||
|
shouldRoundAdvanceValue: 1
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 730 B After Width: | Height: | Size: 977 B |
Binary file not shown.
|
Before Width: | Height: | Size: 772 B After Width: | Height: | Size: 1.0 KiB |
Loading…
x
Reference in New Issue
Block a user