Files
bd2/go/internal/server/gamedata/event_tasks.go
T

237 lines
6.8 KiB
Go

package gamedata
import (
"database/sql"
"fmt"
"sort"
)
type EventAttendance struct{ ID, Group, Ticket uint64 }
type EventAttendanceGroup struct{ Group, ID, Next uint64 }
type EventAttendanceReward struct {
Group, ID, Day uint64
Basic, Premium Reward
}
type EventMissionGroup struct {
ID, Type, ScheduleType, UsePass, CompleteHide uint64
Groups []uint64
}
type EventTask struct {
ID, Group, Type, SubType, Target, PassExp, UnlockPack, UnlockQuest uint64
Params []uint64
Rewards []Reward
}
type EventPass struct {
ID, MissionGroup, LevelGroup, Type, ScheduleType, NewbieGroup, NewbieStep uint64
Core Reward
}
type EventPassLevel struct {
ID, NeedExp, PremiumType uint64
Basic, Premium Reward
}
type EventPassBuy struct {
ID, Type, CashGroup, CashID, CashSales uint64
// PassBuyTable.UnlockLevel is the number of levels granted by a purchase.
// LocalText 2403 displays it as "Pass Level +{0}", not a prerequisite.
LevelsGranted uint64
Cost Reward
Rewards []Reward
}
type EventTasksDesign struct {
Attendance map[uint64]EventAttendance
AttendanceGroups map[[2]uint64]EventAttendanceGroup
AttendanceRewards map[uint64][]EventAttendanceReward
LimitRewards map[[2]uint64]uint64
MissionGroups map[uint64]EventMissionGroup
Missions map[uint64]EventTask
Passes map[uint64]EventPass
PassLevels map[uint64][]EventPassLevel
PassBuys map[uint64][]EventPassBuy
}
func LoadEventTasksDesign(root, version string) (*EventTasksDesign, error) {
db, done, e := openStatDatabase(root, version)
if e != nil {
return nil, e
}
defer done()
return loadEventTasksDesign(db)
}
func loadEventTasksDesign(db *sql.DB) (*EventTasksDesign, error) {
d := &EventTasksDesign{Attendance: map[uint64]EventAttendance{}, AttendanceGroups: map[[2]uint64]EventAttendanceGroup{}, AttendanceRewards: map[uint64][]EventAttendanceReward{}, LimitRewards: map[[2]uint64]uint64{}, MissionGroups: map[uint64]EventMissionGroup{}, Missions: map[uint64]EventTask{}, Passes: map[uint64]EventPass{}, PassLevels: map[uint64][]EventPassLevel{}, PassBuys: map[uint64][]EventPassBuy{}}
each := func(table string, fn func([]byte) error) error {
rows, e := db.Query("SELECT ProtoBuf FROM " + table)
if e != nil {
return e
}
defer rows.Close()
for rows.Next() {
var p []byte
if e = rows.Scan(&p); e != nil {
return e
}
if e = fn(p); e != nil {
return fmt.Errorf("gamedata: %s: %w", table, e)
}
}
return rows.Err()
}
scalar := func(p []byte, n int) (uint64, error) { return optionalScalar(p, n) }
read := func(p []byte, m map[int]*uint64) error {
for n, target := range m {
v, e := scalar(p, n)
if e != nil {
return e
}
*target = v
}
return nil
}
reward := func(p []byte, t, i, c int) (Reward, error) {
r := Reward{}
e := read(p, map[int]*uint64{t: &r.Type, i: &r.ID, c: &r.Count})
return r, e
}
if e := each("AttendanceAlwaysTable", func(p []byte) error {
r := EventAttendance{}
e := read(p, map[int]*uint64{3: &r.ID, 1: &r.Group, 2: &r.Ticket})
d.Attendance[r.ID] = r
return e
}); e != nil {
return nil, e
}
if e := each("AttendanceAlwaysGroupTable", func(p []byte) error {
r := EventAttendanceGroup{}
e := read(p, map[int]*uint64{1: &r.Group, 2: &r.ID, 3: &r.Next})
d.AttendanceGroups[[2]uint64{r.Group, r.ID}] = r
return e
}); e != nil {
return nil, e
}
if e := each("AttendanceAlwaysRewardTable", func(p []byte) error {
r := EventAttendanceReward{}
if e := read(p, map[int]*uint64{2: &r.Group, 3: &r.ID, 1: &r.Day}); e != nil {
return e
}
var e error
r.Basic, e = reward(p, 9, 8, 7)
if e != nil {
return e
}
r.Premium, e = reward(p, 6, 5, 4)
d.AttendanceRewards[r.Group] = append(d.AttendanceRewards[r.Group], r)
return e
}); e != nil {
return nil, e
}
if e := each("AttendanceLimitRewardTable", func(p []byte) error {
var g, i, b uint64
e := read(p, map[int]*uint64{1: &g, 2: &i, 3: &b})
d.LimitRewards[[2]uint64{g, i}] = b
return e
}); e != nil {
return nil, e
}
if e := each("EventMissionGroupTable", func(p []byte) error {
r := EventMissionGroup{}
if e := read(p, map[int]*uint64{5: &r.ID, 1: &r.Type, 8: &r.ScheduleType, 10: &r.UsePass, 6: &r.CompleteHide}); e != nil {
return e
}
var e error
r.Groups, e = packedInts(p, 7)
d.MissionGroups[r.ID] = r
return e
}); e != nil {
return nil, e
}
if e := each("MissionTable", func(p []byte) error {
g, e := scalar(p, 7)
if e != nil {
return e
}
if g != 2 {
return nil
}
r := EventTask{}
if e = read(p, map[int]*uint64{8: &r.ID, 6: &r.Group, 3: &r.Type, 1: &r.SubType, 4: &r.Target, 12: &r.PassExp, 19: &r.UnlockPack, 20: &r.UnlockQuest}); e != nil {
return e
}
r.Params, e = packedInts(p, 2)
if e != nil {
return e
}
v, e := reward(p, 15, 14, 13)
if e != nil {
return e
}
if v.Type > 0 && v.Count > 0 {
r.Rewards = []Reward{v}
}
d.Missions[r.ID] = r
return nil
}); e != nil {
return nil, e
}
if e := each("PassTable", func(p []byte) error {
r := EventPass{}
if e := read(p, map[int]*uint64{6: &r.ID, 5: &r.MissionGroup, 11: &r.LevelGroup, 13: &r.Type, 15: &r.ScheduleType, 9: &r.NewbieGroup, 10: &r.NewbieStep}); e != nil {
return e
}
var e error
r.Core, e = reward(p, 4, 3, 2)
d.Passes[r.ID] = r
return e
}); e != nil {
return nil, e
}
if e := each("PassLevelTable", func(p []byte) error {
r := EventPassLevel{}
var g uint64
if e := read(p, map[int]*uint64{4: &g, 5: &r.ID, 6: &r.NeedExp, 10: &r.PremiumType}); e != nil {
return e
}
var e error
r.Basic, e = reward(p, 3, 2, 1)
if e != nil {
return e
}
r.Premium, e = reward(p, 9, 8, 7)
d.PassLevels[g] = append(d.PassLevels[g], r)
return e
}); e != nil {
return nil, e
}
if e := each("PassBuyTable", func(p []byte) error {
r := EventPassBuy{}
var g uint64
if e := read(p, map[int]*uint64{7: &g, 8: &r.ID, 12: &r.Type, 13: &r.LevelsGranted, 4: &r.CashGroup, 5: &r.CashID, 6: &r.CashSales}); e != nil {
return e
}
var e error
r.Cost, e = reward(p, 3, 2, 1)
if e != nil {
return e
}
rs, e := monsterHuntRewardArrays(p, 11, 10, 9)
if e != nil {
return e
}
for _, v := range rs {
r.Rewards = append(r.Rewards, Reward{v.Type, v.ID, v.Count})
}
d.PassBuys[g] = append(d.PassBuys[g], r)
return nil
}); e != nil {
return nil, e
}
for g, rs := range d.AttendanceRewards {
sort.Slice(rs, func(i, j int) bool { return rs[i].ID < rs[j].ID })
d.AttendanceRewards[g] = rs
}
for g, rs := range d.PassLevels {
sort.Slice(rs, func(i, j int) bool { return rs[i].ID < rs[j].ID })
d.PassLevels[g] = rs
}
return d, nil
}