DangerousRoads
[ALPHA] Wandering encounters for Outward: out in an overworld region, 1-3 hostiles native to that region turn up out of sight, 40-200m away, and walk in. Vanilla loot, never in a town or dungeon. Toast + compass blips. Co-op is not yet verified.DangerousRoads — Aurai's wilds are not empty anymore
⚠️ Alpha, and single-player only for now. Multiplayer is not tested — see Known issues. Back up saves you care about.
Aurai's overworld is hand-placed and finite. Once you've cleared the road between Cierzo and the Vigil Pillar it stays cleared, and the walk back is a walk through an empty map.
DangerousRoads repopulates it. While you're travelling out in the wilds, hostile creatures can turn up anywhere — out of sight, off the road, behind you. Every stretch of country is country you have to watch again.
They're ordinary wild creatures native to the region you're in: Enmerkar sends beast golems and bandits, Abrassar sends bugs and bandits. They wander, they notice you, they fight, and they drop their normal loot.
What it won't do
- Never in towns or villages. Settlements stay safe.
- Never in dungeons, caves or interiors. Only out in the open.
- Never touches your save. These creatures are temporary — they're gone when you leave the area, and nothing of them is written to your save file.
- No bosses, no story characters, no custom content. Everything it puts in the world is vanilla.
Installing
Install from Thunderstore and the dependencies come with it. By hand: drop ForgeKit/,
NetKit/, DonorKit/, CompanionKit/, SpawnKit/ and DangerousRoads/ side by side into
BepInEx/plugins/. All five are hard dependencies — BepInEx refuses to load a plugin whose
hard dependency is missing, so leaving one out means DangerousRoads silently never starts.
(DangerousRoads names ForgeKit, SpawnKit and CompanionKit directly; NetKit and DonorKit come in
underneath those two.)
Then just play. Nothing to turn on, no key to press — walk out of town and give it a minute.
Settings
BepInEx/config/cobalt.dangerousroads.cfg, created on first launch. The handful worth touching:
[General]
Enabled = true ## false = mod off
[Schedule]
MinIntervalSeconds = 20 ## shortest gap between encounters
MaxIntervalSeconds = 60 ## longest gap — raise both for a quieter world
[Wave]
MinCount = 1 ## how many creatures show up at once
MaxCount = 3
SkipWhileInCombat = true ## hold off while you're already fighting
[Placement]
MinDistanceMeters = 40 ## how close they can appear
MaxDistanceMeters = 200 ## how far away
[Notify]
ShowToast = true ## the on-screen warning
[Compass]
ShowBlips = true ## the compass markers
To turn it off: set Enabled = false and relaunch. To uninstall, delete the DangerousRoads/
folder from BepInEx/plugins/ — nothing of it lives in your save.
⚠ An existing cfg always wins over a new default. BepInEx writes the file once and never
migrates a changed default into it, so a value you (or an older version) put there keeps applying
silently. Each entry carries its shipped default in a # Default value: comment right above it —
if behaviour doesn't match this README, compare those first. Delete the file to regenerate it from
scratch (which also discards every other tweak).
Co-op: the room-wide warm predicate
SpeciesRoster used to ask Spawner.CanMintNow(key) — "is a body resident on this box". It now asks
CanMintNow(key) && Spawner.CanMintRoomWide(key), because a species the host holds and a guest
does not costs that guest a 3.6–14.7 s donor load mid-fight (the disconnect bug). CanMintRoomWide
subsumes the local half, but both are named at the call site on purpose: this is the predicate the
whole mod rests on and "local and room" is what it must be read as.
SpawnableNow()re-asks both halves every call (SpawnKit's cache is a 12-entry LRU, and the peer list moves too) and recordsLastShrink: species dropped purely because a peer is cold. A locally-cold species comes backColdLocallyand is never reported as a peer's fault.RosterOrder.ForRoomWarm/ForPrewarm(pure, inDangerousRoads.Core) rank the region by how much spawnable roster the work buys: tier 0 = the party lacks it but the host holds it (onesk.want, free), tier 1 = nobody holds it (real local harvest), tier 2 = already room-wide. Ties keep source-trust order, soForPrewarmis byte-identical to the pre-co-op order for any snapshot, not just an empty one.AmbushDirector.ArmForRegionpushesSpawner.RequestRoomWarm(top N)after resetting the prewarmer, and the wave path re-pushesLastShrinkwhen a wave is blocked. Neither is throttled here — SpawnKit's want book owns the repeat rule ([Coop] RoomWarmRequestTimeoutSecondsand the doubling backoff); a second DR timer would just be a second, differently-wrong opinion.ReportShrinkprints one[ROSTER]line per distinct (region, species+reason+actors) situation (RosterShrink.KeyForcanonicalises it) plus one degrade line per region whenRoomWarmModeisRoomDegraded, and fires oneToasts.RosterShrunkper region arm.roadsrostergains the room glyph column (● / ◐ / ○).
No DR config. The mode knob is SpawnKit's [Coop] RoomWarmMode in
BepInEx/config/cobalt.spawnkit.cfg:
[Coop]
RoomWarmMode = RoomDegraded
Built 2026-08-20, not live-verified — docs/guest-mirror-harvest-testplan.md GM10–GM19.
Event deck
Each time the timer comes due the director now draws a card instead of always running an
ambush. Card #0 is the classic hostile wave; card #1 is the wandering merchant (its runner ships
separately — until it is present, its weight is logged once, at the first draw, and ignored). Weights are
relative shares of whatever is eligible; a card on cooldown leaves the pool entirely, so the ambush
takes its draws and nothing falls through to "no event". With DeckEnabled = false, or with the
ambush as the only enabled card, no roll is pulled and the mod behaves exactly as it did before.
With every weight at 0 nothing fires at all (roadsstatus shows the soft block; roadsdeck shows
drawable=0) — the deck never falls back to an ambush the operator weighted out. A card that
throws mid-run is logged and treated as a soft outcome, so the director keeps ticking.
BepInEx/config/cobalt.dangerousroads.cfg:
[Events]
DeckEnabled = true ## false = every event is an ambush (the pre-deck mod)
AmbushWeight = 1.0 ## relative share; 1.0 vs 0.35 below is ~74% ambush
MerchantWeight = 0.35 ## 0 = no merchants
MerchantCooldownSeconds = 600 ## stamped at DRAW, not on success
Pure draw logic: core/DangerousRoads.Core/EventDeck.cs (unit-tested, incl. one-card parity).
Game side: Events/EventDirector.cs (cards from config, last draw, Register(IEventCard) seam),
Events/AmbushCard.cs (wraps WaveRunner.Run unchanged). Built 2026-08-22, not live-verified.
Wandering merchant (card #1)
A Travelling Merchant (Merchants faction, Mefino's trade backpack, friendly to the player) appears
out of sight on the same verified ground an ambush would, then walks the road to a zone exit and
despawns there. Talk to him: greeting → Shop (the vanilla shop, stocked from this region's caravan
trader table) or leave. He is a tank that barely hits back (Health 450,
Protection 20, DamageMult 0.25, targets Bandits only) so that when bandits raid him the player
has to step in; once he has been hit and the fight has ended, his greeting switches to the
thanks-for-the-rescue line. Not lootable, never saved; one on the road at a time; a region change
drops him.
The 2026-08-22 live pass (Cobalt, legion) found him fighting the player's pet instead of walking ("he kept running from me even when I tried talking"), naked, jogging, and alone. Built the same day:
- Protected.
AggroTools.Protect(merchant, "dangerousroads.caravan")at spawn,Unprotectat despawn: the player's weapons, lock-on, pet and its combat anchor, and every Player-faction ally's AI detection treat him as untargetable. The raid's bandits get an explicit re-allow pair (TargetableOverrides.Set(raider, merchant, true, owner)), so they can still hit him.[Merchant] Protected(default true;protected=falseon the card for a session that needs to hurt him by hand). - Stops to greet. While any player is within
GreetRadius(4 m) or he is in his dialogue (NpcRegistry.IsInDialogue), the carrot is parked at his own feet, the stall clock is held like combat, and he turns to face the nearest player (LateUpdate); he walks onGreetResumeSeconds(3 s) after the last player leaves. CoreGreetPause;[MERCHANT] paused to greet/resumed the walkonce per edge.WalkSpeeddefault dropped 1.1 → 0.5 — the value isAISWander.SpeedModif, a multiplier on the body's run speed (vanilla wanderers 0.3, SideLoader 1.1 = a jog). - The raid.
Merchant/RaidRunneron the body: rolled once at spawn (RaidChance0.75,RaidMin–RaidMax2–3 raiders), springs when a player comes withinRaidTriggerMeters(90 m) or afterRaidDelaySeconds(120 s) so it is witnessed. Species from the region roster (warm, not blocked), preferring theBanditsfaction, then any non-Merchants/non-Player faction, then unknown (CoreRaidPlan.PickSpecies); placed on a 15–30 m ring (ClusterPlan.Offsets→NavProbe.SnapToWalkable);Spawner.Spawnwith this mod'sOwnerTagsoMaxOwnActive, the far cache androadssweeptreat them as wave members — the count is clamped to the slots left underMaxOwnActivefirst (CoreRaidPlan.CapToRoom; a full cap = no raid, logged); each oneAggroTools.ForceTargeted onto him once its handle is alive. Toast "Bandits are closing on the merchant!" (its own throttle, so the merchant toast half a second earlier cannot swallow it). The rescue edge is unchanged (hit + combat exit). Despawn sweeps every override owned bydangerousroads.caravan(ClearOwnedBy), so a region change mid-raid — where neitherUnprotectnor the runner'sOnDestroycan see the body — leaks nothing.roadsmerchant raidsprings it now;roadsmerchant statusshowsraid=armed/RAIDING/done. - Dressed.
NpcSpec.RandomVisuals = true+OutfitPoolfromMerchant/MerchantOutfits(seven combos of Trader / Master Trader / Adventurer / Pilgrim / Padded / Worker / Scholar kit, by display name, checked againstdata/registries/items.json);outfit=<index>pins one.
The body is StoryKit's (NpcSpec → SideLoader template → Merchant graft → dialogue); DR decides
where (AnchorRegistry.FindSpots), which exit (Core/RoadRoute.ChooseExit over the scene's
InteractionSwitchArea census, preferring one ≥ MinRouteMeters away) and the route (NavMesh
spawn → exit, threaded through the caravanner's roadside RandomPositionOnStart.SpawnPoints, each
seed path-checked from the spawn and dropped when the navmesh cannot reach it). The
walk is a carrot: an empty GO the SL wander state follows (AISWander.FollowTransform), advanced
by Merchant/RoadWalker — combat states interrupt it and following resumes on their own. A stall
toward an intermediate waypoint skips it (up to 3 per walk, Core/RouteSkip); a stall toward
the exit gets one last straight try; only then does the walk end as stuck, and the warning carries
the agent's own path state (pathStatus, hasPath, remainingDistance, isOnNavMesh, velocity,
AI state, carrot position). The live stall of 2026-08-22 — "no progress for 90s toward waypoint 1/6
(16m away)", despawn at 134 s — is what this replaces.
Finding him. The toast names the bearing; the HUD compass also carries a green dot for him
from the toast until he despawns, at any distance, drawn a little larger than the red hostile blips.
That dot is this mod's. The other marker you may see in co-op is vanilla's own other-player
compass element (OtherPlayersCompass), which points at your partner's character — not at the
merchant, and not drawn by DangerousRoads.
BepInEx/config/cobalt.dangerousroads.cfg:
[Compass]
ShowMerchantBlip = true ## live; the merchant's compass dot, independent of ShowBlips
MerchantBlipColor = #34C759 ## live; green. Unparseable = green, never red
BepInEx/config/cobalt.dangerousroads.cfg:
[Merchant]
Health = 450 ## next spawn; he must survive a raid until you arrive
Protection = 20 ## next spawn
DamageMult = 0.25 ## next spawn; if he clears a raid alone there is no rescue
WalkSpeed = 0.5 ## live; SpeedModif multiplier — 0.3 vanilla amble, 1.1 SideLoader jog
ExitRadius = 6 ## live; "arrived" = despawn. <= 0 never arrives
StuckSeconds = 90 ## live; no progress outside combat for this long = despawn. 0 = never
MinRouteMeters = 150 ## next spawn; prefer an exit at least this far from the spawn spot
DefendsHimself = true ## next spawn; false = fully passive
GreetRadius = 4 ## live; stops + faces a player this close (0 = never; dialogue still holds him)
GreetResumeSeconds = 3 ## live; walks on this long after the last player leaves
Protected = true ## next spawn; the player side cannot hurt/target him; bandits can
RaidChance = 0.75 ## next spawn; 0 = the lone walker, 1 = always raided
RaidMin = 2 ## next spawn
RaidMax = 3 ## next spawn; each raider counts against [Wave] MaxOwnActive
RaidTriggerMeters = 90 ## live; springs when a player is this close (0 = delay only)
RaidDelaySeconds = 120 ## live; springs this long after spawn regardless (0 = proximity only)
Files: Events/MerchantCard.cs (spec, spawn + roadscard overrides, route validation, rescue
greeting swap, despawn, LivePosition for the dot; attaches the walker and the raid runner),
Merchant/RoadWalker.cs (carrot, skip/last-try/stuck policy, stop-to-greet, diagnostics, rescue edge),
Merchant/RaidRunner.cs (the raid), Merchant/MerchantOutfits.cs (the outfit pool),
Merchant/RoadExits.cs (exit census + roadside seeds), Merchant/CaravanStock.cs (stock-table name +
roadsstock census); pure Core/WalkProgress.cs (stuck tracker + rescue edge), Core/RouteSkip.cs
(the skip policy), Core/GreetPause.cs, Core/RaidPlan.cs, Core/CardArgs.cs (the key=value parser)
and Core/MerchantText.cs (the lines), all unit-tested. Log tag [MERCHANT]. Built 2026-08-22, not live-verified — docs/road-merchant-testplan.md.
Card #2: the town-guard patrol
Two or three town guards in the region's colours fighting four to six troglodytes on the road, with
the guards in REAL danger without the player — that danger is the card, and it is a tuning number,
printed on every [PATROL] RESOLVED line as guards N/M alive at X% health.
- The guards are StoryKit human NPCs, not the game's town guards: those are static
SNPCprops with noCharacterand no AI (Monsoon's are the lone exception), so there is nothing to clone. Per-spawn specsdr_guard_<n>, Merchants faction,TargetableFactions = [Bandits, Mercs](the two buckets the trogs live in), dressed fromPatrol/GuardOutfits— a pool perCore/GuardLook.GuardTown, by display name, every one checked againstdata/registries/items.jsonand re-checked against ForgeKit's live item index once per session (roadspatrol looks).AggroTools.Protect(guard, "dangerousroads.patrol")shields them from the player side, exactly as the merchant is shielded and for the same live reason (a pet's anchor dragged him into combat). - The troglodytes are ordinary DR spawns: same
OwnerTag, so[Wave] MaxOwnActivecaps them (RaidPlan.CapToRoom),roadssweepclears them and the far cache parks them. Species come fromCore/PatrolPlan.TrogSpecies— the seven spawnable keys, spelled exactly asSpeciesFactions.txtspells them (a unit test reads the embedded resource back) — intersected with the warm roster, with the full list as a logged fallback. The Queen is refused by GameObject name on the resolved handle (PatrolPlan.IsQueenBody): she has no species key of her own and sharesCharacter.Namewith the Mana Troglodyte, so nothing earlier in the pipeline can exclude her. - The wiring is pairwise, not by faction:
TargetableOverrides.Setboth ways per (trog, guard) plusAggroTools.ForceTargetin both directions with the RaidRunner 10 × 0.5 s retry, re-run every 5 s while Fighting for anything that lost its target to a death. - The phases are pure (
Core/PatrolState): Spawning → Fighting → Resolved → Leaving → Gone, with a stalemate window and one hard rule — Resolved never re-enters Fighting, because the far cache can make a "dead" trog read alive again minutes later and the reward handshake must not re-run. - The reward is
Core/PatrolLedger+PatrolPlan.Reward: uid-keyed spawned/dead/helped sets, a rate rolled once per encounter, andMarkPaidso a patrol pays at most once. "Helped" is Cobalt's rule — ANY player-side damage to ANY of the patrol's trogs — observed byPatrol/HelpWatchthrough three deliberately overlapping taps (Character.HasHit,Projectile.OnProjectileHit, and a per-trogOnHitPreResistancebackup). Each tap is counted separately and the resolve summary prints the disagreement, which is the diagnostic if a real hit ever reads as no help. The row is a StoryKitChoice.Actionon ONE surviving guard, computed at pay time, paid withInventory.AddMoney(MP-safe: it routes an RPC for a guest). - Leaving and removal: after
LingerSeconds(extended while anyone is in dialogue) the survivors walk to an exit chosen AWAY from the nearest player (dot-product over the census), on routes built by the sharedMerchant/RoadRouteBuilder. Each guard is removed —Unprotect, pairwise overrides cleared,NpcRegistry.Unregister(which also drops itsChoiceActions) — the first tick it is farther thanRemoveRadiusMetersfrom EVERY player (FarCache.FarFromAll, which returns false on an empty player list, so an unknown situation keeps the guard rather than blinking it out).
The runner (Patrol/GuardParty) lives on its own dr_patrol GameObject, NOT on a guard: unlike the
merchant's RaidRunner, here the body it would ride is the one in danger, and a runner destroyed
mid-fight would leave live trogs, live overrides and a registry entry with nobody to clean them.
BepInEx/config/cobalt.dangerousroads.cfg:
[Events]
PatrolWeight = 0.25 ## relative draw weight; 0 = never
PatrolCooldownSeconds = 900 ## stamped at DRAW, not on success
[Patrol]
GuardMin = 2 ## next spawn
GuardMax = 3 ## next spawn
TrogMin = 4 ## next spawn
TrogMax = 6 ## next spawn; counts against [Wave] MaxOwnActive
GuardHealth = 450 ## next spawn (template-baked)
GuardProtection = 12 ## next spawn
GuardDamageMult = 0.9 ## next spawn; under 1 so the party cannot wipe them before you can help
GuardChanceToAttack = 85 ## next spawn; percent
GuardProtected = true ## at spawn; the player side cannot hurt/target them, the trogs can
RewardSilverMin = 5 ## live; per spawned-and-now-dead trog, IF you helped
RewardSilverMax = 6 ## live; rate rolled once per encounter
TrogRingMin = 12 ## live
TrogRingMax = 18 ## live
GuardRingMeters = 4 ## live
StalemateSeconds = 90 ## live; 0 = a fight must end by a wipe
LingerSeconds = 20 ## live; extended while a guard is in dialogue
LeaveSpeed = 1.4 ## live, read when the walk starts
LeaveTimeoutSeconds = 300 ## live; removal still waits for "far from every player"
RemoveRadiusMeters = 120 ## live; keep in step with [FarCache] DespawnRadius
Verbs: roadspatrol [status|spawn [key=value …]|resolve|help|leave|despawn|looks [town]], and
roadscard patrol [key=value …].
Files: Events/PatrolCard.cs (town, placement, guard specs, exit choice),
Patrol/GuardParty.cs (trogs, aggro, phases, reward, leaving, removal), Patrol/HelpWatch.cs
(the three help taps), Patrol/GuardOutfits.cs (the per-town looks + the name check);
pure Core/PatrolPlan.cs, Core/PatrolState.cs, Core/PatrolLedger.cs, Core/GuardLook.cs,
Core/PatrolText.cs, all unit-tested. Log tag [PATROL]. Built 2026-08-26, not live-verified —
docs/road-patrol-testplan.md.
Forcing a card with parameters: roadscard
roadscard <id> [key=value …] forces one card through the real Fire path with optional overrides.
Every key is optional — an absent key is the card's normal random/config default, so
roadscard merchant is exactly a deck draw of the merchant and roadscard alone is a real deck
draw. roadsdeck <id> … and roadsmerchant spawn … accept the same tail. Unknown keys are warned
once ([EVENT]/[MERCHANT] ignoring unknown key(s)) and the card still runs.
| Card | Key | Meaning |
|---|---|---|
merchant |
exit=<n> |
walk to exit n from roadsexits (out of range = refused, not defaulted) |
dest=<text> |
walk to the first exit whose name contains text (no match = refused) |
|
health= protection= damage=<mult> |
the body's numbers for this spawn (config defaults otherwise) | |
speed= |
walk speed for this merchant (overrides the live WalkSpeed for him only) |
|
defends=true|false |
fights bandits / fully passive | |
at=here |
spawn 3 m in front of you instead of a hidden verified spot — "show me" mode | |
name=<text> |
display name | |
raid=0|1 |
forbid / force the bandit raid for this merchant (absent = roll RaidChance) |
|
raiders=<n> |
raider count (absent = roll RaidMin–RaidMax) |
|
raidspecies=<key> |
raider species (absent = roster pick, Bandits preferred) | |
outfit=<n> |
pin outfit n from the pool (0–6); out of range warns and stays random |
|
protected=true|false |
override [Merchant] Protected for this spawn |
|
patrol |
at=here |
spawn 8 m in front of you instead of a hidden verified spot |
region=<town or region> |
dress the guards for that town (Berg, Abrassar, New Sirocco…) |
|
guards=<n> trogs=<n> |
party sizes (absent = roll the config bands) | |
species=<key> |
pin the troglodyte species (absent = a warm one from the seven) | |
health= protection= damage=<mult> atk=<percent> |
the guards' numbers for this spawn | |
outfit=<n> |
pin outfit n from that town's pool; out of range warns and stays random |
|
protected=true|false |
override [Patrol] GuardProtected for this spawn |
|
exit=<n> |
the exit they leave by, from roadsexits (out of range = refused) |
|
reward=<silver> |
pin the per-dead-trog rate instead of rolling RewardSilverMin–Max |
|
ambush |
count= species= |
exactly roadsnow's forced count / species |
roadscard merchant at=here health=50 # in front of you, fragile
roadscard merchant exit=0 # walk to roadsexits #0
roadscard merchant dest=Cierzo defends=false
roadscard merchant at=here raid=1 raiders=2 # the raid, guaranteed, two bandits
roadscard ambush count=2 species=Hyena
roadscard patrol at=here trogs=4 guards=2 # a patrol in front of you
roadscard patrol species="Troglodyte Archmage" region=Berg
Dev verbs
Every verb below is read from BepInEx/config/DangerousRoads_cmd.txt — write the verb on a line of
its own and it runs on the next poll; results go to BepInEx/LogOutput.log. Meant for debugging,
not for play.
| Verb | What it does |
|---|---|
roadsstatus |
director state: armed/disarmed, next-wave timer, last wave, last deck draw, what's blocking |
roadsdeck |
the event deck: cards, live weights, cooldown remaining, last draw. roadsdeck draw forces a draw through the real path; roadsdeck <id> [key=value …] forces that card |
roadscard [id] [key=value …] |
force one card with optional overrides (key table above); no id = a real deck draw |
roadsmerchant [status|spawn [key=value …]|despawn|rescue|raid|goto <exit>] |
the wandering merchant: where he is (walk, greet pause, raid state) / put one on the road now (same keys as roadscard merchant) / remove him / fake the rescue edge (greeting swap) / spring the raid now / re-route to an exit index from roadsexits |
roadsexits |
census of this scene's zone exits: index, destination, distance, bearing |
roadsstock |
which live Merchant carries the caravan-trader stock table the road merchant copies |
roadsroster |
this region's species roster, with anything BLOCKED marked |
roadsfactions |
the faction each rostered species actually reports |
roadsledger |
the anchor ledger — where waves have been placed and from what source |
roadsanchors |
candidate anchors near you |
roadssquadpoints |
vanilla AISquadSpawnPoints in range |
roadsprobe / roadsmark |
probe a placement position / mark one for inspection |
roadsui / roadsblips |
toast and compass-blip state (roadsblips counts hostile and merchant dots separately) |
roadsnow |
force a wave immediately |
roadsarm / roadsdisarm |
arm the director so the next wave is due now / stop the timer |
roadswarm |
pre-warm species templates |
roadssweep |
despawn everything this mod has out |
selftest |
run the offline self-test ([SELFTEST] PASS/FAIL … DONE) |
Known gap: roadsstatus throws a NullReferenceException if called on a fresh boot before the
first wave has been computed. It self-heals once any wave fires.
⚠️ Known issues
- A Wolfgang can turn up on the wrong side. The Wolfgang family's allegiance is driven by your
plot and relationship progression in the base game, not by a fixed table value, so an ambush wave
that draws one can spawn it in an allegiance the mod didn't intend — including friendly. The fix
is to drop the whole family from the encounter roster (not to hard-code a faction for them, which
would just be wrong at a different point in the story); that isn't in 0.1.0. If you hit it and
want it gone now, add the names to
[Species] ExtraBlocklistin the config and relaunch —Wolfgang Captainis already blocked by default,Wolfgang VeteranandWolfgang Mercenaryare not. - A few other species report an unstable faction. The Mantis family (Rock/Mana Mantis, Mantis Shrimp), Veaber and Caldera's Boreo have each been seen reporting different factions on different spawns. Under investigation; the practical symptom is the same as above — an encounter that doesn't fight you.
- Multiplayer is untested. Only the host would ever run encounters, which is the right shape, but no real two-machine session has been played. Treat co-op as unsupported for now.
- Encounter frequency varies by region. Some parts of the map give the mod more good places to put things than others, so the wilds are livelier in some regions than in others.
- Three of the six regions have had a deep test pass; the rest have had less.
Compatibility
Outward must be on its Mono Steam beta branch, not the default IL2CPP build (Properties → Betas →
select mono). If the game runs but no mods load and there's no crash log, this is almost always why.
Works alongside Beastwhispering and the rest of this mod family.
License
Apache License 2.0 — see LICENSE.
