Implement memoir sub-status system with level-based unlocks

This commit is contained in:
Ilya Groshev
2026-04-22 14:03:26 +03:00
parent 7828de031c
commit 4dc722c5d3
12 changed files with 228 additions and 1 deletions
+1
View File
@@ -30,6 +30,7 @@ func CloneUserState(u UserState) UserState {
out.Parts = maps.Clone(u.Parts)
out.PartsGroupNotes = maps.Clone(u.PartsGroupNotes)
out.PartsPresets = maps.Clone(u.PartsPresets)
out.PartsStatusSubs = maps.Clone(u.PartsStatusSubs)
out.ImportantItems = maps.Clone(u.ImportantItems)
out.CostumeActiveSkills = maps.Clone(u.CostumeActiveSkills)
out.WeaponSkills = cloneSliceMap(u.WeaponSkills)
+1
View File
@@ -129,6 +129,7 @@ func SeedUserState(userId int64, uuid string, nowMillis int64, platform model.Cl
Parts: make(map[string]PartsState),
PartsGroupNotes: make(map[int32]PartsGroupNoteState),
PartsPresets: make(map[int32]PartsPresetState),
PartsStatusSubs: make(map[PartsStatusSubKey]PartsStatusSubState),
ImportantItems: make(map[int32]int32),
CostumeActiveSkills: make(map[string]CostumeActiveSkillState),
WeaponSkills: make(map[string][]WeaponSkillState),
+11
View File
@@ -60,6 +60,7 @@ func initMaps(u *store.UserState) {
u.Parts = make(map[string]store.PartsState)
u.PartsGroupNotes = make(map[int32]store.PartsGroupNoteState)
u.PartsPresets = make(map[int32]store.PartsPresetState)
u.PartsStatusSubs = make(map[store.PartsStatusSubKey]store.PartsStatusSubState)
u.DeckTypeNotes = make(map[model.DeckType]store.DeckTypeNoteState)
u.ConsumableItems = make(map[int32]int32)
u.Materials = make(map[int32]int32)
@@ -453,6 +454,16 @@ func loadMapTables(db *sql.DB, uid int64, u *store.UserState) {
u.PartsPresets[v.UserPartsPresetNumber] = v
})
queryRows(db, `SELECT user_parts_uuid, status_index, parts_status_sub_lottery_id, level,
status_kind_type, status_calculation_type, status_change_value, latest_version
FROM user_parts_status_subs WHERE user_id=?`, uid,
func(rows *sql.Rows) {
var v store.PartsStatusSubState
rows.Scan(&v.UserPartsUuid, &v.StatusIndex, &v.PartsStatusSubLotteryId, &v.Level,
&v.StatusKindType, &v.StatusCalculationType, &v.StatusChangeValue, &v.LatestVersion)
u.PartsStatusSubs[store.PartsStatusSubKey{UserPartsUuid: v.UserPartsUuid, StatusIndex: v.StatusIndex}] = v
})
queryRows(db, `SELECT deck_type, max_deck_power, latest_version FROM user_deck_type_notes WHERE user_id=?`, uid,
func(rows *sql.Rows) {
var dt int32
+18
View File
@@ -290,6 +290,12 @@ func writeUserState(tx *sql.Tx, uid int64, u *store.UserState) error {
return err
}
}
for _, v := range u.PartsStatusSubs {
if err := exec(`INSERT INTO user_parts_status_subs (user_id, user_parts_uuid, status_index, parts_status_sub_lottery_id, level, status_kind_type, status_calculation_type, status_change_value, latest_version) VALUES (?,?,?,?,?,?,?,?,?)`,
uid, v.UserPartsUuid, v.StatusIndex, v.PartsStatusSubLotteryId, v.Level, v.StatusKindType, v.StatusCalculationType, v.StatusChangeValue, v.LatestVersion); err != nil {
return err
}
}
for _, v := range u.DeckTypeNotes {
if err := exec(`INSERT INTO user_deck_type_notes (user_id, deck_type, max_deck_power, latest_version) VALUES (?,?,?,?)`,
uid, int32(v.DeckType), v.MaxDeckPower, v.LatestVersion); err != nil {
@@ -808,6 +814,18 @@ func diffAndSave(tx *sql.Tx, uid int64, before, after *store.UserState) error {
return []any{v.UserPartsPresetNumber, v.UserPartsUuid01, v.UserPartsUuid02, v.UserPartsUuid03, v.Name, v.UserPartsPresetTagNumber, v.LatestVersion}
}, "user_parts_preset_number, user_parts_uuid01, user_parts_uuid02, user_parts_uuid03, name, user_parts_preset_tag_number, latest_version")
for k, v := range after.PartsStatusSubs {
if old, ok := before.PartsStatusSubs[k]; !ok || old != v {
exec(`INSERT OR REPLACE INTO user_parts_status_subs (user_id, user_parts_uuid, status_index, parts_status_sub_lottery_id, level, status_kind_type, status_calculation_type, status_change_value, latest_version) VALUES (?,?,?,?,?,?,?,?,?)`,
uid, k.UserPartsUuid, k.StatusIndex, v.PartsStatusSubLotteryId, v.Level, v.StatusKindType, v.StatusCalculationType, v.StatusChangeValue, v.LatestVersion)
}
}
for k := range before.PartsStatusSubs {
if _, ok := after.PartsStatusSubs[k]; !ok {
exec(`DELETE FROM user_parts_status_subs WHERE user_id=? AND user_parts_uuid=? AND status_index=?`, uid, k.UserPartsUuid, k.StatusIndex)
}
}
// Deck type notes (key is model.DeckType which is int32-based)
for k, v := range after.DeckTypeNotes {
if old, ok := before.DeckTypeNotes[k]; !ok || old != v {
+1
View File
@@ -123,6 +123,7 @@ func (s *SQLiteStore) ImportUser(u *store.UserState) error {
"user_deck_sub_weapons",
"user_decks",
"user_deck_characters",
"user_parts_status_subs",
"user_parts_presets",
"user_parts_group_notes",
"user_parts",
+20
View File
@@ -80,6 +80,7 @@ type UserState struct {
Parts map[string]PartsState
PartsGroupNotes map[int32]PartsGroupNoteState
PartsPresets map[int32]PartsPresetState
PartsStatusSubs map[PartsStatusSubKey]PartsStatusSubState
ImportantItems map[int32]int32
CostumeActiveSkills map[string]CostumeActiveSkillState
WeaponSkills map[string][]WeaponSkillState // key: userWeaponUuid
@@ -197,6 +198,9 @@ func (u *UserState) EnsureMaps() {
if u.PartsPresets == nil {
u.PartsPresets = make(map[int32]PartsPresetState)
}
if u.PartsStatusSubs == nil {
u.PartsStatusSubs = make(map[PartsStatusSubKey]PartsStatusSubState)
}
if u.ImportantItems == nil {
u.ImportantItems = make(map[int32]int32)
}
@@ -833,6 +837,22 @@ type PartsPresetState struct {
LatestVersion int64
}
type PartsStatusSubKey struct {
UserPartsUuid string
StatusIndex int32
}
type PartsStatusSubState struct {
UserPartsUuid string
StatusIndex int32
PartsStatusSubLotteryId int32
Level int32
StatusKindType int32
StatusCalculationType int32
StatusChangeValue int32
LatestVersion int64
}
type NotificationState struct {
GiftNotReceiveCount int32
FriendRequestReceiveCount int32