IEntitySource - tModLoader/tModLoader GitHub Wiki
If you are making a 1.4 tModLoader mod, you will need to use IEntitySource
. This guide will go over the purpose of IEntitySource
and the most frequent uses of it.
Purpose of IEntitySource
IEntitySource
works with the OnSpawn
hooks to provide additional information about why a Projectile/NPC/Item
is spawned in the world. There are two primary use cases:
- Altering the properties of an
NPC
/Projectile
only when spawned from a specific context (eg bombs from pots, or minions of a boss). - Transferring stats or buffs (such as npc banner id, or player/weapon crit chance), from the source to the spawned entity (normally a
Projectile
)
For example, when a Boss NPC spawns minions, those minions are spawned with the IEntitySource
value resulting from the helper method NPC.GetSource_FromAI()
. The result of that helper method is a EntitySource_Parent
class with an Entity
field of type NPC
. This IEntitySource
could then be detected by a mod that intended to reduce the HP of all boss minions by half. This additional info can help facilitate many more effects that were previously impossible to accomplish with mods.
Note that OnSpawn
does not let you prevent the spawning of an entity. On/IL hooks are currently required for that, but such a hook could be considered in the future (causing the returned entity to be the 'dummy' entity slot at the end of the array).
See ExampleSourceDependentProjectileTweaks
, ExampleSourceDependentItemTweaks
, or ProjectileWithGrowingDamage
classes in Example Mod for some uses.
Lifetime
Do not store IEntitySource
in fields. The validity of the information they encapsulate is only relevant at the moment of spawning. Any lasting effects of the source information will need to be registered in fields within your mod at the time of spawning. The details on why it is a bad idea are too advanced for this guide.
Methods requiring IEntitySource
The following commonly used methods require IEntitySource
.
Gore.NewGore
Gore.NewGoreDirect
Gore.NewGorePerfect
Player.QuickSpawnItem
Player.QuickSpawnClonedItem
Item.NewItem
NPC.NewNPC
Projectile.NewProjectile
Projectile.NewProjectileDirect
Using Sources
EntitySource_Parent
If in doubt use something which extends from Most of the time, this means calling GetSource_FromThis()
, GetSource_FromAI()
, GetSource_Loot()
, GetSource_Death()
, GetSource_OnHit()
or GetSource_OnHurt()
EntitySource_Parent
is the most important source. tML uses this to transfer values such as bannerIdToRespondTo/CritChance/ArmorPenetration
from the parent NPC
or Player
(or Player
+ Item
in the case of EntitySource_ItemUse
) to a spawned Projectile
. These values are also transferred from parent projectiles to child projectiles via EntitySource_Parent
ensuring the initial 'source' value is retained.
Detailed list
- NPC spawning projectiles should use
NPC.GetSource_FromAI()
- NPC spawning item drops should use
NPC.GetSource_Loot()
(if loot) orNPC.GetSource_DropAsItem()
(if anything else). (Note that 99.9% of NPC item drops should be using the new loot system) - NPC spawning other NPC, such as boss minions, should use
NPC.GetSource_FromAI()
- NPC spawning gore on death should use
NPC.GetSource_Death()
- Projectiles spawning items, such as arrow recovery drops, should use
Projectile.GetSource_DropAsItem()
- Projectiles spawning other projectiles, like a splitting projectile or a shooting minion, should use
Projectile.GetSource_FromThis()
- Held projectile weapons spawning other projectiles using ammo should use
player.GetSource_ItemUse_WithPotentialAmmo(player.HeldItem, usedAmmoItemId)
- Spawning minions or pets in
ModBuff.Update
: useplayer.GetSource_Buff(buffIndex)
- An accessory spawning a projectile: use
player.GetSource_Accessory(itemInstance)
orplayer.GetSource_Accessory_OnHurt(itemInstance, hurtInfo.DamageSource)
- An armor set bonus spawning a projectile: Use
player.GetSource_FromThis("SetBonus_MySetName")
- Spawning things in
ModItem.UseItem
, or anyModItem
not covered elsewhere:player.GetSource_ItemUse(Item)
- Player spawning Projectiles in
ModItem.Shoot
should use thesource
passed into the method - Tile dropping an item (
ModTile.KillMultiTile
orGlobalTile.Drop
) should useWorldGen.GetItemSource_FromTileBreak(i, j)
- Player spawning an item due to dropping or being unable to recover an item from a UISlot (player.GetItem overflow) should use
new EntitySource_OverfullInventory(player)
Retrieving Information from IEntitySource
Using the information provided by IEntitySource
is the other half of the purpose of this feature. There are various methods available that provide the source to the modder, all called OnSpawn
.
For example, in GlobalProjectile.OnSpawn
, there is a IEntitySource source
parameter. We can use casting to cast the IEntitySource
to the source that we wish to check. This code uses the is
operator and the property pattern to quickly match a specific set of conditions.
// Property pattern approach
if (source is EntitySource_Parent { Entity: NPC { type: NPCID.TacticalSkeleton } }) {
// Do things here to projectiles (BulletDeadeye) spawned by the TacticalSkeleton enemy without affecting others
}
// Non property pattern approach
if (source is EntitySource_Parent parent && parent.Entity is NPC npc && npc.type == NPCID.TacticalSkeleton) {
// Do things here to projectiles (BulletDeadeye) spawned by the TacticalSkeleton enemy without affecting others
}
For maximum compatibility with mods which add custom entity sources, use is
with interfaces rather than classes when they exist:
is IEntitySource_WithStatsFromItem
instead ofis EntitySource_ItemUse
is IEntitySource_OnHit
instead ofis EntitySource_OnHit
is IEntitySource_OnHurt
instead ofis EntitySource_OnHurt
Note that for most things, you'll have to manually sync changes. OnSpawn happens on the client or server that spawns the entity, any changes that should reflect on other clients need to by synced in some manner. The files in ExampleMod/Common/EntitySources show examples of this.