Files
bd2/go/internal/server/gamedata/immortal.go
T
Flechazo 5b5a219dc2 feat(server): add special loot and data-driven gameplay rules
Generate equipment loot atomically, grant random boxes and prevent repeat claims.
Read gacha pools, pity, products, tickets, missions, presets, chapter rewards
and inventory costs from GameData; extend both collaboration UR ticket pools.
Sync owned recipes, configure startup state and calendars in versioned seeds,
and validate unlock tickets and revival talents.
2026-10-04 19:15:59 +08:00

99 lines
2.3 KiB
Go

package gamedata
import "fmt"
// ImmortalDesign resolves exactly the current character talent and skill level.
// Full restoration is evidenced for value 10000; other values require official
// server evidence of their rounding/scaling semantics before being enabled.
type ImmortalDesign struct {
Characters map[uint64]uint64
FullRestore map[[2]uint64]bool
}
func LoadImmortalDesign(root, version string) (*ImmortalDesign, error) {
db, closeDB, err := openStatDatabase(root, version)
if err != nil {
return nil, err
}
defer closeDB()
d := &ImmortalDesign{Characters: map[uint64]uint64{}, FullRestore: map[[2]uint64]bool{}}
talents := map[uint64]uint64{}
rows, err := db.Query("SELECT id,ProtoBuf FROM TalentTable")
if err != nil {
return nil, err
}
for rows.Next() {
var id uint64
var raw []byte
if err := rows.Scan(&id, &raw); err != nil {
rows.Close()
return nil, err
}
group, err := optionalScalar(raw, 18)
if err != nil {
rows.Close()
return nil, err
}
talents[id] = group
}
if err := rows.Err(); err != nil {
rows.Close()
return nil, err
}
rows.Close()
rows, err = db.Query("SELECT id,ProtoBuf FROM CharTable")
if err != nil {
return nil, err
}
for rows.Next() {
var id uint64
var raw []byte
if err := rows.Scan(&id, &raw); err != nil {
rows.Close()
return nil, err
}
talent, err := optionalScalar(raw, 18)
if err != nil {
rows.Close()
return nil, err
}
if group := talents[talent]; group != 0 {
d.Characters[id] = group
}
}
if err := rows.Err(); err != nil {
rows.Close()
return nil, err
}
rows.Close()
rows, err = db.Query("SELECT groupId,id,ProtoBuf FROM TalentSkillTable")
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var group, level uint64
var raw []byte
if err := rows.Scan(&group, &level, &raw); err != nil {
return nil, err
}
class, err := optionalScalar(raw, 2)
if err != nil {
return nil, err
}
if class != 14 {
continue
}
values, err := fixed32Floats(raw, 14)
if err != nil || len(values) == 0 {
return nil, fmt.Errorf("gamedata: immortal skill missing value")
}
d.FullRestore[[2]uint64{group, level}] = values[0] == 10000
}
return d, rows.Err()
}
func (d *ImmortalDesign) CanRestore(characterID, level uint64) bool {
return d != nil && d.FullRestore[[2]uint64{d.Characters[characterID], level}]
}