diff --git a/src/types.ts b/src/types.ts index 64d56214..6f17625b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -12,10 +12,17 @@ export interface PlayerType { playerIndex: number; port: number; characterId: number | null; - characterColor: number | null; - startStocks: number | null; type: number | null; + startStocks: number | null; + characterColor: number | null; + teamShade: number | null; + handicap: number | null; teamId: number | null; + playerBitfield: number | null; + cpuLevel: number | null; + offenseRatio: number | null; + defenseRatio: number | null; + modelScale: number | null; controllerFix: string | null; nametag: string | null; displayName: string; @@ -30,11 +37,34 @@ export enum GameMode { export interface GameStartType { slpVersion: string | null; isTeams: boolean | null; + gameInfo: GameInfo | null; isPAL: boolean | null; stageId: number | null; players: PlayerType[]; scene: number | null; gameMode: GameMode | null; + randomSeed: number | null; + isFrozenPS: boolean | null; + minorScene: number | null; + majorScene: number | null; +} + +export interface GameInfo { + gameBitfield1: number | null; + gameBitfield2: number | null; + gameBitfield3: number | null; + gameBitfield4: number | null; + bombRain: boolean | null; + itemSpawnBehavior: number | null; + selfDestructScoreValue: number | null; + stageId: number | null; + gameTimer: number | null; + itemSpawnBitfield1: number | null; + itemSpawnBitfield2: number | null; + itemSpawnBitfield3: number | null; + itemSpawnBitfield4: number | null; + itemSpawnBitfield5: number | null; + damageRatio: number | null; } export interface PreFrameUpdateType { diff --git a/src/utils/slpReader.ts b/src/utils/slpReader.ts index de24e680..d1401194 100644 --- a/src/utils/slpReader.ts +++ b/src/utils/slpReader.ts @@ -3,7 +3,14 @@ import fs from "fs"; import iconv from "iconv-lite"; import _ from "lodash"; -import type { EventCallbackFunc, EventPayloadTypes, MetadataType, PlayerType, SelfInducedSpeedsType } from "../types"; +import type { + EventCallbackFunc, + EventPayloadTypes, + GameInfo, + MetadataType, + PlayerType, + SelfInducedSpeedsType, +} from "../types"; import { Command } from "../types"; import { toHalfwidth } from "./fullwidth"; @@ -295,16 +302,46 @@ export function parseMessage(command: Command, payload: Uint8Array): EventPayloa playerIndex: playerIndex, port: playerIndex + 1, characterId: readUint8(view, 0x65 + offset), - characterColor: readUint8(view, 0x68 + offset), - startStocks: readUint8(view, 0x67 + offset), type: readUint8(view, 0x66 + offset), + startStocks: readUint8(view, 0x67 + offset), + characterColor: readUint8(view, 0x68 + offset), + teamShade: readUint8(view, 0x6c + offset), + handicap: readUint8(view, 0x6d + offset), teamId: readUint8(view, 0x6e + offset), + playerBitfield: readUint8(view, 0x71 + offset), + cpuLevel: readUint8(view, 0x74 + offset), + offenseRatio: readFloat(view, 0x7d + offset), + defenseRatio: readFloat(view, 0x81 + offset), + modelScale: readFloat(view, 0x85 + offset), controllerFix: cfOption, nametag: nametag, displayName: displayName, connectCode: connectCode, }; }; + + const getGameInfoBlock = (): GameInfo => { + const offset = 0x5; + + return { + gameBitfield1: readUint8(view, 0x0 + offset), + gameBitfield2: readUint8(view, 0x1 + offset), + gameBitfield3: readUint8(view, 0x2 + offset), + gameBitfield4: readUint8(view, 0x3 + offset), + bombRain: (readUint8(view, 0x6 + offset)! & 0xff) > 0 ? true : false, + itemSpawnBehavior: readInt8(view, 0xb + offset), + selfDestructScoreValue: readInt8(view, 0xc + offset), + stageId: readUint16(view, 0xe + offset), + gameTimer: readUint32(view, 0x10 + offset), + itemSpawnBitfield1: readUint8(view, 0x23 + offset), + itemSpawnBitfield2: readUint8(view, 0x24 + offset), + itemSpawnBitfield3: readUint8(view, 0x25 + offset), + itemSpawnBitfield4: readUint8(view, 0x26 + offset), + itemSpawnBitfield5: readUint8(view, 0x27 + offset), + damageRatio: readFloat(view, 0x30 + offset), + }; + }; + return { slpVersion: `${readUint8(view, 0x1)}.${readUint8(view, 0x2)}.${readUint8(view, 0x3)}`, isTeams: readBool(view, 0xd), @@ -313,6 +350,11 @@ export function parseMessage(command: Command, payload: Uint8Array): EventPayloa players: [0, 1, 2, 3].map(getPlayerObject), scene: readUint8(view, 0x1a3), gameMode: readUint8(view, 0x1a4), + gameInfo: getGameInfoBlock(), + randomSeed: readUint32(view, 0x13d), + isFrozenPS: readBool(view, 0x1a2), + minorScene: readUint8(view, 0x1a3), + majorScene: readUint8(view, 0x1a4), }; case Command.PRE_FRAME_UPDATE: return {