Team up as Batman or Wonder Woman on Thematic’s official server! Craft gadgets, resize with Pehkui, and roleplay with friends in Minecraft 1.20.1. Featuring Mr Fantastic, Superman, Invincible, Batman, Deadpool
Thematic is a superhero mod with 104 craftable armors from DC, Marvel, The Boys and Invincible. You make them in survival at the Suit Bench.
Superman flies and has heat vision. The Flash is faster than anything else in the game. Green Lantern builds things out of light, and Batman gets by on gadgets and a grapple. We try to make each character play like themselves instead of giving everyone the same three powers.
You can see every suit, its powers and its recipe on the website.
Features
104 craftable armors across 32 collections, with comic, movie, show and game versions of most characters
A starter suit you pick on your first join, which you upgrade as you play
The Suit Bench, where you craft everything else
Rarities, shinies, and team bonuses when your friends wear suits from the same collection
Gadgets and weapons for the heroes who don't have powers
New ores, mobs, bosses and structures, plus the Speed Force
How to start
Thematic is a Fabric mod for Minecraft 1.20.1. This project is the suits. They run on the Thematic core, which needs Fabric API. The Modrinth App installs both for you.
When you join a world you'll get to pick a starter suit. After that, your goal is a Suit Bench:
At the bench you can look through every suit, check its stats and powers, and craft the one you want.
Each power has its own key. You can change them under Controls. The in-game wiki explains the rest, and the same pages are on the website.
Official server
We run a server at thematic.bond. You can also find it in the multiplayer menu under Official Server. Setup help is here.
FAQ
Forge? NeoForge?
Not yet, but we're working on it. A Forge 1.20.1 port is in progress, and there are alpha builds for 1.21 on NeoForge and Fabric.
Can you add (character)?
They might already be done. Turn off Hide Suits in the mod settings to see the suits we're still working on.
# New suits
## Starfire
- Starbolt (Equip): fires a single Starbolt.
- Dual Starbolt (Utility): fires a Starbolt from each hand.
- Starbolt Strike: fly at the enemy, blast them back on contact, and set them on fire for 2s.
- Starbolt Swerve: hand lasers that blast you backwards, for escapes or repositioning.
- Starbolt Spiral: fly up and forward, spinning a spiral of Starbolts that knocks targets up.
- Flying Clothesline: charge in and clothesline the target, knocking them Prone for 3s.
- Charged Starbolt: charge for 1s, then release a two-handed blast that slows.
- Starbolt Barrage (Ultimate): a knockback wave that grounds and slows for 2s, then 5 supercharged Starbolts that explode and stun for 2s.
## Captain Atom
- Flying Kick (new): fly forward into a kick. It doesn't auto-aim.
- Irradiated Slash (new): throws a crescent that explodes and poisons, including the target it hits directly.
- Rising Radiation (new): an uppercut you ride upward, carrying and poisoning anyone in front of you.
- Atomic Explosion Barrage (new, Utility): only unlocks below 300 HP. You take no damage while the atom shell is up, and it no longer heals.
- Sonic Punch (new): its in-game entry is still a placeholder, so no description yet.
- Radiation Blast: moved to Equip and now pierces.
- Irradiated Fists: moved to Ability 1.
# Kit reworks
## Beast
- Slashing Frenzy (Equip): a fast two-armed flurry on whoever is in front of you, opening wounds.
- Running Jumpkick: run up and hit with both feet, launching the target.
- Weighted Flip: flips into a weighted slam strike.
- Clawed Pounce: pounce through a crowd, hitting each enemy along the path once, slowing them and sometimes causing bleed.
- Cultured Thinker: armour-ignoring psychic damage while you recite a literary quote. You're heavily slowed while reciting.
- Devious Dilution: an acid vial that poisons, blinds, slows, burns through absorption, and leaves a pool behind.
- Run Wild: a stun-immune charge that launches everyone it hits, heals you per hit, and grants overshield. Your other abilities are locked while it runs, and it falls off ledges.
- Clawed Sweep Kick (Utility): knocks Prone and applies Bleed.
- Stars and Garters (Ultimate): a volley of vials that Douses targets for 6s.
- Stats: Attack 75-98 » 60-68, Speed 45-55 » 44-60, Utility 40-45 » 78-89, Defense 80-99 » 40-50. Regen and Combat removed.
## Wolverine
- Latch » X Slash: lunge and carve an X through a small area. Almost everything hit bleeds.
- Fillet » Feral Leap: a running leap that drags anyone you catch down and pins them, slowed and grounded.
- Healing Factor » Clawed Pounce: the same crowd pounce Beast gets.
- Frenzied Swipes » Slashing Frenzy: the same flurry Beast gets.
- Feral Lunge » Claw Stab: skewer the target on a claw, then kick them off it.
- Hunter Vision » Berserker Tunnel: a slashing dash that leaves a tunnel of claw marks behind it. Anyone inside is pinned and keeps bleeding until they get out.
- Toggle Claws » Retract Claws: claws out gives more melee damage, more reach and a bleed chance. Most of the kit needs them out; Feral Leap doesn't.
- Berserker » Berserker Rage: launch the target, slam them down, then rage: you hit harder, take less, heal, and bleed twice as often.
- Scent Tracker (new, Utility): follow one target's scent trail, see them through walls, and get a bleed bonus. The target briefly takes more damage when marked.
- Regenerative Healing Factor (new, Passive): triggers near death to heal and clear poison, burning and slow. You take 25% less damage while it's active. Long cooldown, so once per fight.
- Stats: Attack 55-65 » 62-72, Speed 45-55 » 55-62, Defense 50-55 » 45-50, Combat 80-98 » 88-99. Regen removed.
- Claw visuals: trails now come off the blade tips, and blood stretches along the cut.
Thematic Heroes v1.0.9
- Update pack version
- Fix version
- Update changelog
- fixes
- - Spectre & Captain Atom Remodels
- chore: more fixes
- chore: fixes
- feat: tilt the whole mannequin, and move the cape off its shoulders
Facing turned the figure but nothing tipped it, so a mannequin could not be
laid out flat or leaned into a wind. Tilt does that, and both it and Facing
now turn about the block's base centre rather than inside each rig - which
is where the feet are, now that the suit stands on the block, so a tilt
tips the figure over instead of swinging it about a point near its head.
Applying them once above both rigs also means the stub and the suit cannot
drift apart under them.
The cape already follows the back: it hangs off armorBody, so the torso
bone carries it, and it will now carry the whole-body tilt too. What it did
not have was any way to be adjusted - so Angle overrides the hang on top of
whatever the body is doing, and Up and Back move it off the shoulders in
the bone's own space, where Y is up and Z is back.
That needed room the panel did not have. The tabs go from three to four -
Rotate, Move, Cape, Body - over five shared slider rows, each tab showing
as many as it needs. Facing and Scale move onto Body alongside Tilt, which
frees the two rows the cape's offsets took. No taller screen.
Picking follows the tilt, applying it in the same order the renderer does,
so a tipped figure is still clickable where it is drawn.
Claude-Session: https://claude.ai/code/session_019MmVQ3xatM6eW5Adx5wLhE
- fix: mirror the stub's limbs, which sat on the wrong sides of a suit
GeckoLib negates X when it bakes a model - BakedModelFactory flips bone
pivots and cube pivots alike - so a bone authored at x=-4 is drawn at x=+4.
The stub is a plain ModelPart rig with no such flip, and I had matched its
limbs to the geo's authored coordinates rather than its baked ones. Every
limb therefore stood on the opposite side from the sleeve it stands in for,
which showed the moment a suit came on or off.
Right arm and right leg both move to +X, left to -X, which is where the
suit actually draws them once the flip is accounted for: bipedRightArm is
authored at -4 and baked to +4, and bipedLeftLeg - which RIGHT_LEG maps to,
because the geos cross the legs - is authored at -2 and baked to +2. The
picking in the posing screen reads the same pivots, so click targets follow
without further change.
- fix: restore the suit's render type after the cape, and hang the glider correctly
The cape layer put the matrix back but not the buffer, and that is what
painted the whole mannequin in the cape's texture.
VertexConsumerProvider.Immediate hands every uncommon render layer the same
fallback BufferBuilder, so asking it for the cape's layer rebound that
builder to the cape's texture. The layer runs part way through the model,
so every bone drawn after it kept writing into that builder. The worn
layers have restored it for exactly this reason all along -
FastBaseThematicRenderLayer.executeWithErrorHandling re-requests the render
type in its finally - and the mannequin layer now does the same.
The glider was low and on the chest because it was sharing the cape's
transform chain, and it does not have one. The worn path takes the half
turn about X but deliberately not the one about Y - that is what puts wings
on the back - skips the cape's shoulder translate entirely in favour of a
small offset of its own, anchors the whole wing on part 0 rather than
bending along its length, and hangs from a fixed angle instead of the
authored height, which for a glider is a wing span and would tip it nearly
upright. The display path now mirrors all of it, and renders the real
armor_glider geo model: it only ever needed the stack from the renderer,
for a texture and an animatable, so an overload takes that directly.
A suit declaring a glider no longer also reveals its modelled glider bone,
which would have hung two off the same back.
- feat: real capes on mannequins, correct placement, two default poses
A mannequin never drew a cape. The State picker only revealed the modelled
`brood` and `glider` bones, and just 23 of 993 armour geos have a brood
bone and 16 have a glider one, so for nearly every suit there was nothing
there to reveal. What players mean by a cape is a different system: a
procedural Cape declared in 243 armour JSONs, drawn by a layer that exists
only on the worn renderer.
That layer cannot be reused - its base class hard-casts to
ThematicArmorRenderer, and Cape.render wants a GeoArmorRenderer and a
LivingEntity, neither of which a block entity has. But the physics is not
in Cape at all. It lives in a per-entity component ticked only for players
and armour stands, and everything derived from it funnels through four
numbers per part. So Cape gains a display path that takes those four
numbers from a curve instead, and a new layer on the item renderer anchors
it to the same armorBody bone the worn one uses. The worn path is
untouched; the new layer falls out on its first line for every render that
is not a mannequin, which keeps capes off inventory icons.
The curve is wind rather than cloth: direction and strength on the Cape
tab, so a row of mannequins can be made to stream the same way, plus a slow
drift so a still one is not a plank. The simulated numbers are deviations
from a straight hang, so dead air is already correct and zero.
Placement is settled by measurement rather than guesswork. The pipeline was
traced end to end - the fixed display transform, item rendering's -0.5,
GeckoLib's +0.51 - and nothing in this mod alters any of it. At 2.675/1.054
the figure stood 2.14 blocks tall with its soles a tenth of a block
underground; 2.5/1.08375 makes it exactly two blocks, standing on the
block, vanilla-player sized. The stub derives from the same pair.
That also turned up the bug behind "the positions don't line up": the
posing screen projected limbs with a plain 1/16, while the renderer uses
the slightly larger pixel the item pipeline produces. Click targets sat
seven percent short of the figure they belonged to. Both now read the same
constants.
Defaults drop from sixteen poses to Straight and Running. Everything past a
neutral stance and a run is a judgement call about a character rather than
a starting point, and the library is the place for those.
- feat: pose library, undo/redo, and cape states on mannequins
Presets become the player's own. The sixteen built-ins now seed a library
in config/thematic-poses.nbt the first time it is written, and from then on
they are ordinary entries: rename them, overwrite them, delete them. Saving
and loading happens in an overlay drawn over the posing screen rather than
a screen of its own, since swapping screens would tear down the mannequin's
container along with it.
Ctrl+Z and Ctrl+Shift+Z (or Ctrl+Y) walk the pose back and forward, Ctrl+C
and Ctrl+V move it between mannequins, and Ctrl+Shift+V pastes it mirrored.
Undo steps are cut at press-to-release boundaries, so dragging a limb
across the screen is one step to undo rather than four hundred. Typing in
the name field swallows keys outright: the inherited handler closes the
whole screen when it sees the inventory key, which is otherwise just E.
Suits carry pieces that only make sense in a particular state -- a brooding
cape, a deployed glider, shoulder extensions -- and the item renderer hides
every one of them on sight, because an item render has no state to justify
them. A mannequin does, so a State picker brings one out and the Cape tab
angles it. This is the modelled cape, not the simulated one: that hangs off
a LivingEntity through a layer on the worn renderer, and a block entity has
none to give it.
Also links the stub's transform to the suit's rather than deriving it
separately. Where the suit lands depends on the item pipeline applying the
fixed display transform and two translations of its own after ours, so the
hand-tuned originals are restored as the source of truth and the stub is
placed by the same arithmetic. One pair of constants now moves both.
- feat: lighter posing panel, white titles, eight more pose presets
The panel was near-black with the inherited dark-grey titles drawn on top
of it, which left "Mannequin" and "Inventory" all but invisible. The
background is drawn with fills rather than a texture, so this is a palette
change: mid grey for the panel, a lighter bevel, and slots darker than the
panel so they read as recessed the way vanilla's do. Both titles are now
white with a shadow, via a drawForeground override - the inherited one
hardcodes the dark grey that suits vanilla's pale background.
Presets go from eight to sixteen: Heroic, Pointing, Waving, Blasting,
Blocking, Hero Landing, Crouching and Charging. All follow the rig's
conventions - positive pitch forward, positive roll across the body - and
the ones that fold at the hip drop the whole figure to match, since the rig
has no knees to bend.
- chore: encounters on NPCs
- feat: pose mannequin limbs from a GUI
Right-clicking a mannequin now opens a posing screen instead of a bare
armour slot. Click a limb in the live preview and drag to swing it, or use
the sliders when you want an exact angle; there are presets, mirror,
copy/paste between mannequins, and per-limb offsets plus a whole-model
scale. The pose is stored on the block entity, rides its existing NBT sync
outwards, and comes back as one whole-document packet on mouse release, so
dragging a limb costs no network traffic at all. Breaking and replacing a
mannequin keeps its pose, via copy_nbt on the loot table.
The preview is drawn by the same MannequinRenderer.renderPosed call the
world uses, so it is genuinely what will be standing there afterwards.
Two conventions in the existing models had to be untangled first. The suit
geos disagree with themselves about which side is right -- bipedRightArm
sits at x=-4 but bipedRightLeg at x=+2, and 665 of the 690 armour geos
defining all four bones agree on that -- so MannequinPart deliberately maps
RIGHT_LEG onto bipedLeftLeg to put everything the screen calls "right" on
one side of the body. And MannequinModel's pivots were placeholders, with
the legs turning about the head; they are re-authored as 32 - geoY to match
the suit bone for bone. The suit itself was rendering 7% oversized with its
feet a tenth of a block underground, which went unnoticed while it was a
rigid figure with the stub hidden inside it, and is corrected here so a
posed limb and its sleeve swing together.
Performance, since a base can hold a hundred of these. A suit is a few
hundred cubes -- the median armour geo is 269 -- so past sixteen blocks the
six-cube stub stands in for it. The line-of-sight raycast that culls
occluded mannequins is cached against the player's block position rather
than run every frame, and ThematicArmorItemRenderer's bone snapshotting now
reuses flat buffers instead of allocating a map and an object per bone per
frame. For a hall of a hundred suits that is roughly 8,500 cubes a frame
instead of 26,900, and some 21,000 fewer allocations.
- revert: drop suit skin mode, keep the vanilla cape hiding
Skin mode repainted a suit's exposed skin in the wearer's own complexion,
and needed a fair amount of machinery to do it: a composite texture cache,
a copy mask, a skin pixel cache and tone sampler, two PlayerSkinTexture
mixins, a raw-tag scan in ArmorRegistry so a client connected to a remote
server could still read the opt-out tags, and a no_skin tag on seven
armors. All of it comes out here.
The cape half of the same commit stays. Suppressing a Migrator cape that
hangs through a suit's own cape has nothing to do with repainting skin, so
CapeFeatureRendererMixin, the hideVanillaCape config and its ModMenu
toggle are untouched.
Nothing is lost: the original work is still on origin/feat/suit-skin-mode.
- feat: suit skin mode + hide vanilla capes under suits
Two client-side appearance options, both off the same Visuals config page.
Vanilla cape: nothing suppressed Minecraft's own CapeFeatureRenderer, so a
Migrator cape hung straight through a suit's own simulated cape. A HEAD-cancel
mixin hides it whenever any ThematicArmor chest piece is worn. On by default.
Skin mode: makes a suit show the wearer rather than the character. Two layers,
because the armor models are not consistent enough for either alone.
Copy. Where a model provably samples the vanilla player-skin layout at one
texel per block unit, the wearer's real skin is copied straight in, so their
face, stubble and markings come across. This has to be judged per texel, not
per rectangle: only 87 of 992 models have a head no other cube overlaps, but
785 keep a usable face once contested texels are subtracted.
Recolour. Everything the copy cannot reach -- limbs on models that ignore the
vanilla layout, contested parts of a face, bare torso -- is found by colour
and repainted in the wearer's complexion, each texel keeping its brightness
relative to the suit's median flesh tone so shading survives.
An earlier attempt copied by coordinate alone and looked badly wrong, because
602 of 992 models have no vanilla-sized head cube, black_manta's head is 10x6x9,
44 models park 2x2x2 detail cubes at the head's UV origin, and 57 use arm slices
like 3.5x6x4. The strict per-texel conformance test is what keeps the copy layer
honest; the recolour layer never moves a texel and so cannot misalign at all.
Masked suits need no special handling: Batman and Spider-Man contain no flesh
and match neither layer. Suits whose material merely happens to be flesh-toned
are the one case colour cannot judge, and opt out with a no_skin tag -- seeded
here for the seven verified by inspection.
Opt-out tags are read through a new raw index in ArmorRegistry as well as the
item's tag list, because ArmorRegistry.reload only runs from a SERVER_DATA
listener and so leaves getTags() empty on clients connected to a remote server.
Also widens SliderWidget.setValue to extendable. Cloth Config declares its own
setValue, which only collides with the final vanilla method once Loom remaps
Minecraft into yarn names, crashing every config screen -- including Cloth's own
demo -- in dev. Unrelated to skin mode but needed to reach the toggle.
Claude-Session: https://claude.ai/code/session_01PKwNGgVPgtVdXATB5U1AkM
- feat: Movie Poster Blocks
- feat: New Billboards & other deco
- chore: Added parent models for various groups of blocks
- fix: containment suit cooldown never applied on servers
The vent's cooldown was charged from inside the last staged ServerTimer
callback, 20 ticks after the burst. Those tasks live only in memory and
their callbacks are wrapped in a catch that logs at debug level, so
logging out mid-vent, a server stop, or any exception in scatterExplosions
skipped the one line that charged it -- silently. The suit was then free
to vent again as soon as health dropped back under the trigger.
Charge it at the burst instead, before any ring goes out, and mirror the
expiry as an absolute world-tick deadline in PERSISTENT_DATA. Dying drops
the chest piece, and that equipment change wipes the whole ABILITY_DATA
map, cooldowns included -- which is exactly what happens after venting at
150 health -- so the cooldown has to survive somewhere the reset cannot
reach. onTick puts back whatever is left of it.
- chore: cleaning up timer code, stalk code
- feat: added penguin and twoface brute variants
- chore: cleaned up missions
- fix: incinerating ice CD
- fix: lightning shard fixes
- fix: optimized renderlayer on containment suit, added CD
- feat: missions
- fix: ER on speedsters/flyers
- containment suit
- feat: detective work fixes
- feat: HUD rendering
- feat: new detective work
- feat: Enhanced reflexes rework
- New xray HUD, cosmetic wheel changes, and fast out-of-combat healing
- Ping stuff
- Embrace fear fixes
- Drop the Draco dependency from the shipped jar
com.openize:drako was jar-in-jar'd into the mod (375 KB, 247 classes) to
decode a single 8.6 KB asset -- assets/thematic/gltf/atom.glb, the only glTF
model that ships. Uncompressed, that asset is 22 KB, so Draco was buying
~13 KB of asset at a cost of 375 KB of library.
It was also already a dead end for the models that matter: drako 26.3.0
loses every component after the first on multi-component integer GENERIC
attributes, so GltfDracoDecoder refused JOINTS_0 outright -- meaning skinned
meshes, which is all of the armor models, could never be Draco-compressed
anyway.
atom.glb is replaced by a decode-and-repack of the exact bytes the game was
already producing at runtime, verified value-for-value against the Draco
decode (geometry and animation both), so nothing about the render changes.
GltfModelLoader now rejects any model declaring extensionsRequired, naming
the extension. Nothing read that field before -- the only extension ever
supported was Draco -- so without it a Draco-compressed model would fail on
a bufferView-less accessor several frames later.
Also restores src/test/resources/gltf/atom.gltf, which
GlbContainerTest.glbAndEmbeddedBase64DecodeToIdenticalAccessorData has always
read but which was never committed, so that test failed on every run. CI
never caught it: stage and finalize both build with -x test.
Claude-Session: https://claude.ai/code/session_01RF5QvS67ib5giQQ8v7q1rL
- Set mod_version to 1.6.6 for release
main inherited the alpha-suffixed version (1.6.6-a37) from the merge of
v1.20.1, which fails the stale-version check in stage-core-release.yml --
between releases mod_version must be exactly one patch ahead of the last
v*.*.* tag (v1.6.5), with no alpha suffix.
Thematic Heroes v1.0.8
- Drop the Draco dependency from the shipped jar
com.openize:drako was jar-in-jar'd into the mod (375 KB, 247 classes) to
decode a single 8.6 KB asset -- assets/thematic/gltf/atom.glb, the only glTF
model that ships. Uncompressed, that asset is 22 KB, so Draco was buying
~13 KB of asset at a cost of 375 KB of library.
It was also already a dead end for the models that matter: drako 26.3.0
loses every component after the first on multi-component integer GENERIC
attributes, so GltfDracoDecoder refused JOINTS_0 outright -- meaning skinned
meshes, which is all of the armor models, could never be Draco-compressed
anyway.
atom.glb is replaced by a decode-and-repack of the exact bytes the game was
already producing at runtime, verified value-for-value against the Draco
decode (geometry and animation both), so nothing about the render changes.
GltfModelLoader now rejects any model declaring extensionsRequired, naming
the extension. Nothing read that field before -- the only extension ever
supported was Draco -- so without it a Draco-compressed model would fail on
a bufferView-less accessor several frames later.
Also restores src/test/resources/gltf/atom.gltf, which
GlbContainerTest.glbAndEmbeddedBase64DecodeToIdenticalAccessorData has always
read but which was never committed, so that test failed on every run. CI
never caught it: stage and finalize both build with -x test.
Claude-Session: https://claude.ai/code/session_01RF5QvS67ib5giQQ8v7q1rL
- Set mod_version to 1.6.6 for release
main inherited the alpha-suffixed version (1.6.6-a37) from the merge of
v1.20.1, which fails the stale-version check in stage-core-release.yml --
between releases mod_version must be exactly one patch ahead of the last
v*.*.* tag (v1.6.5), with no alpha suffix.
- Cleaned up
- Add construct gun debuff back
- Lowered construct damage by 33%
- Fix serverside crash
- Undo wolverine
- Update changelog
- Fixed constructs & dampeners
- feat: grab now prevents other ability usage
- fix: crimson feast heal amount
- V1.20.1 batman gam (#461)
* fix: force optic prone to set on cooldown on active ability
* feat; new abilities to replace batswarm, frenzied swipes on G&M & Owlman
* feat; new abilities on a few suits
* feat; crimson feast change
- V1.20.1 irradiated fists (#460)
* irradiated fists
* Cleanup
- feat/irradiated-fists (#459)
- feat: Added major detonation render and ability
- feat: added slashing sounds to wolverine
- feat: add vital points (pressure points) to cap atom and starfire (#457)
* feat: add vital points (pressure points) to cap atom and starfire
* fix: based off review
- V1.20.1 crippling kick (#456)
* feat: begin on starfire's crippling kick
* fix: changes based off review
- - Added Crippling Kick Victim Anim
- feat: better tracking for claw extensions
- fix: Alts with wrong tiers
- fix: Green Canary missing flight
- fix: Wolverine (2000) missing cubes
- chore: better grounding
- chore: entity cleanup
- V1.20.1 review fixes (#455)
* fix: skull crusher lands its first blow instead of throwing
ServerTimer.schedule rejects a non-positive delay, and the arm-on-press
rewrite moved off scheduleMilliSeconds, which had clamped it. The i=0 blow
asked for 0 ticks, so the exception escaped onArmedHit and the
AttackEntityCallback into packet handling: no damage landed at all and the
hitting flag was left stuck true.
* fix: the ability lock extends cooldowns rather than refunding them
setCooldown writes an absolute value, so locking a victim for 60 ticks
handed back anything longer they were already sitting on. Optic Prone could
be spammed to cap a target's whole kit at three seconds.
* fix: the grounded slam spares the applying hit, climbers and swimmers
GroundedEffect rides the same effect list as PUSH_EFFECT and every effect in
that list damages in turn, so the slam fired on the applying hit and wiped
the knockback Perfect Angle had just set. Stamping the tick keeps it to
every hit after, as the effect's own doc says.
The slam also only measured the drop, never whether the target was airborne:
a ladder is footing of its own and water has no floor a straight-down ray
can find, so a point of chip damage dragged the target the length of the
climb or down to the seabed.
* fix: armed abilities honour the cooldown throttle
onTick ignored its tickCooldown argument, so an armed ability recharged
straight through a speed stun that froze everything else. The arm window
shares the same counter but is a deadline rather than a recharge, so it
keeps running.
* fix: flat dashes keep their heading at the pitch stop
Flattening the look vector and normalising it returns ZERO below a length of
1.0E-4, and at the pitch stop the horizontal part is about 4.4e-8. Clawed
Pounce and Feral Leap parked the player motionless in mid-air for the whole
duration; X Slash silently produced no lunge. Deriving the heading from the
yaw keeps it unit length at any pitch.
* fix: the blood trail spares its caster and their allies
The bleed tick applied to every living entity standing on a blood decal, so
the Wolverine who cast the tunnel bled themselves walking back down their
own trail, as did teammates and pets, for the decal's full lifetime. Every
other damage path in the ability already filters. Decals now carry an owner,
so the trail answers to the same friendly-fire rules.
Also takes the two heading reads off the flatten-and-normalise pattern, which
had the same pitch-stop zero vector as the other dashes.
* fix: scent tracker stops stripping a glow it never applied
The glow moved client-side to GlowMixin, but onDeactivate still removed the
vanilla effect, cancelling a spectral arrow or a teammate's ability when the
window ended.
- V1.20.1 next update list (#454)
* feat: grounded entities are slammed into the ground when hit
GROUNDED only ever slowed creative flight and blocked fast flight. Now every
hit that lands on a grounded entity drives it back down to the floor it was
trying to leave: raycast for the surface below, teleport onto it when there is
room, and point what is left of the momentum straight down.
Works off the effect rather than off a flight suit, so it bites on any living
entity. Respects the existing grounded override window, and skips hits that
were swallowed by the invulnerability window - HitEntityCallback fires from the
tail of damage() without reading its result.
* refactor: homelander melee abilities arm on press
Skull Crusher, Deafening Clap and Heartbreaker fired at whichever entity the
target lock happened to be holding - set by any melee hit, ever, and never
cleared - then flew the player across the map at it. Now the press only arms
them and the next punch you land is the payoff, so the victim is the one you
chose. Same pattern Claw Stab uses.
The whole approach phase goes with it: at armed-hit time the target is already
in melee range, so there is nothing to fly at and nothing to abort.
Also fixes two things that fell out of the conversion:
- amplifier() falls back to 16 when the CSV says -1, so all three had been
applying IMMOBILE/NAUSEA/CONFUSION at amplifier 16. Debuff strength and
length are now constants, and duration() becomes the arm window.
- Heartbreaker's 15-tick lock decremented in both onTick and its living-tick
listener, making it really seven. onTick is now the interface's, leaving the
listener as sole owner.
* feat: optic prone locks abilities, perfect angle grounds
Optic Prone now knocks whatever the target has running out of their hands
alongside the prone stun, and Perfect Angle takes their flight away.
Both arrive as their own AbilityEffect rather than by widening ProneEffect,
which any suit can already attach through the laser_effects option - bolting a
kit lockout onto plain prone would be a balance change to suits nobody asked
about. Suits that do want it can opt in by id.
The "cancel everything this entity has running" loop moves out of the
Homelander ultimate into AbilityControl, where the new effect can reach it.
* feat: persistent fake block registry, and blood that bites
Berserker Tunnel's blood was a fire-and-forget block update: it reached whoever
happened to be watching the spot at that instant and nothing else. Players who
arrived later never saw it, any chunk round trip put the real block back, and
the revert reached a different set of people than the placement did - which is
why the blood sometimes outlived its timer and sometimes vanished early.
FakeBlockRegistry keeps them instead. Expiry runs on the server clock so
everyone loses them together, decals are replayed to anyone who starts watching
the chunk, and holding the positions means gameplay can finally ask what is on
the ground - so standing in the blood now opens the cuts back up, a second in
it for two seconds of bleeding.
Lifetime drops to two minutes and the per-cast cap to 96: now that the decals
really do follow players around, 160 of them was a packet burst every time
somebody walked back into the area.
* balance: shorten the berserker tunnel dash
Thirty-two ticks at 1.8 carried the charge nearly sixty blocks, which is most
of a render distance and impossible to use indoors. Twenty blocks still reads
as a charge and lands where you aimed it.
* fix: scent tracker requires aim, glows locally, frees the arms
Three things wrong with picking up a scent:
The target was whichever entity came first out of the area query that could see
you, so aiming had nothing to do with it. It is a cone now, and one that
prefers the nearest candidate.
The mark was a GLOWING status effect, which the server hands to every client in
the world - everyone could see who Wolverine was tracking. The outline is drawn
on the tracker's own client instead, off the target UUID that was already being
synced for the HUD.
The limb override was keyed to the ability being active, so the arms stayed
locked for the full ten seconds of tracking rather than the second the sniff
takes.
* balance: x slash lunges flat and shorter
The slash jumped and then launched, which threw Wolverine well over anything he
was slashing at. It is a lunge along the ground now. The old dash vector also
normalised a vertical component it immediately discarded, shrinking the
horizontal reach it was supposed to be setting.
* fix: drop the claw trail from retract claws
Popping the claws is not a swing; it should not draw one.
* fix: clawed pounce sustains a flat dash
One impulse at activation and nothing afterwards, so friction had eaten it two
blocks in and the pounce halted. The push is held every tick now, read fresh
from where the player is looking so it steers, with the vertical zeroed each
tick to cancel gravity and keep it dead flat.
* balance: cap wall climb speed
Gravity is off while gripping and the climb increment is added to the vertical
speed already there, so a long climb accelerated until drag caught it around
two blocks a tick. Lowering the increment alone only slowed the ramp; the fix
is the ceiling.
* feat: feral leap flies a plateau, and survives the landing
Three impulses fired four ticks apart read as a stutter-hop, not a leap. The
velocity is driven every tick now, through a rise, a level cruise and a
descent: up over the wall, flat across the gap, down onto whoever is at the far
end. Zeroing the vertical during the cruise cancels the gravity accumulated
since the last tick, which is what makes the middle stretch flat, and the
heading is still read fresh so it steers.
Coming down off a plateau that high is well past acrobatics' four-point cutoff,
so the leap now eats fall damage of its own for the flight and three seconds
after it.
Also drops the claw trail - the leap is a pounce, not a swing.
- fix: cyclops changes to rage, tunnel, stab, lunge
- fix: slashing frenzy anim
- remove workflows!
- feat: Wolverine rework, full new kit (#452)
* feat: X-Slash ability
* Wolverine rework: new kit, renders, sounds
Replace Wolverine's kit with ten purpose-built abilities on Wolverine-only
ids, leaving the shared ids (frenzied_swipes, feral_lunge, healing_factor,
berserker, toggle_claw, latch, fillet, hunter_vision) untouched so X-23,
Beast, Cheetah, Blade, Deadpool, Red Hood, Omni-Man and Hawkman keep their
current behaviour.
* - Added Feral Leap Anim
- Added Feral Leap Victim Anim
* - Added Berserker Tunnel Anim
- Added Retract Claws Anim
* - Added Berserker Rage Slash Up Anim
- Added Berserker Rage Slam Anim
* feat: radiation beam and radiation blast and base hand blast (#448)
* radiation beam and radiation blast and base hand blast
* book stuff and explosion
* ne sounds and fixed useability
* Made the beams a little more generic & reusable
* feat: claw render trail
* chore: cleaned up comments
* feat; clawed pounce, claw stab, feral leap, x-slash all complete
* feat: berserker tunnel first draft
* feat: new damage calculation, cleaner climbing
* fix: undo climb changes
* chore: clean up
- - Added Hypnosis Anim - Added Clawed Pounce Anim - Added Mist Form Anim
- Added solar glare back to ultraman
- Cleanup gift of the gods description
- feat: New deco blocks
- feat: Prone book entry
- fix: Background of Centrifuge/Alloy Smelter not rendering
- fix: bug fixes for banner transform, ooze canister, and visor-off ability (#450)
* Update sentinel and criminal spawn rates (#445)
* New release structure (#446)
* - Added X Slash Anim
- Added Claw Stab Anim
_ Added Clawed Pounce Anim
* - Added Starbolt Swerve Recovery Anim
_ Updated Starbolt Swerve Anim Seperation
* fix: Sheetmetal Fencing Model
* fix: Prone status effect icon
* book entry: Alts and Shinies
* Bug fixes for banner transform, ooze canister, and visor-off ability
- fix: aerial charge, grapple gun (#451)
* Run ability cleanup on external deactivation; fix grapple cut and item dupes
Three themes, plus review fixes on top of the working-tree changes.
Ability deactivation
- Add AbilityUtils.deactivate(...) and ThematicAbility#deactivate(...), which
clear the active flag and then run ITemporarilyActiveAbility#onDeactivate.
A raw setActive(..., false) only flipped the stored flag, so state set up in
onActivate leaked: Latch never dismounted, Malleability never removed its
temporary scales. Replace the ~15 external setActive(..., false) call sites.
- The id-based overload falls back to the AbilityRegistry prototype when the
ability is not on the currently worn armor, so component- and status-effect-
driven deactivations (enemy_mimic, quantum_tunneling) still get cleanup.
- LatchAbility now ends when the ride ends. Its getTickInterval override was
dead code - AbilityEventDispatcher never consulted it - and is removed.
Grapple cut
- Move the cut to a UseItemCallback in ServerHandler. Vanilla skips Item#use
entirely while an item is on cooldown, so after the gun set its 5s cooldown
on fire, the right-click meant to release the grapple never reached the item.
Fabric injects at the head of interactItem, ahead of the cooldown gate.
- destroyHook now clears the NBT key even when the entity is already gone
(unloaded chunk, dimension change), which previously left hasHook() stuck
true forever. It also guards on GrappleHookEntity before discarding: entity
network ids are per-session, so a stale id resolved to an unrelated entity
and deleted it. Cutting now zeroes the player's momentum, matching
GrappleHookEntity#discardHook.
Item pickup and dupes
- NthMaceEntity persists its stack and dealtDamage to NBT; without it the mace
reloaded empty, tryPickup always failed, and it orbited the owner forever.
tryPickup now rejects an empty stack, since insertStack returns true for
ItemStack.EMPTY and the caller would discard the mace and give nothing back.
- AquamanTridentEntity refuses a second pickup while the whirlpool is spinning,
and activateWhirlpool drops the trident at the player's feet when the
inventory is full instead of silently destroying it.
- AerialChargeAbility only grabs what the player is looking at, validates the
stored target before use, and moves it with a swept collision-resolved step
instead of setPosition. The old fallback slammed an arbitrary bystander on
every deactivation.
- SonicStrikes clears its target key with remove(); storeUUID ignores empty
strings, so the old reset was a silent no-op and stale UUIDs survived.
Gift of the Gods
- Apply the documented attack boost and defense penalty via getEffectedStats,
and stop routing the effect choice back through getEffectedPart() where an
isActive() hiccup could drop it. Rebalance to 8s duration / 30s cooldown /
amplifier 2.
- Note: the book entry is shared between Wonder Woman, where this is ability_2,
and Wonder Girl, where it is the ultimate. The "[ULT]" prefix is dropped, so
the label is now accurate for Wonder Woman and not for Wonder Girl.
* Code cleanup
- - Added Slashing Frenzy Anim
- - Added Berserker Rage Slash Up Anim - Added Berserker Rage Slam Anim
- - Added Berserker Tunnel Anim - Added Retract Claws Anim
- - Added Feral Leap Anim - Added Feral Leap Victim Anim
- - Added Starbolt Swerve Recovery Anim _ Updated Starbolt Swerve Anim Seperation
- - Added X Slash Anim - Added Claw Stab Anim _ Added Clawed Pounce Anim
- Make modpack update manual and check both components at once
Drops the automatic workflow_run trigger (which also sidesteps the
workflow_run/default-branch gotcha) in favor of a single manual dispatch
that checks core and heroes' latest published state together. The patch
script is now idempotent: it only touches whichever component actually
changed and bumps the modpack's own version at most once per run.
- Add dispatch for modpack
- Attempt #6
- Fix versioning on releases
- Fix push
- Fix versioning
- Fix pipelines
- Updated the release structure (#447)