Goals and behaviour
Attack goals, sitting and sleeping, trinkets and spellbooks, reusable goals, and the order interactions run in.
Attack goals
createAttackGoal(min, max) returns an Iron's Spellbooks WizardAttackGoal (or a subclass). The lib calls it again with higher spell quality whenever the owner puts on or takes off the familiar's trinket, so always pass min and max to setSpellQuality. FamiliarGoals.FamiliarWizardAttackGoal no longer exists: use WizardAttackGoal directly for walking familiars.
Signature spells: Iron's setSingleUseSpell(spell, minDelay, maxDelay, minLevel, maxLevel) makes the familiar cast a spell outside its tags every so often (delays in ticks). It can be called more than once. Add these spells to getCompendiumSpells() too, so the compendium shows them.
FamiliarGoals provides these goals for familiars that need special movement:
| Goal | For | Extra builder methods |
|---|---|---|
FlyingWizardAttackGoal | Flying casters: orbit the target from above, keep their distance and retreat from nearby threats | setPreferredHeight(height), setCombatRanges(min, optimal, max), setThreatAwarenessRadius(radius) |
FlyingSkirmisherAttackGoal | Flying melee fighters: dash in for melee combos, then pull back | setPreferredDistance, setEngageThreshold, setDisengageDistance, setEngageCooldown, setMaxEngageTicks, setMaxDisengageTicks, setEngageSpeedMultiplier, setDisengageSpeedMultiplier, setMaxCombosPerEngage, setGapCloserSpell(spell, level), setGapCloserDistance, setSpellCastChance, setThreatAwarenessRadius, setCrowdedThreshold |
MeleeSpellCastWarlockAttackGoal | Walking melee fighters that cast a gap-closing spell on far targets | setGapCloserSpell(spell, level), setGapCloserDistance(distance) |
FlyingWizardAttackGoal defaults to a height of 4, ranges of 5 / 10 / 20 blocks and a threat radius of 14. The two melee goals need an entity that implements Iron's IAnimatedAttacker.
Sitting and sleeping
A familiar is in one of these poses:
| Pose | When | Animation | Render offset |
|---|---|---|---|
| Sleeping | Sitting on a familiar bed, or stunned without a sit animation | sleep | getSleepingOffsetY() |
| Sitting | Sitting off a bed, or stunned with a sit animation | sit, or idle without a sit animation | getSittingOffsetY() |
| Normal | Anything else | The usual animations | None |
Being asleep on a bed takes priority over a stun.
Sit animation
The sit animation is off by default, so familiars without one aren't affected. Add a looping sit animation to the familiar's animation file and enable it:
@Override
protected boolean hasSitAnimation() {
return true;
}While the sit animation plays, isAnimating() returns true, so the idle/walk controller stops and the head and legs follow the animation instead of being animated procedurally. To keep the head looking around while sitting, override shouldAlwaysAnimateHead():
@Override
public boolean shouldAlwaysAnimateHead() {
return isInSittingPose();
}Vertical offsets
Move the model up or down while sitting or sleeping, for example to sink it into a bed cushion:
@Override
public float getSittingOffsetY() {
return -0.2F; // blocks, negative = down
}
@Override
public float getSleepingOffsetY() {
return -0.1F;
}- The offsets are in blocks, applied after the renderer's own scaling, so a scaled-down model moves less: tune them in-game.
- Only the model and its layers (colors, hats, weapons) move. The hitbox and shadow stay where the familiar is.
- The offset is applied automatically for every familiar, through GeckoLib's pre-render event. Don't also translate the pose stack for it in your renderer, or it's applied twice.
- The offset snaps on and off, like the sleep animation.
Pose helpers
boolean isInSittingPose(); // sitting off a bed, or stunned with a sit animation
boolean isInSleepingPose(); // on a bed, or stunned without a sit animation
float getPoseOffsetY(); // the offset being applied right nowThe poses are updated once per tick, on both sides.
Custom sit items
By default, a familiar sits or stands up when its owner right-clicks it with an item in familiarslib:familiar_sit_items (see Sit items). Override isSitItem to give a familiar its own:
@Override
protected boolean isSitItem(ItemStack stack) {
return stack.is(MyItems.BONE_FLUTE.get()) || super.isSitItem(stack);
}Leave out super.isSitItem(stack) for the familiar to ignore the shared tag. The tag key is ModTags.FAMILIAR_SIT_ITEMS; to add your items with datagen:
tag(ModTags.FAMILIAR_SIT_ITEMS).add(MyItems.BONE_FLUTE.get());Trinkets, schools and items
Trinket: every familiar declares its trinket. While its owner wears it in any curio slot, the familiar's spell quality switches from getOriginalQualityValues() (0.1 to 0.3) to getTrinketQualityValues() (0.4 to 0.6):
@Override
protected Item getValidTrinket() {
return MyItems.MY_FAMILIAR_TRINKET.get();
}School: getPreferredPowerAttribute() returns the spell power attribute that matches the familiar's school, or null. Familiar mods use it for bonuses that depend on which familiars are out, such as Alshanex's Familiars' Familiologist set.
Base items you can extend:
| Class | What it is |
|---|---|
AbstractFamiliarTotem | A totem bound to one familiar, used up to revive it (stores the familiar in the familiarslib:soul_link component) |
AbstractMultiSelectionCurio | A curio that turns on multi-familiar summoning (see Summoning several familiars) |
AbstractFamiliarSpellbookItem | A spellbook that shares its wearer's magic attributes with their summoned familiars: half of the wearer's bonus above the base value, split evenly between them, for spell power, spell resist, and every school's power and resist (addon schools included). Default stats: +200 max mana, +12% cast time reduction, +8% spell power; override getSpellbookAttributes() to change them |
AbstractRuneItem | Legacy. A shard that creates a familiar when used. Typed Familiar Eggs replace shards and need no item class; this class is kept so old shards keep working |
Reusable goals
FamiliarGoals also has ready-made goals your familiars can add in registerGoals(). They already respect sitting, stuns, houses (canExecuteGoalsInHouse()) and disabled movement. Among them:
| Goal | What it does |
|---|---|
FindAndUsePetBedGoal(pet, radius) | Hurt familiars look for a free familiar bed and sleep in it until healed |
MovementAwareFollowOwnerGoal, TeleportToOwnerGoal | Follow the owner, and teleport to them when too far |
TargetAttackerOfPlayersGoal(pet, owner) | Targets mobs that are targeting the owner |
StealItemsWhenNotWatchedGoal(pet, radius) | Picks up items in familiarslib:illusionist_steals when no player is looking |
ThunderstrikeGoal(pet) | Walks to nearby creepers and charges them |
WitherifyGoal(pet) | Turns nearby skeletons into wither skeletons |
WanderAroundHouseGoal, StayNearHouseGoal, CasualLookAtPlayerGoal, CasualRandomLookGoal | Behavior while wandering around a familiar house |
The base familiar classes already add the goals every familiar needs (following, beds, houses...), so check registerGoals() in AbstractSpellCastingPet before adding one twice. The ability goals (stealing, charging creepers, witherifying) are opt-in.
Interaction order
When a player right-clicks their own familiar, the lib's handlers run before the familiar's mobInteract:
- Identity Vessel: takes or gives an identity; never does anything else.
- Cosmetics: a shrunk cosmetic is put on; sneak + empty main hand takes one off.
- Override rules (server): a matching rule that changes a color applies and stops; one that changes nothing skips the dye step too.
- Dyes: a dye sets the dye slot of dyeable familiars, or the second dye slot while sneaking. A shrunk dye sets the eye slot, or the second eye slot while sneaking.
- Otherwise the familiar's normal interaction runs (feeding, consumables, sit items...).
The Familiar Camera doesn't use right-click on familiars: its photos are taken with left-click and never hurt them.
Color changes and taming unlock compendium colors.
