Exemple #1
0
        public MoveBlockRedirect(EntityData data, Vector2 offset)
            : base(data.Position + offset)
        {
            Depth    = Depths.Above;
            Collider = new Hitbox(data.Width, data.Height);

            FastRedirect = data.Bool("fastRedirect");
            OneUse       = data.Bool("oneUse");
            DeleteBlock  = data.Bool("deleteBlock") || (Operation == Operations.Multiply && Modifier == 0f);

            Operation = data.Enum("operation", Operations.Add);
            Modifier  = Math.Abs(data.Float("modifier"));

            overrideColor     = data.HexColorNullable("overrideColor");
            overrideUsedColor = data.HexColorNullable("overrideUsedColor");

            if (float.TryParse(data.Attr("direction"), out float fAngle))
            {
                angle = fAngle;
            }
            else
            {
                Direction = data.Enum <Directions>("direction");
                angle     = Direction.Angle();
            }

            string str = data.Attr("reskinFolder").Trim().TrimEnd('/');

            reskinFolder = str == "" ? null : "objects/" + str;

            AddTextures();
        }
Exemple #2
0
        public CassetteMoveBlock(Vector2 position, EntityID id, int width, int height, Directions direction, float moveSpeed, int index, float tempo, Color?overrideColor)
            : base(position, id, width, height, index, tempo, dynamicHitbox: true, overrideColor)
        {
            startPosition  = position;
            Direction      = direction;
            this.moveSpeed = moveSpeed;

            homeAngle = targetAngle = angle = direction.Angle();

            Add(moveSfx = new SoundSource());
            Add(new Coroutine(Controller()));

            P_Activate = new ParticleType(MoveBlock.P_Activate)
            {
                Color = color
            };
            P_Move = new ParticleType(MoveBlock.P_Move)
            {
                Color = color
            };
            P_MovePressed = new ParticleType(MoveBlock.P_Move)
            {
                Color = pressedColor
            };
            P_Break = new ParticleType(MoveBlock.P_Break)
            {
                Color = color
            };
            P_BreakPressed = new ParticleType(MoveBlock.P_Break)
            {
                Color = pressedColor
            };

            Add(new MoveBlockRedirectable(new MonoMod.Utils.DynamicData(this))
            {
                Get_CanSteer  = () => false,
                Get_Direction = () => Direction,
                Set_Direction = dir => {
                    int index            = (int)Math.Floor((0f - angle + (float)Math.PI * 2f) % ((float)Math.PI * 2f) / ((float)Math.PI * 2f) * 8f + 0.5f);
                    arrow.Texture        = GFX.Game.GetAtlasSubtextures("objects/CommunalHelper/cassetteMoveBlock/arrow")[index];
                    arrowPressed.Texture = GFX.Game.GetAtlasSubtextures("objects/CommunalHelper/cassetteMoveBlock/arrowPressed")[index];
                    Direction            = dir;
                }
            });
        }
Exemple #3
0
        public override void Update()
        {
            base.Update();
            UpdateAppearance();

            if (lastMoveBlock != null && !CollideCheck(lastMoveBlock.Entity))
            {
                lastMoveBlock = null;
            }
            else if ((lastMoveBlock == null || FastRedirect) && maskAlpha != 0f)
            {
                maskAlpha = Calc.Approach(maskAlpha, 0f, (FastRedirect && !DeleteBlock ? 2.5f : 4f) * Engine.DeltaTime);
            }

            MoveBlockRedirectable redirectable = Scene.Tracker.GetComponents <MoveBlockRedirectable>().FirstOrDefault(c => CollideCheck(c.Entity)) as MoveBlockRedirectable;
            Entity block = redirectable?.Entity; // Non-null if redirectible isn't null

            if (Collidable && redirectable != null && redirectable != lastMoveBlock && !redirectable.CanSteer &&
                block.Width == Width && block.Height == Height)
            {
                if (!Collider.Contains(block.Collider, 0.001f))
                {
                    Directions dir           = redirectable.Direction;
                    Vector2    prevPosOffset = -dir.Vector(redirectable.Speed);

                    float edgeMin;
                    float edgeMax;
                    bool  wentThrough = false;
                    if (dir is Directions.Down or Directions.Up)
                    {
                        edgeMin     = Math.Min(block.Top, block.Top + prevPosOffset.Y);
                        edgeMax     = Math.Max(block.Bottom, block.Bottom + prevPosOffset.Y);
                        wentThrough = X == block.X && edgeMin <= Top && edgeMax >= Bottom;
                    }
                    else
                    {
                        edgeMin     = Math.Min(block.Left, block.Left + prevPosOffset.X);
                        edgeMax     = Math.Max(block.Right, block.Right + prevPosOffset.X);
                        wentThrough = Y == block.Y && edgeMin <= Left && edgeMax >= Right;
                    }

                    if (!wentThrough)
                    {
                        return;
                    }
                }

                lastMoveBlock = redirectable;

                if (DeleteBlock)
                {
                    Coroutine routine = block.Get <Coroutine>();
                    block.Remove(routine);
                    block.Add(new Coroutine(BreakBlock(redirectable, routine, FastRedirect, OneUse)));
                }
                else
                {
                    if (FastRedirect)
                    {
                        SetBlockData(redirectable);
                        maskAlpha = 1f;
                        if (OneUse)
                        {
                            Disappear();
                        }
                    }
                    else
                    {
                        Coroutine routine = block.Get <Coroutine>();
                        block.Remove(routine);
                        Add(new Coroutine(RedirectRoutine(redirectable, routine)));
                    }
                }
            }
Exemple #4
0
        public MoveSwapBlock(EntityData data, Vector2 offset)
            : base(data.Position + offset, data.Width, data.Height, data.Nodes[0] + offset, Themes.Normal)
        {
            swapBlockData = new DynData <SwapBlock>(this);
            Theme         = Themes.Moon; // base() gets Normal for the block texture, then we set to Moon to remove the path background

            doesReturn   = data.Bool("returns", true);
            freezeOnSwap = data.Bool("freezeOnSwap", true);

            // Replaces SwapBlock.OnDash with MoveSwapBlock.OnDash if this block doesn't return
            DashListener     listener    = Get <DashListener>();
            Action <Vector2> orig_OnDash = listener.OnDash;

            listener.OnDash = (dir) => {
                if (State == MovementState.Breaking)
                {
                    return;
                }
                else if (doesReturn)
                {
                    orig_OnDash(dir);
                }
                else
                {
                    OnDash(dir);
                }
            };

            // We use some local variable to temporarily store private SwapBlock fields for less reflection
            start      = Position;
            end        = data.Nodes[0] + offset;
            difference = end - start;

            // Structs are value types
            startingRect = swapBlockData.Get <Rectangle>("moveRect");

            swapBlockData["maxForwardSpeed"] = maxForwardSpeed = 360f * data.Float("swapSpeedMultiplier", 1f) / Vector2.Distance(start, end);
            startPosition = Position;

            // Replace/Add SwapBlock textures
            middleCardinal  = GFX.Game["objects/CommunalHelper/moveSwapBlock/midBlockCardinal"];
            middleDiagonal  = GFX.Game["objects/CommunalHelper/moveSwapBlock/midBlockDiagonal"];
            Add(middleArrow = new Image(middleCardinal));
            middleArrow.CenterOrigin();

            Remove(swapBlockData.Get <Sprite>("middleGreen"), swapBlockData.Get <Sprite>("middleRed"));
            swapBlockData["middleGreen"] = middleGreen = CommunalHelperModule.SpriteBank.Create("swapBlockLight");
            swapBlockData["middleRed"]   = middleRed = CommunalHelperModule.SpriteBank.Create("swapBlockLightRed");
            Add(middleGreen, middleRed);

            Add(middleOrange = new Image(GFX.Game["objects/CommunalHelper/moveSwapBlock/midBlockOrange"]));
            middleOrange.CenterOrigin();

            canSteer         = data.Bool("canSteer", false);
            maxMoveSpeed     = data.Float("moveSpeed", 60f);
            moveAcceleration = data.Float("moveAcceleration", Accel);
            MoveDirection    = data.Enum("direction", Directions.Left);
            homeAngle        = targetAngle = angle = MoveDirection.Angle();
            angleSteerSign   = angle > 0f ? -1 : 1;

            int      tilesX               = (int)Width / 8;
            int      tilesY               = (int)Height / 8;
            MTexture buttonTexture        = GFX.Game["objects/moveBlock/button"];
            MTexture buttonPressedTexture = GFX.Game["objects/CommunalHelper/moveSwapBlock/buttonPressed"];

            if (canSteer && (MoveDirection == Directions.Left || MoveDirection == Directions.Right))
            {
                for (int x = 0; x < tilesX; x++)
                {
                    int offsetX = (x != 0) ? ((x < tilesX - 1) ? 1 : 2) : 0;
                    AddImage(buttonTexture.GetSubtexture(offsetX * 8, 0, 8, 8), new Vector2(x * 8, -4f), 0f, new Vector2(1f, 1f), topButton);
                    AddImage(buttonPressedTexture.GetSubtexture(offsetX * 8, 0, 8, 8), new Vector2(x * 8, -4f), 0f, new Vector2(1f, 1f), topButton);
                }
            }
            else if (canSteer && (MoveDirection == Directions.Up || MoveDirection == Directions.Down))
            {
                for (int y = 0; y < tilesY; y++)
                {
                    int offsetY = (y != 0) ? ((y < tilesY - 1) ? 1 : 2) : 0;
                    AddImage(buttonTexture.GetSubtexture(offsetY * 8, 0, 8, 8), new Vector2(-4f, y * 8), (float)Math.PI / 2f, new Vector2(1f, -1f), leftButton);
                    AddImage(buttonPressedTexture.GetSubtexture(offsetY * 8, 0, 8, 8), new Vector2(-4f, y * 8), (float)Math.PI / 2f, new Vector2(1f, -1f), leftButton);
                    AddImage(buttonTexture.GetSubtexture(offsetY * 8, 0, 8, 8), new Vector2((tilesX - 1) * 8 + 4, y * 8), (float)Math.PI / 2f, new Vector2(1f, 1f), rightButton);
                    AddImage(buttonPressedTexture.GetSubtexture(offsetY * 8, 0, 8, 8), new Vector2((tilesX - 1) * 8 + 4, y * 8), (float)Math.PI / 2f, new Vector2(1f, 1f), rightButton);
                }
            }
            UpdateColors();

            debrisTextures = new Chooser <MTexture>();
            foreach (MTexture debris in GFX.Game.GetAtlasSubtextures("objects/CommunalHelper/moveSwapBlock/debris"))
            {
                debrisTextures.Add(debris, 1);
            }
            debrisTextures.Add(GFX.Game["objects/CommunalHelper/moveSwapBlock/debrisRed00"], 0.3f);
            debrisTextures.Add(GFX.Game["objects/CommunalHelper/moveSwapBlock/debrisGreen00"], 0.05f);

            Add(moveBlockSfx = new SoundSource());
            Add(new Coroutine(Controller()));

            Add(new MoveBlockRedirectable(new DynamicData(this))
            {
                Get_Speed       = () => moveSpeed,
                Get_TargetSpeed = () => targetMoveSpeed,
                Get_MoveSfx     = () => moveBlockSfx,
                Get_Direction   = () => MoveDirection,
                Set_Direction   = dir => MoveDirection = dir,
            });
        }