1. Hey,

    I've been scratching my head and searching the forums, but cannot find what I'm looking for. As the thread title suggests, is there a specific method called when a resource, such as a Tree or other node is destroyed.

    I've had a look at OnEntityDeath and can't see how that relates, I've also had a look at OnDispenserGather and not sure how I'd check for the last drop before the node is removed as an alternative.

    Info about what I'm trying to do, I'm giving a small amount of money for resource harvesting. I'm aware of another plugin that does the same, however I'm specifically looking to do so when a node is removed.

    Thanks for reading.
     
  2. ResourceDispenser.fractionRemaining == 0 is my best guess
    [DOUBLEPOST=1454435074][/DOUBLEPOST]Although to implement it would prob be like this:
    Code:
    private void OnDispenserGather(ResourceDispenser dispenser, BaseEntity entity, Item item)
            {
                if (dispenser.fractionRemaining == 0)
                {
                    //It is probably ded
                }
            }
     
  3. I would've liked this to work, but unfortunately not. I'll keep trying.
     
  4. Calytic

    Calytic Community Admin Community Mod

    Technically trees are entities. OnEntityDeath is what you need. If that doesn't work I don't know what to tell you. =)
     
  5. Thanks, I'll have another look ok into it.
     
  6. OnEntityDeath won't be triggered when a tree or another resource dispenser is destroyed because they are handled differently by the server. The most reliable way to capture the destroy event of a tree or another dispenser would be by checking the remaining fraction as mentioned above, the only thing you need to keep in mind when checking the remaining fraction is that if you want the actual value you need to calculate this yourself. This is because the hook is actually triggered before the remaining fraction is updated.

    Code:
    using System.Linq;namespace Oxide.Plugins
    {
        [Info("Tests", "Mughisi", 1.0)]
        class Tests : RustPlugin
        {
            private void OnDispenserGather(ResourceDispenser dispenser, BaseEntity entity, Item item)
            {
                if (IsEmpty(dispenser)) Puts($"The {dispenser} is empty and has been destroyed.");
            }        private bool IsEmpty(ResourceDispenser dispenser)
            {
                return dispenser.containedItems.Sum((ItemAmount x) => x.amount)/
                       dispenser.containedItems.Sum((ItemAmount x) => x.startAmount) <= 0f;
            }
        }
    }
     
  7. Thanks for your response, I really appreciate it.

    I was working towards, taking the resulting fraction reduction from the first hit and calculating how many hits remained by dividing the whole by the reduction.

    Thinking about it, it's not very efficient.
     
  8. Actually I do think there is another way:

    Let's take a look at the TreeEntity class inside the Assembly-CSharp.dll. Specifically at this bit of code:
    Code:
    public override void OnAttacked(HitInfo info)
    {
        if (base.isServer)
        {
            if (this.resourceDispenser != null)
            {
                this.resourceDispenser.OnAttacked(info);
            }
            if (!info.DidGather)
            {
                if (this.protection)
                {
                    this.protection.Scale(info.damageTypes);
                }
                float single = info.damageTypes.Total();
                TreeEntity treeEntity = this;
                treeEntity.health = treeEntity.health - single;
                if (this.health <= 0f)
                {
                    base.Kill(BaseNetworkable.DestroyMode.None);
                    return;
                }
            }
        }
    }
    The last if statement seems to be responsible for destroying the tree, so let's check out how exactly the tree is destroyed by looking at the Kill(BaseNetworkable.DestroyMode mode = 0) function:
    Code:
    public void Kill(BaseNetworkable.DestroyMode mode = 0)
    {
        if (this.isDestroyed)
        {
            Debug.LogWarning(string.Concat("Calling kill - but already IsDestroyed!? ", this));
            return;
        }
        base.BroadcastMessage("OnParentDestroying", SendMessageOptions.DontRequireReceiver);
        this.Term(mode);
        this.OnDestroy();
        Object.Destroy(base.gameObject);
    }
    If you are familiar with Unity, you might know what the following function call does:
    Code:
    base.BroadcastMessage("OnParentDestroying", SendMessageOptions.DontRequireReceiver);
    In short, it does the following:
    Code:
    public void BroadcastMessage(string methodName, SendMessageOptions options);
    Calls the method named methodName on every MonoBehaviour in this game object or any of its children.
    (source: Unity - Scripting API:)

    So what if we could attach a custom MonoBehaviour class with a function called OnParentDestroying(...) that does whatever we want.
    We should actually be able to do just that with the following Oixde hook:
    Code:
    void OnEntitySpawned(BaseNetworkable entity)
    {
        // filter out the entities that you want and attach your custom MonoBehaviour class to it
    }
    I'm not completely sure if this works but it's worth a try.
     
    Last edited by a moderator: Feb 2, 2016