Android build v1.0.34
This commit is contained in:
+51
-30
@@ -103,6 +103,7 @@ const offlineSaveKey = 'chronicle.offlineSave.v1'
|
||||
const onlineCacheKey = 'chronicle.onlineCache.v1'
|
||||
const authTokenKey = 'chronicle.authToken.v1'
|
||||
const offlineAccount = { id: -1, username: 'Offline' }
|
||||
const ABILITY_SLOT_COUNT = 6
|
||||
|
||||
function clone<T>(value: T): T {
|
||||
return structuredClone(value)
|
||||
@@ -147,7 +148,7 @@ function upgradeV1Save(v1: { profile: CharacterProfile; lootRolls: Record<string
|
||||
level: cid === p.character.classId ? p.character.level : 1,
|
||||
experience: cid === p.character.classId ? p.character.experience : 0,
|
||||
talentPoints: cid === p.character.classId ? p.character.talentPoints : 1,
|
||||
abilitySlots: cid === p.character.classId ? [...p.abilitySlots] : [],
|
||||
abilitySlots: cid === p.character.classId ? normalizeAbilitySlots(p.abilitySlots) : [],
|
||||
talentRanks,
|
||||
inventory: cid === p.character.classId ? clone(p.inventory) : [],
|
||||
}
|
||||
@@ -164,11 +165,32 @@ function upgradeV1Save(v1: { profile: CharacterProfile; lootRolls: Record<string
|
||||
}
|
||||
|
||||
function upgradeV2Save(v2: Omit<OfflineSave, 'version' | 'completedRaidPhases'> & { version: 2 }): OfflineSave {
|
||||
return {
|
||||
return normalizeSaveAbilitySlots({
|
||||
...v2,
|
||||
version: 3,
|
||||
completedRaidPhases: 0,
|
||||
})
|
||||
}
|
||||
|
||||
function normalizeAbilitySlots(abilitySlots: unknown): Array<number | null> {
|
||||
const slots = Array.isArray(abilitySlots)
|
||||
? abilitySlots
|
||||
.slice(0, ABILITY_SLOT_COUNT)
|
||||
.map((value) => {
|
||||
if (value === null || value === undefined) return null
|
||||
const id = Number(value)
|
||||
return Number.isInteger(id) ? id : null
|
||||
})
|
||||
: []
|
||||
while (slots.length < ABILITY_SLOT_COUNT) slots.push(null)
|
||||
return slots
|
||||
}
|
||||
|
||||
function normalizeSaveAbilitySlots(save: OfflineSave): OfflineSave {
|
||||
for (const character of Object.values(save.characters)) {
|
||||
character.abilitySlots = normalizeAbilitySlots(character.abilitySlots)
|
||||
}
|
||||
return save
|
||||
}
|
||||
|
||||
function normalizeOfflineSave(raw: unknown): OfflineSave | null {
|
||||
@@ -178,12 +200,12 @@ function normalizeOfflineSave(raw: unknown): OfflineSave | null {
|
||||
profile?: CharacterProfile
|
||||
lootRolls?: Record<string, LootRoll>
|
||||
}
|
||||
if (candidate.version === 3) return candidate as OfflineSave
|
||||
if (candidate.version === 3) return normalizeSaveAbilitySlots(candidate as OfflineSave)
|
||||
if (candidate.version === 2) {
|
||||
return upgradeV2Save(candidate as Omit<OfflineSave, 'version' | 'completedRaidPhases'> & { version: 2 })
|
||||
}
|
||||
if (candidate.version === 1 && candidate.profile) {
|
||||
return upgradeV1Save(candidate as { profile: CharacterProfile; lootRolls: Record<string, LootRoll> })
|
||||
return normalizeSaveAbilitySlots(upgradeV1Save(candidate as { profile: CharacterProfile; lootRolls: Record<string, LootRoll> }))
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -448,7 +470,7 @@ function mergeProfileIntoSave(profile: CharacterProfile, existingSave?: OfflineS
|
||||
level: profile.character.level,
|
||||
experience: profile.character.experience,
|
||||
talentPoints: profile.character.talentPoints,
|
||||
abilitySlots: [...profile.abilitySlots],
|
||||
abilitySlots: normalizeAbilitySlots(profile.abilitySlots),
|
||||
talentRanks,
|
||||
inventory: clone(profile.inventory),
|
||||
}
|
||||
@@ -787,9 +809,9 @@ function emptyCharacterData(classId: number): CharacterData {
|
||||
const inventory: Item[] = []
|
||||
const startingAbilitySlots: Array<number | null> = gc.spells
|
||||
.filter((s) => s.unlockLevel === 1)
|
||||
.slice(0, 5)
|
||||
.slice(0, ABILITY_SLOT_COUNT)
|
||||
.map((s) => s.id)
|
||||
while (startingAbilitySlots.length < 6) startingAbilitySlots.push(null)
|
||||
while (startingAbilitySlots.length < ABILITY_SLOT_COUNT) startingAbilitySlots.push(null)
|
||||
return {
|
||||
level: 1,
|
||||
experience: 0,
|
||||
@@ -829,31 +851,30 @@ function createLocalRepository(store: LocalSaveStore): GameRepository {
|
||||
},
|
||||
async saveProfile(classId, abilitySlots) {
|
||||
const save = requireStoredSave(store)
|
||||
const static_ = clone(starterProfile) as CharacterProfile
|
||||
const gameClass = static_.classes.find((candidate) => candidate.id === classId)
|
||||
if (!gameClass) throw new Error('Selected class does not exist.')
|
||||
const static_ = clone(starterProfile) as CharacterProfile
|
||||
const gameClass = static_.classes.find((candidate) => candidate.id === classId)
|
||||
if (!gameClass) throw new Error('Selected class does not exist.')
|
||||
|
||||
const slots = abilitySlots.slice(0, 6)
|
||||
while (slots.length < 6) slots.push(null)
|
||||
const selectedIds = slots.filter((id): id is number => id !== null)
|
||||
if (new Set(selectedIds).size !== selectedIds.length) {
|
||||
throw new Error('The same ability cannot be equipped twice.')
|
||||
}
|
||||
const activeChar = save.characters[save.activeClassId]
|
||||
const validIds = new Set(
|
||||
gameClass.spells
|
||||
.filter((spell) => spell.unlockLevel <= activeChar.level)
|
||||
.map((spell) => spell.id),
|
||||
)
|
||||
if (selectedIds.some((id) => !validIds.has(id))) {
|
||||
throw new Error('One or more abilities are locked or belong to another class.')
|
||||
}
|
||||
const slots = normalizeAbilitySlots(abilitySlots)
|
||||
const selectedIds = slots.filter((id): id is number => id !== null)
|
||||
if (new Set(selectedIds).size !== selectedIds.length) {
|
||||
throw new Error('The same ability cannot be equipped twice.')
|
||||
}
|
||||
const activeChar = save.characters[save.activeClassId]
|
||||
const validIds = new Set(
|
||||
gameClass.spells
|
||||
.filter((spell) => spell.unlockLevel <= activeChar.level)
|
||||
.map((spell) => spell.id),
|
||||
)
|
||||
if (selectedIds.some((id) => !validIds.has(id))) {
|
||||
throw new Error('One or more abilities are locked or belong to another class.')
|
||||
}
|
||||
|
||||
if (!save.characters[classId]) {
|
||||
save.characters[classId] = emptyCharacterData(classId)
|
||||
}
|
||||
save.characters[classId].abilitySlots = slots
|
||||
save.activeClassId = classId
|
||||
if (!save.characters[classId]) {
|
||||
save.characters[classId] = emptyCharacterData(classId)
|
||||
}
|
||||
save.characters[classId].abilitySlots = slots
|
||||
save.activeClassId = classId
|
||||
store.writeSave(save)
|
||||
return buildProfile(save)
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user