Esempio n. 1
0
        protected async Task PlaySpeech(string content, SoundOptions options)
        {
            UpdateInfo("Testing...");
            await Speech.SayAllOf(content, options);

            UpdateInfo("Test complete.");
        }
Esempio n. 2
0
            protected override async Task startActionAsync()
            {
                foreach (var fx in ValidGlyphs.Select(s => GetFeedbackFX(s)))
                {
                    fx.Play(0.0, true);
                }

                if (ValidGlyphs == null || ValidGlyphs.Count == 0)
                {
                    await Speech.SayAllOf("Casting mistake.  You don't know any spells which begin with that sequence of glyphs.");

                    Deactivate();
                }
                Task.Run(async() =>
                {
                    try
                    {
                        await Shaking.AwaitResult();
                        if (Shaking.AwaitableTask.Status != TaskStatus.RanToCompletion)
                        {
                            return;
                        }
                        abortAction();
                        Deactivate();
                    }
                    catch (TaskCanceledException)
                    {
                        Log.Info("Atropos|GlyphCastStage", "Shaking monitor canceled.");
                    }
                }, StopToken).LaunchAsOrphan();
            }
Esempio n. 3
0
 protected override async void startAction()
 {
     sayIt = Speech.SayAllOf($"Hold device at each position until you hear the tone.  Take your zero stance to begin.",
                             volume: 0.5, cancelToken: StopToken);
     await sayIt;
     //Speech.Say("Hold device at each position yadda yadda.");
     await Task.Delay(1000);
 }
Esempio n. 4
0
            protected override async Task nextStageActionAsync()
            {
                await AttitudeProvider.SetFrameShiftFromCurrent();

                SpellBeingTrained.ZeroStance = AttitudeProvider.FrameShift;

                Log.Debug("SpellTraining", $"Zero stance assigned at {SpellBeingTrained.ZeroStance.ToEulerAngles():f1}.");

                await Speech.SayAllOf("Begin");

                //Speech.Say("Begin");
                CurrentStage = new GlyphTrainingStage($"Glyph 0", Implement, AttitudeProvider);
            }
Esempio n. 5
0
            protected override async Task nextStageActionAsync()
            {
                Current.FormBeingTrained.Strokes.Add(thisStroke);
                int reps = Current.FormBeingTrained.Strokes.Count;
                await Speech.SayAllOf($"Data recorded.  You now have {reps} reps saved.");

                await Task.Delay(500);

                await Speech.SayAllOf($"Return to your ahn garde to record another repetition for averaging, or use onscreen controls to fiddle with data.");

                Current.CheckStrokeCount();
                CurrentStage = new EnGardeStage($"En Garde for rep {reps}", "Setting up another recording. Wait for it...",
                                                new StrokeTrainingStage($"{Current.FormBeingTrained.FormName} stroke, rep {reps}"), true);
            }
Esempio n. 6
0
        public async Task SynchSay(string verbal = null, IEffect aural = null,
                                   float?pitch   = null, float?rate    = null, float?FXvolume = null)
        {
            Verbal     = verbal ?? Verbal;
            Aural      = aural ?? Aural;
            SpeakPitch = pitch ?? SpeakPitch;
            SpeakRate  = rate ?? SpeakRate;

            //await Speech.SayAllOf(Verbal, pitch: SpeakPitch, speakRate: SpeakRate,
            //    doOnStart: () => { Aural.Play(FXvolume ?? defaultFXvolume); });
            await Task.WhenAll(Speech.SayAllOf(Verbal, pitch: SpeakPitch, speakRate: SpeakRate), Aural.PlayToCompletion(FXvolume ?? defaultFXvolume));

            //if (Aural.IsPlaying) Aural.Stop();
        }
Esempio n. 7
0
            //protected override void prestartAction()
            //{
            //    AttitudeProvider = EnGardeStage.EngardeProvider ?? new FrameShiftedOrientationProvider(
            //        Android.Hardware.SensorType.GameRotationVector, Blade.EnGardeOrientation.Average); // .Inverse()?
            //    Log.Debug("Form training", $"Attitude Provider reference frame is {AttitudeProvider.FrameShift.ToStringFormatted("f4")}");
            //    if (!AttitudeProvider.IsActive) AttitudeProvider.Activate();
            //}

            protected override async Task startActionAsync()
            {
                if (IsInitialPoseEstimate)
                {
                    await Speech.SayAllOf("First we need approximate readings of where the stroke begins and ends.");

                    await Task.Delay(500);

                    await Speech.SayAllOf("Take a still pose at roughly the start of the smooth central portion of the stroke.");
                }
                else
                {
                    await Speech.SayAllOf("Got it.  Next, take a still pose at roughly the end of that smooth central part of the stroke.");
                }
                await SFX.PlayByID(Current, Resource.Raw._175949_clash_t).WhenFinishedPlaying;
            }
Esempio n. 8
0
        protected override async void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.MeleeTraining);

            currentSignalsDisplay = FindViewById <TextView>(Resource.Id.current_signals_text);
            bestSignalsDisplay    = FindViewById <TextView>(Resource.Id.best_signals_text);
            resultsDisplay        = FindViewById <TextView>(Resource.Id.result_text);

            SetUpFormButtons();

            // See if the current sword is already in our (local, for now) library, and load it if so.  Otherwise, create one.
            var swordString = Res.SpecificTags.Get(InteractionLibrary.CurrentSpecificTag);

            if (swordString != null && swordString.Length > 0)
            {
                ThePlayersSword = Sword.FromString(swordString, InteractionLibrary.CurrentSpecificTag);
                CurrentStage    = GestureRecognizerStage.NullStage;
                return;
            }
            else if (InteractionLibrary.CurrentSpecificTag == InteractionLibrary.MeleeTeaching.Name + "0000")
            {
                Sword.InitMasterSword();
                InteractionLibrary.CurrentSpecificTag = Sword.MasterSword.TagID;
                Log.Info("Training", "Using master sword.");
                ThePlayersSword = Sword.MasterSword;
            }
            else
            {
                ThePlayersSword = new Sword(InteractionLibrary.CurrentSpecificTag);
            }

            if (ThePlayersSword.EnGardeOrientation == null || ThePlayersSword.EnGardeOrientation.Average.AngleTo(Quaternion.Identity) < 1)
            {
                await Speech.SayAllOf("No pre-existing ahn garde stance found.  Please take and hold your ahn garde stance to begin.");

                CurrentStage = new DefineEnGardeStage("Defining new en garde", true);
            }
            else
            {
                await Speech.SayAllOf("Confirm your saved ahn garde stance to begin.");

                setFormNameButton.Text = RetrainEnGardeText;
                CurrentStage           = new EnGardeStage("Confirm en garde", "Okay. Use onscreen buttons to train specific forms.", GestureRecognizerStage.NullStage, true);
            }
        }
Esempio n. 9
0
            protected override async Task nextStageActionAsync()
            {
                if (IsInitialPoseEstimate)
                {
                    Current.FormBeingTrained.InitialOrientation = AttitudeProvider.Quaternion;
                    Log.Debug("Stroke still stances", $"Still position #1 set at {AttitudeProvider.Quaternion}, {AttitudeProvider.Quaternion.AngleTo(Quaternion.Identity)} degrees from En Garde.");
                    CurrentStage = new FormSetupStage($"{Current.FormBeingTrained.FormName} form, second still pose", AttitudeProvider, true);
                }
                else
                {
                    await Speech.SayAllOf("Thank you. Take your ahngarde stance again.");

                    Current.FormBeingTrained.FinalOrientation = AttitudeProvider.Quaternion;
                    Log.Debug("Stroke still stances", $"Still position #2 set at {AttitudeProvider.Quaternion}, {AttitudeProvider.Quaternion.AngleTo(Quaternion.Identity)} degrees from En Garde.");
                    CurrentStage = new EnGardeStage("En Garde before stroke training", "Wait for the cue, then execute the form as you wish it to be judged in play.",
                                                    new StrokeTrainingStage($"{Current.FormBeingTrained.FormName}, stroke training, rep 0"), true);
                }
            }
Esempio n. 10
0
            protected override async Task nextStageActionAsync()
            {
                //await AttitudeProvider.SetFrameShiftFromCurrent();
                //Blade.EnGardeOrientation = new AdvancedRollingAverageQuat(10, null, AttitudeProvider.FrameShift.Inverse());
                //Blade.EnGardeOrientation = new AdvancedRollingAverageQuat(10, null, AverageAttitude.Average, 1.0f);
                Blade.EnGardeOrientation = AverageAttitude;
                Blade.EnGardeOrientation.Update(AttitudeProvider.Quaternion);
                Log.Debug("Melee Training", $">>>> Setting en garde to {Blade.EnGardeOrientation.Average}, with sigma {Blade.EnGardeOrientation.Sigma}.  In reference frame {AttitudeProvider.FrameShift}.");
                Blade.SaveSpecifics(); // Saves both the average attitude itself, and also the standard deviation of it.  Important for later!

                await Speech.SayAllOf("Okay.  Use the onscreen controls to train specific forms.");

                CurrentStage = GestureRecognizerStage.NullStage;
                Current.formNameTextbox.Enabled = true;
                //await Speech.SayAllOf("Begin");
                //if (Current.AppendMode == null || Current.AppendMode == false)
                //    CurrentStage = new FormSetupStage($"{Label} form prep", AttitudeProvider);
                //else
                //    CurrentStage = new StrokeTrainingStage($"{Label} appending ({Current.FormBeingTrained.Strokes.Count})", AttitudeProvider);
            }
Esempio n. 11
0
            protected override async Task nextStageActionAsync()
            {
                if (Current.setFormNameButton.Text == RetrainEnGardeText)
                {
                    Current.setFormNameButton.Text = "Random";                                                       // Undoes our little textual flag that lets us retrain the en garde using this button instead of its usual function.
                }
                var oldOrientation = Blade.EnGardeOrientation.Average;

                Blade.EnGardeOrientation.Update(AttitudeProvider.Quaternion); // Subtle trick: we keep averaging the En Garde orientation so it "tracks" the player's shifts in taking it, over time.
                Log.Debug("EnGarde Stage", $"Updating the prior en garde ({oldOrientation}), using the new one ({AttitudeProvider.Quaternion}," +
                          $" {AttitudeProvider.Quaternion.AngleTo(oldOrientation)} degrees away), producing a new one ({Blade.EnGardeOrientation.Average}," +
                          $" {Blade.EnGardeOrientation.Average.AngleTo(oldOrientation)} degrees away from the prior one).");

                //// In order to *pass along* a provider, to an arbitrary Gesture Stage which has already been created and passed to us
                //// (and which might or might not want to use our provider at all), we use this trick.  Activate it in here, and during
                //// activation, a specific STATIC provider is made available.  We lock so that (in theory) two EnGarde Stages which were
                //// running in separate threads wouldn't end up accessing the static value at the wrong times.
                //using (await _asyncLock.LockAsync())
                //{
                //    //EngardeProvider = AttitudeProvider; // Can be referenced from inside the prestartAction of the provided stage, if desired. (Not during the ctor... that's already gone by!)
                //    EngardeProvider = new FrameShiftedOrientationProvider(Android.Hardware.SensorType.GameRotationVector);
                //    await Task.WhenAll(EngardeProvider.SetFrameShiftFromCurrent(), Speech.Say(NextStageCue));
                //    CurrentStage = NextStage;
                //    CurrentStage.Activate();
                //    EngardeProvider = null;
                //}

                // Different approach to solving the above problem.
                var EngardeProvider = new FrameShiftedOrientationProvider(Android.Hardware.SensorType.GameRotationVector);
                await Task.WhenAll(EngardeProvider.SetFrameShiftFromCurrent(), Speech.SayAllOf(NextStageCue));

                CurrentStage = NextStage;
                var cStage = CurrentStage as ITakeAnAttitudeProvider;

                if (cStage != null)
                {
                    cStage.AttitudeProvider = EngardeProvider;
                }
                CurrentStage.Activate();
            }
Esempio n. 12
0
        protected void CreateSpeechTests()
        {
            CategoryNames.Add("Speech Tests");
            CreateTest("Simple", () => PlaySpeech("Some simple speech.", SoundOptions.Default));
            CreateTest("OnHeadphones", () => PlaySpeech("Some simple speech.", SoundOptions.OnHeadphones));
            CreateTest("OnSpeaker", () => PlaySpeech("Some simple speech.", SoundOptions.OnSpeakers));
            CreateTest("Softer", () => PlaySpeech("Not exactly whispering, but as close as we get.", new SoundOptions()
            {
                Volume = 0.2
            }));
            CreateTest("Plus SFX", async() =>
            {
                UpdateInfo("Testing...");
                await Task.WhenAll(Speech.SayAllOf("This is a clash; we'll use it in a parry cue in melee."),
                                   Task.Delay(500).ContinueWith(_ => { var eff = new Effect("Clash", Resource.Raw._175949_clash_t); return(eff.PlayToCompletion()); }));
                UpdateInfo("Test complete.");
            });
            CreateTest("Overlapping*", async() =>
            {
                UpdateInfo("Testing");
                await Task.WhenAll(Speech.SayAllOf("This is stream number one."), Speech.SayAllOf("This is stream number two."));
                UpdateInfo("Testing complete.");
            });
            CreateTest("Pitch increase", () => PlaySpeech("Scaramouche, scaramouche, will you do the fandango?", new SoundOptions()
            {
                Pitch = 4.0
            }));
            CreateTest("Pitch decrease", () => PlaySpeech("Figaro. Figaro figaro figaro.", new SoundOptions()
            {
                Pitch = 0.25
            }));
            CreateTest("Rate increase", () => PlaySpeech("How much wood can a woodchuck chuck?", new SoundOptions()
            {
                Speed = 2.5
            }));
            CreateTest("Rate decrease", () => PlaySpeech("Hobbits can be very hasty. Very hasty indeed.", new SoundOptions()
            {
                Speed = 0.35
            }));
            CreateTest("Cancelled (Timed)", async() =>
            {
                cts = new CancellationTokenSource();
                UpdateInfo("Testing...");
                var speechTask = Speech.SayAllOf("This sentence should end in silence before it reaches its end.  Don't fret; this test is expected to fail.", new SoundOptions()
                {
                    CancelToken = cts.Token
                })
                                 .SwallowCancellations();
                await Task.WhenAny(
                    speechTask,
                    Task.Delay(1500));
                UpdateInfo("Interrupt token sent. Ideally, speech should stop; test continues.");
                cts.Cancel();
                await speechTask;
                await Task.Delay(500);
                UpdateInfo("Test complete.");
                cts = null;
            });
            CreateTest("Cancelled (Manual)", async() =>
            {
                var token = SetupStopButtonOneShot("Interrupt token sent. Sound should stop; test continues.");

                UpdateInfo("Testing...");
                var speechString = "This is a test of the interrupt mechanism.  This is only a test.  If this were a real interrupt, I would have stopped speaking by now, assuming you hit the stop button by this point.  If not, you should, quick, before I'm done. I'm done.";
                await Speech.SayAllOf(speechString, new SoundOptions()
                {
                    CancelToken = token
                }).SwallowCancellations();
                UpdateInfo("Test complete.");
            });
            CreateTest("Interrupted (Timed)", async() =>
            {
                UpdateInfo("Testing...");
                var speechTask = Speech.SayAllOf("This sentence should be interrupted before it reaches its end.  If you're hearing this, the test has been failed.")
                                 .SwallowCancellations();
                await Task.WhenAny(
                    speechTask,
                    Task.Delay(1500));
                UpdateInfo("Interrupt speech sent. Ideally, speech should switch abruptly; test continues.");
                new Effect("Grunt", Resource.Raw._129346_male_grunt_1).Play();
                var speechTask2 = Speech.SayAllOf("Aw, never mind.", new SoundOptions()
                {
                    Interrupt = true
                });
                await speechTask2;
                UpdateInfo("Test complete.");
            });
        }
Esempio n. 13
0
        private void SetUpFormButtons()
        {
            var layoutpanel = FindViewById <LinearLayout>(Resource.Id.Form_list_layoutpane);

            formNameTextbox    = FindViewById <EditText>(Resource.Id.form_name_textbox);
            setFormNameButton  = FindViewById <Button>(Resource.Id.Set_form_name_button);
            strokeCountDisplay = FindViewById <TextView>(Resource.Id.stroke_count_display);
            reassessButton     = FindViewById <Button>(Resource.Id.reassess_button);
            pauseButton        = FindViewById <Button>(Resource.Id.pause_button);
            finalizeButton     = FindViewById <Button>(Resource.Id.finalize_button);
            paramAbox          = FindViewById <EditText>(Resource.Id.parameterAtextbox);
            paramBbox          = FindViewById <EditText>(Resource.Id.parameterBtextbox);
            paramCbox          = FindViewById <EditText>(Resource.Id.parameterCtextbox);

            foreach (string formName in MasterFechtbuch.formNames?.DefaultIfEmpty() ?? new string[0])
            {
                var form       = MasterFechtbuch.Get(formName);
                var formButton = new Button(this);
                var codicil    = (form != null && form != Form.None) ? "" : " (Unknown)";
                formButton.SetText(formName + codicil, TextView.BufferType.Normal);
                formButton.SetPadding(20, 20, 20, 20);
                layoutpanel.AddView(formButton);
                formButtons.Add(formButton);

                formButton.Click += async(o, e) =>
                {
                    if (FormBeingTrained != null)
                    {
                        return;                            // Debouncing, basically.
                    }
                    if (form != null && form != Form.None) // The target form does already exist in more than theory.
                    {
                        AppendMode         = true;
                        FormBeingRetrained = form;
                        FormBeingTrained   = form;
                        foreach (Button btn in formButtons)
                        {
                            btn.Enabled = false;
                        }
                        setFormNameButton.Text    = "Retrain Instead";
                        formNameTextbox.Text      = formName;
                        formNameTextbox.Focusable = false;
                        CheckStrokeCount();
                        await Speech.SayAllOf($"Adding more training for {formName}. Ahn garde!");

                        CurrentStage = new EnGardeStage($"En Garde for rep {FormBeingTrained.Strokes.Count}", "Setting up another recording. Wait for the cue...",
                                                        new StrokeTrainingStage($"{Current.FormBeingTrained.FormName} stroke, rep {FormBeingTrained.Strokes.Count}"), true);
                    }
                    else // It only existed as a theory - treat it as if the user had typed in the name.
                    {
                        formNameTextbox.Text = formName;
                        setFormNameButton.CallOnClick();
                    }
                };
            }

            formNameTextbox.KeyPress += (object sender, View.KeyEventArgs e) =>
            {
                e.Handled = false;
                if (e.Event.Action == KeyEventActions.Down && e.KeyCode == Keycode.Enter && formNameTextbox.Text.Length > 0)
                {
                    setFormNameButton.CallOnClick();
                }
                if (formNameTextbox.Text.Length > 0)
                {
                    setFormNameButton.Text = "Train";
                }
                else
                {
                    setFormNameButton.Text = "Random";
                }
            };

            setFormNameButton.Click += async(o, e) =>
            {
                if (setFormNameButton.Text == RetrainEnGardeText)
                {
                    CurrentStage.Deactivate();
                    setFormNameButton.Text = "Random";
                    CurrentStage           = new DefineEnGardeStage("Redefining en garde", true);
                    return;
                }
                if (FormBeingRetrained != null)
                {
                    if (AppendMode == true)
                    {
                        AppendMode             = false;
                        FormBeingTrained       = new Form(FormBeingRetrained.FormName, FormBeingRetrained.IsOffense);
                        setFormNameButton.Text = "Erase form";
                        await Speech.SayAllOf("Retraining from start.");

                        return;
                    }
                    else if (setFormNameButton.Text == "Erase form")
                    {
                        setFormNameButton.Text = "Confirm erasure";
                        return;
                    }
                    else if (setFormNameButton.Text == "Confirm erasure")
                    {
                        MasterFechtbuch.Erase(FormBeingRetrained.FormName);
                        ThePlayersSword.ForgetForm(FormBeingRetrained.FormName);
                        await Speech.SayAllOf($"Deleting {FormBeingRetrained.FormName} from the master library.");

                        CurrentStage.Deactivate();
                        CurrentStage = GestureRecognizerStage.NullStage;
                        Finish();
                        return;
                    }
                }
                FormBeingRetrained = null;
                AppendMode         = null;
                if (formNameTextbox.Text.Length == 0)
                {
                    formNameTextbox.Text = GenerateRandomFormName();
                }
                await Task.Delay(100); // Let the screen update.

                FormBeingTrained = new Form(formNameTextbox.Text, !(formNameTextbox.Text.EndsWith("Parry")));
                foreach (Button btn in formButtons)
                {
                    btn.Enabled = false;
                }
                formNameTextbox.Focusable = false;
                await Speech.SayAllOf($"Training {FormBeingTrained.FormName}.  Ahn garde!");

                CheckStrokeCount();
                CurrentStage = new EnGardeStage("EnGarde pre-Form Setup", "", new FormSetupStage($"Init training for {FormBeingTrained.FormName}"), true);
            };

            reassessButton.Click += (o, e) =>
            {
            };

            pauseButton.Click += async(o, e) =>
            {
                if (pauseButton.Text == "Pause Sensors")
                {
                    pauseButton.Text = "Resume Sensors";
                    Res.SFX.StopAll();
                    CurrentStage.Deactivate();
                    await Speech.SayAllOf($"Pausing sensors.  Take your time and play with the parameter buttons.");

                    CurrentStage = GestureRecognizerStage.NullStage;
                }
                else
                {
                    pauseButton.Text = "Pause Sensors";
                    await Speech.SayAllOf($"Resume training for {FormBeingTrained.FormName}. Ahn garde!");

                    CurrentStage = new EnGardeStage($"En Garde for rep {FormBeingTrained.Strokes.Count}", "Setting up another recording. Wait for the cue...",
                                                    new StrokeTrainingStage($"{Current.FormBeingTrained.FormName} stroke, rep {FormBeingTrained.Strokes.Count}"), true);
                }
            };

            finalizeButton.Click += async(o, e) =>
            {
                if (finalizeButton.Text == "Finalize")
                {
                    // Halt ongoing processeses (if not already done via the Pause button).
                    Res.SFX.StopAll();
                    CurrentStage.Deactivate();
                    CurrentStage        = GestureRecognizerStage.NullStage;
                    finalizeButton.Text = "Commit to Fechtbuch";
                }
                else
                {
                    // TODO: Stuff.
                    MasterFechtbuch.Inscribe(FormBeingTrained);
                    ThePlayersSword.LearnForm(FormBeingTrained);

                    if (FormBeingRetrained == null)
                    {
                        await Speech.SayAllOf($"Adding {FormBeingTrained.FormName} to the master fechtbuch.");
                    }
                    else
                    {
                        await Speech.SayAllOf($"Updating form listing for {FormBeingTrained.FormName}.");
                    }
                    Log.Info("MeleeTraining", $"Here's the form string for copy-and-pasting as a constant: {FormBeingTrained.ToString()}");
                    Finish();
                }
            };
        }
Esempio n. 14
0
        // This is currently a bit of a hack, because we only support a single security panel.  It's virtual, though, so... you do the math.
        public virtual void SetUpSecurity()
        {
            // Create all of the instances.  Their ctors will take care of inserting them in the dictionaries.
            var A = new SecurityPanelNode("Upper Solenoid", "A", Resource.Drawable.securitypanel_overlay_topleft);    // The one kept hot-meaning-unlocked so that the doors will auto-seal if power dies.
            var B = new SecurityPanelNode("Lower Solenoid", "B", Resource.Drawable.securitypanel_overlay_bottomleft); // The one kept cool-meaning-locked which is used to open them normally.
            var C = new SecurityPanelNode("Communications", "C", Resource.Drawable.securitypanel_overlay_bottom);
            var D = new SecurityPanelNode("Processor", "D", Resource.Drawable.securitypanel_overlay_center);

            Nodes.Add(A);
            Nodes.Add(B);
            Nodes.Add(C);
            Nodes.Add(D);

            var AtoB = new SecurityPanelNodeLink(A, B);
            var AtoC = new SecurityPanelNodeLink(A, C, true);
            var AtoD = new SecurityPanelNodeLink(A, D, true);
            var BtoA = new SecurityPanelNodeLink(B, A);
            var BtoC = new SecurityPanelNodeLink(B, C, true);
            var BtoD = new SecurityPanelNodeLink(B, D, true);
            var CtoA = new SecurityPanelNodeLink(C, A);
            var CtoB = new SecurityPanelNodeLink(C, B);
            var CtoD = new SecurityPanelNodeLink(C, D, true);
            var DtoA = new SecurityPanelNodeLink(D, A, true);
            var DtoB = new SecurityPanelNodeLink(D, B, true);
            var DtoC = new SecurityPanelNodeLink(D, C, true);

            // Define Examine strings
            A.Results[0] = "Clearly a solenoid used to shift the door's locking bolts.  No way to tell if 'powered on' means the door is locked or unlocked, though.";
            A.Results[2] = "This one is hot to the touch - must be live and at fairly high voltage.";
            B.Results[0] = A.Results[0];
            B.Results[2] = "This one is cool to the touch.  Probably off at present.";
            C.Results[0] = "Fiber-optic communications line to elsewhere in the building.";
            C.Results[2] = "Not a lot of data flowing out right now, mostly just telemetry from the processor over on the right.";
            D.Results[0] = "The central processor for this panel.  Not very smart, but smart enough.";
            D.Results[2] = "";

            // Define Measure linkages
            AtoB.MeasureResults[0] = "There's no direct connection between the two solenoids.";
            AtoC.MeasureResults[0] = "Looks like there's a single status line running from the solenoid to the comm relay.";
            AtoC.MeasureResults[1] = "This one is showing 3.3V, steady.  A pretty standard signal for 'on' or some other binary 'one'.";
            AtoD.MeasureResults[0] = "Looks like there's just a simple status line running back to the processor.";
            AtoD.MeasureResults[1] = AtoC.MeasureResults[2];

            BtoA.MeasureResults[0] = AtoB.MeasureResults[0];
            BtoC.MeasureResults[0] = AtoC.MeasureResults[0];
            BtoC.MeasureResults[1] = "This line is rated for the usual few volts, but currently it just reads zero.";
            BtoD.MeasureResults[0] = AtoD.MeasureResults[0];
            BtoD.MeasureResults[1] = BtoC.MeasureResults[1];

            CtoA.MeasureResults[0] = "There's no sign of any data in this direction.";
            CtoB.MeasureResults[0] = CtoA.MeasureResults[0];
            CtoD.MeasureResults[0] = "There's certainly some data flowing along this route, on an intermittent basis.";
            CtoD.MeasureResults[2] = "You do identify one channel here: an encrypyted data stream, probably from a card reader or some other access device.  If we had implemented it, your decker might be able to hack this and fake a valid code, but that's not coded yet.";

            DtoA.MeasureResults[0] = "A 3.3 volt control signal is stepped up to plus sixty volts and a pretty high current in the solenoid.";
            DtoA.MeasureResults[2] = "The way they've engineered this link, it's pretty clear that it's intended to stay hot much if not most of the time.";
            DtoB.MeasureResults[0] = "The step-up transformers along this path seem to be sitting idle; the high voltage lines currently inactive.";
            DtoC.MeasureResults[0] = "A data bus carries several signals out to the comms relay from the processor.";
            DtoC.MeasureResults[2] = "You'd have to have access to the source code, or several hours to play with this, before you could make any sense of what's in this data stream.";

            // Wire Cutter results (where nontrivial).
            // Note that .IsLinked = False is automatically a result; this is apart from that,
            // and a check for .IsLinked that will send up a "nothing to cut" if relevant is likewise built in.
            AtoC.WirecutterResult = () => { SuspiciousInfoHasBeenSent = true; };                       // Looks to the control panel like the backup locks just locked themselves.
            AtoD.WirecutterResult = () => { AlarmHasBeenRaised = true; Blare(AlarmFX); };              // The door knows IT didn't tell the backups to go dead, so someone's tampering.
            DtoC.WirecutterResult = () => { AlarmHasBeenRaised = true; Blare(AlarmFX); };              // Control just lost all communications with this door.
            DtoA.WirecutterResult = () => { SecondaryBoltsAreEngaged = true; Blare(BoltsClosingFX); }; // Congrats, you just screwed up and locked yourself out.
            DtoB.WirecutterResult = () => { DtoB.SolderingResult = AtoB.SolderingResult; };

            // Soldering results - similar IsLinked comments as above.
            AtoB.SolderingResult = async() =>
            {
                if (BtoC.IsLinked)
                {
                    SuspiciousInfoHasBeenSent = true;
                }
                if (BtoD.IsLinked)
                {
                    AlarmHasBeenRaised = true; Blare(AlarmFX);
                }
                ;
                Blare(BoltsOpeningFX);
                MainBoltsAreEngaged = false;
                await Speech.SayAllOf("Doors are now open; proceed.");
            };
            BtoA.SolderingResult = async() =>
            {
                await BoltsClosingFX.PlayToCompletion(10.0, true);

                SecondaryBoltsAreEngaged = true;
                await Speech.SayAllOf("Uh-oh.  That was the secondary bolts engaging - and you're pretty sure the solenoid won't be capable of opening them again.  Looks like Paper Crane is going to be making a service call... or two.");
            };
            AtoC.SolderingResult = AtoD.SolderingResult = async() =>
            {
                AlarmHasBeenRaised = true;
                await SparksFX.PlayToCompletion(1.0, true);

                await Speech.SayAllOf("You have managed to put about six amps through a delicate piece of circuitry.  Congratulations - you just 'bricked' this door.");

                AlarmFX.Play(1.0, false, true);
            };
        }
Esempio n. 15
0
        private void SetUpSpellButtons()
        {
            var layoutpanel = FindViewById <LinearLayout>(Resource.Id.Spell_casting_layoutpane);

            foreach (var spB in spellButtons)
            {
                spB.Visibility = ViewStates.Gone;
            }
            spellButtons.Clear();

            foreach (string spellName in MasterSpellLibrary.spellNames?.DefaultIfEmpty() ?? new List <string>())
            {
                if (spellName == Spell.None.SpellName)
                {
                    continue;
                }
                var spell       = MasterSpellLibrary.Get(spellName);
                var spellButton = new Button(this);
                spellButtons.Add(spellButton);
                spellButton.SetText(spellName + " (Retrain)", TextView.BufferType.Normal);
                spellButton.SetPadding(20, 20, 20, 20);
                layoutpanel.AddView(spellButton);

                spellButton.Click += (o, e) =>
                {
                    if (SpellBeingTrained != null)
                    {
                        return;                            // Debouncing, basically.
                    }
                    SpellBeingRetrained = spell;
                    SpellBeingTrained   = new Spell(spellName);
                    foreach (Button btn in spellButtons)
                    {
                        btn.Visibility = ViewStates.Gone;
                    }
                    setSpellNameButton.Text    = "Erase spell";
                    spellNameTextbox.Text      = spellName;
                    spellNameTextbox.Focusable = false;
                    CheckGlyphCount();
                    Speech.Say($"Retraining {spellName}.");
                    CurrentStage = new Spell_Training_TutorialStage($"Retraining {spellName}", ThePlayersFocus, true);
                };
            }

            spellNameTextbox   = FindViewById <EditText>(Resource.Id.spell_name_textbox);
            setSpellNameButton = FindViewById <Button>(Resource.Id.Set_spell_name_button);
            glyphCountDisplay  = FindViewById <TextView>(Resource.Id.glyph_count_display);
            undoGlyphButton    = FindViewById <Button>(Resource.Id.undo_glyph_button);
            inscribeButton     = FindViewById <Button>(Resource.Id.inscribe_spell_button);

            spellNameTextbox.KeyPress += (object sender, View.KeyEventArgs e) =>
            {
                e.Handled = false;
                if (e.Event.Action == KeyEventActions.Down && e.KeyCode == Keycode.Enter && spellNameTextbox.Text.Length > 0)
                {
                    setSpellNameButton.CallOnClick();
                }
                if (spellNameTextbox.Text.Length > 0)
                {
                    setSpellNameButton.Text = "Train";
                }
                else
                {
                    setSpellNameButton.Text = "Random";
                }
            };
            spellNameTextbox.ClearFocus(); // Not working, dunno why.

            setSpellNameButton.Click += async(o, e) =>
            {
                if (SpellBeingRetrained != null)
                {
                    if (setSpellNameButton.Text == "Erase spell")
                    {
                        setSpellNameButton.Text = "Confirm erasure"; return;
                    }
                    else if (setSpellNameButton.Text == "Confirm erasure")
                    {
                        MasterSpellLibrary.Erase(SpellBeingRetrained.SpellName);
                        ThePlayersFocus.ForgetSpell(SpellBeingRetrained.SpellName);
                        CurrentStage.Deactivate();
                        await Speech.SayAllOf($"Deleting {SpellBeingRetrained.SpellName} from the master library.");

                        CurrentStage = GestureRecognizerStage.NullStage;
                        //SetUpSpellButtons();
                        Current.Finish();
                        return;
                    }
                }
                SpellBeingRetrained = null;
                if (spellNameTextbox.Text.Length == 0)
                {
                    spellNameTextbox.Text = GenerateRandomSpellName();
                }
                Current.HideKeyboard();
                await Task.Delay(100); // Let the screen update.

                SpellBeingTrained = new Spell(spellNameTextbox.Text);
                foreach (Button btn in spellButtons)
                {
                    btn.Visibility = ViewStates.Gone;
                }
                //spellNameTextbox.Focusable = false;
                CheckGlyphCount();
                await Speech.SayAllOf($"Training {SpellBeingTrained.SpellName}.");

                CurrentStage = new Spell_Training_TutorialStage($"Init training for {SpellBeingTrained.SpellName}", ThePlayersFocus, true);
            };

            FindViewById <Button>(Resource.Id.glyph_training_btn).Click += async(o, e) =>
            {
                var glyphText = Res.Storage.Get(NewGlyphTrainingStage.GlyphKey);
                if (glyphText != null)
                {
                    Log.Debug("SpellTraining", "\n" + glyphText);
                }

                Current.HideKeyboard();
                await Task.Delay(100); // Let the screen update.

                foreach (Button btn in spellButtons)
                {
                    btn.Visibility = ViewStates.Gone;
                }
                await Speech.SayAllOf($"Training core glyphs.");

                //CurrentStage = new Spell_Training_TutorialStage($"Init training for {SpellBeingTrained.SpellName}", ThePlayersFocus, true);

                var provider = new GravityOrientationProvider();
                provider.Activate();
                Task.Delay(50)
                .ContinueWith(async _ => await SensorProvider.EnsureIsReady(provider))
                .ContinueWith(_ => CurrentStage = new NewGlyphTrainingStage(0, ThePlayersFocus, provider))
                .LaunchAsOrphan();
            };

            undoGlyphButton.Click += async(o, e) =>
            {
                if (SpellBeingTrained.Glyphs.Count == 0)
                {
                    foreach (Button btn in spellButtons)
                    {
                        btn.Enabled = true;
                    }
                    spellNameTextbox.Text      = "";
                    spellNameTextbox.Focusable = true;
                    setSpellNameButton.Enabled = true;
                    setSpellNameButton.Text    = "Random";
                    SpellBeingRetrained        = null;
                    SpellBeingTrained          = null;
                    CurrentStage.Deactivate();
                    CurrentStage = GestureRecognizerStage.NullStage;
                    SetUpSpellButtons();
                    await Speech.SayAllOf("Aborting spell training.");
                }
                else
                {
                    SpellBeingTrained.UndoAddGlyph();
                    await Speech.SayAllOf("Removing most recent glyph.");
                }
                CheckGlyphCount();
            };

            var feedbackSFXbtn = FindViewById <Button>(Resource.Id.spell_feedback_sfx_button);
            var progressSFXbtn = FindViewById <Button>(Resource.Id.spell_progress_sfx_button);
            var successSFXbtn  = FindViewById <Button>(Resource.Id.spell_success_sfx_button);

            if (!MasterSpellLibrary.GetSFXReadyTask().Wait(5000))
            {
                Log.Error("Spell training", "Can't prep the buttons (as is, anyway) without our SFX loaded, which doesn't seem to be happening.");
            }
            var feedbackSFXoptions = new SimpleCircularList <string>("Magic.Ethereal",
                                                                     "Magic.Aura", "Magic.DeepVenetian", "Magic.InfiniteAubergine", "Magic.Ommm", "Magic.AfricanDrums",
                                                                     "Magic.Rommble", "Magic.MidtonePianesque", "Magic.FemReverbDSharp", "Magic.FemReverbCSharp",
                                                                     "Magic.FemReverbF", "Magic.FemReverbE", "Magic.AlienTheremin",
                                                                     "Magic.TrompingBuzzPulse", "Magic.GrittyDrone", "Magic.Galewinds", "Magic.NanobladeLoop",
                                                                     "Magic.ViolinLoop", "Magic.StrongerThanTheDark", "Magic.MelodicPad");
            var progressSFXoptions = new SimpleCircularList <string>(MasterSpellLibrary.SpellSFX.Keys.Where(sfx => !feedbackSFXoptions.Contains(sfx)).DefaultIfEmpty().ToArray());
            var successSFXoptions  = new SimpleCircularList <string>(MasterSpellLibrary.CastingResults.Keys.ToArray());

            while (progressSFXoptions.Next != MasterSpellLibrary.defaultProgressSFXName)
            {
            }                                                                                // Cycle the list to the correct starting point.
            while (successSFXoptions.Next != "Play " + MasterSpellLibrary.defaultSuccessSFXName)
            {
            }                                                                                        // Cycle the list to the correct starting point.

            inscribeButton.Click += async(o, e) =>
            {
                if (inscribeButton.Text == "Inscribe Spell")
                {
                    // Halt ongoing processeses
                    MasterSpellLibrary.SpellFeedbackSFX.Deactivate();
                    CurrentStage.Deactivate();
                    CurrentStage = GestureRecognizerStage.NullStage;

                    // Display SFX modification buttons
                    feedbackSFXbtn.Visibility = ViewStates.Visible;
                    progressSFXbtn.Visibility = ViewStates.Visible;
                    successSFXbtn.Visibility  = ViewStates.Visible;

                    IEffect sampleSFX = null;
                    Func <SimpleCircularList <string>, Button, string, EventHandler> HandlerFactory
                        = (circList, btn, label) =>
                        {
                        return((ob, ev) =>
                        {
                            sampleSFX?.Stop();
                            btn.Text = $"{label} ('{circList.Next}')";
                            if (MasterSpellLibrary.SpellSFX.ContainsKey(circList.Current.Split(' ').Last()))
                            {
                                sampleSFX = MasterSpellLibrary.SpellSFX[circList.Current.Split(' ').Last()];
                                sampleSFX.Play();
                            }
                            else
                            {
                            }
                        });
                        };
                    feedbackSFXbtn.Click += HandlerFactory(feedbackSFXoptions, feedbackSFXbtn, "Feedback SFX");
                    progressSFXbtn.Click += HandlerFactory(progressSFXoptions, progressSFXbtn, "Progress SFX");
                    successSFXbtn.Click  += HandlerFactory(successSFXoptions, successSFXbtn, "Success Func");

                    inscribeButton.Text = "Finish Inscribing";
                }
                else
                {
                    feedbackSFXbtn.Visibility = ViewStates.Gone;
                    progressSFXbtn.Visibility = ViewStates.Gone;
                    successSFXbtn.Visibility  = ViewStates.Gone;

                    SpellBeingTrained.CastingResult = MasterSpellLibrary.CastingResults[successSFXoptions.Current];
                    foreach (var glyph in SpellBeingTrained.Glyphs)
                    {
                        glyph.FeedbackSFXName = feedbackSFXoptions.Current;
                        glyph.ProgressSFXName = progressSFXoptions.Current;
                    }
                    MasterSpellLibrary.Inscribe(SpellBeingTrained);
                    ThePlayersFocus.LearnSpell(SpellBeingTrained);

                    //ResetSpell();
                    if (SpellBeingRetrained == null)
                    {
                        await Speech.SayAllOf($"Adding {SpellBeingTrained.SpellName} to the master library.");
                    }
                    else
                    {
                        await Speech.SayAllOf($"Updating spell listing for {SpellBeingTrained.SpellName}.");
                    }
                    Log.Info("SpellTraining", $"Here's the spell string for copy-and-pasting as a constant: {SpellBeingTrained.ToString()}");
                    Current.Finish();
                }
            };
        }
Esempio n. 16
0
 protected override void startAction()
 {
     Speech.SayAllOf($"Train glyph {TargetGlyph.Name}.  {TargetGlyph.Instruction_Short}.").Wait();
     MasterSpellLibrary.SpellFeedbackSFX.Play(Volume, true);
     StopToken.Register(() => MasterSpellLibrary.SpellFeedbackSFX.Stop());
 }