chore: checkpoint stable battle and eidolon progression
This commit is contained in:
1 parent
365e66ffe0
commit
a681affdb3
23 files changed
+34511
-11310
No files matched your search
@@ -67,52 +67,55 @@ func init() {
|
||||
|
||||
}
|
||||
|
||||
// handleExRankUnlock handles CmdID 400 (Affinitive Eidolon / Ex-Rank unlock request from client).
|
||||
// The EX request remains obfuscated in PearlSR 005d2c1: field 5 is
|
||||
// interpreted as an avatar, EX-rank or material ID only by an explicit mapping.
|
||||
// Never unlock every avatar when an unknown value is received.
|
||||
func handleExRankUnlock(s *Session, payload []byte) error {
|
||||
Log(fmt.Sprintf("[EX-RANK] Received cmd 400 (len: %d) payload: %x", len(payload), payload))
|
||||
|
||||
var req goproto.HIGLJHLNODG
|
||||
if err := proto.Unmarshal(payload, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
parsedVal := req.OJFIGABCKLG
|
||||
|
||||
value := req.OJFIGABCKLG
|
||||
resources, err := loadEidolonResources()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var avatarID uint32
|
||||
if parsedVal >= 100000 {
|
||||
avatarID = parsedVal / 100 // e.g. 120401 -> 1204, 121301 -> 1213, 130801 -> 1308
|
||||
} else if parsedVal >= 1000 && parsedVal < 10000 {
|
||||
avatarID = parsedVal
|
||||
}
|
||||
|
||||
Log(fmt.Sprintf("[EX-RANK] Target avatarID: %d (from val: %d)", avatarID, parsedVal))
|
||||
|
||||
player := s.JSON()
|
||||
if player != nil {
|
||||
if avatarID == 0 {
|
||||
// Fallback: unlock for all avatars that have ExRank defined (1204, 1213, 1308)
|
||||
for aid := range common.AvatarExRankMap {
|
||||
if av, ok := player.Avatars[aid]; ok {
|
||||
av.ExRankUnlocked = true
|
||||
Log(fmt.Sprintf("[EX-RANK] Fallback set ExRankUnlocked=true for avatar %d", aid))
|
||||
syncNotify := &goproto.PlayerSyncScNotify{}
|
||||
buildSync(player, syncNotify, []uint32{aid}, nil, nil)
|
||||
_ = s.Send(syncNotify)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if av, ok := player.Avatars[avatarID]; ok {
|
||||
av.ExRankUnlocked = true
|
||||
Log(fmt.Sprintf("[EX-RANK] Set ExRankUnlocked=true for avatar %d", avatarID))
|
||||
}
|
||||
syncNotify := &goproto.PlayerSyncScNotify{}
|
||||
buildSync(player, syncNotify, []uint32{avatarID}, nil, nil)
|
||||
_ = s.Send(syncNotify)
|
||||
for id, exID := range common.AvatarExRankMap {
|
||||
if value == id || value == exID || value == resources.ExMaterials[id].ItemID {
|
||||
avatarID = id
|
||||
break
|
||||
}
|
||||
player.SavePersistent()
|
||||
}
|
||||
|
||||
// The matching response is declared by the current upstream schema.
|
||||
return s.Send(&goproto.LPOLGDLAADM{})
|
||||
rsp := &goproto.LPOLGDLAADM{}
|
||||
player := s.JSON()
|
||||
if player == nil || avatarID == 0 || player.Avatars[avatarID] == nil {
|
||||
rsp.Retcode = uint32(goproto.Retcode_RET_AVATAR_NOT_EXIST)
|
||||
Log(fmt.Sprintf("[EX-RANK] rejected unmapped value=%d", value))
|
||||
return s.Send(rsp)
|
||||
}
|
||||
if _, active := CURRENT_BATTLE.Load(s.Token); active {
|
||||
rsp.Retcode = uint32(goproto.Retcode_RET_AVATAR_RANK_NOT_MATCH)
|
||||
return s.Send(rsp)
|
||||
}
|
||||
avatar := player.Avatars[avatarID]
|
||||
previous := avatar.ExRankUnlocked
|
||||
avatar.ExRankUnlocked = true
|
||||
if err := player.SavePersistentChecked(); err != nil {
|
||||
avatar.ExRankUnlocked = previous
|
||||
return err
|
||||
}
|
||||
notify := &goproto.PlayerSyncScNotify{}
|
||||
buildSync(player, notify, []uint32{avatarID}, nil, nil)
|
||||
notify.MaterialList, err = eidolonMaterials(player)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.Send(notify); err != nil {
|
||||
return err
|
||||
}
|
||||
Log(fmt.Sprintf("[EX-RANK] unlocked avatar=%d value=%d", avatarID, value))
|
||||
return s.Send(rsp)
|
||||
}
|
||||
|
||||
// challengeGroupStatsReply uses the current typed statistics response.
|
||||
|
||||
Reference in new issue
Block a user