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; }
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); } }
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)); }