Files
bd2/go/internal/server/gamedata/gacha_character.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

56 lines
1.4 KiB
Go

package gamedata
import (
"database/sql"
"fmt"
)
// Costume ownership refers to a unique character, not a numeric costume ID
// prefix. The initial growth grade is the base character, excluding pack-only
// temporary copies; ambiguous rows are rejected instead of selecting an ID.
func loadCostumeBaseCharacterID(db *sql.DB, costumeID uint64) (uint64, error) {
var raw []byte
if err := db.QueryRow("SELECT ProtoBuf FROM CostumeTable WHERE id=?", costumeID).Scan(&raw); err != nil {
return 0, err
}
unique, err := optionalScalar(raw, 27)
if err != nil || unique == 0 {
return 0, fmt.Errorf("gamedata: costume %d unique character unavailable", costumeID)
}
rows, err := db.Query("SELECT id,ProtoBuf FROM CharTable WHERE uniqueCharId=?", unique)
if err != nil {
return 0, err
}
defer rows.Close()
var result uint64
for rows.Next() {
var id uint64
var row []byte
if err := rows.Scan(&id, &row); err != nil {
return 0, err
}
growth, err := optionalScalar(row, 10)
if err != nil {
return 0, err
}
temporary, err := optionalScalar(row, 21)
if err != nil {
return 0, err
}
if growth != 1 || temporary != 0 {
continue
}
if result != 0 {
return 0, fmt.Errorf("gamedata: costume %d has ambiguous base character", costumeID)
}
result = id
}
if err := rows.Err(); err != nil {
return 0, err
}
if result == 0 {
return 0, fmt.Errorf("gamedata: costume %d has no base character", costumeID)
}
return result, nil
}