feat(all): implement SkyWay progression, battles and dispatch; fix field reward position ordering
This commit is contained in:
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
type DispatchDesign struct {
|
||||
Group, ID, Pack, Difficulty, TypeGroup, TypeID, AP, ClearTime, Growth uint64
|
||||
GroundID uint64
|
||||
GroundID, APType uint64
|
||||
Rewards []BattleReward
|
||||
boxes map[uint64]*dispatchGroup
|
||||
}
|
||||
@@ -63,6 +63,7 @@ func LoadDispatchDesign(root, version string, group, id uint64) (*DispatchDesign
|
||||
}
|
||||
ids, err = packedInts(raw, 15)
|
||||
boss, _ = optionalScalar(raw, 4)
|
||||
d.APType, _ = optionalScalar(raw, 1)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -47,7 +47,7 @@ func loadFieldPacks(db *sql.DB) (map[int]FieldPack, error) {
|
||||
values[field] = v[0]
|
||||
}
|
||||
}
|
||||
if values[55] != 3 && values[55] != 10 {
|
||||
if values[55] != 3 && values[55] != 5 && values[55] != 10 {
|
||||
continue
|
||||
}
|
||||
if id <= 0 || values[25] != uint64(id) {
|
||||
|
||||
@@ -4,51 +4,6 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type SkyWayOverwhelmRule struct {
|
||||
Group, Map, APType, Boss, BossAP uint64
|
||||
Monsters, AP []uint64
|
||||
}
|
||||
|
||||
func LoadSkyWayOverwhelm(root, version string) ([]SkyWayOverwhelmRule, error) {
|
||||
db, done, e := openStatDatabase(root, version)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
defer done()
|
||||
rows, e := db.Query("SELECT ProtoBuf FROM SkyWayFieldTable")
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
defer func() { _ = rows.Close() }()
|
||||
var out []SkyWayOverwhelmRule
|
||||
for rows.Next() {
|
||||
var b []byte
|
||||
if e = rows.Scan(&b); e != nil {
|
||||
return nil, e
|
||||
}
|
||||
r := SkyWayOverwhelmRule{}
|
||||
for f, p := range map[int]*uint64{10: &r.Group, 13: &r.Map, 1: &r.APType, 4: &r.Boss, 3: &r.BossAP} {
|
||||
*p, e = optionalScalar(b, f)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
r.Monsters, e = packedInts(b, 15)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
r.AP, e = packedInts(b, 14)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
if len(r.Monsters) != len(r.AP) {
|
||||
return nil, fmt.Errorf("gamedata: malformed skyway AP mapping")
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
type OverwhelmQuestRule struct {
|
||||
Type, Count uint64
|
||||
Targets []uint64
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
package gamedata
|
||||
|
||||
import "fmt"
|
||||
|
||||
type SkyWayStage struct {
|
||||
Group, ID, Difficulty, Map, Point, APType, Boss, BossAP, PositionGroup uint64
|
||||
Monsters, AP []uint64
|
||||
}
|
||||
|
||||
type SkyWayDesign struct {
|
||||
Pack int
|
||||
Stages []SkyWayStage
|
||||
Monsters map[uint64]HuntingMonster
|
||||
SafeMaps map[int]bool
|
||||
}
|
||||
|
||||
func LoadSkyWayDesign(root, version string) (*SkyWayDesign, error) {
|
||||
db, done, err := openStatDatabase(root, version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer done()
|
||||
d := &SkyWayDesign{Monsters: map[uint64]HuntingMonster{}, SafeMaps: map[int]bool{}}
|
||||
rows, err := db.Query("SELECT ProtoBuf FROM SkyWayFieldTable ORDER BY groupId,difficulty")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var raw []byte
|
||||
if err = rows.Scan(&raw); err != nil {
|
||||
_ = rows.Close()
|
||||
return nil, err
|
||||
}
|
||||
var s SkyWayStage
|
||||
for f, p := range map[int]*uint64{1: &s.APType, 3: &s.BossAP, 4: &s.Boss, 6: &s.Difficulty, 10: &s.Group, 12: &s.ID, 13: &s.Map, 17: &s.Point, 18: &s.PositionGroup} {
|
||||
*p, err = optionalScalar(raw, f)
|
||||
if err != nil {
|
||||
_ = rows.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
s.Monsters, err = packedInts(raw, 15)
|
||||
if err != nil {
|
||||
_ = rows.Close()
|
||||
return nil, err
|
||||
}
|
||||
s.AP, err = packedInts(raw, 14)
|
||||
if err != nil {
|
||||
_ = rows.Close()
|
||||
return nil, err
|
||||
}
|
||||
if s.Group == 0 || s.Group > 7 || s.ID == 0 || s.Boss == 0 || s.Map == 0 || len(s.AP) != len(s.Monsters) || (s.APType != 1 && s.APType != 2) {
|
||||
_ = rows.Close()
|
||||
return nil, fmt.Errorf("gamedata: invalid SkyWay stage")
|
||||
}
|
||||
d.Stages = append(d.Stages, s)
|
||||
}
|
||||
if err = rows.Err(); err != nil {
|
||||
_ = rows.Close()
|
||||
return nil, err
|
||||
}
|
||||
if err = rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, s := range d.Stages {
|
||||
var pack int
|
||||
if err = db.QueryRow("SELECT packId FROM MapTable WHERE id=?", s.Map).Scan(&pack); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Pack != 0 && d.Pack != pack {
|
||||
return nil, fmt.Errorf("gamedata: SkyWay maps span packs")
|
||||
}
|
||||
d.Pack = pack
|
||||
}
|
||||
if d.Pack == 0 {
|
||||
return nil, fmt.Errorf("gamedata: no SkyWay pack")
|
||||
}
|
||||
rows, err = db.Query("SELECT id,ProtoBuf FROM MapTable WHERE packId=?", d.Pack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var id int
|
||||
var raw []byte
|
||||
if err = rows.Scan(&id, &raw); err != nil {
|
||||
_ = rows.Close()
|
||||
return nil, err
|
||||
}
|
||||
typ, e := optionalScalar(raw, 22)
|
||||
if e != nil {
|
||||
_ = rows.Close()
|
||||
return nil, e
|
||||
}
|
||||
if typ == 0 {
|
||||
d.SafeMaps[id] = true
|
||||
}
|
||||
}
|
||||
if err = rows.Err(); err != nil {
|
||||
_ = rows.Close()
|
||||
return nil, err
|
||||
}
|
||||
if err = rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pdb, release, err := openPackDatabase(root, version, d.Pack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer release()
|
||||
for _, s := range d.Stages {
|
||||
for _, id := range append(append([]uint64(nil), s.Monsters...), s.Boss) {
|
||||
if _, ok := d.Monsters[id]; ok {
|
||||
continue
|
||||
}
|
||||
var raw []byte
|
||||
if err = pdb.QueryRow("SELECT ProtoBuf FROM FieldMonsterTable WHERE id=?", id).Scan(&raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := HuntingMonster{ID: id, Rewards: map[uint64][]BattleReward{}}
|
||||
m.Type, err = optionalScalar(raw, 30)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m.Decks, err = packedInts(raw, 2)
|
||||
if err != nil || len(m.Decks) == 0 {
|
||||
return nil, fmt.Errorf("gamedata: SkyWay monster missing decks")
|
||||
}
|
||||
for _, deck := range m.Decks {
|
||||
if err = pdb.QueryRow("SELECT ProtoBuf FROM BattleDeckTable WHERE id=?", deck).Scan(&raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rs, e := parallelRewards(raw, 36, 34, 33)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
for _, r := range rs {
|
||||
m.Rewards[deck] = append(m.Rewards[deck], BattleReward(r))
|
||||
}
|
||||
}
|
||||
d.Monsters[id] = m
|
||||
}
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (d *SkyWayDesign) Stage(group, id uint64) (SkyWayStage, bool) {
|
||||
for _, s := range d.Stages {
|
||||
if s.Group == group && s.ID == id {
|
||||
return s, true
|
||||
}
|
||||
}
|
||||
return SkyWayStage{}, false
|
||||
}
|
||||
|
||||
// Battle modes are the current protocol's contiguous SKY_WAY enum family.
|
||||
func SkyWayMode(group uint64) uint64 { return 8 + group }
|
||||
func IsSkyWayMode(mode uint64) bool { return mode >= 9 && mode <= 15 }
|
||||
@@ -70,7 +70,7 @@ func loadStoryCatalog(db *sql.DB) (*StoryCatalog, error) {
|
||||
_ = rows.Close()
|
||||
return nil, err
|
||||
}
|
||||
if kind != 0 && kind != 1000 {
|
||||
if kind != 0 && kind != 5 && kind != 1000 {
|
||||
continue
|
||||
}
|
||||
protoID, err := read(25)
|
||||
|
||||
Reference in New Issue
Block a user