- 新增Archive相关资源和预制体 - 新增SalesSystem销售系统基础 - 添加火山美术资源文件夹 Co-Authored-By: Claude Code <noreply@anthropic.com>
238 lines
8.9 KiB
C#
238 lines
8.9 KiB
C#
using UnityEngine;
|
||
using System.Collections.Generic;
|
||
|
||
namespace AibisDream.MiniGame.Language
|
||
{
|
||
/// <summary>
|
||
/// 分析模式关卡配置(ScriptableObject)
|
||
/// 用于存储每个分析谜题的数据
|
||
/// </summary>
|
||
[CreateAssetMenu(fileName = "AnalysisLevel", menuName = "AIBIS/Language/Analysis Level")]
|
||
public class AnalysisModeData : ScriptableObject
|
||
{
|
||
[Header("关卡基础信息")]
|
||
[Tooltip("关卡名称")]
|
||
public string levelName = "Level 1";
|
||
|
||
[Tooltip("关卡描述")]
|
||
[TextArea(2, 4)]
|
||
public string description = "找出隐藏在笑话中的真实情绪";
|
||
|
||
[Header("解码器配置")]
|
||
[Tooltip("解码器宽度(列数)")]
|
||
public int decoderWidth = 5;
|
||
|
||
[Tooltip("解码器高度(行数)")]
|
||
public int decoderHeight = 3;
|
||
|
||
[Tooltip("孔洞位置(相对于解码器左上角)")]
|
||
public List<Vector2Int> holePositions = new List<Vector2Int>
|
||
{
|
||
new Vector2Int(0, 0), // 第1行第1列
|
||
new Vector2Int(1, 1), // 第2行第2列
|
||
new Vector2Int(2, 4) // 第3行第5列
|
||
};
|
||
|
||
[Tooltip("解码器文字(按行从上到下、列从左到右的顺序)\n每个格子显示2字,孔洞位置自动跳过\n例如:要来了,不合格被骂了,这让我很\n需要字符数 = (宽×高 - 孔洞数) × 2")]
|
||
[TextArea(2, 5)]
|
||
public string decoderText = "要来了,不合格被骂了,这让我很";
|
||
|
||
[Header("答案配置")]
|
||
[Tooltip("答案所属情绪")]
|
||
public EmotionType answerEmotion = EmotionType.Fear;
|
||
|
||
[Tooltip("答案词语(按孔洞顺序)")]
|
||
public List<string> answerWords = new List<string> { "临检", "英里", "担心" };
|
||
|
||
[Tooltip("解码器在网格中的正确位置(行,列)")]
|
||
public Vector2Int correctDecoderPosition = new Vector2Int(3, 5);
|
||
|
||
[Tooltip("完整的答案句子(用于提示)")]
|
||
public string completeSentence = "[临检]要来了,不合格[英里]被骂了,这让我很[担心]";
|
||
|
||
[Header("词池配置")]
|
||
[Tooltip("每种情绪的词库(用于填充网格)")]
|
||
public EmotionWordPool wordPool = new EmotionWordPool();
|
||
|
||
[Header("笑话配置(可选)")]
|
||
[Tooltip("笑话短句(用于初始演出,如果为空则使用词池)")]
|
||
public List<string> jokePhrases = new List<string>();
|
||
|
||
[Header("难度配置")]
|
||
[Tooltip("诱饵数量:每种情绪的非答案词数量")]
|
||
[Range(5, 50)]
|
||
public int decoyCountPerEmotion = 15;
|
||
|
||
[Tooltip("频率容差:验证时允许的频率偏差")]
|
||
[Range(1f, 15f)]
|
||
public float frequencyTolerance = 8f;
|
||
|
||
[Header("完成回调")]
|
||
[Tooltip("成功完成时跳转的Yarn节点")]
|
||
public string successNodeName = "";
|
||
|
||
[Tooltip("失败时跳转的Yarn节点")]
|
||
public string failNodeName = "";
|
||
|
||
/// <summary>
|
||
/// 验证配置是否有效
|
||
/// </summary>
|
||
public bool Validate(out string errorMessage)
|
||
{
|
||
// 检查答案词数量与孔洞数量是否匹配
|
||
if (answerWords.Count != holePositions.Count)
|
||
{
|
||
errorMessage = $"答案词数量({answerWords.Count})与孔洞数量({holePositions.Count})不匹配";
|
||
return false;
|
||
}
|
||
|
||
// 检查答案词是否都是2字符
|
||
foreach (var word in answerWords)
|
||
{
|
||
if (string.IsNullOrEmpty(word) || word.Length != 2)
|
||
{
|
||
errorMessage = $"答案词'{word}'必须是2个字符";
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 检查孔洞位置是否在解码器范围内
|
||
foreach (var hole in holePositions)
|
||
{
|
||
if (hole.x < 0 || hole.x >= decoderHeight || hole.y < 0 || hole.y >= decoderWidth)
|
||
{
|
||
errorMessage = $"孔洞位置({hole.x}, {hole.y})超出解码器范围({decoderHeight}x{decoderWidth})";
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 检查词池是否有足够的词
|
||
if (!wordPool.HasEnoughWords(answerEmotion, decoyCountPerEmotion + answerWords.Count))
|
||
{
|
||
errorMessage = $"情绪{answerEmotion}的词池不足,需要至少{decoyCountPerEmotion + answerWords.Count}个词";
|
||
return false;
|
||
}
|
||
|
||
errorMessage = "";
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取网格尺寸建议(根据词数量自动计算)
|
||
/// </summary>
|
||
public Vector2Int GetRecommendedGridSize()
|
||
{
|
||
// 计算总词数:答案词 + 诱饵词(所有情绪)
|
||
int totalWords = answerWords.Count + decoyCountPerEmotion * 4; // 4种情绪
|
||
|
||
// 添加一些中性词作为填充
|
||
int neutralWords = totalWords / 2;
|
||
totalWords += neutralWords;
|
||
|
||
// 推荐网格尺寸(接近正方形)
|
||
int size = Mathf.CeilToInt(Mathf.Sqrt(totalWords));
|
||
return new Vector2Int(size, size);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 情绪词池
|
||
/// </summary>
|
||
[System.Serializable]
|
||
public class EmotionWordPool
|
||
{
|
||
[Header("快乐词语")]
|
||
[Tooltip("Joy情绪的词语库(2字词)")]
|
||
public List<string> joyWords = new List<string>
|
||
{
|
||
"开心", "快乐", "高兴", "喜悦", "欢笑", "愉快", "兴奋", "幸福",
|
||
"满足", "得意", "舒畅", "轻松", "欣慰", "庆幸", "欢喜", "喜庆"
|
||
};
|
||
|
||
[Header("悲伤词语")]
|
||
[Tooltip("Sadness情绪的词语库(2字词)")]
|
||
public List<string> sadnessWords = new List<string>
|
||
{
|
||
"悲伤", "难过", "伤心", "痛苦", "失望", "沮丧", "忧伤", "哀愁",
|
||
"失落", "绝望", "悲痛", "心碎", "凄凉", "孤独", "寂寞", "落寞"
|
||
};
|
||
|
||
[Header("愤怒词语")]
|
||
[Tooltip("Anger情绪的词语库(2字词)")]
|
||
public List<string> angerWords = new List<string>
|
||
{
|
||
"愤怒", "生气", "恼怒", "暴怒", "气愤", "愤恨", "恨意", "怒火",
|
||
"恼火", "火大", "抓狂", "烦躁", "憋屈", "不爽", "愤慨", "恼恨"
|
||
};
|
||
|
||
[Header("恐惧词语")]
|
||
[Tooltip("Fear情绪的词语库(2字词)")]
|
||
public List<string> fearWords = new List<string>
|
||
{
|
||
"恐惧", "害怕", "惊恐", "畏惧", "担心", "忧虑", "焦虑", "紧张",
|
||
"不安", "慌张", "惊慌", "胆怯", "恐慌", "惊吓", "惧怕", "临检",
|
||
"英里", "担忧", "忐忑", "惶恐"
|
||
};
|
||
|
||
[Header("中性词语")]
|
||
[Tooltip("Neutral情绪的词语库(用于填充,2字词)")]
|
||
public List<string> neutralWords = new List<string>
|
||
{
|
||
"工作", "学习", "生活", "时间", "地方", "事情", "人们", "世界",
|
||
"问题", "方法", "结果", "过程", "开始", "结束", "继续", "停止",
|
||
"前进", "后退", "上下", "左右", "这里", "那里", "现在", "以后"
|
||
};
|
||
|
||
/// <summary>
|
||
/// 获取指定情绪的词语列表
|
||
/// </summary>
|
||
public List<string> GetWords(EmotionType emotion)
|
||
{
|
||
switch (emotion)
|
||
{
|
||
case EmotionType.Joy: return joyWords;
|
||
case EmotionType.Sadness: return sadnessWords;
|
||
case EmotionType.Anger: return angerWords;
|
||
case EmotionType.Fear: return fearWords;
|
||
case EmotionType.Neutral: return neutralWords;
|
||
default: return neutralWords;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否有足够的词
|
||
/// </summary>
|
||
public bool HasEnoughWords(EmotionType emotion, int requiredCount)
|
||
{
|
||
return GetWords(emotion).Count >= requiredCount;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取随机词(不重复)
|
||
/// </summary>
|
||
public List<string> GetRandomWords(EmotionType emotion, int count, List<string> exclude = null)
|
||
{
|
||
List<string> pool = new List<string>(GetWords(emotion));
|
||
|
||
// 排除指定词语
|
||
if (exclude != null)
|
||
{
|
||
pool.RemoveAll(w => exclude.Contains(w));
|
||
}
|
||
|
||
// 随机打乱
|
||
for (int i = 0; i < pool.Count; i++)
|
||
{
|
||
int randomIndex = Random.Range(i, pool.Count);
|
||
string temp = pool[i];
|
||
pool[i] = pool[randomIndex];
|
||
pool[randomIndex] = temp;
|
||
}
|
||
|
||
// 返回指定数量
|
||
return pool.GetRange(0, Mathf.Min(count, pool.Count));
|
||
}
|
||
}
|
||
}
|
||
|