QuestionAnswerManager.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. import { _decorator, Component, Node, Button, Label } from 'cc';
  2. import { DialogueManager } from './DialogueManager';
  3. import { PassCardManager } from './PassCardManager';
  4. import { GameFlowManager } from './GameFlowManager';
  5. const { ccclass, property } = _decorator;
  6. /**
  7. * 问答对接口,添加表情支持
  8. */
  9. interface QuestionAnswer {
  10. question: string; // 问题文本
  11. answers: string[]; // 回答文本数组
  12. showPassCard?: boolean; // 是否显示通行证
  13. }
  14. // 将固定问题的索引定义为常量
  15. const ASK_PASS_QUESTION_INDEX = 1; // 询问通行证的问题固定为第二个问题
  16. @ccclass('QuestionAnswerManager')
  17. export class QuestionAnswerManager extends Component {
  18. @property({
  19. type: DialogueManager,
  20. tooltip: '对话管理器引用'
  21. })
  22. dialogueManager: DialogueManager = null;
  23. @property({
  24. type: [Button],
  25. tooltip: '问题按钮数组',
  26. readonly: true
  27. })
  28. questionButtons: Button[] = [];
  29. @property({
  30. type: [Node],
  31. tooltip: '问题文本节点数组(Label组件所在的节点)',
  32. readonly: true
  33. })
  34. questionLabels: Node[] = [];
  35. @property({
  36. type: PassCardManager,
  37. tooltip: '通行证管理器引用 (已弃用,请使用GameFlowManager中的通行证管理器)'
  38. })
  39. passCardManager: PassCardManager = null;
  40. @property({
  41. type: Node,
  42. tooltip: '游戏流程管理器所在的节点'
  43. })
  44. gameFlowManagerNode: Node = null;
  45. // 游戏流程管理器引用
  46. private gameFlowManager: GameFlowManager = null;
  47. // 问答对数组
  48. private questionAnswerPairs: QuestionAnswer[] = [];
  49. // 当前显示的问题索引
  50. private currentQuestionIndices: number[] = [0, 1, 2];
  51. start() {
  52. // 初始化默认问答对
  53. // this.initDefaultQuestionAnswers();
  54. // 注册按钮事件
  55. this.registerButtons();
  56. // 更新问题按钮文本
  57. this.updateQuestionButtonTexts();
  58. // 从节点获取GameFlowManager组件
  59. if (this.gameFlowManagerNode) {
  60. this.gameFlowManager = this.gameFlowManagerNode.getComponent(GameFlowManager);
  61. if (!this.gameFlowManager) {
  62. console.error('游戏流程管理器节点上没有GameFlowManager组件');
  63. } else {
  64. console.log('成功获取GameFlowManager组件');
  65. }
  66. } else {
  67. console.error('游戏流程管理器节点未设置');
  68. // 尝试在场景中查找
  69. this.gameFlowManager = this.node.scene.getComponentInChildren(GameFlowManager);
  70. if (this.gameFlowManager) {
  71. console.log('在场景中找到GameFlowManager组件');
  72. } else {
  73. console.error('无法在场景中找到GameFlowManager组件');
  74. }
  75. }
  76. }
  77. /**
  78. * 初始化默认问答对
  79. */
  80. private initDefaultQuestionAnswers(): void {
  81. // 添加一些默认的问答对
  82. this.questionAnswerPairs = [
  83. {
  84. question: "询问为何不在名单内?",
  85. answers: ["我没见过你的资料。你确定你应该在这个区域吗?"]
  86. },
  87. {
  88. question: "询问通行证?",
  89. answers: ["这是我的通行证,请过目。"],
  90. showPassCard: true // 这个问题会显示通行证
  91. },
  92. {
  93. question: "询问外貌?",
  94. answers: ["我对你的外貌没有任何评价。我只负责确认身份。"]
  95. },
  96. {
  97. question: "你是谁?",
  98. answers: ["我是这个区域的安全管理员,负责身份验证和访问控制。"]
  99. },
  100. {
  101. question: "这是什么地方?",
  102. answers: ["这是一个受限制的区域,需要特殊许可才能进入。"]
  103. },
  104. {
  105. question: "我可以离开吗?",
  106. answers: ["如果你没有通行证,建议你尽快离开,否则可能会有麻烦。"]
  107. }
  108. ];
  109. }
  110. /**
  111. * 注册按钮事件
  112. */
  113. private registerButtons(): void {
  114. for (let i = 0; i < this.questionButtons.length; i++) {
  115. const button = this.questionButtons[i];
  116. const index = i; // 保存当前索引
  117. if (button) {
  118. // 注册点击事件
  119. button.node.on(Button.EventType.CLICK, () => {
  120. this.onQuestionButtonClicked(index);
  121. }, this);
  122. }
  123. }
  124. }
  125. /**
  126. * 更新问题按钮文本
  127. */
  128. private updateQuestionButtonTexts(): void {
  129. console.log('updateQuestionButtonTexts');
  130. // 为每个按钮设置对应的问题文本
  131. for (let i = 0; i < Math.min(this.questionLabels.length, this.currentQuestionIndices.length); i++) {
  132. const questionIndex = this.currentQuestionIndices[i];
  133. const labelNode = this.questionLabels[i];
  134. if (labelNode && questionIndex >= 0 && questionIndex < this.questionAnswerPairs.length) {
  135. // 获取Label组件并设置文本
  136. const label = labelNode.getComponent(Label);
  137. if (label) {
  138. label.string = this.questionAnswerPairs[questionIndex].question;
  139. }
  140. }
  141. }
  142. }
  143. /**
  144. * 问题按钮点击回调
  145. * @param buttonIndex 按钮索引
  146. */
  147. private onQuestionButtonClicked(buttonIndex: number): void {
  148. console.log(`问题按钮点击: index=${buttonIndex}`);
  149. if (buttonIndex < 0 || buttonIndex >= this.currentQuestionIndices.length) {
  150. console.error(`无效的按钮索引: ${buttonIndex}`);
  151. return;
  152. }
  153. const questionIndex = this.currentQuestionIndices[buttonIndex];
  154. console.log(`对应问题索引: ${questionIndex}`);
  155. if (questionIndex < 0 || questionIndex >= this.questionAnswerPairs.length) {
  156. console.error(`无效的问题索引: ${questionIndex}`);
  157. return;
  158. }
  159. // 获取问答对
  160. const qa = this.questionAnswerPairs[questionIndex];
  161. // 从回答数组中随机选择一个回答
  162. let selectedAnswer = "";
  163. if (qa.answers && qa.answers.length > 0) {
  164. const randomIndex = Math.floor(Math.random() * qa.answers.length);
  165. selectedAnswer = qa.answers[randomIndex];
  166. } else {
  167. selectedAnswer = "无法回答这个问题。";
  168. }
  169. console.log(`问题: "${qa.question}", 选择的回答: "${selectedAnswer}", 显示通行证: ${qa.showPassCard}`);
  170. // 检查是否需要显示通行证
  171. if (qa.showPassCard) {
  172. console.log('准备显示通行证');
  173. // 通过GameFlowManager获取通行证管理器
  174. if (this.gameFlowManager && this.gameFlowManager.passCardManager) {
  175. // 使用GameFlowManager提供的PassCardManager
  176. const passCardManager = this.gameFlowManager.passCardManager;
  177. // 获取当前NPC数据
  178. if (this.gameFlowManager.getCurrentNpcData) {
  179. const npcData = this.gameFlowManager.getCurrentNpcData();
  180. if (npcData && npcData.pass) {
  181. console.log('显示通行证:', npcData.pass);
  182. passCardManager.showPassCard(npcData.pass);
  183. } else {
  184. console.error('当前NPC没有通行证数据');
  185. }
  186. } else {
  187. console.error('GameFlowManager没有getCurrentNpcData方法');
  188. }
  189. } else if (this.passCardManager) {
  190. // 兼容:如果直接设置了passCardManager属性,则使用它
  191. // 获取当前NPC数据
  192. if (this.gameFlowManager && this.gameFlowManager.getCurrentNpcData) {
  193. const npcData = this.gameFlowManager.getCurrentNpcData();
  194. if (npcData && npcData.pass) {
  195. console.log('显示通行证:', npcData.pass);
  196. this.passCardManager.showPassCard(npcData.pass);
  197. } else {
  198. console.error('当前NPC没有通行证数据');
  199. }
  200. } else {
  201. console.error('无法获取NPC通行证数据');
  202. }
  203. } else {
  204. console.error('无法获取通行证管理器');
  205. }
  206. }
  207. // 显示对话
  208. if (this.dialogueManager) {
  209. this.dialogueManager.showDialogue(selectedAnswer);
  210. } else {
  211. console.error('对话管理器未设置,无法显示回答');
  212. }
  213. }
  214. /**
  215. * 添加新的问答对
  216. * @param questionAnswers 要添加的问答对数组
  217. */
  218. public addQuestionAnswers(questionAnswers: QuestionAnswer[]): void {
  219. if (!questionAnswers || questionAnswers.length === 0) {
  220. return;
  221. }
  222. // 添加新的问答对
  223. this.questionAnswerPairs = [...this.questionAnswerPairs, ...questionAnswers];
  224. // 更新按钮文本(如果需要)
  225. this.updateQuestionButtonTexts();
  226. }
  227. /**
  228. * 设置问题按钮显示的问题索引
  229. * @param indices 问题索引数组,长度应与按钮数量相同
  230. */
  231. public setQuestionIndices(indices: number[]): void {
  232. // 验证索引有效性
  233. const validIndices = indices.filter(index =>
  234. index >= 0 && index < this.questionAnswerPairs.length
  235. );
  236. // 更新当前显示的问题索引
  237. this.currentQuestionIndices = validIndices.slice(0, this.questionButtons.length);
  238. // 如果索引数量少于按钮数量,使用默认索引填充
  239. while (this.currentQuestionIndices.length < this.questionButtons.length) {
  240. const defaultIndex = this.currentQuestionIndices.length % this.questionAnswerPairs.length;
  241. this.currentQuestionIndices.push(defaultIndex);
  242. }
  243. // 更新按钮文本
  244. this.updateQuestionButtonTexts();
  245. }
  246. /**
  247. * 获取当前所有问答对
  248. * @returns 所有问答对数组
  249. */
  250. public getAllQuestionAnswers(): QuestionAnswer[] {
  251. return [...this.questionAnswerPairs];
  252. }
  253. /**
  254. * 清除所有问答对并重置为默认值
  255. */
  256. public resetToDefault(): void {
  257. this.initDefaultQuestionAnswers();
  258. this.currentQuestionIndices = [0, 1, 2];
  259. this.updateQuestionButtonTexts();
  260. }
  261. /**
  262. * 更新特定索引的问答对
  263. * @param index 要更新的问答对索引
  264. * @param newQA 新的问答对
  265. */
  266. public updateQuestionAnswer(index: number, newQA: QuestionAnswer): void {
  267. if (index >= 0 && index < this.questionAnswerPairs.length && newQA) {
  268. this.questionAnswerPairs[index] = newQA;
  269. this.updateQuestionButtonTexts();
  270. }
  271. }
  272. /**
  273. * 替换所有问答对
  274. * @param newQAPairs 新的问答对数组
  275. */
  276. public replaceAllQuestionAnswers(newQAPairs: QuestionAnswer[]): void {
  277. console.log('替换问答对:', newQAPairs);
  278. // 清空现有问答对
  279. this.questionAnswerPairs = [];
  280. // 添加固定的"询问通行证"问题
  281. const passCardQuestion = {
  282. question: "询问通行证?",
  283. answers: ["这是我的通行证,请过目。"],
  284. showPassCard: true
  285. };
  286. console.log('添加通行证问题:', passCardQuestion);
  287. // 添加新的问答对
  288. for (let i = 0; i < newQAPairs.length; i++) {
  289. if (i === ASK_PASS_QUESTION_INDEX) {
  290. // 在第二个位置插入通行证问题
  291. this.questionAnswerPairs.push(passCardQuestion);
  292. console.log(`在位置${i}添加通行证问题`);
  293. } else {
  294. this.questionAnswerPairs.push(newQAPairs[i]);
  295. console.log(`在位置${i}添加问题:`, newQAPairs[i]);
  296. }
  297. // 确保不超过三个问题
  298. if (this.questionAnswerPairs.length >= 3) break;
  299. }
  300. // 如果问题不足三个,补充通行证问题
  301. if (this.questionAnswerPairs.length < 3) {
  302. // 如果还没有添加通行证问题,则添加
  303. const hasPassQuestion = this.questionAnswerPairs.some(qa => qa.showPassCard);
  304. if (!hasPassQuestion) {
  305. this.questionAnswerPairs.push(passCardQuestion);
  306. console.log('添加缺失的通行证问题');
  307. }
  308. // 依然不足三个,可以使用默认问题补充
  309. while (this.questionAnswerPairs.length < 3) {
  310. const backupQuestion = {
  311. question: `备用问题${this.questionAnswerPairs.length + 1}`,
  312. answers: ["这是一个标准回答。"]
  313. };
  314. this.questionAnswerPairs.push(backupQuestion);
  315. console.log('添加备用问题:', backupQuestion);
  316. }
  317. }
  318. // 确保第二个问题是通行证问题
  319. if (this.questionAnswerPairs.length >= 2 && !this.questionAnswerPairs[1].showPassCard) {
  320. console.log('强制第二个问题为通行证问题');
  321. this.questionAnswerPairs[1] = passCardQuestion;
  322. }
  323. console.log('最终问答对:', this.questionAnswerPairs);
  324. // 重置当前显示的问题索引
  325. this.currentQuestionIndices = [0, 1, 2];
  326. // 更新问题按钮文本
  327. this.updateQuestionButtonTexts();
  328. }
  329. }