Files
Erupe/server/channelserver/handlers_reward.go
Houmgaor 2bd92c9ae7 feat(diva): implement Diva Defense (UD) system
Add full Diva Defense / United Defense system: schema, repo layer,
i18n bead names, and RE-verified packet handler implementations.

Schema (0011_diva.sql): diva_beads, diva_beads_assignment,
diva_beads_points, diva_prizes tables; interception_maps/points
columns on guilds and guild_characters.

Seed (DivaDefaults.sql): 26 prize milestones for personal and
guild reward tracks (item_type=26 diva coins).

Repo (DivaRepo): 11 new methods covering bead assignment, point
accumulation, interception point tracking, prize queries, and
cleanup. Mocks wired in test_helpers_test.go.

i18n: Bead struct with EN/JP names for all 18 bead types (IDs
1–25). Session tracks currentBeadIndex (-1 = none assigned).

Packet handlers corrected against mhfo-hd.dll RE findings:
- GetKijuInfo: u8 count, 512-byte desc, color_id+bead_type per entry
- SetKiju: 1-byte ACK; persists bead assignment to DB
- GetUdMyPoint: 8×18-byte entries, no count prefix
- GetUdTotalPointInfo: u8 error + u64[64] + u8[64] + u64 (~585 B)
- GetUdSelectedColorInfo: u8 error + u8[8] = 9 bytes
- GetUdDailyPresentList: correct u16 count format (was wrong hex)
- GetUdNormaPresentList: correct u16 count format (was wrong hex)
- GetUdRankingRewardList: correct u16 count with u32 item_id/qty
- GetRewardSong: 22-byte layout with 0xFFFFFFFF prayer_end sentinel
- AddRewardSongCount: parse implemented (was NOT IMPLEMENTED stub)
2026-03-20 17:52:01 +01:00

68 lines
2.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package channelserver
import (
"erupe-ce/common/byteframe"
"erupe-ce/network/mhfpacket"
)
func handleMsgMhfGetAdditionalBeatReward(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetAdditionalBeatReward)
// Actual response in packet captures are all just giant batches of null bytes
// I'm assuming this is because it used to be tied to an actual event and
// they never bothered killing off the packet when they made it static
const beatRewardResponseSize = 0x104
doAckBufSucceed(s, pkt.AckHandle, make([]byte, beatRewardResponseSize))
}
func handleMsgMhfGetUdRankingRewardList(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetUdRankingRewardList)
// RankingRewardList: u16 count + count × 14-byte entries.
// Entry: u8 rank_type, u16 rank_from, u16 rank_to, u8 item_type,
// u32 item_id, u32 quantity. No padding gaps.
bf := byteframe.NewByteFrame()
bf.WriteUint16(0) // count = 0 (no entries configured)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfGetRewardSong(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetRewardSong)
// RE-confirmed layout (22 bytes):
// +0x00 u8 error
// +0x01 u8 usage_count
// +0x02 u32 prayer_id
// +0x06 u32 prayer_end (0xFFFFFFFF = no active prayer)
// then 4 × (u8 color_error, u8 color_id, u8 color_usage_count)
bf := byteframe.NewByteFrame()
bf.WriteUint8(0) // error
bf.WriteUint8(0) // usage_count
bf.WriteUint32(0) // prayer_id
bf.WriteUint32(0xFFFFFFFF) // prayer_end: no active prayer
for colorID := uint8(1); colorID <= 4; colorID++ {
bf.WriteUint8(0) // color_error
bf.WriteUint8(colorID) // color_id
bf.WriteUint8(0) // color_usage_count
}
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfUseRewardSong(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUseRewardSong)
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00})
}
func handleMsgMhfAddRewardSongCount(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfAddRewardSongCount)
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00})
}
func handleMsgMhfAcquireMonthlyReward(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfAcquireMonthlyReward)
resp := byteframe.NewByteFrame()
resp.WriteUint32(0)
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
}
func handleMsgMhfAcceptReadReward(s *Session, p mhfpacket.MHFPacket) {} // stub: unimplemented