import { _decorator, AudioSource, EditBox, EventTouch, isValid, Label, Node, ScrollView, Sprite, Tween, tween, UIOpacity, utils, v3, Vec3 } from 'cc'; import { GButton } from '../../Main/Common/GButton'; import Utils from '../../Main/Common/Utils'; import { ViewManager } from '../../Main/Manager/ViewManager'; import { InnerMsgCode } from '../../Main/Config/InnerMsgCode'; import li_BaseView from '../../Main/Common/li_BaseView'; import SubManager from '../SubManager'; import GameManager, { E_TalkStage, E_TalkStatusType } from '../../Main/Manager/GameManager'; import { I_LevelConfig, I_NpcTalkBack } from '../../Main/Config/CommonConfig'; import HttpUnit from '../../Main/Common/HttpUnit'; import { SDKManager } from '../../Main/Channel/SDKManager'; import ResManager from '../../Main/Manager/ResManager'; import PlayerDataManager from '../../Main/Manager/PlayerDataManager'; import GameRootUI from '../../Main/Common/GameRootUI'; import { E_AD_TARGET } from './TalkAdDialog'; import GlobalValue from '../../Main/Common/GlobalValue'; import AudioManager from '../../Main/Manager/AudioManager'; const { ccclass, property } = _decorator; //聊天界面 @ccclass('Talk_UI') export class Talk_UI extends li_BaseView { private _nodeTab: any = {}; private _data; private dazijiInfo = {stage: 0, idx: 0, str: "", tm:0, ts:0.05, lab:null}; //打字机信息 stage:0-未开始,1-正在打字,2-打字结束 private npcTalkInfo = {stage: 0, str:"", dotStr:"...", dotIdx:0, dotTm:0, dotTs:0.3, tm:0, ts:1.5}; //等待npc回复 stage:0-未开始,1-获取中,2-获取完成 private aiHuifuInfo = {stage: 0, labAry:[], dotStr:"...", dotIdx:0, dotTm:0, dotTs:0.3}; //等待ai回复 stage:0-未开始,1-获取中,2-获取完成 private ebTalk: EditBox; private labNpcTalk: Label; private xindongSpt: Sprite; private lvCfg: I_LevelConfig = null; //当前关卡配置 private lastRandTalkIdx: number = -1; //上一次随机对话的索引 //----重写父类接口--------------------------------------- onLoadCT() { Utils.parseNode(this.node, this._nodeTab) this.registerListenner(); this.ebTalk = this._nodeTab.ebTalk.getComponent(EditBox); this.labNpcTalk = this._nodeTab.npcTalk.getComponent(Label); this.xindongSpt = this._nodeTab.xindongSpt.getComponent(Sprite); this.ebTalk.node.on('editing-did-began', this.onEditingBegan, this); this.ebTalk.node.on('editing-did-ended', this.onEditingEnded, this); this.ebTalk.node.on('editing-return', this.onEditingReturn, this); // this._nodeTab.npcTalkSV.on(Node.EventType.TOUCH_START, (event: EventTouch)=>{ // event.preventSwallow = true; //允许点击事件穿透 // }, this); this._nodeTab.npcTalkSV.getChildByName("view").on(Node.EventType.TOUCH_END, (event:EventTouch) => { // event.preventSwallow = true; //允许点击事件穿透 this.onNpcFramClick(); }, this); this._nodeTab.arrowNode.active = false; let npcNextArrow:Node = this._nodeTab.npcNextArrow tween(npcNextArrow) .to(0.5, {position: new Vec3(15, 0, 0)}) .to(0.5, {position: new Vec3(-15, 0, 0)}) .union() .repeatForever() .start() } openUIDataCT(data: any): void { this._data = data } registerListenner() { Utils.addInnerEL(InnerMsgCode.Data_NpcTalkBack, this, this.resiveNpcTalkBack) Utils.addInnerEL(InnerMsgCode.UI_Socket_Timeout, this, this.resiveSocketTimeout) Utils.addInnerEL(InnerMsgCode.UI_TalkStageUp, this, this.resiveTalkStageUp) Utils.addInnerEL(InnerMsgCode.Data_LevelStarUp, this, this.resiveLevelStarUp) Utils.addInnerEL(InnerMsgCode.Data_ChehuiUp, this, this.resiveChehuiUp) Utils.addInnerEL(InnerMsgCode.UI_ResartGame, this, this.resiveResartGame) } start() { GButton.BandClick(this._nodeTab.btnBack, this.onBackClick, this); GButton.BandClick(this._nodeTab.btnSend, this.onSendClick, this); GButton.BandClick(this._nodeTab.btnSuiji, this.onSuijiClick, this); //弹窗适配 let scaleRatio = Utils.getScaleRatio(2) if (scaleRatio > 1) { scaleRatio = 1; } this._nodeTab.gs1frame.scale = new Vec3(scaleRatio, scaleRatio, 1) //规则内容 Utils.setString(this._nodeTab.labGs1Tips, GlobalValue.RuleStr) // GButton.BandClick(this._nodeTab.npcTalkFrame, ()=>{ // this.onNpcFramClick(); // }, this, 0, null, null, false); GButton.BandClick(this._nodeTab.btnRecord, ()=>{ // // 测试代码 // if (true) { // this.showXinAddAnimation() // return // } ViewManager.I.openBundlesView("UI/StartUI/Record_UI") }, this); GButton.BandClick(this._nodeTab.btnTishi, ()=>{ ViewManager.I.openBundlesView("UI/StartUI/Tips_UI") //上报服务器记录 HttpUnit.ins.sendTipRecord({level_id: this.lvCfg.id}, null) }, this); GButton.BandClick(this._nodeTab.btnAD, ()=>{ let contStr = "" let levelData = GameManager.CurLevelData if (!levelData || levelData.ad_num <= 0) { contStr = "关卡内续航次数已用完" } else { contStr = `看广告或分享可额外获取对话次数,剩余${levelData.ad_num}次` } ViewManager.I.openBundlesView("UI/StartUI/TalkAdDialog", { type: E_AD_TARGET.liaotian, //加聊天次数 content: contStr, adCallback: ()=>{ SDKManager.show_reward_video_ad(this.node.uuid, 1) }, shareCallback: ()=>{ SDKManager.show_reward_share(this.node.uuid, 1) } }) }, this); GButton.BandClick(this._nodeTab.btnJia10, ()=>{ let contStr = "" let levelData = GameManager.CurLevelData if (!levelData || levelData.can_use_strength_cnt <= 0) { contStr = "关卡内加分次数已用完" } else { contStr = `观看广告,下一次聊天的最终得分增加 10 分(不会超过 100 分,也不会影响对话效果),剩余${levelData.can_use_strength_cnt}次` } ViewManager.I.openBundlesView("UI/StartUI/TalkAdDialog", { type: E_AD_TARGET.baoji, //加聊天次数 content: contStr, adCallback: ()=>{ SDKManager.show_reward_video_ad(this.node.uuid, 2) }, shareCallback: ()=>{ SDKManager.show_reward_share(this.node.uuid, 2) } }) }, this); GButton.BandClick(this._nodeTab.btnRole, ()=>{ this._nodeTab.ruleNode.active = true }, this); GButton.BandClick(this._nodeTab.btnRoleOk, ()=>{ this.onRoleCloseClick() }, this); GButton.BandClick(this._nodeTab.btnRoleClose, ()=>{ this.onRoleCloseClick() }, this); //ai语音开关 GButton.BandClick(this._nodeTab.btnYuyin, ()=>{ GameManager.AIVoiceSwt = !GameManager.AIVoiceSwt; this.refreshAIVoiceState() }, this); this.refreshAIVoiceState() if (!SDKManager.checkSupportBase64Audio()) { this._nodeTab.btnYuyin.active = false } SDKManager.register_video_reward(this.node.uuid, (tag:number)=>{ console.log("视频广告回调", tag) if (tag == 1) { // 加次数 SubManager.ShowPrompt("观看视频成功,获得聊天次数") this.doAddLevelCnt(1) } else if (tag == 2) { // 甜蜜暴击 SubManager.ShowPrompt("观看视频成功") this.doStrengthTalk() } }) SDKManager.register_share_reward(this.node.uuid, (tag:number)=>{ console.log("分享回调", tag) if (tag == 1) { // 加次数 SubManager.ShowPrompt("分享成功,获得聊天次数") this.doAddLevelCnt(2) } }) this.initedGame() this.initXinAni() } onDestroy () { super.onDestroy() if (isValid(this.ebTalk)) { this.ebTalk.node.off('editing-did-began', this.onEditingBegan, this); this.ebTalk.node.off('editing-did-ended', this.onEditingEnded, this); this.ebTalk.node.off('editing-return', this.onEditingReturn, this); } } update(deltaTime: number) { //region 打字机效果逻辑 if (this.dazijiInfo.stage == 1) { this.dazijiInfo.tm += deltaTime if (this.dazijiInfo.tm >= this.dazijiInfo.ts) { this.dazijiInfo.tm = 0 this.dazijiInfo.lab.string = this.dazijiInfo.str.substring(0, this.dazijiInfo.idx) this.dazijiInfo.idx += 1 if (this.dazijiInfo.idx > this.dazijiInfo.str.length) { this.dazijiInfo.stage = 2 } let talksv = this._nodeTab.npcTalkSV.getComponent(ScrollView) talksv.scrollToBottom(0.1) } } else if (this.dazijiInfo.stage == 2) { console.log("文本打字机效果结束") this.dazijiInfo.stage = 0 this.dazijiInfo.lab.string = this.dazijiInfo.str this._nodeTab.arrowNode.active = true; let talksv = this._nodeTab.npcTalkSV.getComponent(ScrollView) this.scheduleOnce(() => { talksv.scrollToBottom(0.1) }, 0.1) } //接收npc回复逻辑 if (this.npcTalkInfo.stage == 1) { //...的频率 this.npcTalkInfo.dotTm += deltaTime if (this.npcTalkInfo.dotTm >= this.npcTalkInfo.dotTs) { this.npcTalkInfo.dotTm = 0 this.labNpcTalk.string = this.npcTalkInfo.dotStr.substring(0, this.npcTalkInfo.dotIdx) this.npcTalkInfo.dotIdx += 1 if (this.npcTalkInfo.dotIdx > this.npcTalkInfo.dotStr.length) { this.npcTalkInfo.dotIdx = 0 } } //sorket获取频率 this.npcTalkInfo.tm += deltaTime if (this.npcTalkInfo.tm >= this.npcTalkInfo.ts) { this.npcTalkInfo.tm = 0 GameManager.I.getNpcTalkBack({}) } } //接收ai回复逻辑 if (this.aiHuifuInfo.stage == 1) { //...的频率 this.aiHuifuInfo.dotTm += deltaTime if (this.aiHuifuInfo.dotTm >= this.aiHuifuInfo.dotTs) { this.aiHuifuInfo.dotTm = 0 this.aiHuifuInfo.labAry.forEach((_lab: Label) => { _lab.string = "提示加载中" + this.aiHuifuInfo.dotStr.substring(0, this.aiHuifuInfo.dotIdx) }) this.aiHuifuInfo.dotIdx += 1 if (this.aiHuifuInfo.dotIdx > this.aiHuifuInfo.dotStr.length) { this.aiHuifuInfo.dotIdx = 0 } } } } //region NPC回复消息 /**接收到npc回复数据流 */ resiveNpcTalkBack(data:I_NpcTalkBack) { this.npcTalkInfo.stage = 0 GameManager.TurnToStage(E_TalkStage.npcTalk) let npcTalk = GameManager.CurNpcTalkData //npc回复后清空玩家之前的输入 if (npcTalk.judgement > -1) { this.ebTalk.string = "" this.refreshInputNum() } //友盟事件上报 对话轮数 let id = HttpUnit.GetID() SDKManager.umaEvent(SDKManager.Uma_Event_TalkRound, { userId: id+"", //玩家id ISay: npcTalk.userInput, //玩家发言 NpcSay: npcTalk.aiResponse, //npc发言 }) } /**socket连接超时 */ resiveSocketTimeout(data:any) { SubManager.ShowConfirm({ content: "连接已断开,请重新开始游戏", hideNo: true, //隐藏取消按钮 yesCallback: () => { ViewManager.I.closeAllView(); Utils.sendInnerMsg(InnerMsgCode.UI_Talk_Back, {}) }, closeCallback: () => { ViewManager.I.closeAllView(); Utils.sendInnerMsg(InnerMsgCode.UI_Talk_Back, {}) } }) this.npcTalkInfo.stage = 0 } /**接收到聊天状态变化消息 */ resiveTalkStageUp(data:any) { this.refreshTalkStage() } /**接收到星级变化消息 */ resiveLevelStarUp(data:any) { if (data && data.level == GameManager.CurLevelId) { for (let i=1; i<=3; i++) { let lsStar = this._nodeTab["lsStar"+i].getComponent(Sprite) let starPath = data.star >= i ? "lv_3" : "lv_2" ResManager.I.changeBundleSpriteFrame(lsStar, starPath, "Zhujiemian") } } } //region 撤回逻辑 /**收到撤回消息 */ resiveChehuiUp(data:any) { //刷新次数 this.refreshTalkStepData() //刷新对话得分 this.refreshDuihuaDefen() //刷新心动次数 this.refreshXindongCishu(false) //刷新npc表情 let talkdata = GameManager.CurNpcTalkData let aiEmoji = talkdata ? talkdata.aiEmoji : "" let rolePath = GameManager.GetNpcEmoPic(aiEmoji) Utils.sendInnerMsg(InnerMsgCode.SceneLayerBgUp, {rolePath:rolePath}) } /**重新开始游戏 */ resiveResartGame(data:any) { console.log("重新开始游戏") this.initedGame() } //region UI初始化 /**初始化 */ initedGame() { this.lvCfg = GameManager.getLevelCfg(GameManager.CurLevelId) //背景乐 let bgmUrl = `https://hxzgame.vip.hnhxzkj.com/lzx/XiangQin/BGM/${this.lvCfg.bgm}.mp3` AudioManager.I.PlayRemoteMusic(bgmUrl, true) //名称 Utils.setString(this._nodeTab.npcName, this.lvCfg.name) //刷新历史星级 for (let i=1; i<=3; i++) { let lsStar = this._nodeTab["lsStar"+i].getComponent(Sprite) let starPath = this.lvCfg.star >= i ? "lv_3" : "lv_2" ResManager.I.changeBundleSpriteFrame(lsStar, starPath, "Zhujiemian") } this._nodeTab.ruleNode.active = false this.hideAiAnswer() this.refreshTalkStage() //刷新状态显示 this.refreshTalkStepData() this.refreshBaojiState() this.refreshXindongCishu(false) this.refreshDuihuaDefen() //检测引导 this.checkGuide() //开始时先自动显示一下npc的攻略 if (PlayerDataManager.I.GuideTalkFinished) { this.autoShowNpcTip() } } //输入框开始编辑事件 onEditingBegan(param1:any, param2:any) { console.log("聊天界面1: onEditingBegan", param1, param2) } //输入框回车事件 onEditingReturn(param1:any, param2:any) { console.log("聊天界面2: onEditingReturn", param1, param2) } //输入框结束编辑事件 onEditingEnded(param1:any, param2:any) { console.log("聊天界面3: onEditingEnded", param1, param2) } //输入框文本改变事件 onTextChanged(param1:any, param2:any) { // console.log("聊天界面4: onTextChanged", param1, param2) this.refreshInputNum() } //刷新AI语音状态 private refreshAIVoiceState() { let voicePath = GameManager.AIVoiceSwt ? "lv_4" : "lv_5" let sptYuyin = this._nodeTab.sptYuyin.getComponent(Sprite) ResManager.I.changeBundleSpriteFrame(sptYuyin, voicePath, "Zhujiemian") } //播放AI语音 private playAIVoice(str:string) { if (!GameManager.AIVoiceSwt) { return //开关没开 } if (!SDKManager.checkSupportBase64Audio()) { return //不支持base64音频 } HttpUnit.ins.getAIVoice({record_id: GameManager.RecordId, text:str}, (data) => { if (data) { console.log("播放AI语音11", data) SDKManager.playBase64Audio(data.url, false) } }) } //region 刷新聊天状态 private refreshTalkStage() { let gStage = GameManager.curStage if (gStage == E_TalkStage.prologue) { this.showNpcPrologue() } else if (gStage == E_TalkStage.myTalk) { this.turnToMyTalk() this.showAiAnswer() } else if (gStage == E_TalkStage.waitNpcTalk) { this.turnToWaitNpcTalk() } else if (gStage == E_TalkStage.npcTalk) { this.turnToNpcTalk(GameManager.CurNpcTalkData) } else if (gStage == E_TalkStage.npcFixedTalk) { this.turnToNpcFixedTalk(GameManager.CurNpcFixedTalkText) } else if (gStage == E_TalkStage.upTalkStatus) { this.turnToUpdateStage() } } //显示NPC开场白 private showNpcPrologue() { this._nodeTab.NpcTalkNode.active = true this._nodeTab.MyTalkNode.active = false this._nodeTab.arrowNode.active = false; //开场白 this.dazijiInfo.stage = 1 this.dazijiInfo.idx = 0 this.dazijiInfo.lab = this.labNpcTalk this.dazijiInfo.str = this.lvCfg.prologueMessage this.dazijiInfo.tm = this.dazijiInfo.ts GameManager.AddTalkRecord({talk:this.lvCfg.prologueMessage, isMe:false, score:-1, scoreBase:-1, scoreAdditional:0}) // this.playAIVoice(this.lvCfg.prologueMessage) } /**切换到玩家说话状态 */ private turnToMyTalk() { this._nodeTab.NpcTalkNode.active = false this._nodeTab.MyTalkNode.active = true // //刷新npc表情 // let rolePath = GameManager.GetNpcEmoPic("") // Utils.sendInnerMsg(InnerMsgCode.SceneLayerBgUp, {rolePath:rolePath}) } /**切换到等待NPC说话状态 */ private turnToWaitNpcTalk() { this._nodeTab.NpcTalkNode.active = true this._nodeTab.MyTalkNode.active = false this._nodeTab.arrowNode.active = false; this.labNpcTalk.string = "" } /**切换到NPC说话状态 */ private turnToNpcTalk(data:I_NpcTalkBack) { this._nodeTab.NpcTalkNode.active = true this._nodeTab.MyTalkNode.active = false this._nodeTab.arrowNode.active = false; GameManager.AddStepScore(data.aiScore) //记录本次分数 this.refreshDuihuaDefen() //npc回复 // this.labNpcTalk.string = data.aiResponse this.dazijiInfo.stage = 1 this.dazijiInfo.idx = 0 this.dazijiInfo.lab = this.labNpcTalk this.dazijiInfo.str = data.aiResponse this.dazijiInfo.tm = this.dazijiInfo.ts GameManager.AddTalkRecord({talk:data.aiResponse, isMe:false, score:data.aiScore, scoreBase:data.aiBaseScore, scoreAdditional:data.aiAdditionalScore}) this.playAIVoice(data.aiResponse) //刷新npc表情 let rolePath = GameManager.GetNpcEmoPic(data.aiEmoji) Utils.sendInnerMsg(InnerMsgCode.SceneLayerBgUp, {rolePath:rolePath}) //额外分数 if (data.aiAdditionalScore > 0) { SubManager.ShowPrompt(`恭喜!聊天加分成功!${data.aiBaseScore} + ${data.aiAdditionalScore}`) } //对话轮次 GameManager.srouceCnt = data.sourceCnt this.refreshTalkStepData() } /**切换到npc固定话术展示状态 */ private turnToNpcFixedTalk(str:string) { this._nodeTab.NpcTalkNode.active = true this._nodeTab.MyTalkNode.active = false this._nodeTab.arrowNode.active = false; //npc固定话术 this.dazijiInfo.stage = 1 this.dazijiInfo.idx = 0 this.dazijiInfo.lab = this.labNpcTalk this.dazijiInfo.str = str this.dazijiInfo.tm = this.dazijiInfo.ts } /**切换到更新聊天状态状态 */ private turnToUpdateStage() { HttpUnit.ins.getTalkStage({record_id: GameManager.RecordId}, (data) => { if (data) { GameManager.CurLevelData = data.level this.refreshTalkStepData() this.refreshBaojiState() this.checkIsFinish() } }) } /**刷新心动次数 */ private refreshXindongCishu(doAct:boolean = true) { let maxCount = HttpUnit.GetXindongMaxCount() let curCount = GameManager.xindongCishu Utils.setString(this._nodeTab.xindongNum, `${curCount}/${maxCount}`) Tween.stopAllByTarget(this.xindongSpt) if (doAct) { tween(this.xindongSpt).to(0.3, { fillRange: curCount / maxCount }).start() } else { this.xindongSpt.fillRange = curCount / maxCount } } /**刷新对话得分 */ private refreshDuihuaDefen() { let curScore = GameManager.getCurStepScore() let [totalScore, pjScore] = GameManager.getGameScore() Utils.setString(this._nodeTab.scoreNew, curScore+"") Utils.setString(this._nodeTab.scoreTotal, totalScore+"") } /**刷新当前状态显示 */ private refreshTalkStepData() { let curCnt = GameManager.srouceCnt let stepData = GameManager.CurLevelData Utils.setString(this._nodeTab.lunciNum, `${curCnt}/${stepData.total_cnt}`) } /**刷新暴击状态是否显示 */ private refreshBaojiState() { let stepData = GameManager.CurLevelData this._nodeTab.baojiNode.active = stepData && stepData.is_strength_take_effect == true } /**刷新玩家输入字数 */ private refreshInputNum() { let numMax = this.ebTalk.maxLength let numCur = this.ebTalk.string.length Utils.setString(this._nodeTab.labStrLen, `(${numCur}/${numMax})`) } //region 检测是否结束 /**检查对话轮次是否用完 * @returns [是否结束对话,是否显示广告加次数] */ private checkIsFinish() { let isFinish = false //是否结束对话 let isShowAD = false //是否显示广告 let isSendEnd = false //是否发送结束请求 let stepData = GameManager.CurLevelData if (stepData.status == E_TalkStatusType.succ) { //已成功 isFinish = true } else if (stepData.status == E_TalkStatusType.fail) { //已失败 isFinish = true } else if (stepData.status == E_TalkStatusType.noCount) { //次数已用完 isFinish = true isShowAD = stepData.ad_num > 0 //true isSendEnd = true } if (isFinish) { if (isShowAD) { ViewManager.I.openBundlesView("UI/StartUI/TalkAdDialog", { type: E_AD_TARGET.liaotian, //加聊天次数 content: "看广告或分享可额外获取对话次数", adCallback: ()=>{ SDKManager.show_reward_video_ad(this.node.uuid, 1) }, shareCallback: ()=>{ SDKManager.show_reward_share(this.node.uuid, 1) }, closeCallback: ()=>{ if (isSendEnd) { this.doJiesuan() } else { ViewManager.I.openBundlesView("UI/StartUI/Finish_UI", stepData) } } }) } else { if (isSendEnd) { this.doJiesuan() } else { ViewManager.I.openBundlesView("UI/StartUI/Finish_UI", stepData) } } } else { GameManager.TurnToStage(E_TalkStage.myTalk) } } //增加聊天次数 atype: 1=看广告 2=分享 private doAddLevelCnt(atype:number) { HttpUnit.ins.addTalkCnt({record_id: GameManager.RecordId, type:atype}, (data) => { if (data) { GameManager.CurLevelData = data.level this.refreshTalkStepData() this.refreshBaojiState() //判断是否继续对话 if (GameManager.srouceCnt < data.level.total_cnt) { if (GameManager.curStage != E_TalkStage.waitNpcTalk) { GameManager.TurnToStage(E_TalkStage.myTalk) } } else { this.doJiesuan() } } }) } /**增强下一轮对话 */ private doStrengthTalk() { HttpUnit.ins.sendTalkStrength({record_id: GameManager.RecordId}, (data) => { if (data) { GameManager.CurLevelData = data.level this.refreshBaojiState() } }) } //结算 private doJiesuan() { let [score_all, score] = GameManager.getGameScore() HttpUnit.ins.sendLevelFinish({record_id: GameManager.RecordId, score:score, score_all:score_all}, (data) => { if (data && data.level) { //成功 ViewManager.I.openBundlesView("UI/StartUI/Finish_UI", data.level) } else { //失败 console.warn("结算失败,服务器返回异常!") ViewManager.I.closeAllView(); Utils.sendInnerMsg(InnerMsgCode.UI_Talk_Back, {}) } }) } //退出聊天 onBackClick() { SubManager.ShowConfirm({ content: "确定退出吗?\n(退出会保留当前聊天进度)", yesCallback: () => { //退出并结算 // this.doJiesuan(); //只退出聊天,不结算 this.onClose(); Utils.sendInnerMsg(InnerMsgCode.UI_Talk_Back, {}) } }) } //发送消息 onSendClick() { let str = this.ebTalk.string; if (str.length == 0) { SubManager.ShowPrompt("请先输入内容") return } GameRootUI.DisableOper(2) HttpUnit.ins.sendUserTalk({record_id: GameManager.RecordId, user_input: str}, (data) => { GameRootUI.EnableOper() if (data) { if (GameManager.curStage != E_TalkStage.myTalk) { return } GameManager.TurnToStage(E_TalkStage.waitNpcTalk) this.hideAiAnswer() //使用服务器处理过的字符串 if (data.user_input) { str = data.user_input } GameManager.AddTalkRecord({talk:str, isMe:true, score:-1, scoreBase:-1, scoreAdditional:0}) //开始接收npc回复 this.npcTalkInfo.stage = 1 this.npcTalkInfo.str = "" this.npcTalkInfo.dotTm = this.npcTalkInfo.dotTs this.npcTalkInfo.tm = this.npcTalkInfo.ts this.npcTalkInfo.dotIdx = 1 } }) } //随机回复对话 onSuijiClick() { let sjLen = this.lvCfg.randomInputPool.length let randIdx = Utils.getRandomInt(0, sjLen-1) console.log("随机回复对话:", randIdx, sjLen) if (randIdx == this.lastRandTalkIdx) { randIdx++ if (randIdx >= sjLen) randIdx = 0 } this.lastRandTalkIdx = randIdx this.ebTalk.string = this.lvCfg.randomInputPool[randIdx] this.refreshInputNum() } //点击npc对话背景 onNpcFramClick() { if (this.dazijiInfo.stage == 1) { this.dazijiInfo.stage = 2 } else { if (GameManager.curStage == E_TalkStage.prologue) { GameManager.TurnToStage(E_TalkStage.upTalkStatus) } else if (GameManager.curStage == E_TalkStage.npcTalk) { let npcTalk = GameManager.CurNpcTalkData if (npcTalk.judgement == 0) { console.log("固定鼓励话术展示!", GameManager.npcFixTalkCountXihuan) if (GameManager.npcFixTalkCountXihuan > 0) { GameManager.TurnToStage(E_TalkStage.upTalkStatus) } else { GameManager.CurNpcFixedTalkText = this.lvCfg.encourageMessage GameManager.TurnToStage(E_TalkStage.npcFixedTalk) } GameManager.npcFixTalkCountXihuan = GameManager.npcFixTalkCountXihuan + 1 GameManager.xindongCishu = GameManager.xindongCishu + 1 this.showXinAddAnimation() // this.refreshXindongCishu(true) } else if (npcTalk.judgement == 2) { console.log("固定厌恶话术展示!", GameManager.npcFixTalkCountTaoyan) if (GameManager.npcFixTalkCountTaoyan > 0) { GameManager.TurnToStage(E_TalkStage.upTalkStatus) } else { GameManager.CurNpcFixedTalkText = this.lvCfg.hateMessage GameManager.TurnToStage(E_TalkStage.npcFixedTalk) } GameManager.npcFixTalkCountTaoyan = GameManager.npcFixTalkCountTaoyan + 1 } else { GameManager.TurnToStage(E_TalkStage.upTalkStatus) } } else if (GameManager.curStage == E_TalkStage.npcFixedTalk) { GameManager.TurnToStage(E_TalkStage.upTalkStatus) } } } //region ai生成的回复 /**从服务器获取回复 */ private showAiAnswer() { this._nodeTab.aiAnsNode.active = true //获取到之前 this.aiHuifuInfo.labAry = [] for (let i=1; i<=3; i++) { let AiAnsItem: Node = this._nodeTab["AiAnsItem"+i] let labAns = AiAnsItem.getComponentInChildren(Label) labAns.string = "" // "提示加载中..." GButton.RemoveAndBandClick(AiAnsItem, ()=>{ SubManager.ShowPrompt("提示获取中,请稍后") }, this); this.aiHuifuInfo.labAry.push(labAns) } //播放ai回复效果 this.aiHuifuInfo.stage = 1 this.aiHuifuInfo.dotTm = this.aiHuifuInfo.dotTs this.aiHuifuInfo.dotIdx = 1 HttpUnit.ins.getAIAutoAns({record_id: GameManager.RecordId}, (data) => { //获取到之后 this.aiHuifuInfo.stage = 0 if (data) { console.log("从服务器获取回复", data) let gStage = GameManager.curStage if (gStage == E_TalkStage.myTalk) { for (let i=1; i<=3; i++) { let AiAnsItem: Node = this._nodeTab["AiAnsItem"+i] let labAns = AiAnsItem.getComponentInChildren(Label) let ans = data["tips"+i] if (ans) { labAns.string = this.clampAiAnswer(ans) GButton.RemoveAndBandClick(AiAnsItem, ()=>{ this.ebTalk.string = ans this.refreshInputNum() }, this); } else { labAns.string = "" GButton.RemoveClick(AiAnsItem); } } } } }) } private hideAiAnswer() { this._nodeTab.aiAnsNode.active = false } //截取字符串,超过长度的用...代替 private clampAiAnswer(ansStr: string) { let labelLimit = 20 //字符串长度限制 let tempStr: string = ""; let tempLen: number = 0; for (let i = 0; i < ansStr.length; i++) { tempLen += ansStr.charCodeAt(i) > 255 ? 2 : 1; if (tempLen > labelLimit) { return tempStr + "..."; } tempStr += ansStr.charAt(i); } return ansStr; } //region 爱心增加动画 private _xin1PosOrig: Vec3 private _xin2PosOrig: Vec3 private _xin2Opa: UIOpacity = null //初始化爱心动画 private initXinAni() { this._xin1PosOrig = (this._nodeTab.xinSpt1 as Node).position.clone() this._xin2PosOrig = (this._nodeTab.xinSpt2 as Node).position.clone() this._xin2Opa = this._nodeTab.xinSpt2.getComponent(UIOpacity) this._xin2Opa.opacity = 0 } //显示爱心增加动画 private showXinAddAnimation() { Tween.stopAllByTarget(this._nodeTab.xinSpt2) Tween.stopAllByTarget(this._xin2Opa) let xinSpt2: Node = this._nodeTab.xinSpt2 //缩放 xinSpt2.scale = new Vec3(0.1, 0.1, 0.1) tween(xinSpt2) .to(0.2, { scale: new Vec3(2.2, 2.2, 1) }, {easing: 'sineIn'}) .to(0.2, { scale: new Vec3(1, 1, 1) }, {easing: 'sineOut'}) .start() //移动 xinSpt2.position = this._xin2PosOrig tween(xinSpt2) .delay(0.4) .to(0.45, { position: this._xin1PosOrig }, {easing: 'sineIn'}) .call(() => { this.showXin2Animation() this.refreshXindongCishu(true) //刷新次数显示 }) .start() // #region 贝塞尔曲线动作 // // 三维空间的缓动 // const quadraticCurve = (t: number, p1: Vec3, cp: Vec3, p2: Vec3, out: Vec3) => { // out.x = (1 - t) * (1 - t) * p1.x + 2 * t * (1 - t) * cp.x + t * t * p2.x // out.y = (1 - t) * (1 - t) * p1.y + 2 * t * (1 - t) * cp.y + t * t * p2.y // out.z = (1 - t) * (1 - t) * p1.z + 2 * t * (1 - t) * cp.z + t * t * p2.z // } // const startPos = this._xin2PosOrig // const controlPos = v3(2, 3, 0) // const endPos = this._xin1PosOrig // const tempVec3 = v3() // tween(xinSpt2) // .to( // 0.45, // { position: endPos }, // { // onUpdate: (target, ratio) => { // quadraticCurve(ratio, startPos, controlPos, endPos, tempVec3) // xinSpt2.setPosition(tempVec3) // }, // } // ) // .call(() => { // this.showXin2Animation() // this.refreshXindongCishu(true) //刷新次数显示 // }) // .start() // #endregion //透明度 this._xin2Opa.opacity = 0 tween(this._xin2Opa) .to(0.05, { opacity: 255 }) .delay(0.75) .to(0.05, { opacity: 0 }) .start() } private showXin2Animation() { Tween.stopAllByTarget(this._nodeTab.xinSpt1) let xinSpt1: Node = this._nodeTab.xinSpt1 xinSpt1.scale = new Vec3(1, 1, 1) tween(xinSpt1) .to(0.3, {scale: new Vec3(1.4, 1.4, 1.4) }, {easing: 'sineInOut'}) .to(0.3, {scale: new Vec3(1, 1, 1) }, {easing: 'sineInOut'}) .start() } //region 引导相关 //检查引导 private checkGuide() { if (PlayerDataManager.I.GuideTalkFinished) { return } let delayInterval = 0.5 GameRootUI.DisableOper(delayInterval) this.scheduleOnce(() => { this._nodeTab.ruleNode.active = true },delayInterval) } //引导完成 private finishGuide() { if (PlayerDataManager.I.GuideTalkFinished) { return } PlayerDataManager.I.SetGuideTalkFinish(true) this.autoShowNpcTip() } //关闭规则弹窗 private onRoleCloseClick() { this._nodeTab.ruleNode.active = false this.finishGuide() } //自动显示NPC提示弹窗 private autoShowNpcTip() { if (GameManager.srouceCnt > 0) { return } let delayInterval = 0.5 GameRootUI.DisableOper(delayInterval) this.scheduleOnce(() => { ViewManager.I.openBundlesView("UI/StartUI/Tips_UI") },delayInterval) } }