Skip to content
Felucca Online

Docs

Creatures and world spawns

Decision #124. Felucca is orc land: the wild between the colonists' towns is full of animals, orc bands, the restless dead and worse, placed from the world atlas' encounter zones and danger. Until creatures get models they are drawn as capsules, coloured and sized per species. The full roster with every species' numbers, and ideas for more monsters: docs/bestiary.md.

PieceWhere
Species catalog (stats, behaviour, look, loot)crates/uo-proto/src/creatures.rs
Loot items (ids 700–749)crates/uo-proto/src/items.rs
Species → fighter, AI archetypes, loot rollscrates/uo-combat/src/beasts.rs, ai.rs
Headless duels for balancingcrates/uo-combat/src/duel.rs, uo-loadtest duel
Zone and danger per cell (wilds.bin)crates/uo-world/src/wilds.rs, written by uo-atlas
Spawn planning per regioncrates/uo-world/src/creatures.rs
Server: spawning, bands, patrols, remains, guarded groundcrates/uo-server/src/sim/region/creatures.rs
Client capsules, hit flash, namescrates/uo-client/src/mesh.rs, online/mobiles.rs

The catalog

31 species. Each has a danger level (1: a colonist's first hunt … 5: bring friends), hits, strength, dexterity, intelligence, one skill for attack, defence and damage, Magery, an armour rating, an attack (bite, claws, a weapon or a bow: damage, AP per strike, reach), the spells it knows, how far it notices enemies (aggro, 0 = only when attacked), its look, the static its body leaves, a loot table and a respawn time.

DangerSpecies
1deer, giant rat, wild boar, grey wolf, mongbat
2brown bear, frost wolf, giant spider, harpy, orc, orc archer, orc raider, skeleton, zombie, lizardman
3orc shaman, orc captain, ghoul, troll, ogre, wisp, bog hag
4wraith, ettin, drake, wyvern, wrathful treant, fire elemental
5lich, frost giant, ancient dragon

Numbers follow UO Renaissance's monsters where there is one, scaled to this game's tempo (1 AP = 250 ms). They are first values for the balance pass (task creature-balance); use the duel tool below to see what they mean against a colonist.

Behaviours map to AI archetypes in uo-combat:

BehaviourArchetypeFights like
PreyPreygrazes, runs from anyone within 6 tiles, never strikes back (deer)
PackPack (new)bites like a beast, runs below 25 % of its hits (wolves, rats, mongbats)
HunterBeastcloses in and bites, never breaks anything (bears, spiders, ghouls, wyverns)
BruteBrutecloses in and swings, breaks what is in the way (orcs, undead, giants, treants)
ArcherArcherkeeps its distance, looks for a clear line (orc archers)
CasterCastercasts from cover, heals itself (shamans, wraiths, liches, wisps, hags)
RaiderRaider (new)patrols, goes for the weakest enemy in sight, a brute in the fight (orc raiders and captains)
MonsterMonster (new)breathes or blasts from afar every 6 s, bites close (drakes, dragons, fire elementals)

Per fighter (uo_combat::Fighter): aggro (sight range for noticing), band (an engaged fighter alerts only allies of its own band, so a wolf pack doesn't wake the orcs next to it), patrol (waypoints an idle mob walks in a loop; its home, and so its leash, follows the waypoint it heads for).

Where they live

uo_world::creatures::plan(world, region, content) is a pure function of the world and the region, like the rest of its content, so server and explorer agree.

  • Zone and danger come from the atlas (decision #97): wilds.bin in the baked world holds the encounter zone and danger 1–5 of every 16×16-tile cell, atlas.json the zone tables (weighted atlas encounter keys) and each encounter's danger range. A world baked before #124 has no wilds.bin: the zone is then guessed from the terrain and the danger from the distance to the nearest town. uo-atlas --wilds-only <world dir> writes just wilds.bin (about the time of generating the atlas, no rebake).
  • Hostile groups: by the danger at the region's centre, none or one near the towns (60 %), one or two at danger 2, two at 3, two or three at 4–5. Each group takes a spot, reads the zone and danger there, picks an encounter from the zone's table among those whose danger range fits (±1), and becomes a party: wolves → 2–4 grey wolves, orcs → orcs, archers, a shaman and a captain from danger 3, undead → skeletons and zombies, a ghoul from 3, a wraith from 4, dragon → one ancient dragon, and so on (PARTIES). Felucca is orc land: orcs join every land zone's table (weight 1.5) that doesn't list them. Brigands, deserters and pirates are bandits of the camp roster. Merchants, pilgrims, refugees, smugglers and faction patrols are people, not creatures: they are left to the NPC work.
  • Wildlife: one or two herds per region by terrain (deer in meadows and forests, boars in forests and jungle, giant rats in fens and on bare ground, deer and wolves on snow).
  • Orc patrols: from danger 2, a third of the regions get a band of 2–3 orc raiders (and a captain from danger 3) walking a round of up to four road tiles far apart (or a loop through the wild when the region has no road).
  • Never in a town's guard zone or within 8 tiles of it, in the sanctuary (#112), within 16 tiles of a bandit camp, or on paved ground; within 48 tiles of a guarded highway (#112) only grazing animals. At most 28 mobs per region. Members stand on every other tile around their group's spot; groups keep 12 tiles apart.

Ids: group key region << 24 | 0x50_0000 + n, member id group key × 16 + member (above the camps' keys, never colliding). The band is a hash of the group key.

On the server

A region puts its spawns into its mob slots on its first tick (load_creatures). Each mob stands up at its spawn (or the nearest free tile), in its band, on its patrol. When one dies, its body lies 1.5 s, then a carcass or corpse static (the species' carcass sprite: deer, wolf and boar carcasses, a slime puddle, bones, ash, a corpse) holds a roll of its loot table, for anyone to loot (Loot / Take, decision #121) until it rots after 5 minutes. Clients draw the remains as the body that fell (#134: the object carries remains, the dead mobile's kind and facing): the species' capsules lying on their side, a bandit dressed as it fought, in the death pose; the carcass sprite is only the fallback art. It stands at its spawn again after its species' respawn time (90 s for rats … an hour for the dragon).

Loot (beasts::loot, beasts::elite_loot): every line of the table is rolled (pct, then an amount in min..=max); humanoids (orcs, the undead with gear, hags, liches) also roll each piece of their gear at 25 %, but loot is never finished gear (#148): a piece comes back as salvage, 1–3 of its material at the tier of the species' danger (an orc's mace: dull copper ingots at danger 2, agapite at 4; jewellery a gem of the tier; builds::elites::salvage). Camp and roaming bandits leave salvage of a quarter of their gear (T1). Mobs drop no coin (#121). Design scrolls by kind (builds::elites::design_drop): see Danger, elites and loot below. New items (ids 700–749): bones, fur, boar tusks, spider's silk, bat wings, feathers, grave dust, troll fat, lizard scales, drake and dragon scales, dragon's blood, wisp essence, treant bark, fire essence, ectoplasm, amber, sapphire, ruby, diamond, orcish idols, frost giants' teeth; they are the build system's components and leathers (#165).

Guarded ground: every arena marks the tiles of non-lawless towns' guard zones and the sanctuary as Arena::keep_out. AI fighters never step onto it, never notice anyone standing on it, and an engaged mob whose target reached it gives up and walks home (checked twice a second). Players walk there freely.

Danger, elites and loot (builds, stream E of #150)

docs/builds.md § 14. Code: uo_combat::builds::elites (rules), uo_world::creatures::elite (which packs), tests uo-combat/src/builds/tests_elites.rs.

Danger follows the tiers. A species of danger d is tuned against complete builds of tier d (the Power sheet of docs/builds-tiers.md): elites::DANGER lifts its profile when it spawns with more damage (a keystone-like "more" bucket, ‰), toughness (every kind of damage taken × 100 / (100 + t)) and more hits (‰). Casters get half the toughness and hits (they heal and kite, so staying power counts double for them).

dangermore damagetoughnessmore hits
1–2–––
3+60 %40+50 %
4+80 %50+60 %
5+140 %80+90 %

Measured with tier_table (a brute-played complete build: tier longsword, six hardened leather pieces with Hands/Arms/Legs affixes, skills 40.0 at T1 … 100.0 at T5; no potions or escapes), win %: T1 clears danger 1 (two wolves 100) and 2 (three orcs 88); danger 3 (a troll) T3 100, T2 100, T1 0; danger 4 (an ettin) T4 100, T3 90, T2 0; danger 5 (a frost giant) T5 100, T4 40, T3 0. The ancient dragon wants friends: three T5 builds win 97 %, two 3 %. Catalogue changes with it: wyvern 210 hits, skill 80.0, sting 10–22 (its armour-piercing Puncture made it a tier harder than the rest of danger 4), treant 300 hits, branches 18–36 (it was a tier easier).

Elite packs (PoE's magic monsters). From danger 2 a hostile pack (encounter party or orc patrol, never grazing animals or camp bandits) is elite at 15 / 20 / 25 / 30 % for danger 2 / 3 / 4 / 5, every member with the same modifiers: one at danger 2, one or two at 3, two or three from 4 (uo_proto::creatures::{EliteMod, Elite}; deterministic from the region and group, as the rest of the plan). Every elite has +50 % hits, and:

modifierwhat it does
Hasted+40 swing speed (SSI), +25 % cooldown recovery, steps in 70 % of the time
Armoured+60 armour, +50 % poise, half again the poise to break
Volatile1.2 s after it dies it blows up: 20 % of its max hits (at least 8) to every enemy within 2
Vampiricleeches 30 % of the damage it deals
Frostboundevery hit chills (Chilled 2 s); +100 cold ward
Shieldingwhile fighting, every 6 s every ally within 4 (itself too) gets a shield of 15 % of its max hits for 4 s
Pack Leaderwhile fighting, allies within 4 (itself too) deal +25 % damage and attack 15 % faster; two leaders count once

Shielding and Pack Leader only in packs of two or more. Clients see them on EntityState::elite (keys, append-only) and name the mob "a Hasted Vampiric grey wolf" (Elite::name); fighters on the server carry that name too; the Volatile blast and the shield pulse are Event::Triggered named after the client's 3D effects they show (corpse_explosion, arcane_shield).

Loot by kind. Elites roll their table twice and drop a gem one tier above their danger at 50 %; they leave a design scroll at 10 % + 5 % per modifier, two in three of them clothing and jewel designs, the rest family and armour designs. Bosses (danger 5) leave clothing and jewel designs (15 %) and their kind's keystone (4 %): the dragon Glass Heart, the lich Pact of Echoes, the frost giant Iron Oath. The isles' (lawless) creatures of danger 4+ leave the other seven keystones (1 %, elites 3 %). Other creatures of danger 2–4 and camp fighters as in #165.

In the client

EntityKind::Creature { species } is unchanged on the wire; the client reads the catalog. Every species is drawn as its code-built model (#141, #143; uo-client/src/creature_models.rs): assets/models/creatures/<species>.glb at true size (the catalog's look.scale is not applied again), facing its heading, toon-shaded like the human characters (vertex PBR, the character outline, rim and light floor), casting shadows and cut by the see-through circles like any mobile. Each species' glTF, scene and clip graph are loaded once and shared by every instance. A model's parts (2–15 skinned meshes, one per modelled part) share one skin and one vertex-PBR material, so once a model has spawned its parts are merged into one skinned mesh (merge_skins), built once per species and shared: one draw per creature, its own draw (NoAutomaticBatching, as for the characters), with bounds that follow the pose (DynamicSkinnedMeshBounds). Held props stay separate meshes on the hand bones.

  • Model data (MODELS, one row per species): label height; hover height and the frames of Death01 over which it drops to the ground (mongbat 0.4 m, harpy 0.5, wraith 0.3, wisp 0.35); the ground speed Walk_Loop is authored for (four-legged and many-legged walkers and the dragons 2.0 m/s, the treant 0.975, retargeted humanoids measured from their feet by tools/creature_walk_speeds.py, 0.79–1.14); props and glow lights (as the demo's bestiary); where and when a shot leaves (Spell_Simple_Shoot: the dragon's jaw at frame 8, the drake's at 6, the fire elemental's hand at 6, the wisp's core at 4; humanoid casters and archers from the hand at once).
  • Clips from game state, crossfaded like the characters': standing = the activity (Idle_Loop; engaged Sword_Idle, casting Spell_Simple_Idle_Loop, else idle when the species lacks them); moving = Walk_Loop at ground speed / authored speed (0.4–3×; fliers and floaters at 1), a humanoid jogs (Jog_Fwd_Loop) only beyond three times its walk; one-shots from the combat events play to their end: swings Sword_Regular_A (or Sword_Attack where the species has it: bite, gore, claw or weapon), shots and breath Spell_Simple_Shoot (else the attack), cast start Spell_Simple_Enter, hits and parries Hit_Chest; death Death01, held on its last frame. Fliers keep hovering while they move and come down during their death.
  • Hit flash: while struck (0.1 s) every material of the model is swapped for its flash copy (ToonMeshParams::flash = 1: the lit colour goes to HDR white), made once per material, so the shared materials are never changed.
  • Corpses (#134) are the model at the end of its death clip (anim::Lying).
  • Shots of a creature model leave its bone when its clip lets go and still land when the server says.
  • A species without a glb (or UO_CREATURE_CAPSULES=1, for comparisons) keeps the capsules of mesh::creature_shape: bobbing when they walk, flashing and recoiling when struck, tipping over when they die.

Their names float over them, red when hostile, grey when not; the target card says family, danger and stance. The explorer (#110) shows the creatures of the regions around it standing at their spawns.

Balancing: duels

uo-loadtest duel runs headless fights of a fresh colonist against catalog creatures with the server's rules and AI (uo_combat::duel), on an open field, and prints win rate, time to win, hits left, damage dealt and taken:

cargo run --release -p uo-loadtest -- duel --class warrior --skill 70 --species wolf,orc,troll --count 2 --fights 200

--class warrior|archer|mage, --skill N sets every combat skill to N (default: the class's own), --champion keeps the players' +120-hit blessing (#69), --count creatures per fight, no --species runs the whole catalog. From code: uo_combat::duel::run(&Duel { .. }).

Measured (2026-10-22, first values)

Duels, 100 fights each, one creature, fresh colonists without the champion blessing (win %):

warrior (90 hits)archer (75)mage (50)
danger 1–2 (animals, orcs, skeletons, lizardmen)10010064–100 (bear 64)
orc captain, troll, ogre (3)10096–1000–1
wisp, bog hag, ghoul, shaman (3)1001003–81
wraith, fire elemental (4)1001000–1
ettin, treant, drake (4)62–9780–900
wyvern (4)27270
lich, frost giant (5)1–73–220
ancient dragon (5)000

With the champion blessing (+120 hits) a warrior beats everything up to danger 4 alone except wyverns (70 %), liches (39 %), frost giants (27 %) and the dragon (0 %). Against three at once a plain warrior still beats wolves, orcs and skeletons every time (86 % of its hits left against three orcs). Mages lose most melee duels because the duel's caster AI stands and casts; the balance pass should look at casters, wyverns and the mage's survivability (task creature-balance).

Tick cost: the three busiest regions of the 1024² test world (17–20 creatures each) fighting five players: mean 6–76 µs of thread CPU per 50-ms tick, worst 6.3 ms (one path search). A whole 1024² world (256 regions, every one ticking) ran on one sim with ticks over budget only while the machine was overloaded (load average 100–400).

Hunters: 6 hunter bots (--mix hunter=1) on the generated world for 4 minutes: 120 attacks, 12 carcasses looted, 5 deaths (wolf packs and bears around the towns' outskirts are dangerous for a lone hunter: a balance question).

Not yet

  • Real models and animations (the capsules are placeholders; task creatures-and-spawns).
  • Creatures in dungeons (task dungeons); creatures at sea (sea serpents, pirates' ships).
  • People of the encounter tables (merchants, pilgrims, faction patrols) as NPCs.
  • Orc raids on caravans need caravans (NPC work); patrols walk the roads already.