Hits and sizes an ability writes by hand¶
Direct hits¶
A hit that calls hurt itself, or AkumaAbilityHelper.hurtBurst without a component, does not grow on its own. Route it through AkumaSize:
AkumaSize.hurt(user, this, target, source, damage); // target.hurt(source, damage x the damage factor)
float grown = AkumaSize.damage(user, this, damage); // the grown figure, for any other path
AkumaAbilityHelper.hurtBurst(target, source, grown);
Pass the ability (this) so the exempt list applies. Never use them on a hit that goes through DealDamageComponent.hurtTarget: it would grow twice.
AkumaLib's own bases (GustAbility, WaveAbility, AuraAbility, DiveStrikeAbility, the blocks of StompAbility, ZoneAbility, SpreadingBlockAbility, BlockWaveAbility) already size their own areas.
Sizes an ability writes: the size-aware blocks¶
A radius, a width, a reach or a round of blocks written as a number stays a man's for a giant: only the hits that go through the size path grow. Every size an ability writes goes through AkumaLib (#664). A man gets exactly the number written, so moving a size to these blocks changes nothing for him; an exempt ability keeps it too.
| What | Block | Before (stays a man's) | After (grows with the user) |
|---|---|---|---|
| A radius, a width, a distance | AkumaSize.reach(user, ability, base) |
double r = RADIUS; |
double r = AkumaSize.reach(user, this, RADIUS); |
| A round, a ball, a strip of blocks | AkumaShapes.disc / ball / strip |
for (dx = -R; dx <= R; dx++) for (dz ...) if (dx*dx + dz*dz <= R*R + 1) |
for (BlockPos pos : AkumaShapes.disc(user, this, centre, R)) |
| A layer on the ground (cream, syrup, mud) | AkumaShapes.layDisc(group, user, ability, level, centre, radius, layer, up, down) |
the loop above with GroundLayers.layOn |
one call, same rules (TemporaryBlocks, GroundLayers) |
| Targets around a point that is not the user (a tentacle, a crest) | AkumaTargeting.around(user, ability, centre, radius, filter) |
getEntitiesOfClass(..., box.inflate(REACH), ...) |
the same bodies within the sized radius |
| The aim of a targeted technique (the one he looks at, the point he aims at) | AkumaTargeting.firstInSight / aimPoint, or AkumaTargeting.aimRange(user, range) for a ray of the kit's own |
WyHelper.rayTraceBlocksAndEntities(user, RANGE) (inside the user's ability it grows by itself since #689; outside it, it does not) |
the ray grown by the reach factor (#657): a giant aims at his feet |
| What the ability spawns (a wave, a tentacle, a construct) | AkumaSpawnSize.sized(entity, user, ability) |
new WaveEntity(..., HALF_WIDTH) |
AkumaSpawnSize.sized(new WaveEntity(..., HALF_WIDTH), user, this) |
| A wall's panels, as big as the body that raises them (maintainer, 2026-10-27) | PanelWalls.raise(...) (by itself), or AkumaSpawnSize.bodySized(entity, user, ability) and PanelWalls.size(user) for the spacing |
panels a block wide, 2 blocks from the feet: a giant's wall in his body | a man's wall grown by SIZE around the feet: each panel, the gaps and the distance ahead; 48 blocks wide at most |
| That spawn's own reach | AkumaSpawnSize.reach(spawn, base) |
inflate(REACH) around the tentacle |
inflate(AkumaSpawnSize.reach(this, REACH)) |
- Every entity a player spawns inherits his size by itself (#670): when it joins the world, an entity whose owner is a player takes his reach factor, once. The owner is read where Minecraft keeps it: a projectile's owner (arrows, tridents, snowballs and fireballs included), a tamed summon's (
OwnableEntity), the owner a construct or a summon declares (TraceableEntity; AkumaLib'sTornadoEntity,HoldingSphereEntityandDecoyEntitydeclare theirs). Along a chain the factor is inherited, never multiplied: a giant's turret at x3 gives x3 to its shell. Creatures ofakumalib:size_followerscount as players; other NPCs and mobs, not yet. - An entity that keeps its owner in a field of its own, or gets it after joining the world, calls
AkumaSpawnSize.inherit(entity, owner)right after it has one (or implementsTraceableEntity).sizedstamps one before it joins; neither grows an entity twice. List such types inakumalib:size_inherits_by_call: the GameTesteverySpawnTypeIsHandledfails on any non-creature type of the base mod, AkumaLib or Missing that declares no owner and sits in neither tag./akumalib spawnsize <targets>shows an entity's factor and where it came from. - A change of dimension stamps nothing new: an entity that joined the world unstamped (a pet tamed after it joined) stays unstamped in the next dimension. A stamped one keeps its factor.
- What grows: the box (against entities and blocks), the drawing, on every client; the factor is saved with the entity. A grown vanilla projectile strikes the creatures its box touches; against blocks it still flies on a line from its centre.
- A living summon is as big as its user (#707, maintainer 2026-10-27): its body is its user's size (
SIZEx the user's size, a small user's too: a Doru clone of a SIZE 6.667 player is 6.667 high, of a SIZE 0.5 one 0.5), so its box, drawing and eyes are those of a player of that size. The rest follows from that body once, as for that player: blows (ATTACK_DAMAGE) by the melee damage curve, walk and max health bySizeBodyStats, its own abilities throughAkumaSize.factor, which reads its master's size. A summon ofakumalib:size_followersgets its blows from the size rule itself, not twice. Saved once: read back from a save it does not grow again. Its own numbers keep the reach factor (below). - Never grown: the entity types of
akumalib:size_exempt(markers, item and XP drops, vanilla pets and mounts, what lives in a dimension of its own). A pack adds to it. - The spawn's own numbers (a pull distance, a search box, a radius) read its factor, one line each:
AkumaSpawnSize.reach(this, base),AkumaSpawnSize.factor(this, Family.DAMAGE). AkumaLib does it for its own bases (tornado's funnel and touch, a hold's slack and smothering hits, a decoy's call, a boomerang's catch) and for the base mod's Raigo (crater, shockwave), Ursus Shock (crater, blast, push), Dai Enkai Entei (boiled water) and MH5 (gas). WaveAbilitytakes the factor as its wave leaves: the wave is wider and, since 6.1.0, runs further by it (the crest's step xwaveScale()).sizedHalfWidth()is for what the subclass draws or lays across the wave inonWaveTick. Give the entity it spawns inonWaveStartthe same withAkumaSpawnSize.sized(wave, user, this).- An area that already uses a
RangeComponentneeds nothing: its range carries the size bonus. - A big body's grab holds several (#658,
SizeGrabs): as many bodies as the reach factor, rounded (SizeGrabs.count: 1 up to SIZE 2.25, 3 for a giant at 6.667 and at the cap, 1 for an exempt ability), the others nearest the user's line of sight and no further along it than the first (SizeGrabs.more), each taking the full blows (maintainer, 2026-10-26).HoldingSphereEntitycloses a copy of itself on each by itself (a subclass with plain fields copies them incopyTo); a technique that already closes on several at once (an area) is not grown again.GrabAbilityandCarryAbilityhold the others beside the first and pass them every blow the user lands on it; their hooks only see the first. A grab of a kit's own takescount/morefor its pick and aSizeGrabs.Held(take,tick,release) for its hold. A big user holds the grabbed body at the edge of his own, not inside his box (#705,SizeGrabs.heldOutward, on everyGrabEntityComponent): out along his facing by the half-width his SIZE added. A man unchanged. A forwarded blow opens the others' frames when the first's are open (ahurtBurstbite lands on each). A hold that stops ticking (death, logout, unequip) forwards nothing more. A grab's first body:SizeGrabs.firstInSight/SizeGrabs.inSight(in place ofAkumaTargeting.firstInSight/AkumaAim.inSight) take the body the sight meets, and for a bigger body that meets none, the one nearest his line of sight within the same lane, as far as his sight reaches (maintainer, 2026-10-27: from a giant's eyes a body at his feet is a small mark). A man, a smaller body or an exempt ability: the sight alone.
Example, a round of cream (Missing's Cream Flood):
// before: a man's 8 blocks, whatever the user's size
for (int dx = -RADIUS; dx <= RADIUS; dx++)
for (int dz = -RADIUS; dz <= RADIUS; dz++)
if (dx * dx + dz * dz <= RADIUS * RADIUS + 1)
GroundLayers.layOn(this.flood, entity, level, centre.offset(dx, 0, dz), cream, 2, 2);
// after: 8 blocks for a man, 16 for a body x4 (reach x2)
AkumaShapes.layDisc(this.flood, entity, this, level, centre, RADIUS, cream, 2, 2);