void CollectOre(OreType type, int amount)
    {
        if (amount == 0)
        {
            return;
        }
        currentOres[(int)type] += amount;
        backPack += amount;
        OnPackFillChanged?.Invoke(backPack, backPackCap);
        // +amount type (total)
        //Debug.Log($"Gained {type} ({currentOres[(int)type]})");

        if (pickupTextQueue.Count < pickupQueueLength)
        {
            // create a new one
            TextFade copy = Instantiate(pickupTextPrefab);
            pickupTextQueue.Enqueue(copy);
        }

        TextFade next = pickupTextQueue.Dequeue();

        next.transform.position = transform.position + pickupOffset; // negate when facing left
        next.UpdateColour(type);
        next.SetText($"+{amount} {type} ({currentOres[(int)type]})");
        next.Reset();
        pickupTextQueue.Enqueue(next); // recycle
        //pickupText.text = $"+{amount} {type} ({currentOres[(int)type]})";

        OnOreChanged?.Invoke((int)type, currentOres[(int)type]);

        if (IsBagFull())
        {
            BagFull();
        }
    }
    public void ReachedTopOfRope()
    {
        // square the rope is at
        xPos      = 7;
        yPos      = 1;
        zPos      = 0;
        targetPos = GetGridPosition(); // so you stay put
        usingRope = false;

        lastAnchorX = 7;
        lastAnchorY = 1;
        lastAnchorZ = 0;

        UpdateDepth();
        OnRopeEnd?.Invoke();
        // should maybe do a cutscene here
        // also I probably fall in a hole
        // DumpOre()
        money += CalculateMoney();
        OnMoneyChanged?.Invoke(money);
        backPack = 0;
        OnPackFillChanged?.Invoke(backPack, backPackCap);
    }
 public void UpgradePack(int size)
 {
     backPackCap += size;
     OnPackFillChanged?.Invoke(backPack, backPackCap);
 }