Beispiel #1
0
 private void OnPickup()
 {
     _player               = Hold.Holder;
     _pickedUp             = true;
     Collidable            = false;
     _unspecializeOnRemove = false;
     Speed = Vector2.Zero;
     AddTag(Tags.Persistent);
     if (IsSpecial)
     {
         FactoryHelperSession factorySession = FactoryHelperModule.Session;
         if (factorySession.SpecialBoxPosition == null)
         {
             factorySession.SpecialBoxPosition = _starterPosition;
             factorySession.OriginalSession    = (Scene as Level).Session;
             factorySession.SpecialBoxLevel    = _levelName;
         }
         ParticleSystem particlesFG = (Scene as Level).ParticlesFG;
         Add(_shimmerParticles = new ParticleEmitter(particlesFG, Key.P_Shimmer, Vector2.UnitY * -6, new Vector2(6f, 6f), 1, 0.2f));
         _shimmerParticles.SimulateCycle();
     }
     if (_tutorialCarry != null)
     {
         _tutorialCarry.Open = false;
     }
     if (_tutorial && _tutorialPutDown == null)
     {
         _tutorialPutDown = new BirdTutorialGui(this, new Vector2(0f, -24f), Dialog.Clean("tutorial_drop"), Dialog.Clean("tutorial_hold"), new Vector2(0f, 1f), "+ ", Dialog.Clean("tutorial_release"), Input.Grab);
         Scene.Add(_tutorialPutDown);
     }
     if (_tutorialPutDown != null)
     {
         _tutorialPutDown.Open = true;
     }
 }
        public static BirdTutorialGui Clone(this BirdTutorialGui birdTutorialGui)
        {
            object entity = birdTutorialGui.Entity.TryFindOrCloneObject();

            if (entity == null)
            {
                return(null);
            }
            return(new BirdTutorialGui((Entity)entity, birdTutorialGui.GetStartPosition(),
                                       birdTutorialGui.GetField("info"),
                                       birdTutorialGui.GetControls()));
        }
        public CustomBirdTutorial(EntityData data, Vector2 offset)
            : base(data, offset)
        {
            BirdId   = data.Attr("birdId");
            onlyOnce = data.Bool("onlyOnce");
            caw      = data.Bool("caw");
            Facing   = data.Bool("faceLeft") ? Facings.Left : Facings.Right;

            object info;

            object[] controls;

            // parse the info ("title")
            string infoString = data.Attr("info");

            if (GFX.Gui.Has(infoString))
            {
                info = GFX.Gui[infoString];
            }
            else
            {
                info = Dialog.Clean(infoString);
            }

            int extraAdvance = 0;

            // go ahead and parse the controls. Controls can be textures, VirtualButtons, directions or strings.
            string[] controlsStrings = data.Attr("controls").Split(',');
            controls = new object[controlsStrings.Length];
            for (int i = 0; i < controls.Length; i++)
            {
                string controlString = controlsStrings[i];

                object modCommand = Everest.Events.CustomBirdTutorial.ParseCommand(controlString);
                if (modCommand is ButtonBinding binding)
                {
                    // convert ButtonBinding to VirtualButton for convenience.
                    modCommand = binding.Button;
                }

                if (modCommand != null)
                {
                    // this is a command a mod registered.
                    controls[i] = modCommand;
                }
                else if (GFX.Gui.Has(controlString))
                {
                    // this is a texture.
                    controls[i] = GFX.Gui[controlString];
                }
                else if (directions.ContainsKey(controlString))
                {
                    // this is a direction.
                    controls[i] = directions[controlString];
                }
                else
                {
                    FieldInfo matchingInput = typeof(Input).GetField(controlString, BindingFlags.Static | BindingFlags.Public);
                    if (matchingInput?.GetValue(null)?.GetType() == typeof(VirtualButton))
                    {
                        // this is a button.
                        controls[i] = matchingInput.GetValue(null);
                    }
                    else
                    {
                        if (controlString.StartsWith("dialog:"))
                        {
                            // treat that as a dialog key.
                            controls[i] = Dialog.Clean(controlString.Substring("dialog:".Length));
                        }
                        else
                        {
                            // treat that as a plain string.
                            controls[i] = controlString;
                        }
                    }
                }

                if (controls[i] is string)
                {
                    // when BirdTutorialGui renders text, it is offset by 1px on the right.
                    // width computation doesn't take this 1px into account, so we should add it back in.
                    extraAdvance++;
                    if (i == 0)
                    {
                        // as the text is rendered 1px to the right, if the first thing is a string, there will be 1px more padding on the left.
                        // we should add that extra px on the right as well.
                        extraAdvance++;
                    }
                }
            }

            gui = new BirdTutorialGui(this, new Vector2(0f, -16f), info, controls);

            DynData <BirdTutorialGui> guiData = new DynData <BirdTutorialGui>(gui);

            // if there is no first line, resize the bubble accordingly.
            if (string.IsNullOrEmpty(infoString))
            {
                guiData["infoHeight"] = 0f;
            }
            // apply the extra width.
            guiData["controlsWidth"] = guiData.Get <float>("controlsWidth") + extraAdvance;
        }
Beispiel #4
0
 public override void Update()
 {
     base.Update();
     if (_soundTimerX > 0f)
     {
         _soundTimerX -= Engine.DeltaTime;
     }
     if (_soundTimerY > 0f)
     {
         _soundTimerY -= Engine.DeltaTime;
     }
     if (Hold.IsHeld)
     {
         _prevLiftSpeed = Vector2.Zero;
     }
     else if (!ConveyorMover.IsOnConveyor)
     {
         if (OnGround())
         {
             float target = (!OnGround(Position + Vector2.UnitX * 3f)) ? 20f : (OnGround(Position - Vector2.UnitX * 3f) ? 0f : (-20f));
             Speed.X = Calc.Approach(Speed.X, target, 800f * Engine.DeltaTime);
             Vector2 liftSpeed = base.LiftSpeed;
             if (liftSpeed == Vector2.Zero && _prevLiftSpeed != Vector2.Zero)
             {
                 Speed          = _prevLiftSpeed;
                 _prevLiftSpeed = Vector2.Zero;
                 Speed.Y        = Math.Min(Speed.Y * 0.6f, 0f);
                 if (Speed.X != 0f && Speed.Y == 0f)
                 {
                     Speed.Y = -60f;
                 }
                 if (Speed.Y < 0f)
                 {
                     _noGravityTimer = 0.15f;
                 }
             }
             else
             {
                 _prevLiftSpeed = liftSpeed;
                 if (liftSpeed.Y < 0f && Speed.Y < 0f)
                 {
                     Speed.Y = 0f;
                 }
             }
         }
         else if (Hold.ShouldHaveGravity)
         {
             float accY = 800f;
             if (Math.Abs(Speed.Y) <= 30f)
             {
                 accY *= 0.5f;
             }
             float accX = 350f;
             if (Speed.Y < 0f)
             {
                 accX *= 0.5f;
             }
             Speed.X = Calc.Approach(Speed.X, 0f, accX * Engine.DeltaTime);
             if (_noGravityTimer > 0f)
             {
                 _noGravityTimer -= Engine.DeltaTime;
             }
             else
             {
                 Speed.Y = Calc.Approach(Speed.Y, 300f, accY * Engine.DeltaTime);
             }
         }
         MoveH(Speed.X * Engine.DeltaTime, OnCollideH);
         MoveV(Speed.Y * Engine.DeltaTime, OnCollideV);
         if (IsSpecial)
         {
             if (Left < _level.Bounds.Left)
             {
                 Left     = _level.Bounds.Left;
                 Speed.X *= -0.4f;
             }
             else if (Right > _level.Bounds.Right)
             {
                 Right    = _level.Bounds.Right;
                 Speed.X *= -0.4f;
             }
             else if (Top < _level.Bounds.Top - 4)
             {
                 Top     = _level.Bounds.Top - 4;
                 Speed.Y = 0;
             }
             else if (Bottom > _level.Bounds.Bottom + 4)
             {
                 Shatter();
             }
         }
         if (_isCrucial && Bottom > _level.Bounds.Bottom + 4)
         {
             Shatter();
         }
         if (Left > _level.Bounds.Right + 8 || Right < _level.Bounds.Left - 8 || Top > _level.Bounds.Bottom + 8 || Bottom < _level.Bounds.Top - 8)
         {
             RemoveSelf();
         }
     }
     if (Collidable)
     {
         Hold.CheckAgainstColliders();
     }
     if (_tutorial && OnGround(4) && !ConveyorMover.IsOnConveyor && _tutorialCarry == null)
     {
         _tutorialCarry      = new BirdTutorialGui(this, new Vector2(0f, -24f), Dialog.Clean("tutorial_carry"), Dialog.Clean("tutorial_hold"), Input.Grab);
         _tutorialCarry.Open = true;
         Scene.Add(_tutorialCarry);
     }
 }
Beispiel #5
0
        public CustomBirdTutorial(EntityData data, Vector2 offset)
            : base(data, offset)
        {
            BirdId   = data.Attr("birdId");
            onlyOnce = data.Bool("onlyOnce");
            caw      = data.Bool("caw");
            Facing   = data.Bool("faceLeft") ? Facings.Left : Facings.Right;

            // apply the facing immediately
            Sprite.Scale.X = (float)Facing;

            object info;

            object[] controls;

            // parse the info ("title")
            string infoString = data.Attr("info");

            if (GFX.Gui.Has(infoString))
            {
                info = GFX.Gui[infoString];
            }
            else
            {
                info = Dialog.Clean(infoString);
            }

            int extraAdvance = 0;

            // go ahead and parse the controls. Controls can be textures, VirtualButtons, directions or strings.
            string[] controlsStrings = data.Attr("controls").Split(',');
            controls = new object[controlsStrings.Length];
            for (int i = 0; i < controls.Length; i++)
            {
                string controlString = controlsStrings[i];

                object modCommand = Everest.Events.CustomBirdTutorial.ParseCommand(controlString);
                if (modCommand is ButtonBinding binding)
                {
                    // convert ButtonBinding to VirtualButton for convenience.
                    modCommand = binding.Button;
                }

                if (modCommand != null)
                {
                    // this is a command a mod registered.
                    controls[i] = modCommand;
                }
                else if (controlString.StartsWith("mod:"))
                {
                    // formatted like `mod:MaxHelpingHand/ShowHints`
                    string[]      autoBinding = controlString.Substring(4).Split('/');
                    EverestModule module      = Everest.Modules.FirstOrDefault(m => m.Metadata.Name == autoBinding[0]);
                    if (module?.SettingsType != null)
                    {
                        PropertyInfo  matchingInput = module.SettingsType.GetProperty(autoBinding[1]);
                        ButtonBinding val           = matchingInput?.GetGetMethod()?.Invoke(module._Settings, null) as ButtonBinding;
                        if (val?.Button != null)
                        {
                            controls[i] = val.Button;
                        }
                        else
                        {
                            Logger.Log(LogLevel.Warn, "CustomBird", $"Public ButtonBinding property not found in {module.SettingsType}. ControlString: {controlString}");
                        }
                    }
                    else
                    {
                        Logger.Log(LogLevel.Warn, "CustomBird", "EverestModule or EverestModule.SettingsType not found. ControlString: " + controlString);
                    }
                }
                else if (GFX.Gui.Has(controlString))
                {
                    // this is a texture.
                    controls[i] = GFX.Gui[controlString];
                }
                else if (directions.ContainsKey(controlString))
                {
                    // this is a direction.
                    controls[i] = directions[controlString];
                }
                else
                {
                    FieldInfo matchingInput = typeof(Input).GetField(controlString, BindingFlags.Static | BindingFlags.Public);
                    if (matchingInput?.GetValue(null)?.GetType() == typeof(VirtualButton))
                    {
                        // this is a button.
                        controls[i] = matchingInput.GetValue(null);
                    }
                    else
                    {
                        if (controlString.StartsWith("dialog:"))
                        {
                            // treat that as a dialog key.
                            controls[i] = Dialog.Clean(controlString.Substring("dialog:".Length));
                        }
                        else
                        {
                            // treat that as a plain string.
                            controls[i] = controlString;
                        }
                    }
                }

                if (controls[i] is string)
                {
                    // when BirdTutorialGui renders text, it is offset by 1px on the right.
                    // width computation doesn't take this 1px into account, so we should add it back in.
                    extraAdvance++;
                    if (i == 0)
                    {
                        // as the text is rendered 1px to the right, if the first thing is a string, there will be 1px more padding on the left.
                        // we should add that extra px on the right as well.
                        extraAdvance++;
                    }
                }
            }

            gui = new BirdTutorialGui(this, new Vector2(0f, -16f), info, controls);

            DynData <BirdTutorialGui> guiData = new DynData <BirdTutorialGui>(gui);

            // if there is no first line, resize the bubble accordingly.
            if (string.IsNullOrEmpty(infoString))
            {
                guiData["infoHeight"] = 0f;
            }
            // apply the extra width.
            guiData["controlsWidth"] = guiData.Get <float>("controlsWidth") + extraAdvance;
        }
 private static void BirdTutorialGuiOnCtor(On.Celeste.BirdTutorialGui.orig_ctor orig, BirdTutorialGui self,
                                           Entity entity, Vector2 position, object info, object[] controls)
 {
     self.TrySetEntityId2(entity, position, info, string.Join("-", controls));
     self.SetStartPosition(position);
     self.SetControls(controls);
     orig(self, entity, position, info, controls);
 }
 public static void SetControls(this BirdTutorialGui birdTutorialGui, object[] control)
 {
     birdTutorialGui.SetExtendedDataValue(BirdTutorialGuiControlsKey, control);
 }
 public static object[] GetControls(this BirdTutorialGui birdTutorialGui)
 {
     return(birdTutorialGui.GetExtendedDataValue <object[]>(BirdTutorialGuiControlsKey));
 }