The first world-reliability target is Concordia Wilderness, map context
1220 (adv_foreas_concordia_wilderness). New Deployment 11 characters enter
private Bootcamp 1985 first; legacy and skipped characters use their saved map.
PR105 replaces the old hostile pools with 580001..580075; Wilderness's
mission-specific public pools use the reserved 630001..630199 namespace.
Use the relevant source bindings rather than a legacy aggregate pool count.
Empty pools are not populated with invented defaults.
For mission creation, use mission authoring and operations and
the data/script reference. This page describes behavior
and acceptance checks. Mission data is installed by the normal provider
migrations: automatically at SQLite startup and manually for MySQL.
The rollout targets fresh merged databases and PR105-existing databases.
The 17 Wilderness provider pairs run after the PR105 tail, from
20261104000000 through 20261104001600; the unshipped September Wilderness
histories are not supported upgrade sources. Regression fixtures within the new
lineage retain their Char state and the same active Targets of Opportunity
assignment. WildernessMigrationTests checks PR105 row preservation, the
separate World ID namespaces, all 69 enabled definitions and class-sourced armor.
Do not reset a user database to run these checks.
After the SDK/dependency setup in the setup guide, run:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~Rasa.Test.World"The fixtures use isolated in-memory worlds, actual outgoing packet queues, deterministic clocks/random sources and disposable SQLite files. They do not connect to a developer database or require the game client.
Deployment 11 Bootcamp coverage is split between focused mission tests and starting-experience gameplay tests. The maintained suites now cover:
- the authored mission chain
1990 -> 1992 -> 1994 -> 1995 - reconnect at mission and objective boundaries
- combat/timed failure, timeout, retry, and respawn paths
- account-wide skip entitlement and second-character skip parity
- two simultaneous Bootcamp characters in distinct private
1985instances - startup validation logging for required-content defects
Run the Bootcamp-focused regression suites with:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~Bootcamp"Run the full mission-suite regression pack with:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~Rasa.Test.Missions"BootcampEndToEndTests covers the normal chain, the 1995 -> 2005 retry
path, entitlement unlock, and simultaneous-character isolation. The mission
files BootcampInitiationTests, BootcampGearingUpTests,
BootcampCaptureTheFlagTests, BootcampCallingForReinforcementsTests, and
BootcampBombRetryTests keep the reconnect, boundary, and failure cases
focused. BootcampCharacterEntryTests, BootcampDepartureTests, and
BootcampSkipTests cover first entry, exit-pad departure, and skip parity.
These automated suites validate server-side mission and gameplay behavior only.
They do not drive the retail client.
Character creation persists a pistol (template 17131) in weapon drawer slot
0, 1,000 rounds (template 28) in the consumables inventory, and rank 1 in
Lightning, Sprint, Firearms, Hand to Hand, and Motor Assist Armor. Lightning and
Sprint occupy drawer slots 0 and 1 (visible positions 1 and 2). These records
share the character-creation transaction. They are not granted again on login,
and existing characters' equipment, allocations and drawer choices are not reset.
Deleting and recreating a character in the same selection pod must start with only the new character's loadout. Moving the old pistol to visible weapon slot 2 before deletion must not leave a second pistol on the replacement character, either in the same session or after reconnecting. Selection pod numbers are not inventory owner IDs.
Level-1 attributes remain 10 Body / 10 Mind / 10 Spirit, with zero unspent attribute or skill points. Later level-ups retain their normal point budgets. Login fills Health and Power but starts adrenaline empty. The first Bootcamp entry reverses the old spawn heading by 180 degrees; reconnect uses the saved heading instead of rotating again.
Initiation (1990) is offered on arrival, not preaccepted. The client receives
DispenseRadioMission and its Accept Mission button sends AssignRadioMission.
Only an active character in its own private Bootcamp instance, with durable
starting-experience state Bootcamp, can accept this arrival offer. The mission
and initial objectives are committed before MissionGained is sent. Reconnecting
before acceptance offers it again; reconnecting after acceptance restores progress.
The two icons under "You will receive" show credits and prestige, not XP.
Initiation grants 100 XP and, after BootcampMissionAudioAndCredits, 100 credits.
Gearing Up, Capture the Flag, Calling for Reinforcements and its retry each
grant 200 credits at their successful mission turn-in. Prestige remains zero.
The retry is the alternative failed-attempt path, not a second grant for the
original mission. The native client has no XP field in this reward tuple. NPC/radio offers,
mission gain and mission-log snapshots use the same authored currency/item
preview as turn-in; creating a preview does not grant rewards.
Mission voices use generic authored audio metadata, not Bootcamp-specific
branches in the manager. The offer's existing audio slot plays narration when
the dialog opens: Bootcamp uses sets 2773, 2774, 2775, and 2776 for
missions 1990, 1992, 1994, and 1995. Eloh announcements bind sets 2788
and 2789; successful Initiation completion binds McAllister's set 2777.
These IDs refer to installed native audio sets, not copied sound files.
Accepted/completed/announcement cues run after committed progress and are not
replayed by a rejected duplicate request or ordinary reconnect. The native
offer narrator owns its dialog playback; it is not played again by a second
acceptance cue unless one is explicitly authored.
The SeedWorldContent migration installs greeting 1634, the client's
Logos/Lightning cue (SQLite applies pending migrations on startup; MySQL
requires an explicit update).
client/ui/conversationwindow.py selects tutlightning_left or
tutlightning_right for that greeting. The client owns the glow animation and
hides it when the animation ends; the server does not change the selected slot
or create a competing timer. The second greeting is unchanged. Native acceptance
should confirm the expected roughly five-second highlight in both UI layouts.
The focused creation, acceptance, rollback, reconnect and cue checks are:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~CharacterStartingExperienceCreationTests|FullyQualifiedName~BootcampCharacterEntryTests|FullyQualifiedName~BootcampInitiationTests|FullyQualifiedName~BootcampLightningCue|FullyQualifiedName~MissionProtocolTests"For guidance on authoring new mission content itself - conversation delivery, text/position sourcing, real-client verification - see the mission authoring guide.
The mission request boundary matches the local 1.16.5.0 client scripts:
AbandonMission(392):(missionId,)AssignNPCMission(407):(npcId, missionId)AssignRadioMission(408):(missionId,), requiring a current server-authored radio offerAssignSharedMission(409):(sourcePlayerEntityId, missionId), requiring a current party offerCompleteNPCMission(430):(npcId, missionId, selectionIdx, rating)CompleteNPCObjective(431):(npcId, missionId, objectiveId, playerFlagId)CompleteRadioMission(432):(missionId, selectionIdx, rating)PerformNPCChoice(497):(npcId, missionId, objectiveId, playerFlagId, choiceIdx)RewardNPCMission(540):(npcId, missionId, selectionIdx, rating)ShareMission(547):(missionId,)
selectionIdx and rating accept only Python int or None; boolean structs,
longs, and incorrect tuple sizes are rejected. Registering these handlers does
not activate source-only mission definitions. Unknown and inactive requests do
not mutate runtime or durable state and do not publish success packets.
Objective updates use the client receiver tuple layouts for
ObjectiveRevealed, ObjectiveActivated, ObjectiveCompleted,
ObjectiveFailed, UpdateObjectiveCounter, and
UpdateObjectiveItemCounter. Each serialized objective has eight fields,
including separate generic and item counter dictionaries, nullable remaining
time, and complete X/Y/Z indicator coordinates. Objective state and current
counter values are persisted separately from immutable initial/target metadata.
Radio and shared offers use the six-field conversation information tuple, not
the five-field mission-status tuple. Radio channels and party sharing use the
same acceptance/reward planners with separate durable source authority; a
submitted mission ID alone grants nothing. Bootcamp remains private, Once and
unshareable, and only its existing Initiation arrival source is enabled in
production. See the radio and sharing checks.
Run the focused boundary checks with:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~Rasa.Test.Missions.MissionProtocolTests|FullyQualifiedName~Rasa.Test.Missions.MissionTrackerTests|FullyQualifiedName~Rasa.Test.Missions.MissionRewardTests"Movement is accepted only for an active, assigned player in a world cell, with finite position/motion values and no pending transfer or logout. Rejected input does not change the authoritative position.
The existing grid uses 25.6-unit cells, a 32768 coordinate bias and 16-bit cell-key components. Cell identities must not wrap onto another cell. Packed movement coordinates retain their signed 24-bit representation. Channel sequences reject duplicates/older messages and continue across uint32 wrap.
Cell transitions notify both sides when players leave visibility. Introductions are queued before movement reaches a newly visible observer. Recipients are deduplicated and disconnected clients are excluded. Losing visibility does not unregister the unseen player from the world.
No anti-cheat speed tolerance or terrain/collision boundary is inferred from these checks. Those require client timing or map data that is not present in the repo.
Both local and dropship destinations must be discovered by that character, available and uncontested. Selection also requires a nearby source station of the matching type: the existing proximity ranges are two units for local waypoints and five for dropship triggers. Discovery is persisted before its runtime grant and notification.
One-way starting-experience extraction is not part of this network. Entering its ready beam starts the authored departure directly, without discovery or a travel menu. Old Bootcamp discovery rows are ignored during character loading and destination enumeration, and requests to fly back there are rejected.
Destination map context comes from the waypoint definition. It is not an alias
for the instance identifier. The current shared-world implementation advertises
instance 1; private operations and population instances are separate work.
Menus contain one instance descriptor per map and use authored station positions.
A local transfer uses one authoritative landing position for server state, teleport notification and movement. The existing local one-unit height offset is retained. Position persistence occurs on acknowledgement. Dropships track boarding, departure and map-load acknowledgement, advance only on their owning map, and preserve runtime inventory identities across the map transition.
Configure the deadline in Game's environment-specific settings:
{
"GameConfig": {
"TransferTimeoutSeconds": 60
}
}The value must be positive. The default is 60 seconds. If the client does not acknowledge in time, the server restores the transfer origin and disconnects; the client can reconnect at that origin. This prevents a late acknowledgement from completing a later transfer. A failed position write does not report a successful transfer. Duplicate or unsolicited acknowledgements are ignored.
Provider/query failures are logged and restore the in-memory transfer origin. The disconnect save is best-effort and also logs database failures; durable recovery cannot be promised while the database is unavailable. Departure cancels owned auto-fire timers and completes clan cleanup before discarding runtime inventory.
Run the focused gameplay checks with:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~Rasa.Test.Gameplay.WeaponAmmoConsolidationTests"Weapon commands require an active, living owner and a valid weapon in the selected drawer slot. Shots use the loaded template's ammunition consumption and refire interval. Manual requests and auto-fire share the same deadline. Reloads accumulate matching reserve stacks, retain ammunition already loaded, and recheck inventory when their template-defined delay ends. Switching weapons, interruption and departure invalidate pending work. Reload/draw/stow capture their owner's combat revision at admission; missiles capture source and target revisions at launch. Recovery and impact reject changed revisions even if the same objects have returned to the map or revived. This includes shots left queued while a map has no clients. A valid shot pays for ammunition at launch; invalidating its later impact neither spends another round nor refunds that shot. Auto-fire also captures the owner's combat revision and cannot resume after death/revival.
Shots and reloads persist before changing runtime ammunition or sending success
packets. ICharUnitOfWork.ExecuteTransaction(Action) wraps one character context
in an EF relational transaction. Participating repository calls may save inside
the callback, but must use that same unit of work and propagate errors. The
callback must not publish gameplay state or packets. The operation commits after
the callback and any remaining changes; failure rolls back and clears tracking.
It does not nest transactions or retry an operation automatically.
Transaction completion explicitly detects a lost connection before commit.
Rollback skips an already-ended connection; a rollback error is logged without
replacing the original exception. The transaction boundary still rethrows.
Gameplay catches only explicit planning/stale-state rejection, repository
missing-record, database/update, checked-overflow and capability errors.
Unexpected null dereferences and unrelated InvalidOperationExceptions remain
observable with their identity and stack. Expected failures publish no grant
and allow a later request to retry from durable state.
The SQLite fixtures reopen item and inventory rows after successful operations, injected save failures and retries. They also check drawer selection on relog, equipment/ammunition packet pairing, and launch/impact rejection of stale or cross-map targets. These checks do not establish native crosshair or HUD acceptance. MySQL uses the same EF transaction API but requires separate live provider verification.
The cross-feature regression suites exercise real gameplay entry points and SQLite query/save boundaries:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~Rasa.Test.Gameplay"Successful local/dropship admission uses the same combat-cancellation hook as world departure, before the transfer becomes pending or the position changes. It cancels Lightning, reload/draw/stow, Sprint and auto-fire, and advances the combat revision for queued missiles. Same-map selection and acknowledgement need no intervening worker tick. Rejected travel does not cancel combat. The separate corpse-eligibility revision does not change for local travel; loot remains subject to its original ownership, lifetime and current distance.
The maintainer loot reference defines the five-table contract, frozen Wilderness balance, managed-map readiness and forward migration-based tuning. Run the focused profile/catalog, native corpse, pickup, squad/mission, startup and provider compatibility checks together:
$filter = '(FullyQualifiedName~OrdinaryLoot|FullyQualifiedName~OrdinaryCorpseLootTests|FullyQualifiedName~LootConsolidationTests|FullyQualifiedName~MissionQualifiedLootTests|FullyQualifiedName~BootcampEncounterLootTests|FullyQualifiedName~PublicSceneActorPolicyTests|FullyQualifiedName~ServerStartupLifecycleTests|FullyQualifiedName~BootcampStartupValidationTests|FullyQualifiedName~WildernessMigrationTests|FullyQualifiedName~MigrationConsolidationTests|FullyQualifiedName~MigrationSnapshotsMatchCombinedModels|FullyQualifiedName~MigrationIdsAreUniqueAndOrdered|FullyQualifiedName~Pr95WorldModelRetainsIndexesAndColumnContracts)'
dotnet test src\Rasa.Test\Rasa.Test.csproj --no-restore --filter $filter --logger 'console;verbosity=minimal' -v quietWildernessOrdinaryLootTests
spawns migrated native pools, lands real player missiles and exercises
RequestCorpseLooting, RequestLootAllFromCorpse and
RequestLootItemFromCorpse. Exact drops, native item entities, packet targets/
payloads and persisted pickup are checked for Thrax, Miasma and Glognar, alongside
empty outcomes, duplicate/range/lifetime refusals, full bags, rollback/retry,
creation cleanup, captured unclaimed IDs at map departure and mission 479's
pickup-time assignment revalidation. The latter uses a controlled durable
generation mismatch, not an abandonment/replacement lifecycle.
OrdinaryCorpseLootTests
and MissionQualifiedLootTests
cover ordinary squad allocation and personal mission reservations.
WildernessOrdinaryLootMigrationTests
checks independent frozen native pools, exact rarity weights, fresh/upgrade/
rollback parity and reversible data-only tuning.
Startup tests cover validation before network acceptance; MySQL model/SQL checks
are offline and SQLite fixtures own their disposable databases.
Automated packets and requests do not prove native-client delivery/rendering, live MySQL execution, a deployed restart or original retail probabilities. On a disposable deployment with client 1.16.5.0, verify readiness, kill a regular hostile and named boss without an active mission, open the manual menu, take one item and the remainder, and inspect inventory/closure. Repeat with squad allocation and a qualified collection item. Use explicit MySQL migration and restart steps from setup, not a user database reset. Auto-loot filtering and credits timing are not changed by this rollout.
The full Rasa.Test.Missions selector earlier on this page includes the unchanged
GenericMissionRuntimeFilesDoNotContainBootcampMissionIdSwitches source-scan
failure: it matches 2005 in a MissionApplication.cs explanatory comment.
If excluding that baseline for a targeted gate, name it explicitly and do not
report a full-suite-green result.
This section describes pickup admission and transactions. Ordinary squad allocation and explicit personal authored overrides are described in the loot reference.
Run the focused checks with:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~Rasa.Test.Gameplay.LootConsolidationTests"The default maximum corpse-looting distance is 6 metres, measured in finite 3D world coordinates from the player to the corpse's origin, including height. It applies to both opening the menu and claiming its contents. Configure it in Game's settings:
{
"GameConfig": {
"CorpseLootDistance": 6
}
}A configured limit must be finite and greater than zero. Invalid limits reject
both opening and claiming; they do not silently fall back to a different range.
Explicit configuration overrides still take precedence over the default.
If an existing local configuration sets CorpseLootDistance to 2, update it
to 6 to receive the new behavior.
The native 1.16.5.0 client permits manual looting within the manifestation's
six-metre use range, testing the corpse's DAMAGE1 connection point or its origin.
The previous two-metre server default rejected ordinary clicks at three to five
metres even though the corpse advertised lootability. The server still measures
to the origin, not animated client connection points. Its out-of-range
rejections now include the actual/configured distances in the debug log;
lootability effects alone do not mean a corpse is currently in reach.
Both requests recheck the living, active eligible looter, account/character identity, registered player and corpse, current map/cell membership, corpse attachment and original lifetimes. Logging out, departure/re-entry, expired/removed corpses, foreign ownership and non-finite or out-of-range positions cannot grant loot. No obstacle or collision check is inferred.
Supported requests use the existing layouts:
RequestCorpseLooting(opcode 650):(dispenserEntityId,). It refreshes item entity data,LootInfoandCanLootItems, then sendsLootCorpse(actorId, lootItems)on the dispenser entity to open the menu. It does not grant items or credits.RequestLootAllFromCorpse(opcode 651):(dispenserEntityId, autoLootOnly). Both manual and automatic requests attempt the selected batch and can succeed without a preceding open request. Manual take-all selects every remaining item. Automatic requests select items at or below the player's validatedSetAutoLootThresholdvalue, which defaults to Junk until the client sends its option. Both paths retain the same ownership, range, capacity, transaction and duplicate-grant checks.RequestLootItemFromCorpseclaims one named remaining item into the requested destination slot through the same transaction path.CancelCorpseLootingdetaches the client from the current dispenser without granting its contents.
Malformed tuple arities are rejected. Gameplay rejections return failure and log the reason without grants or success packets; no new wire error layout is assumed.
The planner uses loaded template categories, the existing five 50-slot personal inventory categories and class stack maxima. It merges and splits the complete batch before writing, and validates current durable character ownership, credits, item identities/counts and inventory slots. A batch that does not fit grants nothing, including credits.
Stack updates, new item rows, inventory rows and credits share one
ICharUnitOfWork.ExecuteTransaction(Action) operation. Immediate-save repository
methods propagate failures. No participating operation opens another unit of
work. Runtime inventory, credits and success packets are published only after
commit; rollback frees staged item identities and leaves the corpse available
for a new attempt. The fixtures use migrated SQLite repositories and reopen
state after failures before/after each write, connection loss before commit,
successful retries and inventory relog.
Claims serialize with owner departure and corpse removal. After commit, item
and credit updates precede ActorGotLoot, TakenInfo, disabled CanLootItems,
GotLoot and dispenser destruction. Queued loot packets snapshot their values
before runtime loot is cleared. Consumption is terminal even for empty or
credit-only loot. The dispenser is removed, its item identities reclaimed, and
the corpse attachment cleared. Published dispenser request IDs are not recycled, so a
delayed claim cannot address a later corpse. Corpse age limits remain 20 seconds
when empty, 120 seconds while lootable, and 300 seconds while its menu is open.
Expiry disables/destroys the dispenser before destroying the corpse.
Ordinary item distributions now come from the migrated catalog, and corpse
quality reflects actual items. Credits amounts/timing and this pickup transaction
are unchanged. Mission rewards retain their own atomic turn-in path; ordinary
squad allocation remains the existing policy, not a second pickup engine.
These automated checks do not drive the native 1.16.5.0 client. Verify opening, item display, manual take-all, inventory updates and closure in the native client before declaring the UI complete. Auto-loot threshold behavior is covered by automated manager tests, but its native option and window presentation need separate acceptance. The offline suite covers the shared transaction and migration paths without a live MySQL server. Loss of a database commit acknowledgement is still ambiguous; there is no durable distributed exactly-once claim ledger. Subsequent stale inventory/credit snapshots fail closed.
Inventory loading registers and publishes only the selected character's items
and the account's shared home inventory (character_id = 0). It never adopts an
item from a deleted, unknown or zero character owner into a character inventory,
even when the destination slot is empty. Invalid-owner rows are logged and left
unchanged for explicit repair; another character's valid inventory is not sent
to the client.
Character deletion removes its inventory ownership rows and item records in the same transaction as the character and auction listings. Other characters' inventories and shared account/clan storage remain intact. A failed transaction retains the character and its items. This requires no schema migration or database reset. Items already reassigned by an older build are not removed automatically because their former ownership is no longer recorded. Already-duplicated personal slots are also not repaired automatically, and loot claims still reject them before any inventory or credit writes.
Mission 1992 keeps the existing crate class 29877. Right-click uses its
normal UseObject request and short recovery to open the same loot menu as
creature looting. The Use acknowledgement precedes the menu; it never transfers
items. Do not disable Usable or substitute a different entity class to change
click targeting.
The crate is present at (398, 122, 173) when the private Bootcamp map is
created, before mission acceptance. Its interaction is disabled until Delessio's
gear briefing activates the loot objective. Activation reuses the same physical
entity; it does not replace or duplicate the crate. Dormant crates have no loot
dispenser. A crate already visible when the objective activates receives its
loot attachment without requiring the player to leave the area or reconnect.
The dispenser is introduced after the crate enters the client's visible cells. Opening introduces the real item entities before the menu packet. Selecting a row claims only that row; Loot All claims the remaining contents. Proximity auto-loot cannot claim this crate. Opening and claiming use the existing object use distance, not the shorter configurable corpse-looting distance.
Claims use the same inventory transaction as creature loot. Per-template
receipts in character_mission_scenario_step commit with the inventory changes,
so reconnect restores only unclaimed rows. Collecting the final row completes
the crate objective and grants the existing equipment proficiencies. The empty
crate stays visible in its opened state, including after reconnect and mission
completion. A character whose crate objective was already completed by the old
bulk-grant implementation does not receive a second loadout.
SeedWorldContent installs the final crate behavior without an intermediate
bulk-grant or despawn migration. Apply the current World/Char migrations; see
deployment setup.
The crate's world lifetime now belongs to the experience run. Its per-template
loot-claim records still use character_mission_scenario_step; do not confuse
that loot ledger with the general scene receipt tables. Normal reconnect does
not reset either; the migration-owned branch itself requires fresh databases.
Run the focused server regressions with:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~BootcampCrateLoot|FullyQualifiedName~LootConsolidationTests"Native-client acceptance for this repair remains separate: right-click and confirm all six rows are visible without inventory changes; close and reopen; take one row and reconnect; collect the remainder with Loot All; confirm the crate stays in place and cannot grant duplicates. Repeat creature looting to check that its existing interaction is unchanged.
After the committed acceptance of Gearing Up for Battle (1992), Major
McAllister runs along the map's navigation mesh to (400, 120, 150), stops at
orientation 2.175, and remains there. Rejected acceptance does not move him.
The experience-owned role and committed mission/history facts drive recovery:
reconnecting during or after the run restores him at the destination, not at his
original post. His movement and spawn position affect only the owning
character's private map.
On reconnect, scene recovery can run before the normal static-NPC spawn worker.
A valid automatic spawn pool waiting to produce McAllister leaves his scene
operation pending without an error. His saved final pose is applied to the pool
before spawning, and the existing actor-available notification completes the
pending operation. This avoids the repeated ensure-mcallister / Public actor spawn 510203 is unavailable errors during normal map initialization. Missing,
disabled or invalid spawn definitions still report failures; no NPC is spawned
early to bypass its normal lifecycle.
Corporal DeSimone is a static NPC, creature 510206, conversation package
2562. His corrected spawn is (391.5, 120.059, 164.8). The existing horizontal
position is retained; the height is measured from the checked-in Bootcamp
navigation mesh. The previous height, 114, placed him about six units beneath
the walkable floor, outside the normal three-unit spawn-snapping tolerance.
This is a terrain-validated reconstruction, not a verified retail coordinate.
Finishing Hartmann's training makes Gearing Up ready to turn in at DeSimone.
The mission briefing remains until that turn-in; training completion is not an
automatic reward claim. DeSimone then offers Capture the Flag (1994) through
the existing NPC conversation.
SeedWorldContent includes DeSimone's corrected height and McAllister's nonzero
run speed, while retaining his zero wander speed. It does not change the
mission chain.
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~BootcampMapSetupTests|FullyQualifiedName~BootcampWorldContentGrounds"In the native client, verify the locked crate before accepting Gearing Up, watch McAllister run and stop at the supplied pose, and reconnect to confirm that he stays there. Finish rifle and Lightning training, find DeSimone above ground, turn in Gearing Up, and accept Capture the Flag without relogging.
Committed mission changes refresh the conversation status of visible NPCs. Completing the crate/equipment step must make Delessio available immediately; his handoff must make Hartmann available without reconnecting. NPCs outside the player's visible cells or in another instance are not part of that refresh.
The firing range uses three permanent Practice Dummy objects, entity class
29365 (arch_hum_practice_target_v01.geo), at these exact positions:
| X | Y | Z |
|---|---|---|
| 386 | 120 | 184.7 |
| 380 | 120 | 186 |
| 375 | 120 | 186 |
They exist when the map is created, before accepting mission 1992. Rifle and
Recruit Lightning rank 1 training use the same objects. Hits leave them upright;
they do not die, grant loot, or get replaced when an objective is accepted.
The client receives usable-object damage information and target category
OBJECT, not creature/NPC metadata. The former TestTargetDummy class 26548
is not used for these targets.
The ObjectHit progress event (event_kind = 13) distinguishes object hits
from creature kills and ability hits on creatures. Its subject_id is the
object's entity class and counter_id is the action ID: weapon attack 1 for
objective 3, Recruit Lightning 194 for objective 8. A rifle hit cannot
complete the Lightning objective. Weapon ammunition and Lightning eligibility,
range, costs, interruption and cooldown checks remain on their normal paths.
Other abilities and higher-rank object arc behavior are not added by this change.
Apply the pending World migrations when deploying. SeedWorldContent
installs the shared practice-target bindings and disables show_3d_effect for
the Bootcamp chain, preserving navigation coordinates and radii.
The client's missionlog.py checks this flag before creating the floating
OVERHEAD_MISSION_INDICATOR effects; NPC conversation status is not suppressed.
The client contract was checked against trpython's English entity-class
names, augmentations/inertdestroyable.py, augmentations/usable.py,
actions/abilities/damagebase.py, actions/targetedaction.py, and missionlog.py.
The repository's src\Rasa.NavMesh\data\entity_meshes.csv confirms the model.
No client files are modified.
Run the focused regression cases with:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~BootcampGearingUpInteractionTests|FullyQualifiedName~BootcampPracticeTargets|FullyQualifiedName~BootcampObjectiveIndicators"Native-client acceptance still requires a new connection to the updated server: check all three target models and positions before accepting the mission, finish the rifle/Lightning sequence without relogging, and confirm that objective stars are absent while tracker and NPC interactions continue to work.
BootcampReportedNavigationTests runs the normal navigation loader from the
Game project directory before creating a private instance. It verifies Forean
entity introduction and following to (347.66016, 121.69922, 64.625), both bridge
factions fighting across respawn cycles on walkable ground, and refusal of
unchecked scripted or failed-query movement. Loading the mesh directly inside
a movement fixture does not cover asset discovery at server startup.
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~BootcampReportedNavigationTests|FullyQualifiedName~BootcampInitiationTests|FullyQualifiedName~AcceptingGearingUpRunsAlisterToHisFinalPosition"Apply the paired SeedWorldContent World migration before exercising
mission 1994. It disables the old Collector/Dissector bridge pools, adds a
recurring battle between AFS soldiers and Thrax Infantry Initiates, and authors
the three Forean companions. The cave-exit area and indicator 439 are unchanged.
The Thrax use class 29769, model creature_thrax_soldier_grunt_v01.geo, and
client name 7674. Two AFS soldiers and three Thrax have individual,
terrain-checked bridge spawn points. Both factions fight through normal AI and
missile damage and respawn 20 seconds after death. These soldiers stay in the
bridge encounter; they are not the player's escort. Positions and combat
balance are server reconstructions, not claimed retail measurements.
The companions exist around the shooting range before the mission:
| Companion | Creature | Client name | Entity class | Starting position |
|---|---|---|---|---|
| Forean Guardsman Initiate | 510213 | 7874 | 7034 | (368, 120.21479, 158) |
| Forean Shaman Initiate | 510214 | 7890 | 7035 | (372, 119.956856, 158) |
| Forean Archer Initiate | 510215 | 7986 | 7036 | (374, 119.74777, 164) |
Accepting Capture the Flag makes these same actors follow the character.
UpdateEscortStatus (684) drives the client's OVERHEAD_ESCORT effect
(vfx_overhead_escort) and escort minimap markers. This does not re-enable the
gold 3D objective indicators. Marker state is included when an escort becomes
visible again. Reconnect restores surviving companions near the character's
saved position; deaths remain durable, and losing a companion does not fail the
mission. Only the owning escort's kill can advance the player's objective.
Owned escorts enter catch-up running beyond 10 metres, return to walking within 6 metres, and stop within 4 metres. A bounded catch-up sprint closes a larger gap without teleporting. They assist actual attacks against hostile creatures, rather than attacking anything the player selects, and return to following when the fight ends or the owner moves away. Their kills grant the owning player normal XP, loot and mission progress.
The existing cave-exit trigger starts Tizzik's encounter. Tizzik G is the mission's boss (the client creature-name table spells his name "Tizzik Gi"). He now uses normal combat actions. His defeat retains the existing seven-second Youngblood arrival delay. Scenario objective activation refreshes NPC conversation availability after the actors and objective state converge, so Youngblood is speakable without reconnecting. After the turn-in he remains at the reclaimed base across reconnects and offers Calling for Reinforcements. Complete Mission grants rewards and finishes the mission in one request. Youngblood is an unkillable base defender, not an escort. He fights nearby Thrax while remaining available for conversations. His kills grant player XP and loot only when the player or their owned escort damaged that enemy during its current life; unattended base fighting grants no player rewards.
The paired SeedWorldContent World migration adds twelve packs (42 Thrax total)
along the cave, base, missing-team and crash-site approaches. Each pack contains
three or four level-8-13 infantry; the new pools respawn after 120 seconds.
Tizzik is level 13. The pre-existing bridge battle keeps its 20-second respawn.
Positions are measured against the repaired navmesh, including the underground
cave route, rather than terrain height alone.
Bootcamp Thrax (bridge infantry, route infantry and Tizzik) use a dedicated drop
profile. Each eligible corpse contains one Thrax Skull (template 41666, class
20307) and rolls these additional drops independently:
| Item | Template | Chance | Quantity |
|---|---|---|---|
| Standard cartridges | 28 | 55% | 12-24 |
| Standard batteries | 56 | 30% | 8-16 |
| Basic medpack | 44917 | 15% | 1 |
| Thrax Medal | 41665 | 25% | 1 |
Credits retain the existing 1-9 range. Items are rolled and created once, in a single character transaction, before presenting the corpse. The existing owner-only inventory claim, partial claims and retry protection still apply. Other creatures retain their existing drop behavior. Loot-bearing scenario corpses, including Tizzik, use the ordinary corpse lifetimes (120 seconds unclaimed, 300 seconds while open), not the one-second cleanup used for non-lootable scenario actors.
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~BootcampCaptureTheFlag|FullyQualifiedName~CaptureTheFlagContent|FullyQualifiedName~BootcampEncounterLootTests|FullyQualifiedName~BootcampCompanionCombatTests"The checked-in navmesh\adv_bootcamp.nav used to stop short of a complete route
from the cave exit (279.05, 120.5, 66.07) to Youngblood at
(93.2, 109.64925, 137.5), with escort AI following the partial route and
stopping near (182.84, 108.35, 83.18). Following from the shooting range to
the cave exit already worked; only the cave-to-base leg was broken.
Rebuilding adv_bootcamp from the real client data (data\maps\adv_bootcamp
and data\mesh*.glm; map/terrain files alone omit the bridge and cave
collision meshes) reproduced the same stop point, ruling out a stale checked-in
file. Probing the built mesh isolated the break to a single seam around
(206-207, 105, 96), between the walkable shelf/cavern-entrance geometry
next to the AFS bridge (arch_hum_bridge_48m_v02, reachable from the cave
side) and the bridge deck/terrace geometry reachable from the reclaimed base.
The two sides sit about 0.9-1.1 m apart in height there - a small ledge in the
broken-bridge/cavern-entrance collision (arch_forean_bridge_ceremonial_broken_v01,
arch_forean_eloh_cavern_entrance_v01) - just over the builder's default
0.9 m AgentMaxClimb, so Recast never linked the two regions. The much larger,
genuinely vertical cliff face further north (x about 182-190, dropping from
the cave-exit ledge to the river) stays correctly excluded at any reasonable
climb value; the fix does not touch it, and the repaired route avoids it
entirely, crossing the AFS bridge instead.
Rebuilding just adv_bootcamp with --climb 1.0 (up from the 0.9 m default,
justified by the measured ledge height, and scoped to this one map's build
rather than the shared default in BuildSettings) closes that seam and
produces a complete path. ForeanEscortsCanFollowFromTheCaveExitToTheReclaimedBase
covers this route and is no longer ignored.
The subsequent grounding correction retains that climb setting but uses
0.05-metre vertical cells, one-metre terrain sampling and denser surface-height
details (--detail-distance 1). The previous mesh put Youngblood's base
0.32-0.55 metres above the source terrain despite passing a nearest-navmesh
check. Five measured base points now differ from the source surface by less
than 0.15 metres; BootcampGroundingTests also requires complete cave/bridge,
missing-team and crash-site routes. Youngblood's authored Y is 109.2201 at
(93.2, 137.5) in X/Z. These settings apply only to the regenerated Bootcamp
asset, not the builder defaults or other maps. Native animation and feet-to-ground
rendering still require client acceptance.
To reproduce or re-diagnose on a machine with the full game installation:
dotnet run --project src\Rasa.NavMesh\Rasa.NavMesh.csproj --configuration Release -- --path navmesh\adv_bootcamp.nav 279.05 120.5 66.07 93.2 109.64925 137.5This now returns a complete path and exit code 0. To rebuild adv_bootcamp
into a temporary output directory instead of trusting the checked-in file:
dotnet run --project src\Rasa.NavMesh\Rasa.NavMesh.csproj --configuration Release -- --client "<Tabula Rasa install>" --out <temp dir> --map adv_bootcamp --climb 1.0 --cell-height 0.05 --terrain-step 1 --detail-distance 1Verify any future rebuild with the same --path query before replacing the
checked-in mesh; do not move area/indicator 439, move the base NPCs to
bypass a gap, or raise climb/slope limits without checking the resulting
paths against the actual collision geometry, as was done here.
The repository does not contain a native-client automation harness. Use this
manual script when validating Bootcamp in the retail 1.16.5.0 client.
Calling for Reinforcements (1995) exposes only client objectives 2, 3, 1, 4.
Entering area 435 completes objective 2 ("Locate the missing AFS soldiers")
and reveals Conrad's corpse interaction. No standing survivor NPC is spawned.
Clicking the corpse opens the native mission Continue dialog; only Continue
completes objective 3, places the bomb in Mission inventory and starts the
600-second deadline. Closing the dialog does not grant or advance anything;
finishing the 1400 ms planting windup satisfies it before the fuse and
reinforcement arrival. Planting also starts one six-Thrax assault at the foot
of the hill. The attackers follow a grounded uphill route and engage the player;
combat can interrupt their advance without counting as a death.
After the five-second fuse, the wreck receives its native closed-to-open
destruction transition. Two seconds later the wreck clears and the evacuation
ship appears with Van Valkenberg and two AFS soldiers. The soldiers defend the
pad through normal AI and damage. They do not replace the player's earlier
Forean companions.
Van's check-in stays locked until all six assault enemies are defeated.
Soldier final blows count even without player reward credit. Defeats and their
scene inputs are saved together, so reconnect restores only surviving attackers
and a delayed scene write can recover the final unlock. There are no recurring
assault respawns. Abandonment removes the attempt's attackers, soldiers and ship;
the 2005 retry gets its own encounter.
After checking in, walk into the ship's beam to depart directly. There is no Bootcamp waypoint notification or travel menu, and no normal travel back to Bootcamp afterward. Checking in alone does not board the player. If already inside the beam while boarding was locked, step out and back in after check-in. The hovering ship is replaced by the normal departure flight, followed by the wilderness load and arrival flight at Alia Das. Departure commits the existing Bootcamp progression/entitlement changes once, and the old private map is released after destination persistence succeeds. The mission remains ready for its existing Rogers turn-in in the wilderness.
Internal extraction trigger 60 uses the wreck's pad at
(-225, 101.12099, -71), rather than the old hillside location. It is not a
discoverable waypoint. Bootcamp does not create an always-on hovering ship at
map entry. Other public-world dropship pads keep their existing visuals and menus.
The ready-state sequence clears a retained wreck before staging the ready ship
on reconnect.
SeedWorldContent installs the finale, ready-state cleanup, assault templates
and reinforcement bindings together. SQLite applies it on startup; MySQL
remains manually migrated. The consolidated branch history requires fresh
databases and has no separate mission publication step.
The new encounter positions and balance are authored server behavior, not claimed retail measurements. Native acceptance must check the uphill advance, ship/beam appearance, allied combat, locked/unlocked check-in, and direct boarding.
The bomb target uses tutorial wreck class 24586, not dropship-crate class
24911. Its authored shared role and experience-owned effects drive reconnect
recovery; do not locate it by parsing a legacy scenario-key string. The
crash-site destination is the user-confirmed (-225, 101, -71) near the damaged
landing pad; authored actors and interactions are grounded against the current
Bootcamp navmesh. Conrad and the wreck use their shipped usable-state contract,
including disabled planting after the charge is placed.
The explosion uses native Use for state 31 -> 91, whose client data binds
the transition animation and effect package 37160. ForceState and
UsableInfo set a state directly and are not substitutes for this transition.
The server-side packet/lifecycle sequence is covered automatically; native
animation rendering and camera behavior still require an in-game check.
The bomb target is tutorial wreck class 24586 (mesh 20000024), not dropship
crate class 24911 or extraction landing-pad class 29771. Planting triggers
and interaction enable/disable steps use 24586 for both 1995 and retry
2005. The client uses argument 1 for Conrad and the wreck; their initial
usable states are TreasureDispenser closed (200) and Door closed (31).
Scenario reconstruction replaces old crate visuals and reapplies interaction
state after spawning, so a planted bomb does not become usable again on login.
Enabled scene objects are published as mouse-targetable even when their base
class's target flag is false. The wreck's class 24586 is one such class;
publishing only its enabled usable state left normal mouse interaction blocked.
Disabling the planting interaction also updates targetability.
Recovering Conrad's bomb now places one native Explosives Detonator
(template 11519, class 20000064) in Mission inventory. Planting consumes it;
timeout or abandonment removes it, and accepting retry 2005 supplies one new
bomb. Item changes share the mission/scene transaction and are published only
after commit. Full Mission inventory rejects pickup without completing the
objective. The issuance receipt prevents repeated reconnects from granting
extra bombs. SeedWorldContent uses native conversation-capable class 21081
(UsableNPCHumMCorpseV01, mesh 29456).
Apply both World and Char migrations to fresh databases; SQLite does so during normal startup. No migration repairs older survivor layouts or adopts intermediate branch bomb attempts. Ordinary reconnect preserves progress and deadlines written by the current schema.
The old Conrad placement (-102.4, 86.20677, 66.8) was inside the client's
static trench wall (class 9707), despite having a nearby navmesh polygon.
The C# Bootcamp data migration now places the corpse at (-99, 86.33577, 74)
and indicator 436 at ground (-99, 86.32086, 74). Mission and experience actor
bindings use the same authored position. The new height accounts for class
21081's native render minimum Y of -0.01490639; its X/Z placement is unchanged.
On a fresh migrated database, confirm the corpse is visible beside the missing team, the
marker agrees with its location, and clicking it opens the mission dialog with
a Continue button. Confirm that the search completes on proximity, opening or
closing the dialog grants nothing, and Continue advances objective 3 and
starts the bomb deadline. Check reconnect before opening, before Continue,
after pickup and after planting. Source-geometry checks use the new corpse's
measured footprint and connected approach; native-client rendering still needs
the manual check.
After rebuilding/restarting Game, check that the rifle image appears on login without pressing E, that the bomb appears in the Mission tab, and that the wreck can be right-clicked to plant it. Use a Thrax-dropped medpack as well: it must not disconnect the client, must consume one item and must heal. Mission changes use the normal database migration flow, not a publication script.
The migrated definition uses the client's supported objectives 2, 3, 1, 4,
not the old experimental objective 10. Runtime conversion of old objective
layouts has been removed for the fresh-database design.
The consolidated branch history is fresh-database-only. Its Char schema creates
flags directly without backfilling old qualifications. On the new database, verify that a
mission-set numeric flag survives reconnect, a failed transition grants no flag,
and deleting/recreating a character does not carry flags into the new character.
Bootcamp completion and skip store CharacterFlagIds.BootcampComplete = 1;
the starting-experience state and account skip entitlement remain separate.
- Start from disposable SQLite character/world databases and apply migrations.
- Launch
Rasa.AuthandRasa.Game; normal initialization installs mission data. - Confirm the Game log reaches
Server ready!. - Create a fresh account and a fresh character.
- In a cold client session, validate these ten scenarios and capture the
matching server log window for each:
- complete
1990 -> 1992 -> 1994 -> 1995 -> Alia Das - reconnect at every mission boundary
- reconnect at every objective boundary
- die and respawn during each combat or timed mission
- let
1995time out, confirm the reset, then finish2005 - disconnect during planting and confirm the original deadline survives
- finish planting with five seconds remaining
- complete Bootcamp once, then create a second character and skip
- run two Bootcamp characters at once and confirm they never share actors, rewards, or mission state
- confirm no unsupported packet, stale objective, duplicate actor, duplicate reward, or stranded character appears
- complete
Repeat the same ten scenarios against disposable MySQL character/world databases after explicitly applying the MySQL migrations. See migration operations. If your local setup includes opt-in live MySQL verification, use it. Otherwise, the automated suites still cover offline MySQL migrations and model parity.
Before signing off startup validation, intentionally break one required Bootcamp reference in a disposable database copy. Two safe examples are:
- remove NPC package
2564(Van Valkenberg), or - set
mission_objective_definition.client_body_text_id = 0for mission1995objective2
Restart Rasa.Game and confirm:
- the log prints the exact diagnostic naming the broken mission/objective or missing package
- the log also prints
Mission content validation failed for required content; the Game server will not report ready. Server ready!never appears
Restore the clean database before any other client run.
The ability reference records the approved historical tables, explicit engine policies, transactions, lifecycle guards and native acceptance limits. Sprint ranks 1-5 and Lightning ranks 1-2 are executable. Rank 2 uses Blumster's supplied arc layout. Lightning ranks 3-5 still fail explicitly because the additional Sonic, stun and storm contracts are not established; they do not run as incomplete ranks.
Run LightningConsolidationTests, AbilityTrayConsolidationTests, and
ProgressionPersistenceTests together for action-table bounds, arc selection,
learned rank/cost validation, migrated tray persistence, rollback, resource
snapshots, and replay protection. Selection adds one server-owned character
column through both SQLite and MySQL migrations. Effects receive actual elapsed
time on every map tick.
Run the focused mission checks with:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~Rasa.Test.Missions"Mission progress belongs to persistent character IDs, not account IDs or party
rosters. The current journal row is keyed by (character_id, mission_id) and
has a separate assignment ID, pinned content revision, generation and version.
Reacceptance is a new assignment, not permission to consume the previous run's
timers, signals or grants. Objective rows/counters retain their normalized keys
and optimistic-concurrency checks.
character_mission_history retains terminal outcomes and reward claims when a
journal entry is cleared. Rewarded completions do not consume the 30-slot
journal limit; non-completed journal rows, including pending reward/failed rows,
still count. Clearing a rewarded mission cannot permit another nonrepeatable
reward, and a failed history entry is not a completion/reward claim.
MissionJournalAdapter restores current values against the selected definitions.
An unavailable or changed pinned revision is quarantined and preserved for an
explicit migration decision, not silently rebound to another content revision.
Inconsistent runtime state still follows explicit invalid-row handling; this
fresh-database design does not convert old experimental objective layouts.
Production definitions come from enabled, migrated World data. Optional
invalid and source-only content remains non-operational; required-content
defects block readiness. A new mission is authored as a C# data migration, optionally with a
registered typed script, not inserted into MissionApplication as special code.
The independent Rasa.Missions core evaluates typed progress rules and indexes
only relevant event/NPC bindings. Rules include exact events, waypoint/Logos
distinct sets and explicitly authored generic/item counters. Counters are not
test-only and are not inferred from prose. The Game application rechecks durable
state and stage-specific requirements before persisting changes. Protocol
adapters publish only after commit, preserving counter, objective and
mission-completable ordering and hiding only unrevealed Inactive objectives.
World scene state is independent of the active journal: mission_scene, inbox
messages, named timers, receipts, pending world effects, actor outcomes and
per-character credit deliveries preserve their own run/generation identities.
An authoritative committed objective can recover its queued scene input after
a crash. This is replay of recorded work, not invented progress for quests
accepted later.
Public-map logout/transfer detaches the client according to the encounter's
Wait, Continue or Reset policy. Deliberate default abandonment invalidates
the exact assignment-owned work in the same transaction as deletion; authored
failure transitions remain distinct. Generation checks prevent stale callbacks
or loot/grant intents from affecting a replacement run. Cleanup removes only
the terminated run's created actors, while a leased static actor completes its
own return/reset/respawn lifecycle.
Experience-owned actors survive the appropriate mission's journal cleanup.
Youngblood must still appear after rewarding and clearing 1994, cold
reconnecting, then requesting his 1995 conversation. Persisted scene rows
alone are not sufficient evidence; test the actual actor and client flow.
Group credit is opt-in for supported kill/scenario events. Capture authoritative objective requirements, active objective, map/range and participation eligibility when the event occurs. Deliver only to those frozen assignments; a later party join, acceptance or predicate change neither invents eligibility nor removes earned credit. Delivery still checks exact assignment/generation and current objective state. Personal actions and reward choices are not shared.
Mission turn-in keeps reward items, currencies, XP, terminal state and dependent progress in one character transaction. A failure rolls back that turn-in. Public actors remain shared and an exclusive escort may be unavailable to the next group until it returns or respawns; there is no personal NPC phasing or automatic party acceptance.
The implemented state mapping is:
- Active attempt:
MissionState.ActivewithCompleteable = false. - Completable attempt:
MissionState.ActivewithCompleteable = true. - Legacy pending reward attempt:
MissionState.SuccesswithCompleteable = false. - Completed attempt:
MissionState.CompletedwithCompleteable = false. - Failed attempt:
MissionState.Failed. - Abandoned attempt: the active durable row is removed and
MissionDiscardedis sent.
Login sends one MissionStatusInfo snapshot from durable state. Acceptance
validates the active client, registered NPC, persistent giver identity, current
map instance, stage requirements, duplicate/history state and the durable
30-slot journal capacity, then creates
the mission and all definition-authored objective/counter rows in one
transaction. Hydration combines persisted current values with immutable
definition metadata. Abandonment reloads the durable attempt and cannot remove
completed history from a stale client.
NPC objective completion requires an active operational definition, an
incomplete durable objective, a current-map NPC, and an exact NPC-package/player
flag completion binding. Completion and explicitly authored reveal/activation
transitions load as one tracked objective graph and flush once. Runtime state
and packets include only successor transitions that were durably applied.
Packets are emitted after commit in
ObjectiveCompleted, ObjectiveRevealed, ObjectiveActivated, then
MissionCompleteable(true) order.
Turn-in infrastructure reloads the character and mission inside one serializable
character transaction. Inventory, XP, supported currencies and completion state
commit together on CompleteNPCMission. AssignNPCMission only starts a new
mission; it never claims rewards. Normal turn-in moves directly from completable
Active to Completed, without persisting an intermediate Success state.
Runtime state and packets are published only afterward.
Sequential, reconnect and competing-client retries grant at most once. Staged
item entity IDs are released if planning or publication fails. SQLite fixtures
exercise objective persistence and competing reward transactions; offline
database checks cover MySQL model and migration SQL consistency. selectionIdx
must be None for rewards without selectable items and an in-range zero-based
integer when choices exist; non-null ratings are rejected. An older durable
Success row is advertised as MissionComplete and can resume through
CompleteNPCMission. RewardNPCMission remains supported for legacy reward
requests against Success rows.
NPC conversations derive dispense, objective-complete, and mission-complete
entries from the character's current lifecycle state. A rewarded mission is not
offered again by its giver or receiver.
Vending, auction, and clan behavior remains the fallback when no mission state
applies. The preserved, source-only Wilderness catalog identifies missions
1449 (Wilderness Targets of Opportunity), 1407 (Too Close For Comfort) and
1069 (Receptive Reception), including source-backed objective text identities
and four completion-conversation bindings. Missing ordinals, initial/required
states, transitions, indicators, counters, prerequisites, repeatability, and
rewards remain null/absent in that fallback catalog. Those incomplete fallback
definitions never appear in conversation packets. The later World migrations
install separate, complete operational definitions for the same native IDs;
do not confuse source preservation with the latest deployed content.
The source-only catalog also preserves these bounded progress slices:
- Mission
1069, objective1: exact Logos10(entity class7364, map1220). Objectives2and3retain only completion conversations(168,1,Completion)for Solis creature42/spawn184and(112,1,Completion)for Apirka creature43/spawn219. - Mission
1407, objective1: completion conversation(113,1,Completion), corroborated by Moawi creature38. Objective10retains presentation and(168,1,Completion)conversation metadata only. No escort entity, route, success/failure transition, or Ranger binding is inferred. - Mission
1449, objective1: distinct waypoints{49,50,51,57,61,73,156}. Objective8: distinct Logos{1,2,6,9,10,23,24,28,38,49,53,56}. Objectives20through25bind exact creature IDs{82,83,84,79,80,75}respectively. Objective23explicitly records that Horntail's map-1220 spawn is unresolved. Spawn resolution for objectives20-22and24-25remains unknown rather than inferred from corroborating rows. Every objective outside the exact listed rules has no progress rule.
All three fallback definitions have IsOperational == false, carry no production
rewards, and produce no character mission/objective/counter writes or mission
packets for any progress event. Source preservation is not activation.
The current Wilderness providers enable exactly 64 outdoor definitions plus
the five protected Bootcamp missions. 1449 retains its assignment, counters
and instance-dependent goals across hub upgrades. Outdoor progress cannot
unlock its final reward. Conditional, retired, unmatched and other-zone
candidates remain excluded according to the
native coverage ledger.
Run the progress and adapter boundary checks with:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "FullyQualifiedName~Rasa.Test.Missions.MissionProgressTests|FullyQualifiedName~Rasa.Test.Missions.MissionDefinitionCatalogTests|FullyQualifiedName~Rasa.Test.World|FullyQualifiedName~Rasa.Test.Gameplay.LootConsolidationTests|FullyQualifiedName~Rasa.Test.Gameplay.ProgressionPersistenceTests"The repository's automated database checks compare models, snapshots, migration ordering, and generated MySQL SQL without opening a live connection. The current test project has no opt-in live MySQL category. Validate clean creation, upgrades, rollback, concurrent mission rewards, and shared gameplay transactions against an isolated disposable MySQL 8.0/8.4 instance before claiming live provider acceptance. Do not point exploratory checks at a developer or production database.
Seeded RespawnTime values are interpreted as seconds, converted once to
runtime milliseconds. The worker receives actual elapsed milliseconds for each
active-map tick. For example, seed value 20 means a 20-second cooldown.
An inactive map does not acquire an invented offline catch-up policy.
The existing limit of 64 creatures applies across the whole pool. Configured minimum/maximum counts remain inclusive. Malformed ranges and missing templates are reported without replacing them with default creatures. Manual modes are not silently made automatic.
An animated wave retains its selected creatures until delivery rather than rerolling them. Alive creatures, reserved deliveries and in-flight dropships block another generation. The last such reference leaving starts cooldown; remaining corpses do not delay the next generation. Each death and terminal corpse removal changes counters once, independently of observer count.
The automated release gate uses the real migrated catalog, native request handlers, disposable character persistence and public-map actors:
dotnet test src\Rasa.Test\Rasa.Test.csproj --configuration Release --no-restore --filter "TestCategory=WildernessG2|FullyQualifiedName~WildernessCoverageTests|FullyQualifiedName~WildernessProgressionAcceptanceTests|FullyQualifiedName~WildernessRewardReconstructionTests"
dotnet build Rasa.NET.sln --configuration Release --no-restore
dotnet test Rasa.NET.sln --configuration Release --no-restoreThe G2 category includes the full Quarantine -> council -> Daghda -> medicine ->
Beacham chain and the surrender, refusal and timeout branches. Hub tests use
ordinary latest World migrations rather than reapplying their data helpers.
Provider checks retain baseline round trips and active 1449 identity,
flags, inventory and partial counters. MySQL SQL is generated offline.
Supported consumable rewards use existing medpack action 419, not the
replaced EMP, grenade, adrenaline, trauma or module effects. Tests cover actual
earned rewards, injured-player healing, commit-before-consumption publication,
rejected input and cooldown replay. A recovered ability action is single-use;
replaying its callback cannot consume a second unit from a surviving stack.
Native-client and live-MySQL acceptance for this rollout remain unperformed. W6's scoped healing-disc and salvage-tool cases establish equip/profile/persistence, not native tool-operation acceptance. They also do not establish an OS-process restart midway through Matthew's escort. Before claiming either, use separately authorized, disposable environments:
Record the server commit and uncommitted changes, applied World/Char migrations, provider/version, client version, character class/level and public map instance. For every check, record passed, failed or not run, together with the mission/objective ID, exact action, expected/actual result and supporting evidence. A packet emitted by the server is not sufficient evidence of native presentation.
- Exercise normal Bootcamp extraction, its retry path, account skip and an existing public-world character. Verify arrival and Rogers's existing final turn-in without duplicate starting inventory, rewards, entitlements or assignments.
- Open native offers, reminders, objective conversations, choices and the journal. Check text, objective order, category and counters, with no blank bookkeeping objectives. Closing a conversation must not progress it or grant items; out-of-range and stale callbacks must be rejected.
- Walk each hub and the Solis, Milpas, Pierre, Ranja and survey approaches with the native 1.16.5.0 client. Check floor, collision, headings, markers and reachable interactions. For escorts, cover combat, blocked movement and actual arrival; a transport or respawn shortcut must not complete the route.
- Verify collection from actual eligible corpse pickups, not death alone.
Mission
479requires twelve physical hearts. Check exact turn-in costs, full-bag rejection/retry and cleanup. Destruction needs actual zero HP; reusing or destroying one object cannot replace distinct targets. - Exercise public encounters with two players at incompatible stages, including owner departure, failure, abandonment, reconnect and actor reuse. Check explicit party acceptance where authored and independent inventory, choices and rewards. Private copies of named public actors are not substitutes.
- Use separate characters for mutually exclusive contraband outcomes. Follow the plague chain through both vaccine outcomes and the timed replacement. Check radio expiry, reissue, last-second completion, timeout, new-session authority and Beacham's turn-in. Unowned or old-assignment items must not authorize vaccine or contraband actions.
- Verify native reward previews, selectable alternatives, medpack use and
inventory persistence. Missions
422and434each grant two units of44918; they must not lose a unit when their fixed rows share a template. - Accept
1449early and reconnect after partial progress. Check numeric and distinct counters, previously owned Logos/waypoints, and branch-aware story groups. Preserve assignment identity and earned progress. Unbound cave objectives and genuine instance goals must remain incomplete; proximity to a cave or outdoor-only completion must not unlock the final reward. - Confirm retired, unqualified conditional/event, other-zone and unfinished
instance missions are not advertised as normal outdoor offers.
1449is the deliberate partial-progress exception.
Do not modify an installed client, run acceptance against user saves, or label offline SQL generation and source-geometry checks as live acceptance.
The checkout contains 77 generated .nav files under navmesh. Rasa.Game
loads matching files through GameDataConfig.NavMeshPath, uses them for ground
queries and creature paths, and falls back to straight-line movement when a map
has no usable file. The automated world suite covers map-link transfer and
lifecycle behavior, but it does not certify every generated route or real
terrain/collision interaction.
Native 1.16.5.0 client checks remain separate: two clients crossing visibility boundaries, waypoint/dropship UI behavior, interruption/reconnect, and movement against real terrain. These automated checks do not establish that InfiniteRasa/Rasa.NET#45 or the remaining gameplay issues are complete. See the protocol regression guide for the separate first-map-load acceptance boundary.