DatingScenePresenter.ts 8.8 KB
import { Presenter } from "../../../common/classbase/PresenterBase";
import { DatingEventSceneModel, DatingEventStatus } from "../../model/DatingEventSceneModel";
import { DatingSceneView, DatingSceneViewType } from "../view/type/DatingSceneView";
import { RegPresenter } from "../PresenterCCViewFactory";
import { DeepReadonly, delay } from "simba-utils";
import { SentenceType, Plot } from "../../../avg/model/PlotModel";
import { PlotManager } from "../../../avg/PlotManager";
import { Action, ActionType } from "../../../avg/model/ActionModel";
import { getPlot } from "../../../avg/game-data/PlotsData";
import { PlotSceneType } from "../../Enums";
import { ActionManager } from "../../../avg/ActionManager";
import { GameConstData } from "../../../common/gameplay/gamedata/GameConstData";
import { richNodesToCocosString } from "../../../avg/utils/RichTextUtils";
import { UIManager } from "../../../common/gameplay/managers/UIManager";
import SentenceSelectorViewPresenter from "./SentenceSelectorViewPresenter";
import { SentenceSelectorViewProps } from "../view/type/SentenceSelectorView";
import { FaceType } from "../../../avg/EditorEnums";
import { GameModelManager } from "../../model/GameModelManager";
import { GameRecord } from "../../../avg/game-data/GameRecord";
import { EditorEvents } from "../../../avg/EditorEvents";
import { AudioManager } from "../../../common/gameplay/managers/AudioManager";
import GameRoleDataModel from "../../model/GameRoleDataModel";

type DatingPlot = DeepReadonly<Plot & { face: FaceType, portrait?: number, portraitFace?: FaceType }>
@RegPresenter(DatingSceneViewType)
export class DatingScenePresenter extends Presenter<DatingEventSceneModel, DatingSceneView> {
    static uuid = "DatingScenePresenter";
    private _currPlot?: DatingPlot;
    private _executingPlot = false;
    private _completingPlot = false;
    private _isReview = false;
    private _model: DatingEventSceneModel;
    // private _actionFilter?: (action: DeepReadonly<Action>) => boolean;
    private _plotBranch = 0;
    private _currSelect?: number = undefined;
    private _finished = false;

    onOpen(param: DatingEventSceneModel) {
        super.onOpen(param);
        this._finished = false;
        this.view.completePlotCallback = this.completePlot;
        this._model = param;
        delay(0.1).then(async () => {
            if (param.status === DatingEventStatus.Completed) {
                this._isReview = true;
                // this._actionFilter = (action) => {
                //     return action.type !== ActionType.ModifyVariable;
                // }
                this._model.background = "";
                this._currPlot = await getPlot(param.config.start_plot_id)! as DatingPlot;

            } else {
                let plots = PlotManager.getCurrentPlots();
                this._plotBranch = plots.findIndex(v => v.plotSceneType === PlotSceneType.DatingEvent && v.plotSceneTypeId === param.id);
                this._currPlot = plots[this._plotBranch] as DatingPlot;
                if (this._currPlot.id === this._model.firstPlot.id) {
                    GameRecord.recordVariables.bgm = ""; // 新约会,不继承之前剧情的背景音乐存档
                    this._model.background = "";
                }
                this._currSelect = PlotManager.getPlotSelection(this._currPlot.id);
                if (GameRecord.recordVariables.bgm) {
                    AudioManager.playMusic(GameRecord.recordVariables.bgm);
                }
            }
            if (this._model.background) {
                await this.view.setBackground("textures/background/dating_event/" + this._model.background);
            }
            this.execPlot();
        });

        this._disposable.add(EditorEvents.SET_DATING_BG.on((bgPath) => {
            this._model.background = bgPath;
            if (bgPath) bgPath = "textures/background/dating_event/" + bgPath;
            return this.view.setBackground(bgPath);
        }));
    }

    onClose() {
        UIManager.popToPresenter(this);
    }

    async execPlot() {
        if (this._currPlot) {
            if (this._currPlot.plotSceneType === PlotSceneType.DatingEvent && this._currPlot.plotSceneTypeId === this._model.id) {
                this._executingPlot = true;
                const sentence = this._currPlot.sentences[0];
                const content = sentence.content;
                const roleData = GameModelManager.getRoleData(sentence.roleId)!;
                let otherPortrait: string | undefined = undefined;
                if (this._currPlot.portrait !== undefined) {
                    let otherRole = GameModelManager.getRoleData(this._currPlot.portrait);
                    if (otherRole) {
                        otherPortrait = otherRole.getPortrait(this._currPlot.portraitFace);
                    }
                }
                if (content) { // TODO 图片设置
                    if (content.type === SentenceType.TEXT) {
                        await this.view.setContent(sentence.roleId === GameConstData.GAME_CONST_PLAYER_ROLE_VALUE,
                            richNodesToCocosString(content.value),
                            sentence.roleId === 1 ? undefined : roleData.getConfig().name,
                            sentence.roleId === 1 ? otherPortrait : roleData.getPortrait(this._currPlot.face,),
                            otherPortrait);
                    } else if (content.type === SentenceType.SELECT) {
                        let setSelection = async () => {
                            let value = content.value[this._currSelect!];
                            let str = value.summary;
                            if (value.content && value.content.type === SentenceType.EMPTY) { // 空类型,不做展示
                                this.completePlot();
                                return;
                            } else if (value.content && value.content.type === SentenceType.TEXT) {
                                str = richNodesToCocosString(value.content.value);
                            }
                            await this.view.setContent(true, str, roleData.getConfig().name, roleData.getPortrait(this._currPlot!.face), otherPortrait);
                        }
                        if (this._currSelect === undefined) {
                            let props: SentenceSelectorViewProps =
                            {
                                sentence: content,
                                backgroundpath: "",
                                clickcausehide: false,
                                optionStyle1: true,
                                y: -250,
                                onSelectIndexCallback: (index: number) => { this._currSelect = index; setSelection(); }
                            };
                            UIManager.pushPresenter(SentenceSelectorViewPresenter, props);
                            await this.view.setContent(true, "", roleData.getConfig().name, roleData.getPortrait(this._currPlot!.face), otherPortrait);
                        } else {
                            await setSelection();
                        }
                    } else {
                        console.error("不支持的约会剧情", content);
                    }
                } else { // 没有句子,只设置其立绘、背景等
                    await this.view.setContent(false, "", "", roleData.getPortrait(this._currPlot!.face), otherPortrait);
                }
                if (this._currPlot.sentences[0].actions.actions.length) {
                    await ActionManager.executeActions(this._currPlot.sentences[0].actions, undefined, !this._isReview);
                }
                this._executingPlot = false;
            } else {
                // 本次约会剧情结束
                this._model.status = DatingEventStatus.Completed;
                this._finished = true;
                UIManager.showToast("本次剧情结束");
                this.view.guideBack();
            }
        }
    }

    completePlot = async () => {
        if (this._executingPlot || this._completingPlot || !this._currPlot || this._finished) return;
        let content = this._currPlot.sentences[0].content;
        if (content && content.type === SentenceType.SELECT && this._currSelect === undefined) return;
        this._completingPlot = true;
        if (this._isReview) {
            let nextPlot = await PlotManager.getNextPlot(this._currPlot, this._currSelect);
            if (nextPlot) {
                this._currPlot = nextPlot as DatingPlot;
            }
        } else {
            this._model.status = DatingEventStatus.InProgress;
            let nextPlots = await PlotManager.completePlot(this._currPlot, this._currSelect);
            this._currPlot = nextPlots[this._plotBranch] as DatingPlot;
        }
        this._currSelect = undefined;
        this._completingPlot = false;
        this.execPlot();
    }
}