1. Hello,

    I have been looking everywhere in the Oxide .dll files for some sort of hook or method that allows for me to modify a items condition as it's created in a Barrel/Crate.

    I'm still rather new to learning C# so any guidance would be greatly appreciated!

    Regards,
     
  2. I don't believe your answer is gonna be in the oxide files. Try looking at docs.oxidemod.org if not there you need to look inside the assembly for rust
     
  3. Basic example:
    Code:
    void OnItemAddedToContainer(ItemContainer container, Item item)
    {
        if (container == null || item == null) return;
        if (item.hasCondition)
            item.condition = 100f;
    }
     
  4. @Fujukura - I had very similar code to that but all it would do is repair the item basically if it was placed into a container of any kind. However I didn't have null checks.

    Here was the code I used.

    Code:
    void OnItemAddedToContainer(ItemContainer container, Item item)
    {
                item.condition = item.maxCondition;
                //Puts("OnItemAddedToContainer works!");
    }
    
     
  5. Evano what exactly are you trying to do? Fujikura's code will repair an item to full condition.

    If you wanted that item at half condition you would change the line item.condition = 100f to item.condition = 50f;

    Are you trying to do something other than that?
     
  6. Yes, I'm trying to adjust their condition when they're created in a LootContainer i.e Barrels/Crates the code above just adjusts the condition to max when it's placed in ANY container. So a player can put a broken AK in a small wooden box and it would be repaired. I need items specifically to be max condition when they're created in a Barrel/Crate to override Garry's changes in a previous devblog. does that make sense? I can word things confusing sometimes. :S
    [DOUBLEPOST=1482699958][/DOUBLEPOST][​IMG]
     
  7. Ah! Ok got it. Try this:

    Code:
    void OnItemAddedToContainer(ItemContainer container, Item item)
            {
                if(container == null || item == null) return;
                if(container.entityOwner && !(container.entityOwner is LootContainer)) return;
                if(item.owners.Count != 0) return;
                if(item.hasCondition)
                    item.condition = 100f;
            }
    The item container is not the actual box. Item containers are things that are 'possessed' by StorageContainers or Players. LootContainer is derived from StorageContainer and is the type that refers to all barrels/world spawn boxes.

    So by checking if the container.entityOwner is a LootContainer we are basically saying, "Is the thing that owns this ItemContainer a world spawn loot box or barrel? If not, return"

    If instead we checked if it was a StorageContainer then we could check for all player created loot boxes as well.

    Hope this helps!
    [DOUBLEPOST=1482700373][/DOUBLEPOST]However, do note that if a player places an item inside of a LootContainer (a barrel) it will still affect it's condition. (A player places a Broken AK inside a barrel it's going to repair it).

    To fix that you can put this line in there (before u set the items condition): if(item.owners.Count != 0) return;

    Items that are created by the server dont have an owner yet (to my knowledge). So if it's an item with an owner, dont repair it.

    Let me know if there are any problems!
     
  8. Wow very insightful! I will give it a try when I get home. Happy holidays!
     
  9. Okay @EinTime I tried it and it compiled but it doesn't seem to be changing the condition of anything. I even tried to be a little more specific in the code by added.

    Code:
    if(container.entityOwner is LootContainer && item.hasCondition)
                    item.condition = 100f;
    
    Good news is the check for player storage is working, just not the LootContainers.

    I'm still new to C# but now that I think of it do you think this could be the problem?

    Code:
    if(item.owners.Count != 0) return;
    
    If LootContainer is a owner wouldn't that cause a problem? Or am I reading it wrong?
     
  10. If it's not changing the condition then it means that one of our if statements is returning. Instead of just returning can you do a Puts("This doesnt work") under the if so we can find which one it is.

    An easier solution might also be to use the oxide hook:
    Code:
    void OnLootEntity(BasePlayer player, BaseEntity entity)
    {
        Puts("OnLootEntity works!");
    }
    You could cast that entity to a LootContainer (LootContainer container = entity as LootContainer), check if it's null and, if not, set the condition of all items inside to 100.
    [DOUBLEPOST=1482703250][/DOUBLEPOST]Sorry I can't test them my self, my server only drops components from lootcontainers. Best I can do is maybes, haha
    [DOUBLEPOST=1482703355][/DOUBLEPOST]Exact code for that would be:

    Code:
    void OnLootEntity(BasePlayer player, BaseEntity entity)
            {
                LootContainer container = entity as LootContainer;
                if(container)
                {
                    foreach(var item in container.inventory.itemList)
                    {
                        item.condition = 100f;
                    }
                }
            }
    You might also want to do some checks to make sure the LootContainer has an inventory, and that each item inside isnt null, etc.
     
  11. Do you put it after the method, or under the last if in the method? Because I put it under the last if and I occasionally got spam in the console but I don't know how to use that information to find out what statement is the cause of the problem.
     
  12. For example, instead of:
    Code:
    if(container.entityOwner && !(container.entityOwner is LootContainer)) return;
    Do

    Code:
    if(container.entityOwner == null)
    {
         Puts("Entity Owner is Null");
         return;
    }
    if(!(container.entityOwner is LootContainer))
    {
         Puts("Entity is not LootContainer");
         return;
    }
    Just so we can see which if statement isnt passing.

    However, I think that second approach I posted may be the better one.
     
  13. Okay I did that, here's the code so far.

    Code:
    void OnItemAddedToContainer(ItemContainer container, Item item)
            {
                if(container == null || item == null)return;
              
                if(container.entityOwner == null)
                {
                    Puts("Entity Owner is Null");
                    return;
                }
                if(!(container.entityOwner is LootContainer))
                {
                    Puts("Entity is not LootContainer");
                    return;
                }
                if(item.owners.Count != 0) return;
                if(container.entityOwner is LootContainer && item.hasCondition)
                    item.condition = 100f;
            }
    
    And it's returning "Entity Owner is Null" Whenever I break a barrel or reload LootConfig. So I assume the check for Owner is causing the hangup.
     
  14. Hmm, it's odd that the owner of the item container would be null. To be honest I have no idea why.

    I think the better approach would be to go with the OnLootEntity hook. Also, who knows if the OnItemAddedToContainer hook is even called when the map is spawned and item's are first placed. Since it's during map generation it may be before oxide hooks in? Who knows. But yea, either way, OnLootEntity will be the safer/better option. Give that a try and let me know if it works.
     
  15. Wouldn't that only set condition of items when they're looted? Also something just occurred to me, aren't player entities set to LootContainer on death?
     
  16. I don't believe that player's are set to LootContainer or even StorageContainer on death. Remember there is a big difference between LootContainer (the derived class that barrels and boxes use) and ItemContainer. All BaseEntities have the functionality to be looted. When players die that lootcontainer (their inventory) is then able to be looted.

    As for it only working when players open the barrel, is that a problem?

    I believe that OnLootContainer is called when the player opens a loot container, and not when they extract or deposit loot into it, but I could be wrong about that. OnLootContainer has a BaseEntity parameter, which should be the entity that is being lootEr (and not it's container)

    One more thing: regarding that null reference you were getting prior. Try just forcing a GetComponent<BaseEntity>() on the loot container. May work may not =P
     
    Last edited by a moderator: Dec 26, 2016
  17. Yeah I'm not having luck with OnLootEntity either and no that's not a problem, I misunderstood. As for the GetComponent<BaseEntity>() I'm not familiar with this, did you find this in the .dll? And how do you mean by force?
     
  18. GetComponent<T>() is a unity method. It will get any Type which derives from component that is attached to the same game object as the script that is calling it. So, if ItemContainer is attached to the same GameObject as the BaseEntity that has that loot container you may be able to get a reference to that BaseEntity directly by using GetComponent. Try this,

    BaseEntity be = container.GetComponent<BaseEntity>();

    This will only work if container is indeed a monobehaviour (which I'm not sure is true. I'm not at a computer and can't check)
     
  19. Am i right you trying to revert the changes from DevBlog 85???? Nize, it was created over a year ago :)

    when you search for a solution for this, you need to find out, how its done ;)
    All before leads you maybe into a direction, but sure not the right.

    How its done currently by the game:
    Code:
    // LootContainer
    public virtual void PopulateLoot()
    {
        if (this.lootDefinition == null)
        {
            return;
        }
        for (int i = 0; i < this.maxDefinitionsToSpawn; i++)
        {
            this.lootDefinition.SpawnIntoContainer(this.inventory);
        }
        if (this.SpawnType == LootContainer.spawnType.ROADSIDE || this.SpawnType == LootContainer.spawnType.TOWN)
        {
            foreach (Item current in this.inventory.itemList)
            {
                if (current.hasCondition)
                {
                    current.condition = UnityEngine.Random.Range(current.info.condition.foundCondition.fractionMin, current.info.condition.foundCondition.fractionMax) * current.info.condition.max;
                }
            }
        }
        if (this.distributeFragments)
        {
            int num = 1;
            for (int j = 0; j < this.inventory.capacity; j++)
            {
                Item slot = this.inventory.GetSlot(j);
                if (slot == null)
                {
                    break;
                }
                num += this.ScoreForRarity(slot.info.rarity);
            }
        }
    }
    
    When you want to revert it, you need to to check for "OnEntitySpawned" for LootContainers.
    Afterwards you might need to wait 1 or 2 ticks (NextTick), to let the "PopulateLoot" function finish its job.

    Then you could run the same thing like it did, but reverting it to default, like in example:
    Code:
        LootContainer container = entity.GetComponent<LootContainer>();
        if (container.SpawnType == LootContainer.spawnType.ROADSIDE || container.SpawnType == LootContainer.spawnType.TOWN)
        {
            foreach (Item current in container.inventory.itemList)
            {
                if (current.hasCondition)
                {
                    current.condition = current.info.condition.max;
                }
            }
        }
     
  20. Okay yeah, I saw that when I was digging through the .dll but I was apparently using it wrong.

    So you're saying I have check for OnEntitySpawned on a tick and THEN execute code like in your example? Back to the drawing board, I have more stuff to look up then I have been using the .dll files and other plugins for reference.