From 04034fba45727f1cd0021bf38a11f868d2fa7789 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 10 Apr 2019 16:54:34 -0400 Subject: [PATCH] Store mission progress --- src/idz/decoder/_mission.ts | 28 ++++++++++++++++++++++++++++ src/idz/decoder/saveProfile.ts | 5 +++++ src/idz/encoder/_mission.ts | 26 ++++++++++++++++++++++++++ src/idz/encoder/loadProfile2.ts | 3 +++ src/idz/handler/createProfile.ts | 7 +++++++ src/idz/handler/loadProfile.ts | 2 ++ src/idz/handler/saveProfile.ts | 1 + src/idz/model/index.ts | 1 + src/idz/model/mission.ts | 9 +++++++++ src/idz/request/saveProfile.ts | 2 ++ src/idz/response/loadProfile2.ts | 2 ++ src/idz/world/base.ts | 2 ++ src/idz/world/index.ts | 7 +++++++ 13 files changed, 95 insertions(+) create mode 100644 src/idz/decoder/_mission.ts create mode 100644 src/idz/encoder/_mission.ts create mode 100644 src/idz/model/mission.ts diff --git a/src/idz/decoder/_mission.ts b/src/idz/decoder/_mission.ts new file mode 100644 index 0000000..3470bf5 --- /dev/null +++ b/src/idz/decoder/_mission.ts @@ -0,0 +1,28 @@ +import { MissionGrid } from "../model/mission"; + +export function mission(buf: Buffer): MissionGrid[] { + const grids = new Array(); + + for (let gridNo = 0; gridNo < 5; gridNo++) { + const grid: MissionGrid = { gridNo, cells: [] }; + + for (let cellNo = 0; cellNo < 9; cellNo++) { + let cell = 0; + let mask = 1 << cellNo; + + for (let sliceNo = 0; sliceNo < 3; sliceNo++) { + const slice = buf.readUInt16LE(0x0c * sliceNo + 0x02 * gridNo); + + if (slice & mask) { + cell |= 1 << sliceNo; + } + } + + grid.cells.push(cell); + } + + grids.push(grid); + } + + return grids; +} diff --git a/src/idz/decoder/saveProfile.ts b/src/idz/decoder/saveProfile.ts index fd6be6c..33deecd 100644 --- a/src/idz/decoder/saveProfile.ts +++ b/src/idz/decoder/saveProfile.ts @@ -1,4 +1,5 @@ import { car } from "./_car"; +import { mission } from "./_mission"; import { RequestCode } from "./_defs"; import { BackgroundCode, Id, TitleCode } from "../model/base"; import { Profile } from "../model/profile"; @@ -45,6 +46,10 @@ export function saveProfile(buf: Buffer): SaveProfileRequest { titles: bitmap(buf.slice(0x0042, 0x00f6)) as TitleCode[], background: buf.readUInt8(0x0750) as BackgroundCode, coursePlays, + missions: { + team: mission(buf.slice(0x03c4, 0x03e6)), + solo: mission(buf.slice(0x0724, 0x0746)), + }, car: car(buf.slice(0x0834, 0x0894)), story: { x: buf.readUInt16LE(0x06fc), diff --git a/src/idz/encoder/_mission.ts b/src/idz/encoder/_mission.ts new file mode 100644 index 0000000..5c64a97 --- /dev/null +++ b/src/idz/encoder/_mission.ts @@ -0,0 +1,26 @@ +import { MissionGrid } from "../model/mission"; + +export function mission(grids: MissionGrid[]): Buffer { + const buf = Buffer.alloc(0x24); + + for (const grid of grids) { + const { gridNo } = grid; + const slices = [0, 0, 0]; + + for (let cellNo = 0; cellNo < 9 && cellNo < grid.cells.length; cellNo++) { + const value = grid.cells[cellNo]; + + for (let sliceNo = 0; sliceNo < 3; sliceNo++) { + if (value & (1 << sliceNo)) { + slices[sliceNo] |= 1 << cellNo; + } + } + } + + for (let sliceNo = 0; sliceNo < 3; sliceNo++) { + buf.writeUInt16LE(slices[sliceNo], 0x0c * sliceNo + 0x02 * gridNo); + } + } + + return buf; +} diff --git a/src/idz/encoder/loadProfile2.ts b/src/idz/encoder/loadProfile2.ts index 7b9d503..4b5a70e 100644 --- a/src/idz/encoder/loadProfile2.ts +++ b/src/idz/encoder/loadProfile2.ts @@ -3,6 +3,7 @@ import iconv = require("iconv-lite"); import { bitmap } from "./_bitmap"; import { car } from "./_car"; import { chara } from "./_chara"; +import { mission } from "./_mission"; import { LoadProfileResponse2 } from "../response/loadProfile2"; export function loadProfile2(res: LoadProfileResponse2) { @@ -36,6 +37,7 @@ export function loadProfile2(res: LoadProfileResponse2) { } buf.writeUInt16LE(0x0065, 0x0000); + mission(res.missions.team).copy(buf, 0x038a); buf.writeUInt32LE(res.profileId, 0x03b8); buf.writeUInt16LE(res.settings.bgMusic, 0x03c8); buf.writeUInt16LE(res.lv, 0x03cc); @@ -46,6 +48,7 @@ export function loadProfile2(res: LoadProfileResponse2) { iconv.encode(res.name + "\0", "shift_jis").copy(buf, 0x03ee); buf.writeUInt16LE(res.story.x, 0x06bc); buf.writeUInt8(res.story.y, 0x0670); + mission(res.missions.solo).copy(buf, 0x06e4); chara(res.chara).copy(buf, 0x070c); bitmap(res.titles, 0xb4).copy(buf, 0x720); buf.writeInt32LE(res.teamId || 0, 0x07e0); diff --git a/src/idz/handler/createProfile.ts b/src/idz/handler/createProfile.ts index daf99ab..63347f4 100644 --- a/src/idz/handler/createProfile.ts +++ b/src/idz/handler/createProfile.ts @@ -1,4 +1,5 @@ import { Id } from "../model/base"; +import { MissionState } from "../model/mission"; import { Profile } from "../model/profile"; import { Settings } from "../model/settings"; import { Story } from "../model/story"; @@ -21,6 +22,11 @@ export async function createProfile( dpoint: 0, }; + const missions: MissionState = { + team: [], + solo: [], + }; + const settings: Settings = { bgMusic: 0, forceQuitEn: false, @@ -39,6 +45,7 @@ export async function createProfile( w.profile().save(profile.id, profile), w.chara().save(profile.id, req.chara), w.car().save(profile.id, req.car), + w.missions().save(profile.id, missions), w.settings().save(profile.id, settings), ]); diff --git a/src/idz/handler/loadProfile.ts b/src/idz/handler/loadProfile.ts index 061637b..358e8ae 100644 --- a/src/idz/handler/loadProfile.ts +++ b/src/idz/handler/loadProfile.ts @@ -14,6 +14,7 @@ export async function loadProfile( const chara = await w.chara().load(profile.id); const titles = await w.titles().load(profile.id); const coursePlays = await w.coursePlays().load(profile.id); + const missions = await w.missions().load(profile.id); const car = await w.car().load(profile.id); const story = await w.story().load(profile.id); @@ -30,6 +31,7 @@ export async function loadProfile( chara, titles, coursePlays, + missions, car, story, }; diff --git a/src/idz/handler/saveProfile.ts b/src/idz/handler/saveProfile.ts index e309e5b..c91a809 100644 --- a/src/idz/handler/saveProfile.ts +++ b/src/idz/handler/saveProfile.ts @@ -24,6 +24,7 @@ export async function saveProfile( }), w.car().save(req.profileId, req.car), w.coursePlays().save(req.profileId, req.coursePlays), + w.missions().save(req.profileId, req.missions), w.story().save(req.profileId, req.story), w.titles().save(req.profileId, req.titles), ]); diff --git a/src/idz/model/index.ts b/src/idz/model/index.ts index ef19a1c..71d7304 100644 --- a/src/idz/model/index.ts +++ b/src/idz/model/index.ts @@ -1,6 +1,7 @@ export { AimeId, BackgroundCode, Id, TitleCode } from "./base"; export { Car } from "./car"; export { Chara } from "./chara"; +export { MissionState, MissionGrid } from "./mission"; export { Profile } from "./profile"; export { Settings } from "./settings"; export { Story } from "./story"; diff --git a/src/idz/model/mission.ts b/src/idz/model/mission.ts new file mode 100644 index 0000000..61f5fe6 --- /dev/null +++ b/src/idz/model/mission.ts @@ -0,0 +1,9 @@ +export interface MissionGrid { + gridNo: number; + cells: number[]; +} + +export interface MissionState { + team: MissionGrid[]; + solo: MissionGrid[]; +} diff --git a/src/idz/request/saveProfile.ts b/src/idz/request/saveProfile.ts index aefbf4d..8564606 100644 --- a/src/idz/request/saveProfile.ts +++ b/src/idz/request/saveProfile.ts @@ -1,5 +1,6 @@ import { BackgroundCode, Id, TitleCode } from "../model/base"; import { Car } from "../model/car"; +import { MissionState } from "../model/mission"; import { Profile } from "../model/profile"; import { Story } from "../model/story"; @@ -14,6 +15,7 @@ export interface SaveProfileRequest { titles: TitleCode[]; background: BackgroundCode; coursePlays: number[]; + missions: MissionState; car: Car; story: Story; } diff --git a/src/idz/response/loadProfile2.ts b/src/idz/response/loadProfile2.ts index 5bfa354..19691c4 100644 --- a/src/idz/response/loadProfile2.ts +++ b/src/idz/response/loadProfile2.ts @@ -1,6 +1,7 @@ import { Id, TitleCode } from "../model/base"; import { Car } from "../model/car"; import { Chara } from "../model/chara"; +import { MissionState } from "../model/mission"; import { Profile } from "../model/profile"; import { Settings } from "../model/settings"; import { Story } from "../model/story"; @@ -18,6 +19,7 @@ export interface LoadProfileResponse2 { chara: Chara; titles: TitleCode[]; coursePlays: number[]; + missions: MissionState; car: Car; story: Story; // giga TODO diff --git a/src/idz/world/base.ts b/src/idz/world/base.ts index 2e00492..bffcc7c 100644 --- a/src/idz/world/base.ts +++ b/src/idz/world/base.ts @@ -23,6 +23,8 @@ export interface World { coursePlays(): Repository; + missions(): Repository; + profile(): ProfileRepository; settings(): Repository; diff --git a/src/idz/world/index.ts b/src/idz/world/index.ts index aa15327..fa7cbb7 100644 --- a/src/idz/world/index.ts +++ b/src/idz/world/index.ts @@ -39,6 +39,13 @@ class WorldImpl implements World { ); } + missions() { + return new SingletonJsonRepo( + this._root, + "missions" + ); + } + profile() { return new ProfileRepositoryImpl(this._root); }