QuestionAnswerManager.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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. answer: 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: '通行证管理器引用'
  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. answer: "我没见过你的资料。你确定你应该在这个区域吗?"
  86. },
  87. {
  88. question: "询问通行证?",
  89. answer: "这是我的通行证,请过目。",
  90. showPassCard: true // 这个问题会显示通行证
  91. },
  92. {
  93. question: "询问外貌?",
  94. answer: "我对你的外貌没有任何评价。我只负责确认身份。"
  95. },
  96. {
  97. question: "你是谁?",
  98. answer: "我是这个区域的安全管理员,负责身份验证和访问控制。"
  99. },
  100. {
  101. question: "这是什么地方?",
  102. answer: "这是一个受限制的区域,需要特殊许可才能进入。"
  103. },
  104. {
  105. question: "我可以离开吗?",
  106. answer: "如果你没有通行证,建议你尽快离开,否则可能会有麻烦。"
  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. console.log(`问题: "${qa.question}", 答案: "${qa.answer}", 显示通行证: ${qa.showPassCard}`);
  162. // 检查是否需要显示通行证
  163. if (qa.showPassCard && this.passCardManager) {
  164. console.log('准备显示通行证');
  165. // 获取当前NPC数据
  166. const npcData = this.gameFlowManager ? this.gameFlowManager.getCurrentNpcData() : null;
  167. console.log('当前NPC数据:', npcData);
  168. if (npcData) {
  169. // 显示通行证,使用NPC数据
  170. try {
  171. this.passCardManager.showPassCard({
  172. name: npcData.characterName || '未知',
  173. room: `${Math.floor(Math.random() * 900) + 100}`, // 随机房间号,可以替换为实际数据
  174. id: `ID-${npcData.characterId}-${Math.floor(Math.random() * 1000)}`, // 随机ID,可以替换为实际数据
  175. reason: npcData.type === 'real' ? '合法居民' : '访客',
  176. characterId: npcData.characterId
  177. });
  178. console.log('通行证显示成功');
  179. } catch (error) {
  180. console.error('显示通行证时出错:', error);
  181. }
  182. } else {
  183. console.error('无法获取NPC数据');
  184. // 尝试使用默认数据显示通行证
  185. if (this.passCardManager) {
  186. try {
  187. this.passCardManager.showPassCard({
  188. name: '测试角色',
  189. room: '101',
  190. id: 'ID-TEST-001',
  191. reason: '测试',
  192. characterId: 1
  193. });
  194. console.log('使用默认数据显示通行证');
  195. } catch (error) {
  196. console.error('使用默认数据显示通行证时出错:', error);
  197. }
  198. }
  199. }
  200. } else {
  201. console.log(`不显示通行证,原因: showPassCard=${qa.showPassCard}, passCardManager=${!!this.passCardManager}`);
  202. }
  203. // 使用对话管理器显示回答,包含表情
  204. if (this.dialogueManager && qa) {
  205. this.dialogueManager.showDialogue(qa.answer);
  206. }
  207. }
  208. /**
  209. * 添加新的问答对
  210. * @param questionAnswers 要添加的问答对数组
  211. */
  212. public addQuestionAnswers(questionAnswers: QuestionAnswer[]): void {
  213. if (!questionAnswers || questionAnswers.length === 0) {
  214. return;
  215. }
  216. // 添加新的问答对
  217. this.questionAnswerPairs = [...this.questionAnswerPairs, ...questionAnswers];
  218. // 更新按钮文本(如果需要)
  219. this.updateQuestionButtonTexts();
  220. }
  221. /**
  222. * 设置问题按钮显示的问题索引
  223. * @param indices 问题索引数组,长度应与按钮数量相同
  224. */
  225. public setQuestionIndices(indices: number[]): void {
  226. // 验证索引有效性
  227. const validIndices = indices.filter(index =>
  228. index >= 0 && index < this.questionAnswerPairs.length
  229. );
  230. // 更新当前显示的问题索引
  231. this.currentQuestionIndices = validIndices.slice(0, this.questionButtons.length);
  232. // 如果索引数量少于按钮数量,使用默认索引填充
  233. while (this.currentQuestionIndices.length < this.questionButtons.length) {
  234. const defaultIndex = this.currentQuestionIndices.length % this.questionAnswerPairs.length;
  235. this.currentQuestionIndices.push(defaultIndex);
  236. }
  237. // 更新按钮文本
  238. this.updateQuestionButtonTexts();
  239. }
  240. /**
  241. * 获取当前所有问答对
  242. * @returns 所有问答对数组
  243. */
  244. public getAllQuestionAnswers(): QuestionAnswer[] {
  245. return [...this.questionAnswerPairs];
  246. }
  247. /**
  248. * 清除所有问答对并重置为默认值
  249. */
  250. public resetToDefault(): void {
  251. this.initDefaultQuestionAnswers();
  252. this.currentQuestionIndices = [0, 1, 2];
  253. this.updateQuestionButtonTexts();
  254. }
  255. /**
  256. * 更新特定索引的问答对
  257. * @param index 要更新的问答对索引
  258. * @param newQA 新的问答对
  259. */
  260. public updateQuestionAnswer(index: number, newQA: QuestionAnswer): void {
  261. if (index >= 0 && index < this.questionAnswerPairs.length && newQA) {
  262. this.questionAnswerPairs[index] = newQA;
  263. this.updateQuestionButtonTexts();
  264. }
  265. }
  266. /**
  267. * 替换所有问答对
  268. * @param newQAPairs 新的问答对数组
  269. */
  270. public replaceAllQuestionAnswers(newQAPairs: QuestionAnswer[]): void {
  271. console.log('替换问答对:', newQAPairs);
  272. // 清空现有问答对
  273. this.questionAnswerPairs = [];
  274. // 添加固定的"询问通行证"问题
  275. const passCardQuestion = {
  276. question: "询问通行证?",
  277. answer: "这是我的通行证,请过目。",
  278. showPassCard: true
  279. };
  280. console.log('添加通行证问题:', passCardQuestion);
  281. // 添加新的问答对
  282. for (let i = 0; i < newQAPairs.length; i++) {
  283. if (i === ASK_PASS_QUESTION_INDEX) {
  284. // 在第二个位置插入通行证问题
  285. this.questionAnswerPairs.push(passCardQuestion);
  286. console.log(`在位置${i}添加通行证问题`);
  287. } else {
  288. this.questionAnswerPairs.push(newQAPairs[i]);
  289. console.log(`在位置${i}添加问题:`, newQAPairs[i]);
  290. }
  291. // 确保不超过三个问题
  292. if (this.questionAnswerPairs.length >= 3) break;
  293. }
  294. // 如果问题不足三个,补充通行证问题
  295. if (this.questionAnswerPairs.length < 3) {
  296. // 如果还没有添加通行证问题,则添加
  297. const hasPassQuestion = this.questionAnswerPairs.some(qa => qa.showPassCard);
  298. if (!hasPassQuestion) {
  299. this.questionAnswerPairs.push(passCardQuestion);
  300. console.log('添加缺失的通行证问题');
  301. }
  302. // 依然不足三个,可以使用默认问题补充
  303. while (this.questionAnswerPairs.length < 3) {
  304. const backupQuestion = {
  305. question: `备用问题${this.questionAnswerPairs.length + 1}`,
  306. answer: "这是一个标准回答。"
  307. };
  308. this.questionAnswerPairs.push(backupQuestion);
  309. console.log('添加备用问题:', backupQuestion);
  310. }
  311. }
  312. // 确保第二个问题是通行证问题
  313. if (this.questionAnswerPairs.length >= 2 && !this.questionAnswerPairs[1].showPassCard) {
  314. console.log('强制第二个问题为通行证问题');
  315. this.questionAnswerPairs[1] = passCardQuestion;
  316. }
  317. console.log('最终问答对:', this.questionAnswerPairs);
  318. // 重置当前显示的问题索引
  319. this.currentQuestionIndices = [0, 1, 2];
  320. // 更新问题按钮文本
  321. this.updateQuestionButtonTexts();
  322. }
  323. }