Item Behavior Crashcourse - TeamMoonstorm/MoonstormSharedUtils GitHub Wiki
List of Contents:
- What are item behaviors
- Example of ItemBehaviors
- Why ItemBehaviors
- What Interfaces
- How ItemBehaviors are added
- How ItemBehaviors are used in MSU
- Closing words
What are item behaviors
Item Behaviors are a type of Monobehavior that is found inside the CharacterBody component (CharacterBody.ItemBehavior). The ItemBehavior inherits from the MonoBehavior class of unity, which means it works as a component, and inherits all the utilities a component has, such as having access to OnDestroy(), Start(), Update(), FixedUpdate(), LateUpdate(), etc.
There are 2 key aspects that separate the ItemBehavior from the MonoBehavior component, and that's the inclusion of 2 special fields:
- body: the "body" field is part of the itemBehavior class and always points to the CharacterBody the component is attached to.
- stack: the "stack" field is also part of the itemBehavior class and always represents the amount of stacks the CharacterBody has in their inventory.
Examples of ItemBehaviors
While a lot of items in RoR2 are written in separate classes, there are some items ingame that use ItemBehaviors, some example of these are:
- Items that use NetworkedBodyAttachment, such as:
- Defensive Microbots
- Headstompers
- Genesis Loop
- Resonance Disk
- Volatile Battery
- Empathy Cores
- Mired urn
- The following items also use ItemBehaviors:
- Kjaro & Runald's Bands
- Bustling Fungus
- Stealthkit
- Red Whip
- Little Disciple
Why ItemBehaviors
ItemBehaviors by themselves are a powerful tool. ItemBehaviors allow you to potentially write all the needed code for an item in a single class, most of the time without the need of using on hooks for hooking onto basic unity methods via RoR2Application (Such as RoR2Application.onUpdate).
Not only that, since ItemBehaviors inherit from monobehavior, they themselves have the ability to use the plethora of Interfaces that Risk of Rain 2 has, most of these interfaces completely negate the need of using hooks for most of an item's functionality. and since the item behavior itself only affects the body its attached to, There's no need to write complex systems to make sure whatever body contains enough stacks of an item.
What Interfaces?
RoR2 in reality contains a lot of interfaces that can be used for handling ingame events, below is a list of the most used interfaces that MSU mods tend to use for their items:
- IOnDamageDealtServerReceiver: Used when an body deals damage to a victim.
- IOnDamageInflictedServerReceiver: Used when a body inflicts damage to a victim.
- IOnIncomingDamageServerReceiver: Used when a body is about to receive damage (can be used to completely reject a damage info)
- IOnKilledOtherserverReceiver: Used when the body kills a victim.
- IOnKilledServerReceiver: Used when the body dies
- IOnTakeDamageServerReceiver: Used when the body takes damage
Alongside these interfaces, MSU also implements the following interfaces that can be used in item behaviors:
- IStatItemBehavior: Used for Recalculate stats, everything on "RecalculateStatsStart" happens before orig(self), and everything on "RecalculateStatsEnd" happens after orig(self)
- IOnIncomingDamageOtherServerReceiver: Used as a method for a body to directly modify the damage that an enemy is about to take, you have acces to both the damage info and the health component of the victim.
With this amount of interfaces, there's little to no need on using On.Hooks, at most what you'll need is to use some of the default delegates that ror2 provides.
How ItemBehaviors are added.
Item Behaviors are not added via .AddComponent(). this is because the characterBody itself has its own method for adding an itemBehavior. specifically CharacterBody.AddItemBehavior<T>(int stack)
public T AddItemBehavior<T>(int stack) where T : ItemBehavior
{
T val = GetComponent<T>();
if (stack > 0)
{
if (!(Object)val)
{
val = base.gameObject.AddComponent<T>();
val.body = this;
val.enabled = true;
}
val.stack = stack;
return val;
}
if ((bool)(Object)val)
{
Object.Destroy(val);
}
return null;
}
In very simple terms, you can change stack to Inventory.GetItemCount(ItemDef itemDef)
to get your item's stacks, if the amount is greater than 0, it'll add the item behavior, otherwise, it'll destroy the item behavior.
How ItemBehaviors are used in MSU.
Due to the innate versastility of item behaviors in the game, MSU uses the ItemBehavior class for more than just items, in fact, item behaviors are how MSU handles Items, Certain Equipments and Buffs.
The MoonstormItemManager component that MSU adds to each body actually takes care of adding the item behaviors for you, using the dictionaries that are found in the module bases and minimal amounts of on hooks.
The following classes have a virtual method that you can override to add your own logic for adding an item behavior.
Closing Words
Item behaviors in general are an extremely useful tool that, if used correctly, can be used to cover the basis of most common modded content in Risk of Rain 2. While item behaviors by themselves cannot be networked due to not being NetworkBehaviors, the game uses NetworkedBodyAttachment to circumvent this.