Exemplo n.º 1
0
        private void PrepareTimeout(IUIManager?ui, IReadOnlyList <Enemy> subbosses, SMHandoff smh, Cancellable toCancel)
        {
            smh.Exec.PhaseShifter = toCancel;
            var timeout = Timeout;

            //Note that the <!> HP(hp) sets invulnTime=0.
            if (props.invulnTime != null && props.phaseType != PhaseType.TIMEOUT)
            {
                WaitingUtils.WaitThenCB(smh.Exec, smh.cT, props.invulnTime.Value, false,
                                        () => smh.Exec.Enemy.SetVulnerable(Vulnerability.VULNERABLE));
            }
            WaitingUtils.WaitThenCancel(smh.Exec, smh.cT, timeout, true, toCancel);
            if (props.phaseType?.IsSpell() ?? false)
            {
                smh.Exec.Enemy.RequestSpellCircle(timeout, smh.cT);
                foreach (var subboss in subbosses)
                {
                    subboss.RequestSpellCircle(timeout, smh.cT);
                }
            }
            //else smh.exec.Enemy.DestroySpellCircle();
            if (!props.HideTimeout && smh.Exec.TriggersUITimeout)
            {
                ui?.DoTimeout(props.phaseType?.IsCard() ?? false, timeout, smh.cT);
            }
        }
Exemplo n.º 2
0
 public SMExecutionTracker(GenCtxProperties <StateMachine> props, SMHandoff smh, out bool isClipped)
 {
     looper              = new LoopControl <StateMachine>(props, smh.ch, out isClipped);
     this.smh            = smh;
     this.smh.CanPrepend = true;
     waitChild           = props.waitChild;
     sequential          = props.sequential;
     checkIsChildDone    = null;
 }
Exemplo n.º 3
0
 private static void SetUniqueBossUI(IUIManager?ui, bool first, SMHandoff smh, BossConfig b)
 {
     if (first)
     {
         ui?.AddProfile(b.profile);
     }
     else
     {
         ui?.SwitchProfile(b.profile);
     }
     ui?.SetBossColor(b.colors.uiColor, b.colors.uiHPColor);
 }
Exemplo n.º 4
0
        private async Task OnFinish(SMHandoff smh, ICancellee prepared, CampaignSnapshot start_campaign,
                                    IBackgroundOrchestrator?bgo, IAyaPhotoBoard?photoBoard)
        {
            if (props.BgTransitionOut != null)
            {
                bgo?.QueueTransition(props.BgTransitionOut);
            }
            if (props.BossPhotoHP.Try(out _))
            {
                photoBoard?.TearDown();
            }
            //The shift-phase token is cancelled by timeout or by HP.
            var completedBy = prepared.Cancelled ?
                              (smh.Exec.isEnemy ?
                               (smh.Exec.Enemy.PhotoHP <= 0 && (props.photoHP ?? 0) > 0) ?
                               PhaseClearMethod.PHOTO :
                               (smh.Exec.Enemy.HP <= 0 && (props.hp ?? 0) > 0) ?
                               PhaseClearMethod.HP :
                               (PhaseClearMethod?)null :
                               null) ??
                              PhaseClearMethod.TIMEOUT :
                              PhaseClearMethod.CANCELLED;
            var pc = new PhaseCompletion(props, completedBy, smh.Exec, start_campaign, Timeout);

            if (pc.StandardCardFinish)
            {
                if (props.Boss != null)
                {
                    BulletManager.RequestPowerAura("powerup1", 0, 0, new RealizedPowerAuraOptions(
                                                       new PowerAuraOptions(new[] {
                        PowerAuraOption.Color(_ => ColorHelpers.CV4(props.Boss.colors.powerAuraColor)),
                        PowerAuraOption.Time(_ => 1f),
                        PowerAuraOption.Iterations(_ => - 1f),
                        PowerAuraOption.Scale(_ => 3.5f),
                        PowerAuraOption.Static(),
                        PowerAuraOption.High(),
                    }), GenCtx.Empty, smh.Exec.GlobalPosition(), smh.cT, null !));
                }
                smh.Exec.DropItems(pc.DropItems, 1.4f, 0.6f, 1f, 0.2f, 2f);
                DependencyInjection.MaybeFind <IRaiko>()
                ?.Shake(defaultShakeTime, defaultShakeMult, defaultShakeMag, smh.cT, null);
            }
            GameManagement.Instance.PhaseEnd(pc);
            if (pc.StandardCardFinish && !smh.Cancelled && props.Boss != null && pc.CaptureStars.HasValue)
            {
                Object.Instantiate(GameManagement.References.prefabReferences.phasePerformance)
                .GetComponent <PhasePerformance>().Initialize($"{props.Boss.CasualName} / Boss Card", pc);
                await WaitingUtils.WaitForUnchecked(smh.Exec, smh.cT, EndOfCardDelayTime, false);
            }
        }
Exemplo n.º 5
0
        private static (List <Enemy>, List <BehaviorEntity>) ConfigureAllBosses(IUIManager?ui,
                                                                                SMHandoff smh, BossConfig main, BossConfig[]?all)
        {
            all ??= new[] { main };
            //BossConfig may summon an Enemy or just a BehaviorEntity.
            //Enemies are tracked in the main boss for HP sharing.
            //BehaviorEntities are tracked
            var subbosses  = new List <Enemy>();
            var subsummons = new List <BehaviorEntity>();

            foreach (var(i, b) in all.Enumerate())
            {
                var target = smh.Exec;
                if (i > 0)
                {
                    target = Object.Instantiate(b.boss).GetComponent <BehaviorEntity>();
                    var mov = new Movement(new Vector2(-50f, 0f), 0f);
                    target.Initialize(null, mov, new ParametricInfo(in mov), SMRunner.Null);
                    subsummons.Add(target);
                }
                if (target.TryAsEnemy(out var e))
                {
                    if (i > 0)
                    {
                        e.distorter = null; // i dont really like this but it overlaps weirdly
                        subbosses.Add(e);
                    }
                    e.ConfigureBoss(b);
                    e.SetVulnerable(Vulnerability.NO_DAMAGE);
                }
                string trackerName = b.BottomTrackerName;
                if (trackerName.Length > 0)
                {
                    ui?.TrackBEH(target, trackerName, smh.cT);
                }
            }
            smh.Exec.Enemy.Subbosses = subbosses;
            return(subbosses, subsummons);
        }
Exemplo n.º 6
0
 public override Task Start(SMHandoff smh) => func(smh);
Exemplo n.º 7
0
 public override Task Start(SMHandoff smh)
 {
     Dialoguer.ShowAndResetDialogue();
     return(base.Start(smh).ContinueWithSync(Dialoguer.HideDialogue));
 }
Exemplo n.º 8
0
        public async Task Start(SMHandoff smh, IUIManager?ui, IReadOnlyList <Enemy> subbosses)
        {
            var bgo        = DependencyInjection.MaybeFind <IBackgroundOrchestrator>();
            var photoBoard = DependencyInjection.MaybeFind <IAyaPhotoBoard>();

            PreparePhase(ui, smh, out Task cutins, bgo, photoBoard);
            var lenienceToken = props.Lenient ?
                                GameManagement.Instance.Lenience.CreateToken1(MultiOp.Priority.CLEAR_PHASE) :
                                null;

            if (props.rootMove != null)
            {
                await props.rootMove.Start(smh);
            }
            await cutins;

            smh.ThrowIfCancelled();
            if (props.phaseType?.IsPattern() == true)
            {
                ETime.Timer.PhaseTimer.Restart();
            }
            var joint_smh = smh.CreateJointCancellee(out var pcTS);

            PrepareTimeout(ui, subbosses, joint_smh, pcTS);
            //The start snapshot is taken after the root movement,
            // so meter can be used during the 1+2 seconds between cards
            var start_campaign = new CampaignSnapshot(GameManagement.Instance);

            if (props.phaseType != null)
            {
                DependencyInjection.MaybeFind <IChallengeManager>()?.SetupBossPhase(joint_smh);
            }
            try {
                await base.Start(joint_smh);

                await WaitingUtils.WaitForUnchecked(joint_smh.Exec, joint_smh.cT, 0f,
                                                    true); //Wait for synchronization before returning to parent

                joint_smh.ThrowIfCancelled();
            } catch (OperationCanceledException) {
                if (smh.Exec.PhaseShifter == pcTS)
                {
                    smh.Exec.PhaseShifter = null;
                }
                //This is critical to avoid boss destruction during the two-frame phase buffer
                if (smh.Exec.isEnemy)
                {
                    smh.Exec.Enemy.SetVulnerable(Vulnerability.NO_DAMAGE);
                }
                lenienceToken?.TryRevoke();
                if (props.Cleanup)
                {
                    GameManagement.ClearPhaseAutocull(props.SoftcullProps(smh.Exec));
                }
                if (smh.Exec.AllowFinishCalls)
                {
                    //TODO why does this use parentCT?
                    finishPhase?.Trigger(smh.Exec, smh.GCX, smh.parentCT);
                    await OnFinish(smh, pcTS, start_campaign, bgo, photoBoard);
                }
                if (smh.Cancelled)
                {
                    throw;
                }
                if (props.phaseType != null)
                {
                    Log.Unity($"Cleared {props.phaseType.Value} phase: {props.cardTitle?.ValueOrEn ?? ""}");
                }
                if (endPhase != null)
                {
                    await endPhase.Start(smh);
                }
            }
        }
Exemplo n.º 9
0
 public override Task Start(SMHandoff smh) => Start(smh, null, new Enemy[0]);
Exemplo n.º 10
0
        private void PreparePhase(IUIManager?ui, SMHandoff smh, out Task cutins,
                                  IBackgroundOrchestrator?bgo, IAyaPhotoBoard?photoBoard)
        {
            cutins = Task.CompletedTask;
            ui?.ShowPhaseType(props.phaseType);
            if (props.cardTitle != null || props.phaseType != null)
            {
                var rate = (props.Boss != null) ?
                           GameManagement.Instance.LookForSpellHistory(props.Boss.key, props.Index) :
                           null;
                ui?.SetSpellname(props.cardTitle?.ToString(), rate);
            }
            if (!props.HideTimeout && smh.Exec.TriggersUITimeout)
            {
                ui?.ShowStaticTimeout(Timeout);
            }
            if (props.livesOverride.HasValue)
            {
                ui?.ShowBossLives(props.livesOverride.Value);
            }
            if (smh.Exec.isEnemy)
            {
                if (props.photoHP.Try(out var photoHP))
                {
                    smh.Exec.Enemy.SetPhotoHP(photoHP, photoHP);
                }
                else if ((props.hp ?? props.phaseType?.DefaultHP()).Try(out var hp))
                {
                    if (props.Boss != null)
                    {
                        hp = (int)(hp * GameManagement.Difficulty.bossHPMod);
                    }
                    smh.Exec.Enemy.SetHP(hp, hp);
                }
                if ((props.hpbar ?? props.phaseType?.HPBarLength()).Try(out var hpbar))
                {
                    smh.Exec.Enemy.SetHPBar(hpbar, props.phaseType ?? PhaseType.NONSPELL);
                }
                smh.Exec.Enemy.SetVulnerable(props.phaseType?.DefaultVulnerability() ??
                                             (props.Boss == null ? Vulnerability.VULNERABLE : Vulnerability.NO_DAMAGE));
            }
            if (props.BossPhotoHP.Try(out var pins))
            {
                photoBoard?.SetupPins(pins);
            }
            bool forcedBG = false;

            if (GameManagement.Instance.mode != InstanceMode.CARD_PRACTICE && !SaveData.Settings.TeleportAtPhaseStart)
            {
                if (props.bossCutin && props.Boss != null && props.Background != null)
                {
                    GameManagement.Instance.ExternalLenience(props.Boss.bossCutinTime);
                    SFXService.BossCutin();
                    //Service not required since no callback
                    DependencyInjection.MaybeFind <IRaiko>()?.Shake(props.Boss.bossCutinTime / 2f, null, 1f, smh.cT, null);
                    Object.Instantiate(props.Boss.bossCutin);
                    bgo?.QueueTransition(props.Boss.bossCutinTrIn);
                    bgo?.ConstructTarget(props.Boss.bossCutinBg, true);
                    WaitingUtils.WaitFor(smh, props.Boss.bossCutinBgTime, false).ContinueWithSync(() => {
                        if (!smh.Cancelled)
                        {
                            bgo?.QueueTransition(props.Boss.bossCutinTrOut);
                            bgo?.ConstructTarget(props.Background, true);
                        }
                    });
                    cutins   = WaitingUtils.WaitForUnchecked(smh.Exec, smh.cT, props.Boss.bossCutinTime, false);
                    forcedBG = true;
                }
                else if (props.GetSpellCutin(out var sc))
                {
                    SFXService.BossSpellCutin();
                    DependencyInjection.MaybeFind <IRaiko>()?.Shake(1.5f, null, 1f, smh.cT, null);
                    Object.Instantiate(sc);
                }
            }
            if (!forcedBG && props.Background != null)
            {
                if (props.BgTransitionIn != null)
                {
                    bgo?.QueueTransition(props.BgTransitionIn);
                }
                bgo?.ConstructTarget(props.Background, true);
            }
        }
Exemplo n.º 11
0
 public override Task Start(SMHandoff smh)
 {
     throw new NotImplementedException("Do not call Start on FinishSM");
 }
Exemplo n.º 12
0
        public override async Task Start(SMHandoff smh)
        {
            var jsmh       = smh.CreateJointCancellee(out var cts);
            var subbosses  = new List <Enemy>();
            var subsummons = new List <BehaviorEntity>();
            var ui         = DependencyInjection.MaybeFind <IUIManager>();

            if (props.boss != null)
            {
                GameManagement.Instance.SetCurrentBoss(props.boss, jsmh.Exec, jsmh.cT);
                ui?.SetBossHPLoader(jsmh.Exec.Enemy);
                (subbosses, subsummons) = ConfigureAllBosses(ui, jsmh, props.boss, props.bosses);
            }
            bool firstBoss = true;

            for (var next = jsmh.Exec.phaseController.WhatIsNextPhase();
                 next > -1 && next < phases.Length;
                 next = jsmh.Exec.phaseController.WhatIsNextPhase(next + 1))
            {
                if (phases[next].props.skip)
                {
                    continue;
                }
                if (PHASE_BUFFER)
                {
                    await WaitingUtils.WaitForUnchecked(jsmh.Exec, jsmh.cT, ETime.FRAME_TIME * 2f, false);
                }
                jsmh.ThrowIfCancelled();
                if (props.bgms != null)
                {
                    AudioTrackService.InvokeBGM(props.bgms.GetBounded(next, null));
                }
                if (props.boss != null && next >= props.setUIFrom)
                {
                    SetUniqueBossUI(ui, firstBoss, jsmh,
                                    props.bosses == null ? props.boss :
                                    props.bosses[props.bossUI?.GetBounded(next, 0) ?? 0]);
                    firstBoss = false;
                }
                //don't show lives on setup phase
                if (next > 0 && props.boss != null)
                {
                    ui?.ShowBossLives(RemainingLives(next));
                }
                try {
                    await phases[next].Start(jsmh, ui, subbosses);
                } catch (OperationCanceledException) {
                    //Runs the cleanup code if we were cancelled
                    break;
                }
            }
            cts.Cancel();
            if (props.boss != null && !SceneIntermediary.LOADING)
            {
                ui?.CloseBoss();
                if (!firstBoss)
                {
                    ui?.CloseProfile();
                }
                foreach (var subsummon in subsummons)
                {
                    subsummon.InvokeCull();
                }
            }
        }
Exemplo n.º 13
0
 public override Task Start(SMHandoff smh)
 {
     values.Add(f(smh.GCX));
     return(Task.CompletedTask);
 }