Files
2026-05-23 22:10:14 +08:00

434 lines
8.3 KiB
JavaScript

/*******************************************************************************
*
* 剧情管理
*
*
*
* 2023.06.25
******************************************************************************/
const BridgeController = require( "bridge.controller" );
const PDF = require( "plot.define" );
const TDefine = require( "trace.define" );
const TTT = TDefine.TraceType;
const PlotManager = cc.Class( {
extends: BridgeController,
// 初始化配置数据
initConfig: function() {
this.units = {};
// 插件
nx.plugin.add( this, [ "view" ] );
// 视图创建
this.vbuild( PDF.ViewPlot );
// 全局支持
nx.bridge.plot = this;
},
// 注册监听事件
registerEvents: function() {
},
// 注册协议接受事件
registerProtocals: function() {
// 前端准备完毕
this.RegisterProtocal( 10371, this.onCommited.bind( this ) );
this.RegisterProtocal( 10372, this.onPlotData.bind( this ) );
},
// 从服务器初始化数据
reqBaseFromServer: function( _cb ) {
// 如果当前正在引导,则不重建
if( this.isDoing() ) {
nx.dt.fnInvoke( _cb, true );
return;
}
this.rebuild( ( _ret, _data ) => {
nx.dt.fnInvoke( _cb, _ret, _data );
// 掉线重新激活
if( nx.bridge.mainui ) {
nx.bridge.mainui.tryPlot();
}
} );
},
// 系统重建
rebuild: function( _cb ) {
// 清理
this.records = {};
this.configs = null;
this.vreset();
// 开关
let open = nx.storage.getNumber( PDF.KEY_PLOT_OPEN, 1, true );
this.opened = ( open == 1 );
// 重读配置
let path = cc.path.join( "configs/plots", "catalogs" );
nx.res.loadJson( path, ( _err, _data ) => {
if( _err ) {
nx.error( "$Plot:配置加载失败:", path );
nx.dt.fnInvoke( _cb, false );
return;
}
this.configs = _data;
this.records = nx.storage.getObject( PDF.KEY_PLOTS, true );
if( nx.dt.objEmpty( this.records ) ) {
this.records = {
ids: [],
};
}
this.reqBaseData( _cb );
} );
},
// 请求剧情信息
reqBaseData: function( _cb ) {
this.SendProtocal( 10372, {}, _cb );
},
// 剧情信息
onPlotData: function( _data ) {
if( !this.isGoodData( _data ) ) {
return;
}
let ids = [];
let group = _data.guide_group || [];
group.forEach( t => {
ids.push( t.id );
} );
this.records.ids = ids;
},
// 上传剧情完成
reqComplete: function( _id, _cb ) {
// 已经提交过了
if( this.preCommited ) {
nx.warn( `$Plot:已经提前完成过了!` );
nx.dt.fnInvoke( _cb, true );
return;
}
this.SendProtocal( 10371, {
id: _id + "",
}, _cb );
// 埋点
if( nx.mTrace ) {
nx.mTrace.trace( TTT.plotDone, _id );
}
},
// 剧情上传
onCommited: function( _data ) {
if( !this.isGoodData( _data ) ) {
return;
}
this.preCommited = true;
},
// 引导开关
openPlot: function( _open ) {
this.opened = !!_open;
nx.storage.set( PDF.KEY_PLOT_OPEN, _open ? 1 : 0, true );
},
// 剧情触发
fire: function( _id, _cb, _force = false ) {
// 进行中
let cur = this.vget( "id" );
if( nx.dt.strNEmpty( cur ) ) {
nx.error( "$Plot:进行中,播放失败:", cur, _id );
nx.dt.fnInvoke( _cb, false, "PlotFailed" );
return false;
}
// 获取配置
let info = this.queryCfgs( _id );
if( nx.dt.objEmpty( info ) ) {
nx.dt.fnInvoke( _cb, false, "PlotFailed" );
return false;
}
// 剧情不跳过
if( !this.opened && info.type != "dia" ) {
nx.warn( "$Plot:引导未开启" );
nx.dt.fnInvoke( _cb, false, "PlotFailed" );
return false;
}
// 条件判断
let ret = nx.bridge.checkConditions( info.conditions );
if( nx.dt.objNEmpty( ret ) && !_force ) {
// nx.warn( "$Plot:不滿足觸發條件:", _id );
nx.dt.fnInvoke( _cb, false, "PlotNoConds" );
return false;
}
// 是否触发过
if( nx.dt.arrMember( this.records.ids, _id ) ) {
nx.warn( "$Plot:劇情重複觸發:", _id );
nx.bridge.vset( "DailyPop", 1 );
nx.dt.fnInvoke( _cb, false, "PlotRepeat" );
return false;
}
// 预先标记引导中
this.vset( "id", _id, false );
// 载入剧本
let path = cc.path.join( "configs/plots/jsons", info.json );
nx.res.loadJson( path, ( _err, _data ) => {
if( _err ) {
this.vset( "id", "" );
nx.error( "$Plot:载入剧本失败:", path );
nx.dt.fnInvoke( _cb, false, "PlotFailed" );
return;
}
this.cbDone = _cb;
this.setCurrent( _id, _data );
} );
return true;
},
// 强制触发剧情
fireForce: function( _id, _cb ) {
// 从记录删除
nx.dt.arrDelete( this.records.ids, ( m ) => {
return m == _id;
} );
this.fire( _id, _cb, true );
},
// 设置当前剧情
setCurrent: function( _id, _json ) {
// 清理
let id = "" + _id;
if( nx.dt.strEmpty( id ) ) {
this.vreset();
return;
}
// 新设置
this.vset( "info", _json );
this.vset( "skip", _json.skip );
this.vset( "total", _json.steps.length );
this.vset( "step", -1 );
this.vset( "id", id );
this.preCommited = false;
nx.debug( "$Plot:开始剧情:", id );
// 埋点
if( nx.mTrace ) {
nx.mTrace.trace( TTT.plotStart, id );
}
},
// 下一步
next: function() {
// 剧情完成
let step = this.vget( "step" ) + 1;
if( step >= this.vget( "total" ) ) {
this.done();
return;
}
if( CC_DEBUG ) {
let info = this.vget( "info" );
let data = info ? info.steps[ step ] : null;
console.log( "next:", step, data );
}
// 设置
this.vset( "step", step );
// 埋点
if( nx.mTrace ) {
nx.mTrace.trace( TTT.plotStep, this.vget( "id" ), step );
}
},
// 引导中
isDoing: function() {
let id = this.vget( "id" );
return nx.dt.strNEmpty( id );
},
// 剧情完成
done: function() {
let id = this.vget( "id" );
nx.debug( "$Plot:引导完成.", id );
// 关闭
this.vreset();
nx.bridge.vset( "CloseSpecial", null );
// 存档
this.records.ids.push( id );
nx.storage.setObject( PDF.KEY_PLOTS, this.records, true );
// 尝试一次弹窗
let tryPops = function() {
if( nx.bridge.popups ) {
nx.bridge.popups.tryPopup();
}
};
// 是否有串联剧情
let self = this;
let next = function() {
let info = self.queryCfgs( id );
if( !info || nx.dt.strEmpty( info.next ) ) {
tryPops();
return;
}
self.fire( info.next, ( _ret ) => {
if( !_ret ) {
tryPops();
}
} );
};
// 上传
this.reqComplete( id, () => {
nx.dt.fnInvoke( this.cbDone, true );
this.cbDone = null;
next();
} );
},
// 获取当前步骤剧本
stepData: function() {
let info = this.vget( "info" );
let step = this.vget( "step" );
if( step == -1 ) {
return null;
}
let data = info ? info.steps[ step ] : null;
if( nx.dt.objEmpty( data ) ) {
nx.error( "$Plot:获取当前剧本失败:", this.vget( "id" ), step );
}
return data;
},
// 是否已经解锁
isUnlocked: function( _id ) {
return nx.dt.arrMember( this.records.ids, _id );
},
// ============================================================
// 引导元素
// ============================================================
// 注册引导元素
regUnit: function( _key, _node, _cb ) {
let unit = this.units[ _key ];
if( unit ) {
nx.error( "$Plot:重复注册元素:", _key );
return;
}
this.units[ _key ] = {
node: _node, // 聚焦节点
cb: _cb, // 触发回调
};
nx.debug( "$Plot:注册元素:", _key );
},
// 注销引导元素
unregUnit: function( _key ) {
let unit = this.units[ _key ];
if( unit ) {
nx.debug( "$Plot:注销元素:", _key );
delete this.units[ _key ];
}
},
// 查询引导元素
queryUnit: function( _key ) {
let unit = this.units[ _key ];
if( !unit ) {
nx.error( "$Plot:查询元素失败:", _key );
return null;
}
return this.units[ _key ];
},
// 查询引导配置
queryCfgs: function( _id ) {
let key = nx.frame.vget( "hMode" ) ? `H${ _id }` : _id;
let info = this.configs[ key ];
if( nx.dt.objEmpty( info ) ) {
info = this.configs[ _id ];
}
if( nx.dt.objEmpty( info ) ) {
nx.error( "$Plot:配置缺失:", _id );
return null;
}
return info;
},
// ============================================================
// 剧情事件
// ============================================================
// 发送
postKey: function( _key ) {
nx.debug( "$Plot:事件 ", _key );
this.vset( "key", _key );
},
} );
// 模块导出
module.exports = PlotManager;