Exemple #1
0
    public void Draw()
    {
        foreach (var position in Map.Positions())
        {
            if (!Map.Explored[position])
            {
                continue;
            }

            var vectorPos = new Vector2(position.X, position.Y);

            if (Map.FOV[position] == 0)
            {
                _fog.SetCellv(vectorPos, 0);
            }
            else
            {
                _fog.SetCellv(vectorPos, -1);
            }

            var terrain = Map.GetTerrain <Terrain>(position);

            if (terrain.IsWalkable)
            {
                SetCellv(vectorPos, 1);
            }
            else
            {
                SetCellv(vectorPos, 0);
            }
        }
    }
Exemple #2
0
    void addFlyable(string resourceIdentifier)
    {
        Godot.Vector2 position = prepareFlyablePosition();
        ImageTexture  texture  = prepareItemTexture(resourceIdentifier);

        addItem(position, Data.FLYABLE_SPAWN_DEFAULT_ROTATION, texture);
        connectBarriersToSpawnedFlyable();
    }
Exemple #3
0
    void addItem(Godot.Vector2 position, float rotation, Texture texture)
    {
        ((Sprite)currentlyAdded.GetNode("Sprite")).Texture = texture;
        currentlyAdded.GlobalPosition = position;
        currentlyAdded.Rotation       = rotation;

        AddChild(currentlyAdded);
    }
Exemple #4
0
    void addBarrier(string resourceIdentifier, string groupIdentifier)
    {
        Godot.Vector2 position = prepareBarrierPosition();
        float         rotation = 0;
        ImageTexture  texture  = prepareItemTexture(resourceIdentifier);

        addItem(position, rotation, texture);
        addItemToGroup(groupIdentifier);
    }
    void performAction()
    {
        Godot.Vector2 offset   = new Godot.Vector2(0, 0);
        Godot.Vector2 hitForce = getFlyableLaunchForce();

        flyable.ApplyImpulse(offset, hitForce);

        Data.WaitingForAction = false;
    }
Exemple #6
0
    void visualiseCurrentLocation()
    {
        if (Input.IsActionJustPressed("main"))
        {
            setMode1();
        }

        Godot.Vector2 mousePos = barrier.GetGlobalMousePosition();
        barrier.Position = mousePos;
    }
Exemple #7
0
    public void updateOrganicEnemy(Godot.Vector2 p)
    {
        if (!Powers.getPower(PowerNames.EnemyDetector))
        {
            return;
        }
        var md = distance(p, false);

        if (md < organic_enemy_distance)
        {
            organic_enemy_distance = md;
        }
    }
Exemple #8
0
    public void reset()
    {
        Sprite.FlipH = false;
        GetNode <Sprite>("Sprite").Visible = true;
        this.dead     = false;
        this.velocity = Godot.Vector2.Zero;
        this.transitionState(new IdleState(this));

        GetNode <CollisionShape2D>("CollisionShape2D").Disabled = true;
        this.just_reset = 2;

        dir         = 0;
        jumps       = 0;
        JustClimbed = false;
        CanFreeJump = false;

        Umbrella.reset();
        stopHologram(cleanup: true);
    }
    Godot.Vector2 getFlyableLaunchForce()
    {
        GeoLib.Vector2 mousePos   = new GeoLib.Vector2(flyable.GetGlobalMousePosition().x, flyable.GetGlobalMousePosition().y);
        GeoLib.Vector2 flyablePos = new GeoLib.Vector2(flyable.Position.x, flyable.Position.y);

        MathLine strikeLine = new MathLine(mousePos, flyablePos);
        double   angle      = strikeLine.GetAcuteAngle();

        float xForce = Flyable.FORCE * (float)Math.Cos(angle);
        float yForce = Flyable.FORCE * (float)Math.Sin(angle);

        Godot.Vector2 hitForce = new Godot.Vector2(xForce, yForce);

        if (mousePos.X < flyablePos.X)
        {
            hitForce *= -1;
        }

        return(hitForce);
    }
Exemple #10
0
    public void reset()
    {
        Sprite.FlipH = false;
        GetNode <Sprite>("Sprite").Visible = true;
        this.dead     = false;
        this.velocity = Godot.Vector2.Zero;
        this.transitionState(new IdleState(this));

        SetDeferred("CollisionsDisabled", true);
        //GetNode<CollisionPolygon2D>("CollisionPolygon2D").SetDeferred("disabled", true);
        this.just_reset = 2;

        dir         = 0;
        jumps       = 0;
        JustClimbed = false;
        CanFreeJump = false;

        Umbrella.reset();
        stopHologram(cleanup: true);
        enableAttachment(Powers.Attachment);
    }
    /// <summary>
    ///   Updates the cloud in parallel.
    /// </summary>
    public void QueueUpdateCloud(float delta, List <Task> queue)
    {
        // The diffusion rate seems to have a bigger effect
        delta *= 100.0f;
        var pos = new Vector2(Translation.x, Translation.z);

        for (int i = 0; i < Constants.CLOUD_SQUARES_PER_SIDE; i++)
        {
            for (int j = 0; j < Constants.CLOUD_SQUARES_PER_SIDE; j++)
            {
                var x0   = i;
                var y0   = j;
                var task = new Task(() => PartialUpdateCenter(x0 * Size / Constants.CLOUD_SQUARES_PER_SIDE,
                                                              y0 * Size / Constants.CLOUD_SQUARES_PER_SIDE,
                                                              Size / Constants.CLOUD_SQUARES_PER_SIDE,
                                                              Size / Constants.CLOUD_SQUARES_PER_SIDE,
                                                              delta, pos));
                queue.Add(task);
            }
        }
    }
Exemple #12
0
    private void processFlyMode(float delta)
    {
        var dir = new Godot.Vector2();

        if (juniInput.UpHeld)
        {
            dir.y -= 1f;
        }
        if (juniInput.DownHeld)
        {
            dir.y += 1f;
        }
        if (juniInput.LeftHeld)
        {
            dir.x -= 1f;
        }
        if (juniInput.RightHeld)
        {
            dir.x += 1f;
        }

        Translate(dir.Normalized() * DEBUG_FLY_SPEED * delta);
    }
 private void PartialUpdateCenter(int x0, int y0, int width, int height, float delta, Vector2 pos)
 {
     PartialDiffuseCenter(x0 + Constants.CLOUD_EDGE_WIDTH / 2, y0 + Constants.CLOUD_EDGE_WIDTH / 2, width
                          - Constants.CLOUD_EDGE_WIDTH, height - Constants.CLOUD_EDGE_WIDTH, delta);
     PartialClearDensity(x0, y0, width, height);
     PartialAdvectCenter(x0 + Constants.CLOUD_EDGE_WIDTH / 2, y0 + Constants.CLOUD_EDGE_WIDTH / 2, width
                         - Constants.CLOUD_EDGE_WIDTH, height - Constants.CLOUD_EDGE_WIDTH, delta, pos);
 }
    private void PartialAdvectEdges(int x0, int y0, int width, int height, float delta, Vector2 pos)
    {
        for (int x = x0; x < x0 + width; x++)
        {
            for (int y = y0; y < y0 + height; y++)
            {
                if (OldDensity[x, y].LengthSquared() > 1)
                {
                    var velocity = fluidSystem.VelocityAt(
                        pos + (new Vector2(x, y) * Resolution)) * VISCOSITY;

                    // This is ran in parallel, this may not touch the other compound clouds
                    float dx = x + (delta * velocity.x);
                    float dy = y + (delta * velocity.y);

                    CalculateMovementFactors(dx, dy, out var q0, out var q1, out var r0, out var r1,
                                             out var s1, out var s0, out var t1, out var t0);

                    Density[(q0 + Size) % Size, (r0 + Size) % Size] += OldDensity[x, y] * s0 * t0;
                    Density[(q0 + Size) % Size, (r1 + Size) % Size] += OldDensity[x, y] * s0 * t1;
                    Density[(q1 + Size) % Size, (r0 + Size) % Size] += OldDensity[x, y] * s1 * t0;
                    Density[(q1 + Size) % Size, (r1 + Size) % Size] += OldDensity[x, y] * s1 * t1;
                }
            }
        }
    }
    private void PartialAdvectCenter(int x0, int y0, int width, int height, float delta, Vector2 pos)
    {
        for (int x = x0; x < x0 + width; x++)
        {
            for (int y = y0; y < y0 + height; y++)
            {
                if (OldDensity[x, y].LengthSquared() > 1)
                {
                    var velocity = fluidSystem.VelocityAt(
                        pos + (new Vector2(x, y) * Resolution)) * VISCOSITY;

                    // This is ran in parallel, this may not touch the other compound clouds
                    float dx = x + (delta * velocity.x);
                    float dy = y + (delta * velocity.y);

                    // So this is clamped to not go to the other clouds
                    dx = dx.Clamp(x0 - 0.5f, x0 + width + 0.5f);
                    dy = dy.Clamp(y0 - 0.5f, y0 + height + 0.5f);

                    CalculateMovementFactors(dx, dy, out var q0, out var q1, out var r0, out var r1,
                                             out var s1, out var s0, out var t1, out var t0);

                    Density[q0, r0] += OldDensity[x, y] * s0 * t0;
                    Density[q0, r1] += OldDensity[x, y] * s0 * t1;
                    Density[q1, r0] += OldDensity[x, y] * s1 * t0;
                    Density[q1, r1] += OldDensity[x, y] * s1 * t1;
                }
            }
        }
    }
    /// <summary>
    ///   Updates the edge concentrations of this cloud after the rest of the cloud.
    ///   This is not ran in parallel.
    /// </summary>
    public void UpdateEdgesAfterCenter(float delta)
    {
        // The diffusion rate seems to have a bigger effect
        delta *= 100.0f;
        var pos = new Vector2(Translation.x, Translation.z);

        if (position.x != 0)
        {
            PartialAdvectEdges(0, 0, Constants.CLOUD_EDGE_WIDTH / 2, Size, delta, pos);
            PartialAdvectEdges(Size - Constants.CLOUD_EDGE_WIDTH / 2, 0, Constants.CLOUD_EDGE_WIDTH / 2,
                               Size, delta, pos);
        }

        if (position.x != 1)
        {
            PartialAdvectEdges(Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH / 2,
                               0, Constants.CLOUD_EDGE_WIDTH, Size, delta, pos);
        }

        if (position.x != 2)
        {
            PartialAdvectEdges(2 * Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH / 2,
                               0, Constants.CLOUD_EDGE_WIDTH, Size, delta, pos);
        }

        if (position.y != 0)
        {
            PartialAdvectEdges(Constants.CLOUD_EDGE_WIDTH / 2, 0,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH / 2, delta, pos);
            PartialAdvectEdges(Constants.CLOUD_EDGE_WIDTH / 2, Size - Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH / 2, delta, pos);
            PartialAdvectEdges(Size / Constants.CLOUD_SQUARES_PER_SIDE + Constants.CLOUD_EDGE_WIDTH / 2,
                               0, Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH / 2, delta, pos);
            PartialAdvectEdges(Size / Constants.CLOUD_SQUARES_PER_SIDE + Constants.CLOUD_EDGE_WIDTH / 2,
                               Size - Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH / 2, delta, pos);
            PartialAdvectEdges(2 * Size / Constants.CLOUD_SQUARES_PER_SIDE + Constants.CLOUD_EDGE_WIDTH / 2,
                               0, Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH / 2, delta, pos);
            PartialAdvectEdges(2 * Size / Constants.CLOUD_SQUARES_PER_SIDE + Constants.CLOUD_EDGE_WIDTH / 2,
                               Size - Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH / 2, delta, pos);
        }

        if (position.y != 1)
        {
            PartialAdvectEdges(Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH, delta, pos);
            PartialAdvectEdges(Size / Constants.CLOUD_SQUARES_PER_SIDE + Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH, delta, pos);
            PartialAdvectEdges(2 * Size / Constants.CLOUD_SQUARES_PER_SIDE + Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH, delta, pos);
        }

        if (position.y != 2)
        {
            PartialAdvectEdges(Constants.CLOUD_EDGE_WIDTH / 2,
                               2 * Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH, delta, pos);
            PartialAdvectEdges(Size / Constants.CLOUD_SQUARES_PER_SIDE + Constants.CLOUD_EDGE_WIDTH / 2,
                               Constants.CLOUD_EDGE_WIDTH * Size / Constants.CLOUD_SQUARES_PER_SIDE
                               - Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH, delta, pos);
            PartialAdvectEdges(2 * Size / Constants.CLOUD_SQUARES_PER_SIDE + Constants.CLOUD_EDGE_WIDTH / 2,
                               2 * Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH / 2,
                               Size / Constants.CLOUD_SQUARES_PER_SIDE - Constants.CLOUD_EDGE_WIDTH,
                               Constants.CLOUD_EDGE_WIDTH, delta, pos);
        }
    }
Exemple #17
0
 public void scrollTo(Godot.Vector2 target, float speed)
 {
     this.speed     = speed;
     this.Scrolling = true;
     this.Target    = target;
 }
Exemple #18
0
 // Give position in global space
 public void jumpTo(Godot.Vector2 position)
 {
     this.GlobalPosition = position;
 }
Exemple #19
0
    private static void RenderDrawData(ImDrawDataPtr drawData, RID parent)
    {
        // allocate and clear out our CanvasItem pool as needed
        int neededNodes = 0;

        for (int i = 0; i < drawData.CmdListsCount; i++)
        {
            neededNodes += drawData.CmdListsRange[i].CmdBuffer.Size;
        }

        while (_children.Count < neededNodes)
        {
            RID newChild = VisualServer.CanvasItemCreate();
            VisualServer.CanvasItemSetParent(newChild, parent);
            VisualServer.CanvasItemSetDrawIndex(newChild, _children.Count);
            _children.Add(newChild);
            _meshes.Add(new ArrayMesh());
        }

        // trim unused nodes to reduce draw calls
        while (_children.Count > neededNodes)
        {
            int idx = _children.Count - 1;
            VisualServer.FreeRid(_children[idx]);
            _children.RemoveAt(idx);
            _meshes.RemoveAt(idx);
        }

        // render
        drawData.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale);
        int nodeN = 0;

        for (int n = 0; n < drawData.CmdListsCount; n++)
        {
            ImDrawListPtr cmdList   = drawData.CmdListsRange[n];
            int           idxOffset = 0;

            int nVert = cmdList.VtxBuffer.Size;

            Godot.Vector2[] vertices = new Godot.Vector2[nVert];
            Godot.Color[]   colors   = new Godot.Color[nVert];
            Godot.Vector2[] uvs      = new Godot.Vector2[nVert];

            for (int i = 0; i < cmdList.VtxBuffer.Size; i++)
            {
                var v = cmdList.VtxBuffer[i];
                vertices[i] = new Godot.Vector2(v.pos.X, v.pos.Y);
                // need to reverse the color bytes
                byte[] col = BitConverter.GetBytes(v.col);
                colors[i] = Godot.Color.Color8(col[0], col[1], col[2], col[3]);
                uvs[i]    = new Godot.Vector2(v.uv.X, v.uv.Y);
            }

            for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++, nodeN++)
            {
                ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi];

                int[] indices = new int[drawCmd.ElemCount];
                for (int i = idxOffset, j = 0; i < idxOffset + drawCmd.ElemCount; i++, j++)
                {
                    indices[j] = cmdList.IdxBuffer[i];
                }

                var arrays = new Godot.Collections.Array();
                arrays.Resize((int)ArrayMesh.ArrayType.Max);
                arrays[(int)ArrayMesh.ArrayType.Vertex] = vertices;
                arrays[(int)ArrayMesh.ArrayType.Color]  = colors;
                arrays[(int)ArrayMesh.ArrayType.TexUv]  = uvs;
                arrays[(int)ArrayMesh.ArrayType.Index]  = indices;

                var mesh = _meshes[nodeN];
                while (mesh.GetSurfaceCount() > 0)
                {
                    mesh.SurfaceRemove(0);
                }
                mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);

                RID child = _children[nodeN];

                Texture tex = GetTexture(drawCmd.TextureId);
                VisualServer.CanvasItemClear(child);
                VisualServer.CanvasItemSetClip(child, true);
                VisualServer.CanvasItemSetCustomRect(child, true, new Godot.Rect2(
                                                         drawCmd.ClipRect.X,
                                                         drawCmd.ClipRect.Y,
                                                         drawCmd.ClipRect.Z - drawCmd.ClipRect.X,
                                                         drawCmd.ClipRect.W - drawCmd.ClipRect.Y)
                                                     );
                VisualServer.CanvasItemAddMesh(child, mesh.GetRid(), null, null, tex.GetRid(), new RID(null));

                // why doesn't this quite work?
                // VisualServer.CanvasItemAddTriangleArray(child, indices, vertices, colors, uvs, null, null, tex.GetRid(), -1, new RID(null));

                idxOffset += (int)drawCmd.ElemCount;
            }
        }
    }
Exemple #20
0
 public Vector2 this[Vector2 v] => this[(int)v.x, (int)v.y];
Exemple #21
0
 public static Vector3 FromV2(Godot.Vector2 godotV)
 {
     return(new Vector3(godotV.x, godotV.y, 0));
 }
Exemple #22
0
    public float distanceSquared(Godot.Vector2 p, bool apparent = true)
    {
        var jp = apparent ? ApparentPosition : GlobalPosition;

        return(jp.DistanceSquaredTo(p));
    }
Exemple #23
0
    public float manhattanDistance(Godot.Vector2 p, bool apparent = true)
    {
        var jp = apparent ? ApparentPosition : GlobalPosition;

        return(Math.Abs(p.x - jp.x) + Math.Abs(p.y - jp.y));
    }
Exemple #24
0
    private void PartialAdvectCenter(int x0, int y0, int width, int height, float delta, Vector2 pos)
    {
        for (int x = x0; x < x0 + width; x++)
        {
            for (int y = y0; y < y0 + height; y++)
            {
                if (OldDensity[x, y].LengthSquared() > 1)
                {
                    var velocity = fluidSystem.VelocityAt(
                        pos + (new Vector2(x, y) * Resolution)) * VISCOSITY;

                    // This is ran in parallel, this may not touch the other compound clouds
                    float dx = x + (delta * velocity.x);
                    float dy = y + (delta * velocity.y);

                    // So this is clamped to not go to the other clouds
                    dx = dx.Clamp(x0 - 0.5f, x0 + width + 0.5f);
                    dy = dy.Clamp(y0 - 0.5f, y0 + height + 0.5f);

                    CalculateMovementFactors(dx, dy, out var q0, out var q1, out var r0, out var r1,
                                             out var s1, out var s0, out var t1, out var t0);

                    // NOTE: we add modulo to avoid overflow due to large time steps
                    // This makes this function a duplicate of PartialAdvectEdges
                    // TODO: check for refactorization (and in general of the whole file) --Maxonovien
                    q0 = q0.PositiveModulo(Size);
                    q1 = q1.PositiveModulo(Size);
                    r0 = r0.PositiveModulo(Size);
                    r1 = r1.PositiveModulo(Size);

                    Density[q0, r0] += OldDensity[x, y] * s0 * t0;
                    Density[q0, r1] += OldDensity[x, y] * s0 * t1;
                    Density[q1, r0] += OldDensity[x, y] * s1 * t0;
                    Density[q1, r1] += OldDensity[x, y] * s1 * t1;
                }
            }
        }
    }
    private void PartialAdvectEdges(int x0, int y0, int width, int height, float delta, Vector2 pos)
    {
        for (int x = x0; x < x0 + width; x++)
        {
            for (int y = y0; y < y0 + height; y++)
            {
                if (OldDensity[x, y].LengthSquared() > 1)
                {
                    // TODO: give each cloud a viscosity value in the
                    // JSON file and use it instead.
                    const float viscosity = 0.0525f;
                    var         velocity  = fluidSystem.VelocityAt(
                        pos + (new Vector2(x, y) * Resolution)) * viscosity;

                    // This is ran in parallel, this may not touch the other compound clouds
                    float dx = x + (delta * velocity.x);
                    float dy = y + (delta * velocity.y);

                    int q0 = (int)Math.Floor(dx);
                    int q1 = q0 + 1;
                    int r0 = (int)Math.Floor(dy);
                    int r1 = r0 + 1;

                    float s1 = Math.Abs(dx - q0);
                    float s0 = 1.0f - s1;
                    float t1 = Math.Abs(dy - r0);
                    float t0 = 1.0f - t1;

                    Density[(q0 + Size) % Size, (r0 + Size) % Size] += OldDensity[x, y] * s0 * t0;
                    Density[(q0 + Size) % Size, (r1 + Size) % Size] += OldDensity[x, y] * s0 * t1;
                    Density[(q1 + Size) % Size, (r0 + Size) % Size] += OldDensity[x, y] * s1 * t0;
                    Density[(q1 + Size) % Size, (r1 + Size) % Size] += OldDensity[x, y] * s1 * t1;
                }
            }
        }
    }
Exemple #26
0
    public override void _PhysicsProcess(float delta)
    {
        if (dead)
        {
            return;
        }

        if (just_reset > 0)
        {
            just_reset--;
            if (just_reset == 0)
            {
                GetNode <CollisionShape2D>("CollisionShape2D").Disabled = false;
            }
        }

        // Organic Enemy Distance
        if (Powers.getPower(PowerNames.EnemyDetector) && organic_enemy_distance <= 170f)
        {
            Detector.Visible = true;
            var   m   = Detector.Modulate;
            float max = 1f - (organic_enemy_distance / 170f);
            m.a = GDKnyttDataStore.random.NextFloat(.25f, max * .65f);
            Detector.Modulate = m;
        }
        else
        {
            Detector.Visible = false;
        }

        organic_enemy_distance = float.MaxValue;

        this.checkDebugInput(); // TODO: Check the mode for debug

        // Handle state transitions
        if (next_state != null)
        {
            executeStateTransition();
        }

        this.CurrentState?.PreProcess(delta);

        // Handle umbrella
        if (CanUmbrella && UmbrellaPressed)
        {
            Umbrella.Deployed = !Umbrella.Deployed;
        }

        handleHologram();
        handleXMovement(delta);
        handleGravity(delta);

        this.CurrentState.PostProcess(delta);

        // Pull-over-edge
        if (JustClimbed)
        {
            velocity.x    += (FacingRight ? 1f:-1f) * 30f;
            _just_climbed -= delta;
            if (_can_free_jump <= 0f)
            {
                JustClimbed = false;
            }
        }

        // Can-free-jump
        if (CanFreeJump)
        {
            _can_free_jump -= delta;
            if (_can_free_jump <= 0f)
            {
                jumps++; CanFreeJump = false;
            }
        }

        velocity.y = Mathf.Min(TerminalVelocity, velocity.y);
        velocity   = MoveAndSlide(velocity, Godot.Vector2.Up);
    }