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,
Solved Override item condition on creation?
Discussion in 'Rust Development' started by Evano, Dec 22, 2016.
-
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
-
Basic example:
Code:void OnItemAddedToContainer(ItemContainer container, Item item) { if (container == null || item == null) return; if (item.hasCondition) item.condition = 100f; }
-
@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!"); }
-
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? -
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] -
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; }
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! -
Wow very insightful! I will give it a try when I get home. Happy holidays!
-
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;
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 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!"); }
[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; } } }
-
-
For example, instead of:
Code:if(container.entityOwner && !(container.entityOwner is LootContainer)) return;
Code:if(container.entityOwner == null) { Puts("Entity Owner is Null"); return; } if(!(container.entityOwner is LootContainer)) { Puts("Entity is not LootContainer"); return; }
However, I think that second approach I posted may be the better one. -
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; }
-
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. -
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?
-
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 =PLast edited by a moderator: Dec 26, 2016 -
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?
-
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) -
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); } } }
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; } } }
-
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.