Merge branch 'main' into main

This commit is contained in:
wish
2023-07-29 17:18:32 +10:00
committed by GitHub
21 changed files with 440 additions and 212 deletions

View File

@@ -6,6 +6,7 @@ import (
"erupe-ce/common/mhfcourse"
ps "erupe-ce/common/pascalstring"
"erupe-ce/common/stringsupport"
_config "erupe-ce/config"
"fmt"
"io"
"net"
@@ -447,48 +448,110 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
}
}
case 4: // Find Party
type FindPartyParams struct {
StagePrefix string
RankRestriction uint16
Targets []uint16
Unk0 []uint16
Unk1 []uint16
QuestID []uint16
}
findPartyParams := FindPartyParams{
StagePrefix: "sl2Ls210",
}
bf := byteframe.NewByteFrameFromBytes(pkt.MessageData)
setting := bf.ReadUint8()
numParams := int(bf.ReadUint8())
maxResults := bf.ReadUint16()
bf.Seek(2, 1)
partyType := bf.ReadUint16()
rankRestriction := uint16(0)
if setting >= 2 {
bf.Seek(2, 1)
rankRestriction = bf.ReadUint16()
}
targets := make([]uint16, 4)
if setting >= 3 {
bf.Seek(1, 1)
lenTargets := int(bf.ReadUint8())
for i := 0; i < lenTargets; i++ {
targets[i] = bf.ReadUint16()
for i := 0; i < numParams; i++ {
switch bf.ReadUint8() {
case 0:
values := int(bf.ReadUint8())
for i := 0; i < values; i++ {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
findPartyParams.RankRestriction = bf.ReadUint16()
} else {
findPartyParams.RankRestriction = uint16(bf.ReadInt8())
}
}
case 1:
values := int(bf.ReadUint8())
for i := 0; i < values; i++ {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
findPartyParams.Targets = append(findPartyParams.Targets, bf.ReadUint16())
} else {
findPartyParams.Targets = append(findPartyParams.Targets, uint16(bf.ReadInt8()))
}
}
case 2:
values := int(bf.ReadUint8())
for i := 0; i < values; i++ {
var value int16
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
value = bf.ReadInt16()
} else {
value = int16(bf.ReadInt8())
}
switch value {
case 0: // Public Bar
findPartyParams.StagePrefix = "sl2Ls210"
case 1: // Tokotoko Partnya
findPartyParams.StagePrefix = "sl2Ls463"
case 2: // Hunting Prowess Match
findPartyParams.StagePrefix = "sl2Ls286"
case 3: // Volpakkun Together
findPartyParams.StagePrefix = "sl2Ls465"
case 5: // Quick Party
// Unk
}
}
case 3: // Unknown
values := int(bf.ReadUint8())
for i := 0; i < values; i++ {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
findPartyParams.Unk0 = append(findPartyParams.Unk0, bf.ReadUint16())
} else {
findPartyParams.Unk0 = append(findPartyParams.Unk0, uint16(bf.ReadInt8()))
}
}
case 4: // Looking for n or already have n
values := int(bf.ReadUint8())
for i := 0; i < values; i++ {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
findPartyParams.Unk1 = append(findPartyParams.Unk1, bf.ReadUint16())
} else {
findPartyParams.Unk1 = append(findPartyParams.Unk1, uint16(bf.ReadInt8()))
}
}
case 5:
values := int(bf.ReadUint8())
for i := 0; i < values; i++ {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
findPartyParams.QuestID = append(findPartyParams.QuestID, bf.ReadUint16())
} else {
findPartyParams.QuestID = append(findPartyParams.QuestID, uint16(bf.ReadInt8()))
}
}
}
}
var stagePrefix string
switch partyType {
case 0: // Public Bar
stagePrefix = "sl2Ls210"
case 1: // Tokotoko Partnya
stagePrefix = "sl2Ls463"
case 2: // Hunting Prowess Match
stagePrefix = "sl2Ls286"
case 3: // Volpakkun Together
stagePrefix = "sl2Ls465"
case 5: // Quick Party
// Unk
}
for _, c := range s.server.Channels {
for _, stage := range c.stages {
if count == maxResults {
break
}
if strings.HasPrefix(stage.id, stagePrefix) {
if strings.HasPrefix(stage.id, findPartyParams.StagePrefix) {
sb3 := byteframe.NewByteFrameFromBytes(stage.rawBinaryData[stageBinaryKey{1, 3}])
sb3.Seek(4, 0)
stageRankRestriction := sb3.ReadUint16()
stageTarget := sb3.ReadUint16()
if rankRestriction != 0xFFFF && stageRankRestriction < rankRestriction {
if stageRankRestriction > findPartyParams.RankRestriction {
continue
}
if len(findPartyParams.Targets) > 0 {
for _, target := range findPartyParams.Targets {
if target == stageTarget {
break
}
}
continue
}
count++
@@ -1630,7 +1693,13 @@ func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetRandFromTable(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetSenyuDailyCount)
bf := byteframe.NewByteFrame()
bf.WriteUint16(0)
bf.WriteUint16(0)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
type SeibattleTimetable struct {
Start time.Time

View File

@@ -12,41 +12,29 @@ import (
"go.uber.org/zap"
)
type SavePointer int
const (
pointerGender = 0x51 // +1
pointerRP = 0x22D16 // +2
pointerHouseTier = 0x1FB6C // +5
pointerHouseData = 0x1FE01 // +195
pointerBookshelfData = 0x22298 // +5576
// Gallery data also exists at 0x21578, is this the contest submission?
pointerGalleryData = 0x22320 // +1748
pointerToreData = 0x1FCB4 // +240
pointerGardenData = 0x22C58 // +68
pointerWeaponType = 0x1F715 // +1
pointerWeaponID = 0x1F60A // +2
pointerHRP = 0x1FDF6 // +2
pointerGRP = 0x1FDFC // +4
pointerKQF = 0x23D20 // +8
pointerRPZ = 0x1A076
pointerHouseTierZ = 0x16ECC
pointerHouseDataZ = 0x17161
pointerBookshelfDataZ = 0x195F8
pointerGalleryDataZ = 0x19680
pointerToreDataZ = 0x17014
pointerGardenDataZ = 0x19FB8
pointerWeaponTypeZ = 0x16A75
pointerWeaponIDZ = 0x1696A
pointerHRPZ = 0x17156
pointerGRPZ = 0x1715C
pointerKQFZ = 0x1B080
pGender = iota // +1
pRP // +2
pHouseTier // +5
pHouseData // +195
pBookshelfData // +5576
pGalleryData // +1748
pToreData // +240
pGardenData // +68
pWeaponType // +1
pWeaponID // +2
pHRP // +2
pGRP // +4
pKQF // +8
)
type CharacterSaveData struct {
CharID uint32
Name string
IsNewCharacter bool
Pointers map[SavePointer]int
Gender bool
RP uint16
@@ -66,6 +54,39 @@ type CharacterSaveData struct {
decompSave []byte
}
func getPointers() map[SavePointer]int {
pointers := map[SavePointer]int{pGender: 81}
switch _config.ErupeConfig.RealClientMode {
case _config.ZZ:
pointers[pWeaponID] = 128522
pointers[pWeaponType] = 128789
pointers[pHouseTier] = 129900
pointers[pToreData] = 130228
pointers[pHRP] = 130550
pointers[pGRP] = 130556
pointers[pHouseData] = 130561
pointers[pBookshelfData] = 139928
pointers[pGalleryData] = 140064
pointers[pGardenData] = 142424
pointers[pRP] = 142614
pointers[pKQF] = 146720
case _config.Z2, _config.Z1, _config.G101, _config.G10:
pointers[pWeaponID] = 92522
pointers[pWeaponType] = 92789
pointers[pHouseTier] = 93900
pointers[pToreData] = 94228
pointers[pHRP] = 94550
pointers[pGRP] = 94556
pointers[pHouseData] = 94561
pointers[pBookshelfData] = 103928
pointers[pGalleryData] = 104064
pointers[pGardenData] = 106424
pointers[pRP] = 106614
pointers[pKQF] = 110720
}
return pointers
}
func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) {
result, err := s.server.db.Query("SELECT id, savedata, is_new_character, name FROM characters WHERE id = $1", charID)
if err != nil {
@@ -79,7 +100,9 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error)
return nil, err
}
saveData := &CharacterSaveData{}
saveData := &CharacterSaveData{
Pointers: getPointers(),
}
err = result.Scan(&saveData.CharID, &saveData.compSave, &saveData.IsNewCharacter, &saveData.Name)
if err != nil {
s.logger.Error("Failed to scan savedata", zap.Error(err), zap.Uint32("charID", charID))
@@ -110,13 +133,18 @@ func (save *CharacterSaveData) Save(s *Session) {
save.updateSaveDataWithStruct()
err := save.Compress()
if err != nil {
s.logger.Error("Failed to compress savedata", zap.Error(err))
return
if _config.ErupeConfig.RealClientMode >= _config.G1 {
err := save.Compress()
if err != nil {
s.logger.Error("Failed to compress savedata", zap.Error(err))
return
}
} else {
// Saves were not compressed
save.compSave = save.decompSave
}
_, err = s.server.db.Exec(`UPDATE characters SET savedata=$1, is_new_character=false, hrp=$2, gr=$3, is_female=$4, weapon_type=$5, weapon_id=$6 WHERE id=$7
_, err := s.server.db.Exec(`UPDATE characters SET savedata=$1, is_new_character=false, hrp=$2, gr=$3, is_female=$4, weapon_type=$5, weapon_id=$6 WHERE id=$7
`, save.compSave, save.HRP, save.GR, save.Gender, save.WeaponType, save.WeaponID, save.CharID)
if err != nil {
s.logger.Error("Failed to update savedata", zap.Error(err), zap.Uint32("charID", save.CharID))
@@ -148,54 +176,36 @@ func (save *CharacterSaveData) Decompress() error {
func (save *CharacterSaveData) updateSaveDataWithStruct() {
rpBytes := make([]byte, 2)
binary.LittleEndian.PutUint16(rpBytes, save.RP)
if _config.ErupeConfig.RealClientMode == _config.ZZ {
copy(save.decompSave[pointerRP:pointerRP+2], rpBytes)
copy(save.decompSave[pointerKQF:pointerKQF+8], save.KQF)
} else if _config.ErupeConfig.RealClientMode >= _config.Z1 {
copy(save.decompSave[pointerRPZ:pointerRPZ+2], rpBytes)
copy(save.decompSave[pointerKQFZ:pointerKQFZ+8], save.KQF)
if _config.ErupeConfig.RealClientMode >= _config.G10 {
copy(save.decompSave[save.Pointers[pRP]:save.Pointers[pRP]+2], rpBytes)
copy(save.decompSave[save.Pointers[pKQF]:save.Pointers[pKQF]+8], save.KQF)
}
}
// This will update the save struct with the values stored in the character save
func (save *CharacterSaveData) updateStructWithSaveData() {
save.Name = stringsupport.SJISToUTF8(bfutil.UpToNull(save.decompSave[88:100]))
if save.decompSave[pointerGender] == 1 {
if save.decompSave[save.Pointers[pGender]] == 1 {
save.Gender = true
} else {
save.Gender = false
}
if !save.IsNewCharacter {
if _config.ErupeConfig.RealClientMode == _config.ZZ {
save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRP : pointerRP+2])
save.HouseTier = save.decompSave[pointerHouseTier : pointerHouseTier+5]
save.HouseData = save.decompSave[pointerHouseData : pointerHouseData+195]
save.BookshelfData = save.decompSave[pointerBookshelfData : pointerBookshelfData+5576]
save.GalleryData = save.decompSave[pointerGalleryData : pointerGalleryData+1748]
save.ToreData = save.decompSave[pointerToreData : pointerToreData+240]
save.GardenData = save.decompSave[pointerGardenData : pointerGardenData+68]
save.WeaponType = save.decompSave[pointerWeaponType]
save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[pointerWeaponID : pointerWeaponID+2])
save.HRP = binary.LittleEndian.Uint16(save.decompSave[pointerHRP : pointerHRP+2])
if _config.ErupeConfig.RealClientMode >= _config.G10 {
save.RP = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pRP] : save.Pointers[pRP]+2])
save.HouseTier = save.decompSave[save.Pointers[pHouseTier] : save.Pointers[pHouseTier]+5]
save.HouseData = save.decompSave[save.Pointers[pHouseData] : save.Pointers[pHouseData]+195]
save.BookshelfData = save.decompSave[save.Pointers[pBookshelfData] : save.Pointers[pBookshelfData]+5576]
save.GalleryData = save.decompSave[save.Pointers[pGalleryData] : save.Pointers[pGalleryData]+1748]
save.ToreData = save.decompSave[save.Pointers[pToreData] : save.Pointers[pToreData]+240]
save.GardenData = save.decompSave[save.Pointers[pGardenData] : save.Pointers[pGardenData]+68]
save.WeaponType = save.decompSave[save.Pointers[pWeaponType]]
save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pWeaponID] : save.Pointers[pWeaponID]+2])
save.HRP = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pHRP] : save.Pointers[pHRP]+2])
if save.HRP == uint16(999) {
save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[pointerGRP : pointerGRP+4]))
save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[save.Pointers[pGRP] : save.Pointers[pGRP]+4]))
}
save.KQF = save.decompSave[pointerKQF : pointerKQF+8]
} else if _config.ErupeConfig.RealClientMode >= _config.Z1 {
save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRPZ : pointerRPZ+2])
save.HouseTier = save.decompSave[pointerHouseTierZ : pointerHouseTierZ+5]
save.HouseData = save.decompSave[pointerHouseDataZ : pointerHouseDataZ+195]
save.BookshelfData = save.decompSave[pointerBookshelfDataZ : pointerBookshelfDataZ+5576]
save.GalleryData = save.decompSave[pointerGalleryDataZ : pointerGalleryDataZ+1748]
save.ToreData = save.decompSave[pointerToreDataZ : pointerToreDataZ+240]
save.GardenData = save.decompSave[pointerGardenDataZ : pointerGardenDataZ+68]
save.WeaponType = save.decompSave[pointerWeaponTypeZ]
save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[pointerWeaponIDZ : pointerWeaponIDZ+2])
save.HRP = binary.LittleEndian.Uint16(save.decompSave[pointerHRPZ : pointerHRPZ+2])
if save.HRP == uint16(999) {
save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[pointerGRPZ : pointerGRPZ+4]))
}
save.KQF = save.decompSave[pointerKQFZ : pointerKQFZ+8]
save.KQF = save.decompSave[save.Pointers[pKQF] : save.Pointers[pKQF]+8]
}
}
return
@@ -203,5 +213,5 @@ func (save *CharacterSaveData) updateStructWithSaveData() {
func handleMsgMhfSexChanger(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfSexChanger)
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}

View File

@@ -1,7 +1,6 @@
package channelserver
import (
"encoding/hex"
"erupe-ce/common/byteframe"
ps "erupe-ce/common/pascalstring"
"erupe-ce/common/token"
@@ -140,13 +139,26 @@ func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 {
return timestamps
}
type Trial struct {
type FestaTrial struct {
ID uint32 `db:"id"`
Objective uint8 `db:"objective"`
Objective uint16 `db:"objective"`
GoalID uint32 `db:"goal_id"`
TimesReq uint16 `db:"times_req"`
Locale uint16 `db:"locale_req"`
Reward uint16 `db:"reward"`
Monopoly uint16
Unk uint16
}
type FestaReward struct {
Unk0 uint8
Unk1 uint8
ItemType uint16
Quantity uint16
ItemID uint16
Unk5 uint16
Unk6 uint16
Unk7 uint8
}
func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
@@ -190,36 +202,71 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint32(blueSouls)
bf.WriteUint32(redSouls)
var trials []FestaTrial
var trial FestaTrial
rows, _ = s.server.db.Queryx("SELECT * FROM festa_trials")
trialData := byteframe.NewByteFrame()
var count uint16
for rows.Next() {
trial := &Trial{}
err := rows.StructScan(&trial)
if err != nil {
continue
}
count++
trialData.WriteUint32(trial.ID)
trialData.WriteUint8(0) // Unk
trialData.WriteUint8(trial.Objective)
trialData.WriteUint32(trial.GoalID)
trialData.WriteUint16(trial.TimesReq)
trialData.WriteUint16(trial.Locale)
trialData.WriteUint16(trial.Reward)
trialData.WriteUint8(0xFF) // Unk
trialData.WriteUint8(0xFF) // MonopolyState
trialData.WriteUint16(0) // Unk
trials = append(trials, trial)
}
bf.WriteUint16(uint16(len(trials)))
for _, trial := range trials {
bf.WriteUint32(trial.ID)
bf.WriteUint16(trial.Objective)
bf.WriteUint32(trial.GoalID)
bf.WriteUint16(trial.TimesReq)
bf.WriteUint16(trial.Locale)
bf.WriteUint16(trial.Reward)
trial.Monopoly = 0xFFFF // NYI
bf.WriteUint16(trial.Monopoly)
bf.WriteUint16(trial.Unk)
}
bf.WriteUint16(count)
bf.WriteBytes(trialData.Data())
// Static bonus rewards
rewards, _ := hex.DecodeString("001901000007015E05F000000000000100000703E81B6300000000010100000C03E8000000000000000100000D0000000000000000000100000100000000000000000002000007015E05F000000000000200000703E81B6300000000010200000C03E8000000000000000200000D0000000000000000000200000400000000000000000003000007015E05F000000000000300000703E81B6300000000010300000C03E8000000000000000300000D0000000000000000000300000100000000000000000004000007015E05F000000000000400000703E81B6300000000010400000C03E8000000000000000400000D0000000000000000000400000400000000000000000005000007015E05F000000000000500000703E81B6300000000010500000C03E8000000000000000500000D00000000000000000005000001000000000000000000")
bf.WriteBytes(rewards)
// The Winner and Loser Armor IDs are missing
rewards := []FestaReward{
{1, 0, 7, 350, 1520, 0, 0, 0},
{1, 0, 7, 1000, 7011, 0, 0, 1},
{1, 0, 12, 1000, 0, 0, 0, 0},
{1, 0, 13, 0, 0, 0, 0, 0},
//{1, 0, 1, 0, 0, 0, 0, 0},
{2, 0, 7, 350, 1520, 0, 0, 0},
{2, 0, 7, 1000, 7011, 0, 0, 1},
{2, 0, 12, 1000, 0, 0, 0, 0},
{2, 0, 13, 0, 0, 0, 0, 0},
//{2, 0, 4, 0, 0, 0, 0, 0},
{3, 0, 7, 350, 1520, 0, 0, 0},
{3, 0, 7, 1000, 7011, 0, 0, 1},
{3, 0, 12, 1000, 0, 0, 0, 0},
{3, 0, 13, 0, 0, 0, 0, 0},
//{3, 0, 1, 0, 0, 0, 0, 0},
{4, 0, 7, 350, 1520, 0, 0, 0},
{4, 0, 7, 1000, 7011, 0, 0, 1},
{4, 0, 12, 1000, 0, 0, 0, 0},
{4, 0, 13, 0, 0, 0, 0, 0},
//{4, 0, 4, 0, 0, 0, 0, 0},
{5, 0, 7, 350, 1520, 0, 0, 0},
{5, 0, 7, 1000, 7011, 0, 0, 1},
{5, 0, 12, 1000, 0, 0, 0, 0},
{5, 0, 13, 0, 0, 0, 0, 0},
//{5, 0, 1, 0, 0, 0, 0, 0},
}
bf.WriteUint16(uint16(len(rewards)))
for _, reward := range rewards {
bf.WriteUint8(reward.Unk0)
bf.WriteUint8(reward.Unk1)
bf.WriteUint16(reward.ItemType)
bf.WriteUint16(reward.Quantity)
bf.WriteUint16(reward.ItemID)
bf.WriteUint16(reward.Unk5)
bf.WriteUint16(reward.Unk6)
bf.WriteUint8(reward.Unk7)
}
bf.WriteUint16(0x0001)
bf.WriteUint32(0xD4C001F4)
bf.WriteUint32(s.server.erupeConfig.GameplayOptions.MaximumFP)
bf.WriteUint16(500)
categoryWinners := uint16(0) // NYI
bf.WriteUint16(categoryWinners)
@@ -239,8 +286,18 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
ps.Uint8(bf, "", true) // Guild Name
}
d, _ := hex.DecodeString("000000000000000100001388000007D0000003E800000064012C00C8009600640032")
bf.WriteBytes(d)
// Unknown values
bf.WriteUint32(1)
bf.WriteUint32(5000)
bf.WriteUint32(2000)
bf.WriteUint32(1000)
bf.WriteUint32(100)
bf.WriteUint16(300)
bf.WriteUint16(200)
bf.WriteUint16(150)
bf.WriteUint16(100)
bf.WriteUint16(50)
ps.Uint16(bf, "", false)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}

View File

@@ -63,7 +63,6 @@ type Guild struct {
Recruiting bool `db:"recruiting"`
FestivalColour FestivalColour `db:"festival_colour"`
Souls uint32 `db:"souls"`
Rank uint16 `db:"rank"`
AllianceID uint32 `db:"alliance_id"`
Icon *GuildIcon `db:"icon"`
@@ -116,6 +115,39 @@ func (gi *GuildIcon) Value() (valuer driver.Value, err error) {
return json.Marshal(gi)
}
func (g *Guild) Rank() uint16 {
rpMap := []uint32{
24, 48, 96, 144, 192, 240, 288, 360, 432,
504, 600, 696, 792, 888, 984, 1080, 1200,
}
if _config.ErupeConfig.RealClientMode <= _config.Z2 {
rpMap = []uint32{
3500, 6000, 8500, 11000, 13500, 16000, 20000, 24000, 28000,
33000, 38000, 43000, 48000, 55000, 70000, 90000, 120000,
}
}
for i, u := range rpMap {
if g.RankRP < u {
if _config.ErupeConfig.RealClientMode <= _config.S6 && i >= 12 {
return 12
} else if _config.ErupeConfig.RealClientMode <= _config.F5 && i >= 13 {
return 13
} else if _config.ErupeConfig.RealClientMode <= _config.G32 && i >= 14 {
return 14
}
return uint16(i)
}
}
if _config.ErupeConfig.RealClientMode <= _config.S6 {
return 12
} else if _config.ErupeConfig.RealClientMode <= _config.F5 {
return 13
} else if _config.ErupeConfig.RealClientMode <= _config.G32 {
return 14
}
return 17
}
const guildInfoSelectQuery = `
SELECT
g.id,
@@ -138,14 +170,6 @@ SELECT
recruiting,
COALESCE((SELECT team FROM festa_registrations fr WHERE fr.guild_id = g.id), 'none') AS festival_colour,
(SELECT SUM(souls) FROM guild_characters gc WHERE gc.guild_id = g.id) AS souls,
CASE
WHEN rank_rp <= 48 THEN rank_rp/24
WHEN rank_rp <= 288 THEN rank_rp/48+1
WHEN rank_rp <= 504 THEN rank_rp/72+3
WHEN rank_rp <= 1080 THEN (rank_rp-24)/96+5
WHEN rank_rp < 1200 THEN 16
ELSE 17
END rank,
COALESCE((
SELECT id FROM guild_alliances ga WHERE
ga.parent_id = g.id OR
@@ -912,7 +936,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint32(guild.ID)
bf.WriteUint32(guild.LeaderCharID)
bf.WriteUint16(guild.Rank)
bf.WriteUint16(guild.Rank())
bf.WriteUint16(guild.MemberCount)
bf.WriteUint8(guild.MainMotto)
@@ -966,11 +990,11 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
}
bf.WriteUint32(guild.PugiOutfits)
if guild.Rank >= 3 {
if guild.Rank() >= 3 {
bf.WriteUint8(40)
} else if guild.Rank >= 7 {
} else if guild.Rank() >= 7 {
bf.WriteUint8(50)
} else if guild.Rank >= 10 {
} else if guild.Rank() >= 10 {
bf.WriteUint8(60)
} else {
bf.WriteUint8(30)
@@ -1008,7 +1032,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
} else {
bf.WriteUint16(0)
}
bf.WriteUint16(alliance.ParentGuild.Rank)
bf.WriteUint16(alliance.ParentGuild.Rank())
bf.WriteUint16(alliance.ParentGuild.MemberCount)
ps.Uint16(bf, alliance.ParentGuild.Name, true)
ps.Uint16(bf, alliance.ParentGuild.LeaderName, true)
@@ -1020,7 +1044,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
} else {
bf.WriteUint16(0)
}
bf.WriteUint16(alliance.SubGuild1.Rank)
bf.WriteUint16(alliance.SubGuild1.Rank())
bf.WriteUint16(alliance.SubGuild1.MemberCount)
ps.Uint16(bf, alliance.SubGuild1.Name, true)
ps.Uint16(bf, alliance.SubGuild1.LeaderName, true)
@@ -1033,7 +1057,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
} else {
bf.WriteUint16(0)
}
bf.WriteUint16(alliance.SubGuild2.Rank)
bf.WriteUint16(alliance.SubGuild2.Rank())
bf.WriteUint16(alliance.SubGuild2.MemberCount)
ps.Uint16(bf, alliance.SubGuild2.Name, true)
ps.Uint16(bf, alliance.SubGuild2.LeaderName, true)
@@ -1309,7 +1333,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint32(guild.LeaderCharID)
bf.WriteUint16(guild.MemberCount)
bf.WriteUint16(0x0000) // Unk
bf.WriteUint16(guild.Rank)
bf.WriteUint16(guild.Rank())
bf.WriteUint32(uint32(guild.CreatedAt.Unix()))
ps.Uint8(bf, guild.Name, true)
ps.Uint8(bf, guild.LeaderName, true)

View File

@@ -209,14 +209,14 @@ func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {
}
bf.WriteUint32(alliance.ParentGuildID)
bf.WriteUint32(alliance.ParentGuild.LeaderCharID)
bf.WriteUint16(alliance.ParentGuild.Rank)
bf.WriteUint16(alliance.ParentGuild.Rank())
bf.WriteUint16(alliance.ParentGuild.MemberCount)
ps.Uint16(bf, alliance.ParentGuild.Name, true)
ps.Uint16(bf, alliance.ParentGuild.LeaderName, true)
if alliance.SubGuild1ID > 0 {
bf.WriteUint32(alliance.SubGuild1ID)
bf.WriteUint32(alliance.SubGuild1.LeaderCharID)
bf.WriteUint16(alliance.SubGuild1.Rank)
bf.WriteUint16(alliance.SubGuild1.Rank())
bf.WriteUint16(alliance.SubGuild1.MemberCount)
ps.Uint16(bf, alliance.SubGuild1.Name, true)
ps.Uint16(bf, alliance.SubGuild1.LeaderName, true)
@@ -224,7 +224,7 @@ func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {
if alliance.SubGuild2ID > 0 {
bf.WriteUint32(alliance.SubGuild2ID)
bf.WriteUint32(alliance.SubGuild2.LeaderCharID)
bf.WriteUint16(alliance.SubGuild2.Rank)
bf.WriteUint16(alliance.SubGuild2.Rank())
bf.WriteUint16(alliance.SubGuild2.MemberCount)
ps.Uint16(bf, alliance.SubGuild2.Name, true)
ps.Uint16(bf, alliance.SubGuild2.LeaderName, true)

View File

@@ -285,7 +285,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
{ID: 1102, Value: 5},
{ID: 1103, Value: 2},
{ID: 1104, Value: 10},
{ID: 1106, Value: 0},
{ID: 1145, Value: 200},
{ID: 1146, Value: 0}, // isTower_invisible
{ID: 1147, Value: 0}, // isVenom_playable
@@ -557,6 +556,12 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
tuneValues = append(tuneValues, tuneValue{1037, 1})
}
if s.server.erupeConfig.GameplayOptions.EnableKaijiEvent {
tuneValues = append(tuneValues, tuneValue{1106, 1})
} else {
tuneValues = append(tuneValues, tuneValue{1106, 0})
}
if s.server.erupeConfig.GameplayOptions.EnableHiganjimaEvent {
tuneValues = append(tuneValues, tuneValue{1144, 1})
} else {

View File

@@ -68,7 +68,15 @@ func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
}
func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfReadLastWeekBeatRanking)
bf := byteframe.NewByteFrame()
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfUpdateBeatLevel(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateBeatLevel)

View File

@@ -30,7 +30,7 @@ type Stage struct {
// Objects
objects map[uint32]*Object
objectIndex uint8
objectIndex uint16
// Map of session -> charID.
// These are clients that are CURRENTLY in the stage
@@ -56,7 +56,6 @@ func NewStage(ID string) *Stage {
clients: make(map[*Session]uint32),
reservedClientSlots: make(map[uint32]bool),
objects: make(map[uint32]*Object),
objectIndex: 0,
rawBinaryData: make(map[stageBinaryKey][]byte),
maxPlayers: 4,
}
@@ -97,16 +96,10 @@ func (s *Stage) isQuest() bool {
}
func (s *Stage) NextObjectID() uint32 {
s.objectIndex = s.objectIndex + 1
// Objects beyond 127 do not duplicate correctly
// Indexes 0 and 127 does not update position correctly
if s.objectIndex == 127 {
s.objectIndex = 1
}
s.objectIndex++
bf := byteframe.NewByteFrame()
bf.WriteUint8(0)
bf.WriteUint8(s.objectIndex)
bf.WriteUint16(0)
obj := uint32(bf.Data()[3]) | uint32(bf.Data()[2])<<8 | uint32(bf.Data()[1])<<16 | uint32(bf.Data()[0])<<24
return obj
bf.WriteUint16(127)
bf.WriteUint16(s.objectIndex)
bf.Seek(0, 0)
return bf.ReadUint32()
}