Skip to content

Packet generator quests#25

Open
Seltraeh wants to merge 10 commits into
decompfrontier:mainfrom
Seltraeh:packet-generator-quests
Open

Packet generator quests#25
Seltraeh wants to merge 10 commits into
decompfrontier:mainfrom
Seltraeh:packet-generator-quests

Conversation

@Seltraeh
Copy link
Copy Markdown
Contributor

Rebased to the packet generator
Added:

  • Friend + Friend Unit (Takes strongest leader on update)
  • Summoning added back from Tom's commit
  • Missions reward units now
  • Evolution
  • Fusion
  • Town + Facilities
  • Cutscenes
  • Gaining units is client correct now and removes the "New" badge from older units
  • Leveling up and user stats that are associated to the users current level
  • Energy consumption and recharging

Seltraeh and others added 10 commits April 24, 2026 18:45
- New assets/net/unit.kdl: UnitFavoriteEntry/Req/Resp, UnitEvoReq/Resp
  (req/resp shapes for the UnitFavorite and UnitEvo handlers)
- assets/net/handlers.kdl: import ../net/unit.kdl
- assets/mst/unit.kdl: correct numeric fields from i32::int to i32::str,
  fix comma-separated position fields to plain str, add missing after_image
  field, replace all TODO docs with descriptive strings
- New assets/net/town.kdl: TownUpdateReq/Resp, TownFacilityUpdateReq/Resp,
  TownKarmaPayment, TownFacilityUpdateEntry, TownLocationUpdateEntry
  (handler request/response shapes for the two known town action handlers)
- assets/net/handlers.kdl: import ../net/town.kdl

TownFacilityUpdate (id 8v43tz7g) receives the complete desired facility +
location state from the client along with the total karma cost; this KDL
documents those wire keys.  TownUpdate (id CuQ5oB8U) request shape is not
yet fully reversed; stub documented accordingly.
Five new KDL schema definitions covering the MST tables needed to drive
the quest/campaign/battle systems in the server.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
NEW FILES
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

assets/mst/mission.kdl  —  MissionMst  (hash 2I9V0o6J)
  F_MISSION_MST_1 and F_MISSION_MST_2.  Covers all story campaign missions
  (IDs 1–~1200) and Uncharted Frontier end-game missions (IDs 1005000+).
  Key fields:
    j28VNcUW  id              — mission primary key
    9C64Qwe0  land_id         — land/continent this mission belongs to
    VjCY7rX4  area_id         — area/region within the land
    MHx05sXt  dungeon_id      — dungeon/node within the area
    69vnphig  stamina_cost    — energy cost to enter
    d96tuT2E  exp             — base EXP reward
    Rs7bCE3t  zel             — base zel reward
    HTVh8a65  karma           — base karma reward
    8f4NYKxb  battle_group_ids — colon-sep order:groupId pairs linking to
                                  battle wave data (e.g. '3:10100,1:10101')
    3sRN9BPS  bgm_map         — map/field BGM asset name
    nDf28LtU  bgm_battle      — battle BGM asset name
    1e6jxQzf  npc_encounter_id — links to MissionNpcUnitMst; 0 = no NPC

assets/mst/mission_ep3.kdl  —  MissionEp3Mst  (hash 2I9V0o6J)
  F_MISSION_EP3_MST.  Episode 3 (Summoner's Road) supplemental parameters.
  Augments MissionMst entries (IDs 20100+) with ep3_params: a KEY:VALUE
  string carrying EXP multipliers and ARM_EXP_RATE overrides.

assets/mst/mission_npc_unit.kdl  —  MissionNpcUnitMst  (hash 1e6jxQzf)
  F_MISSION_NPC_UNIT_MST.  Fully-statted NPC/boss units used in campaign
  cutscenes and encounter segments.  Links to MissionMst via encounter_id
  and to SkillMst via skill_id / extra_skill_id / leader_skill_id.
  Carries HP/ATK/DEF/REC, BB/SBB/UBB skill IDs, bb_fill_rate, and
  extra_passive_skill_id.

assets/mst/mission_script.kdl  —  MissionScriptMst  (hash N4XVE1uA)
  F_MISSION_SCRIPT_MST.  Per-mission cutscene / dialogue script entries.
  The script_data field is an '@'-separated sequence of scene commands
  (phase:command:params) that drives the in-game dialogue engine.  The N4XVE1uA
  hash matches the dungeon-state field seen in DungeonEventUpdate requests.

assets/mst/skill.kdl  —  SkillMst  (hash 8aiBoHg5)
  F_SKILL_MST (parts 1-9, merged).  All player BB/SBB/UBB skills, enemy
  auto-attack entries, and leader/extra skill effect definitions.
  Key fields:
    nj9Lw7mV  id            — skill primary key (also used as reference key
                               in MissionNpcUnitMst and unit rows)
    h6UL9A1B  skill_type    — category (1=attack, 2=heal, 3=buff, …)
    AR7y0sY4  skill_rank    — tier (1=BB, 2=SBB, 3=UBB)
    hjAy9St3  process_id    — colon-sep effect chain string
    eyUo6a8c  effect_frame  — animation frame data
    6Aou5M9r  damage_frame  — damage-hit frame data
    n9h7p02P  drop_check_cnt — BC drop-checks per hit
    iNy0ZU5M  element       — elemental override (0=none, 1-6=Fire…Dark)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
USAGE NOTES
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
These schemas are required by the MissionStart battle-engine seed path:
  mission.kdl         → look up stamina_cost, rewards, battle_group_ids
  skill.kdl           → look up BB/SBB/UBB frame data and drop-check counts
  mission_npc_unit    → NPC encounter stat blocks for campaign dialogue
  mission_script.kdl  → cutscene scripts for the scenario viewer
  mission_ep3.kdl     → late-game EXP rate overrides

Not yet wired: the server currently uses hardcoded mission-10 battle data.
Hooking MissionStart up to these MST tables is the next task on the
packet-generator-quests branch.
…ds, justify the str-kept ones with captured wire data, move Req/Resp into handlers.kdl

Audited every contested type-change in PR decompfrontier#21 against real values in
deploy/system/unit.json (2291 rows) to decide which `[i32::str]::sep(comma)`
→ `str` changes were justified and which were not.  Reviewer was right on
five of the six position fields; we have hard evidence for the remaining
three exceptions.

────── assets/mst/unit.kdl — REVERTED to `[i32::str]::sep(comma)` ──────

  home_img_pos       (1W9CxaFK)  — all 2291 rows integer
  detail_img_pos     (6z54rgb3)  — all 2291 rows integer
  confirm_img_pos    (MYK1fq6c)  — all 2291 rows integer
  skill_cut_image_pos(7hLR6pDN)  — all 2291 rows integer
  hp_disp_pos        (3BpHN6VD)  — all 2291 rows integer

  Earlier doc claimed "may contain floats" but the actual data has zero
  decimals across the full table.  The original `[i32::str]::sep(comma)`
  handles signed integers (including the observed negatives like -1, -100,
  -244) without issue.  Each field now carries concrete example values in
  the doc string.

────── assets/mst/unit.kdl — KEPT as `str` (justified, with evidence) ──────

  unknown / 5SUvj4tM (overdriveStats)
    Values have a TRAILING COMMA: "100,100,100,0,", "100,100,100,5000,",
    and "" for most units.  `[i32::str]::sep(comma)` would lose the
    trailing comma on round-trip.  Kept `str` for byte-faithful passthrough.

  bad_state_resists / CEeqs63b
    Values are 6 colon-separated percentages but at least one captured
    row contains a literal SPACE CHARACTER in a slot: "0:0:0:0: :0".
    `[i32::str]::sep(colon)` cannot parse the space as i32.  Kept `str`.

  summon_image_pos / KC3Jk8Br
    56 of 2291 rows contain DECIMAL FLOATS in the width/height columns,
    e.g. "41,231,560.5,387.5,0", "175,314,302.5,302.5,0".  Integer array
    codec would truncate or fail.  Kept `str`.  (This is the only one of
    the six position fields where the "may contain floats" claim was true.)

────── assets/net/unit.kdl — pared back to shared types only ──────

Per reviewer's convention guidance ("request/response network handlers
should go in handlers.kdl; keep separate kdl files only for types that
might need to be reused"), removed:

  UnitFavoriteReq, UnitFavoriteResp, UnitEvoReq, UnitEvoResp

These now live in handlers.kdl alongside the other request/response
wrappers.  UnitFavoriteEntry stays in unit.kdl because both the req
and resp reference it (shared type).

UnitFavoriteEntry doc now carries a concrete example wire-JSON capture:
  {"edy7fq3L":"12345","5JbjC3Pp":"1","2pAyFjmZ":"0"}

────── favorite field type=i32::str (response to bool suggestion) ──────

Reviewer noted favorite (5JbjC3Pp) "sounds as a boolean rather than i32".
Semantically true, but the actual wire format is a QUOTED decimal integer:
"1" / "0".  The available bool modifiers don't match:

  bool::int → emits unquoted `1`/`0`        (number, not string)
  bool::str → emits unquoted `true`/`false` (the wrong tokens entirely)

No `bool::str-num` modifier exists in the schema language, so i32::str
is the only modifier that round-trips the literal wire bytes.  Doc string
updated to explain this explicitly so a future reader doesn't loop on it
again.

────── assets/net/handlers.kdl — new entries ──────

Added the four moved Req/Resp wrappers.  UnitEvoReq/Resp remain
placeholders (the old hand-written handler never parsed the body in
detail) with docs pointing at `extract_createbody("UnitEvoRequest")`
and response_class=UnitOpeEvoResponse for the future implementer.
…rkers

Cross-checked every MST `hash` declaration we authored (mission, mission_ep3,
mission_npc_unit, mission_script, skill) and the upstream-inherited unit.kdl
against three evidence sources:

  1. IDA `response_mappings.json` — what hash maps to what response class
  2. IDA `typed_responses/*.hpp` — generated readparam structs
  3. `deploy/system/*.json` — actual decoded MST data on disk

Found and fixed FIVE wrong hash declarations and made the rest of the
mission/skill KDL hashes explicit about their unverified status.

────── unit.kdl — UnitMst hash corrected (HIGH CONFIDENCE) ──────

Was:   json UnitMst { hash "JYFGe9y6" doc "TODO" ... }
Now:   json UnitMst { hash "2r9cNSdt" doc "F_UNIT_MST — VERIFIED..." }

`JYFGe9y6` is actually the hash for F_UNIT_EXP_PATTERN_MST — confirmed
both by IDA (response_class=UnitExpPatternMstResponse, is_mst=true) and
by `deploy/system/unit_exp_pattern.json` having `JYFGe9y6` as its
top-level key.  `deploy/system/unit.json` has `2r9cNSdt` as its
top-level key, which is the real F_UNIT_MST hash.

`UnitExpPatternMst` definition in the same file kept its original
`JYFGe9y6` hash — that one was correct all along (it's a different
struct in the file; the upstream KDL had two structs sharing the
wrong hash for the wrong one).

────── mission.kdl — hash corrected (per IDA, UNVERIFIED on disk) ──────

Was:   hash "2I9V0o6J"  → IDA: CampaignMissionInfoResponse, is_mst=FALSE
Now:   hash "oXeC1Ak9"  → IDA: MissionMstResponse, is_mst=TRUE

The old `2I9V0o6J` was a network response key, not an MST hash —
fundamentally wrong category.

────── mission_ep3.kdl — hash corrected (per IDA, UNVERIFIED on disk) ──────

Was:   hash "2I9V0o6J"  ← DUPLICATE of mission.kdl's wrong hash
Now:   hash "vE0Qdg33"  → IDA: MissionEp3MstResponse, is_mst=TRUE

────── mission_npc_unit.kdl — UNVERIFIED marker added ──────

Hash `1e6jxQzf` appears only as a field key in IDA, never as a
top-level response_key for any *MstResponse class.  No decoded
`mission_npc_unit.json` on disk to confirm.  Marked UNVERIFIED in
the doc string with explicit instructions to verify post-mstdec.py.

────── mission_script.kdl — UNVERIFIED marker added ──────

Hash `N4XVE1uA` is heavily dual-use (LoginInfoResp field, dungeon-state
field in DungeonEventUpdate, arena MST scenario-script slot).  Whether
it's also the F_MISSION_SCRIPT_MST top-level key cannot be confirmed
without decoded data.  Marked UNVERIFIED.

────── skill.kdl — UNVERIFIED marker added ──────

`8aiBoHg5` IS in IDA but as `UnitSkillMstResponse` (the per-unit skill
assignments table), not a standalone `SkillMstResponse` — IDA has no
class with that name at all.  Marked UNVERIFIED.

────── Method ──────

For each KDL `hash`:

  1. grep response_mappings.json for the hash → if response_class is
     something other than what the KDL claims, it's wrong.
  2. Check deploy/system/<file>.json's top-level key directly:
     `head -c 30 <file>.json` shows it.
  3. If neither check resolves, mark UNVERIFIED in the doc string
     with a clear instruction to verify post-mstdec.
Five response classes covered (F5Vs19mb / 9Q1Lq5FS / UT1SVg59 / 5PR2VmH1 /
4MCxgS5p) plus the mission MST schema fixes that surfaced during testing:

  net/mission.kdl
  - Expanded from 16 lines (MissionBreakInfo stub) to 538 lines with
    full request + response definitions for MissionStart, MissionEnd,
    MissionBreak, MissionReward.
  - MissionReward: all 19 fields named (setLvupFlg / setBeforeLv /
    setIncExp / setActualZel / setActualKarma / setRewardUnits /
    setClearBonus / setRein* / setClear* / setExpUp/ZelUp/KarmaUpType /
    setExp/Zel/KarmaGuild / setEToken / setRepeatClearBonus).  The
    LvupFlg + BeforeLv pair is the actual level-up animation control;
    the d96tuT2E "incExp" field is just the displayed value, not a
    cascade trigger as previously assumed.
  - MissionStartInfo: corrected field semantics — J3stQ7jd is
    FriendPoint (not account_id), Z0Y4RoD7 is DeckNum (not
    ActiveGuildDeck in this context), 1VagK32J is ReinforceInfo
    (was placeholder).

  net/user.kdl
  - UserClearMissionInfo: was a mock/INVALID stub; now has all 7 fields
    with their decoded setters (setUserID / setMissionID / setClearDate /
    setClearCnt / setMostTime / setGetBc / setGetHc).  All
    std::string-typed even when the value is numeric — BF stores them
    as quoted strings.

  mst/mission.kdl
  - Marked 7 fields `optional #true` for the sentinel-row null values
    Glaze otherwise rejects (wHN6nfh9, 8f4NYKxb, N4XVE1uA, L8iA9M6c,
    3sRN9BPS, nDf28LtU, PYgkvcsy).
  - Reverted HSRhkf70 and 1e6jxQzf from i32::str to str — both
    heterogeneous across the 3433-row dataset (single-int + comma-pair
    / colon-list mixed shapes that fail single-int parse).

  mst/user_level.kdl
  - exp doc: per-level chunk semantics confirmed (not cumulative).

  mst/gacha.kdl
  - Doc cleanup for GachaInfoMst.

  net/handlers.kdl
  - import "../mst/mission.kdl" so MissionMst gets generated into the
    C++ headers (was previously dead KDL).

Audit findings are committed to KDL `doc` strings as setter names +
example values per handbook section 6.13 evidence rules.  Audit artifacts
themselves stay private (parent repo's tools/ida/ is gitignored).
IDA readParam audits (server-side handbook §8.32, §8.33, §8.35) decoded
three response classes whose schemas were stubs:

- net/friends.kdl: new FriendInfo (tojMy68W, 50 fields) — populates
  FriendInfoList, the singleton the squad-select friend picker / Social
  tab Friend Info dialog read from. Setter names from the readParam
  dispatch at 0x13D93C0 plus the GuildRaidFriendSelectRequest::createBody
  enumeration at 0x1C5B388. Notes the contextual overloads documented in
  §8.34 (iNy0ZU5M is uint32_t here, NOT string like UserUnitInfo;
  Ge8Yo32T is EquipItemID here, NOT MissionID like ReinforcementInfo;
  2Fh3J7ng is TeamLv here, etc.).

- net/reinforcement_info.kdl: ReinforcementInfo (xZH6EIQ7, 47 fields) +
  FixedReinforcementInfo (T_FIXED_REINFORCEMENT, 21 fields). Renamed
  formerly-unk_* fields to setTeamLv / setFriendType / setLastLoginDate /
  setNormalFriendPoint per the new IDA audit. T_FIXED_REINFORCEMENT
  confirmed as the literal wire key (uppercase with underscores —
  unusual for BF but real, see audit at 0x13950B8 in
  GameResponseParser::getResponseObject).

- net/handlers.kdl: FriendGetResp now wraps both [ReinforcementInfo]
  under xZH6EIQ7 (canonical per the captured prod response) AND
  [FriendInfo] under tojMy68W (for any UI that reads from
  FriendInfoList). Imports net/reinforcement_info.kdl explicitly.

mst/mission.kdl / mst/mission_script.kdl / mst/unit.kdl /
mst/user_level.kdl / mst/gacha.kdl: doc + type touch-ups from
cross-referencing against the audit findings.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants