From 77e7969579dd8055c5da435d222ac6a4f9f0dfd7 Mon Sep 17 00:00:00 2001 From: Houmgaor Date: Fri, 20 Mar 2026 11:22:25 +0100 Subject: [PATCH 1/3] feat(campaign): implement Event Tent campaign system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the full campaign/event-tent feature: Packet layer: - MsgMhfApplyCampaign: Unk0/Unk1/Unk2 → CampaignID/Code (null-terminated 16-byte string) - MsgMhfAcquireItem: Unk0/Length/Unk1 → RewardIDs []uint32 - MsgMhfEnumerateItem: remove Unk0/Unk1 (RE'd: zeroed + always-2, ignored) - MsgMhfStateCampaign: Unk1 → NullPadding (RE'd: always zero) - MsgMhfTransferItem: Unk0/Unk1/Unk2 → QuestID/ItemType/Quantity (RE'd) Handler layer (handlers_campaign.go): - handleMsgMhfEnumerateCampaign: reads campaigns, categories, links from DB; prefix moved into pascal string slot 3 of each event entry (RE confirmed 3-section response format — removes spurious intermediate section) - handleMsgMhfStateCampaign: returns stamp count and redeemable flag - handleMsgMhfApplyCampaign: validates and records code redemption - handleMsgMhfEnumerateItem: lists rewards gated by stamp count - handleMsgMhfAcquireItem: marks rewards as claimed - handleMsgMhfTransferItem: records campaign quest completion (item_type=9) Quest gating (handlers_quest.go): - makeEventQuest: for QuestTypeSpecialTool, check campaign stamp count and deadline before allowing the quest (WriteBool true/false) Database: - 0010_campaign.sql: 8-table schema (campaigns, categories, links, rewards, claimed, state, codes, quest) - CampaignDemo.sql: community-researched live game campaign data --- network/mhfpacket/msg_mhf_acquire_item.go | 12 +- network/mhfpacket/msg_mhf_apply_campaign.go | 14 +- network/mhfpacket/msg_mhf_enumerate_item.go | 6 +- network/mhfpacket/msg_mhf_state_campaign.go | 8 +- network/mhfpacket/msg_mhf_transfer_item.go | 15 +- server/channelserver/handlers_campaign.go | 321 +- server/channelserver/handlers_items.go | 5 - server/channelserver/handlers_quest.go | 29 +- server/migrations/seed/CampaignDemo.sql | 5169 +++++++++++++++++++ server/migrations/sql/0010_campaign.sql | 69 + 10 files changed, 5528 insertions(+), 120 deletions(-) create mode 100644 server/migrations/seed/CampaignDemo.sql create mode 100644 server/migrations/sql/0010_campaign.sql diff --git a/network/mhfpacket/msg_mhf_acquire_item.go b/network/mhfpacket/msg_mhf_acquire_item.go index de86ce846..8bdb65fc9 100644 --- a/network/mhfpacket/msg_mhf_acquire_item.go +++ b/network/mhfpacket/msg_mhf_acquire_item.go @@ -11,9 +11,7 @@ import ( // MsgMhfAcquireItem represents the MSG_MHF_ACQUIRE_ITEM type MsgMhfAcquireItem struct { AckHandle uint32 - Unk0 uint16 - Length uint16 - Unk1 []uint32 + RewardIDs []uint32 } // Opcode returns the ID associated with this packet type. @@ -24,10 +22,10 @@ func (m *MsgMhfAcquireItem) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfAcquireItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint16() - m.Length = bf.ReadUint16() - for i := 0; i < int(m.Length); i++ { - m.Unk1 = append(m.Unk1, bf.ReadUint32()) + bf.ReadUint16() // Zeroed + ids := bf.ReadUint16() + for i := uint16(0); i < ids; i++ { + m.RewardIDs = append(m.RewardIDs, bf.ReadUint32()) } return nil } diff --git a/network/mhfpacket/msg_mhf_apply_campaign.go b/network/mhfpacket/msg_mhf_apply_campaign.go index b39dab499..9eac62af7 100644 --- a/network/mhfpacket/msg_mhf_apply_campaign.go +++ b/network/mhfpacket/msg_mhf_apply_campaign.go @@ -2,6 +2,7 @@ package mhfpacket import ( "errors" + "erupe-ce/common/bfutil" "erupe-ce/common/byteframe" "erupe-ce/network" "erupe-ce/network/clientctx" @@ -9,10 +10,9 @@ import ( // MsgMhfApplyCampaign represents the MSG_MHF_APPLY_CAMPAIGN type MsgMhfApplyCampaign struct { - AckHandle uint32 - Unk0 uint32 - Unk1 uint16 - Unk2 []byte + AckHandle uint32 + CampaignID uint32 + Code string } // Opcode returns the ID associated with this packet type. @@ -23,9 +23,9 @@ func (m *MsgMhfApplyCampaign) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfApplyCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint32() - m.Unk1 = bf.ReadUint16() - m.Unk2 = bf.ReadBytes(16) + m.CampaignID = bf.ReadUint32() + bf.ReadUint16() // Zeroed + m.Code = string(bfutil.UpToNull(bf.ReadBytes(16))) return nil } diff --git a/network/mhfpacket/msg_mhf_enumerate_item.go b/network/mhfpacket/msg_mhf_enumerate_item.go index fea4f3371..21b670599 100644 --- a/network/mhfpacket/msg_mhf_enumerate_item.go +++ b/network/mhfpacket/msg_mhf_enumerate_item.go @@ -11,8 +11,6 @@ import ( // MsgMhfEnumerateItem represents the MSG_MHF_ENUMERATE_ITEM type MsgMhfEnumerateItem struct { AckHandle uint32 - Unk0 uint16 - Unk1 uint16 CampaignID uint32 } @@ -24,8 +22,8 @@ func (m *MsgMhfEnumerateItem) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfEnumerateItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint16() - m.Unk1 = bf.ReadUint16() + bf.ReadUint16() // Zeroed + bf.ReadUint16() // Always 2 m.CampaignID = bf.ReadUint32() return nil } diff --git a/network/mhfpacket/msg_mhf_state_campaign.go b/network/mhfpacket/msg_mhf_state_campaign.go index ab6342c55..a34b72981 100644 --- a/network/mhfpacket/msg_mhf_state_campaign.go +++ b/network/mhfpacket/msg_mhf_state_campaign.go @@ -10,9 +10,9 @@ import ( // MsgMhfStateCampaign represents the MSG_MHF_STATE_CAMPAIGN type MsgMhfStateCampaign struct { - AckHandle uint32 - CampaignID uint32 - Unk1 uint16 + AckHandle uint32 + CampaignID uint32 + NullPadding uint16 } // Opcode returns the ID associated with this packet type. @@ -24,7 +24,7 @@ func (m *MsgMhfStateCampaign) Opcode() network.PacketID { func (m *MsgMhfStateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() m.CampaignID = bf.ReadUint32() - m.Unk1 = bf.ReadUint16() + m.NullPadding = bf.ReadUint16() //0 in Z2 return nil } diff --git a/network/mhfpacket/msg_mhf_transfer_item.go b/network/mhfpacket/msg_mhf_transfer_item.go index 69dfdb13f..a98ae7bb9 100644 --- a/network/mhfpacket/msg_mhf_transfer_item.go +++ b/network/mhfpacket/msg_mhf_transfer_item.go @@ -11,12 +11,9 @@ import ( // MsgMhfTransferItem represents the MSG_MHF_TRANSFER_ITEM type MsgMhfTransferItem struct { AckHandle uint32 - // looking at packets, these were static across sessions and did not actually - // correlate with any item IDs that would make sense to get after quests so - // I have no idea what this actually does - Unk0 uint32 - Unk1 uint8 - Unk2 uint16 + QuestID uint32 + ItemType uint8 + Quantity uint16 } // Opcode returns the ID associated with this packet type. @@ -27,10 +24,10 @@ func (m *MsgMhfTransferItem) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfTransferItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint32() - m.Unk1 = bf.ReadUint8() + m.QuestID = bf.ReadUint32() + m.ItemType = bf.ReadUint8() bf.ReadUint8() // Zeroed - m.Unk2 = bf.ReadUint16() + m.Quantity = bf.ReadUint16() return nil } diff --git a/server/channelserver/handlers_campaign.go b/server/channelserver/handlers_campaign.go index ad6854fee..f7cb79853 100644 --- a/server/channelserver/handlers_campaign.go +++ b/server/channelserver/handlers_campaign.go @@ -9,55 +9,83 @@ import ( "time" ) -// CampaignEvent represents a promotional campaign event. type CampaignEvent struct { - ID uint32 - Unk0 uint32 - MinHR int16 - MaxHR int16 - MinSR int16 - MaxSR int16 - MinGR int16 - MaxGR int16 - Unk1 uint16 - Unk2 uint8 - Unk3 uint8 - Unk4 uint16 - Unk5 uint16 - Start time.Time - End time.Time - Unk6 uint8 - String0 string - String1 string - String2 string - String3 string - Link string - Prefix string - Categories []uint16 + ID uint32 `db:"id"` + MinHR int16 `db:"min_hr"` + MaxHR int16 `db:"max_hr"` + MinSR int16 `db:"min_sr"` + MaxSR int16 `db:"max_sr"` + MinGR int16 `db:"min_gr"` + MaxGR int16 `db:"max_gr"` + RewardType uint16 `db:"reward_type"` + Stamps uint8 `db:"stamps"` + ReceiveType uint8 `db:"receive_type"` + BackgroundID uint16 `db:"background_id"` + Start time.Time `db:"start_time"` + End time.Time `db:"end_time"` + Title string `db:"title"` + Reward string `db:"reward"` + Link string `db:"link"` + Prefix string `db:"code_prefix"` } -// CampaignCategory represents a category grouping for campaign events. type CampaignCategory struct { - ID uint16 - Type uint8 - Title string - Description string + ID uint16 `db:"id"` + Type uint8 `db:"type"` + Title string `db:"title"` + Description string `db:"description"` } -// CampaignLink links a campaign event to its items/rewards. type CampaignLink struct { - CategoryID uint16 - CampaignID uint32 + CategoryID uint16 `db:"category_id"` + CampaignID uint32 `db:"campaign_id"` +} + +type CampaignReward struct { + ID uint32 `db:"id"` + ItemType uint16 `db:"item_type"` + Quantity uint16 `db:"quantity"` + ItemID uint16 `db:"item_id"` + Deadline time.Time `db:"deadline"` +} + +// campaignRequiredStamps returns the stamp requirement for a campaign, +// clamping to a minimum of 1. Campaigns with 0 stamps in the DB are +// treated as requiring a single stamp (code redemption) to unlock. +func campaignRequiredStamps(stamps int) int { + if stamps < 1 { + return 1 + } + return stamps } func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateCampaign) + if s.server.db == nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } bf := byteframe.NewByteFrame() - events := []CampaignEvent{} - categories := []CampaignCategory{} + var events []CampaignEvent + var categories []CampaignCategory var campaignLinks []CampaignLink + err := s.server.db.Select(&events, "SELECT id,min_hr,max_hr,min_sr,max_sr,min_gr,max_gr,reward_type,stamps,receive_type,background_id,start_time,end_time,title,reward,link,code_prefix FROM campaigns") + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + err = s.server.db.Select(&categories, "SELECT id, type, title, description FROM campaign_categories") + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + err = s.server.db.Select(&campaignLinks, "SELECT campaign_id, category_id FROM campaign_category_links") + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } if len(events) > 255 { bf.WriteUint8(255) bf.WriteUint16(uint16(len(events))) @@ -66,7 +94,7 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) { } for _, event := range events { bf.WriteUint32(event.ID) - bf.WriteUint32(event.Unk0) + bf.WriteUint32(0) bf.WriteInt16(event.MinHR) bf.WriteInt16(event.MaxHR) bf.WriteInt16(event.MinSR) @@ -75,34 +103,19 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt16(event.MinGR) bf.WriteInt16(event.MaxGR) } - bf.WriteUint16(event.Unk1) - bf.WriteUint8(event.Unk2) - bf.WriteUint8(event.Unk3) - bf.WriteUint16(event.Unk4) - bf.WriteUint16(event.Unk5) + bf.WriteUint16(event.RewardType) + bf.WriteUint8(event.Stamps) + bf.WriteUint8(event.ReceiveType) + bf.WriteUint16(event.BackgroundID) + bf.WriteUint16(0) bf.WriteUint32(uint32(event.Start.Unix())) bf.WriteUint32(uint32(event.End.Unix())) - bf.WriteUint8(event.Unk6) - ps.Uint8(bf, event.String0, true) - ps.Uint8(bf, event.String1, true) - ps.Uint8(bf, event.String2, true) - ps.Uint8(bf, event.String3, true) + bf.WriteBool(event.End.Before(time.Now())) + ps.Uint8(bf, event.Title, true) + ps.Uint8(bf, event.Reward, true) + ps.Uint8(bf, event.Prefix, true) + ps.Uint8(bf, "", false) ps.Uint8(bf, event.Link, true) - for i := range event.Categories { - campaignLinks = append(campaignLinks, CampaignLink{event.Categories[i], event.ID}) - } - } - - if len(events) > 255 { - bf.WriteUint8(255) - bf.WriteUint16(uint16(len(events))) - } else { - bf.WriteUint8(uint8(len(events))) - } - for _, event := range events { - bf.WriteUint32(event.ID) - bf.WriteUint8(1) // Always 1? - bf.WriteBytes([]byte(event.Prefix)) } if len(categories) > 255 { @@ -137,43 +150,185 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfStateCampaign) + if s.server.db == nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } bf := byteframe.NewByteFrame() - bf.WriteUint16(1) - bf.WriteUint16(0) + var required int + var deadline time.Time + var stamps []uint32 + + err := s.server.db.Select(&stamps, "SELECT id FROM campaign_state WHERE campaign_id = $1 AND character_id = $2", pkt.CampaignID, s.charID) + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + err = s.server.db.QueryRow(`SELECT stamps, end_time FROM campaigns WHERE id = $1`, pkt.CampaignID).Scan(&required, &deadline) + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + bf.WriteUint16(uint16(len(stamps))) + required = campaignRequiredStamps(required) + + if len(stamps) >= required && deadline.After(time.Now()) { + bf.WriteUint16(2) + } else { + bf.WriteUint16(0) + } + + for _, v := range stamps { + bf.WriteUint32(v) + } + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfApplyCampaign(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfApplyCampaign) - bf := byteframe.NewByteFrame() - bf.WriteUint32(1) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + if s.server.db == nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + // Check if the code exists, belongs to this campaign, and check if it's a multi-code + var multi bool + err := s.server.db.QueryRow(`SELECT multi FROM public.campaign_codes WHERE code = $1 AND campaign_id = $2`, pkt.Code, pkt.CampaignID).Scan(&multi) + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + // Check if the code is already used + var exists bool + if multi { + err = s.server.db.QueryRow(`SELECT COUNT(*) > 0 FROM public.campaign_state WHERE code = $1 AND character_id = $2`, pkt.Code, s.charID).Scan(&exists) + } else { + err = s.server.db.QueryRow(`SELECT COUNT(*) > 0 FROM public.campaign_state WHERE code = $1`, pkt.Code).Scan(&exists) + } + if err != nil || exists { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + _, err = s.server.db.Exec(`INSERT INTO public.campaign_state (code, campaign_id, character_id) VALUES ($1, $2, $3)`, pkt.Code, pkt.CampaignID, s.charID) + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateItem) - items := []struct { - Unk0 uint32 - Unk1 uint16 - Unk2 uint16 - Unk3 uint16 - Unk4 uint32 - Unk5 uint32 - }{} - bf := byteframe.NewByteFrame() - bf.WriteUint16(uint16(len(items))) - for _, item := range items { - bf.WriteUint32(item.Unk0) - bf.WriteUint16(item.Unk1) - bf.WriteUint16(item.Unk2) - bf.WriteUint16(item.Unk3) - bf.WriteUint32(item.Unk4) - bf.WriteUint32(item.Unk5) + if s.server.db == nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + bf := byteframe.NewByteFrame() + + var stamps, required, rewardType uint16 + err := s.server.db.QueryRow(`SELECT COUNT(*) FROM campaign_state WHERE campaign_id = $1 AND character_id = $2`, pkt.CampaignID, s.charID).Scan(&stamps) + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + err = s.server.db.QueryRow(`SELECT stamps, reward_type FROM campaigns WHERE id = $1`, pkt.CampaignID).Scan(&required, &rewardType) + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + required = uint16(campaignRequiredStamps(int(required))) + + if stamps >= required { + var items []CampaignReward + if rewardType == 2 { + var exists int + err = s.server.db.QueryRow(`SELECT COUNT(*) FROM campaign_quest WHERE campaign_id = $1 AND character_id = $2`, pkt.CampaignID, s.charID).Scan(&exists) + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + if exists > 0 { + err = s.server.db.Select(&items, ` + SELECT id, item_type, quantity, item_id, TO_TIMESTAMP(0) AS deadline FROM campaign_rewards + WHERE campaign_id = $1 AND item_type != 9 + AND NOT EXISTS (SELECT 1 FROM campaign_rewards_claimed WHERE reward_id = campaign_rewards.id AND character_id = $2) + `, pkt.CampaignID, s.charID) + } else { + err = s.server.db.Select(&items, ` + SELECT cr.id, cr.item_type, cr.quantity, cr.item_id, COALESCE(c.end_time, TO_TIMESTAMP(0)) AS deadline FROM campaign_rewards cr + JOIN campaigns c ON cr.campaign_id = c.id + WHERE campaign_id = $1 AND item_type = 9`, pkt.CampaignID) + } + } else { + err = s.server.db.Select(&items, ` + SELECT id, item_type, quantity, item_id, TO_TIMESTAMP(0) AS deadline FROM campaign_rewards + WHERE campaign_id = $1 + AND NOT EXISTS (SELECT 1 FROM campaign_rewards_claimed WHERE reward_id = campaign_rewards.id AND character_id = $2) + `, pkt.CampaignID, s.charID) + } + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + bf.WriteUint16(uint16(len(items))) + for _, item := range items { + bf.WriteUint32(item.ID) + bf.WriteUint16(item.ItemType) + bf.WriteUint16(item.Quantity) + bf.WriteUint16(item.ItemID) //HACK:placed quest id in this field to fit with Item No pattern. however it could be another field... possibly the other unks. + bf.WriteUint16(0) //Unk4, gets cast to uint8 + bf.WriteUint32(0) //Unk5 + bf.WriteUint32(uint32(item.Deadline.Unix())) + } + if len(items) == 0 { + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + } else { + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + } + } else { + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfAcquireItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireItem) + if s.server.db == nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + for _, id := range pkt.RewardIDs { + _, err := s.server.db.Exec(`INSERT INTO campaign_rewards_claimed (reward_id, character_id) VALUES ($1, $2)`, id, s.charID) + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + } + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} + +func handleMsgMhfTransferItem(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfTransferItem) + if s.server.db == nil { + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + return + } + if pkt.ItemType == 9 { + var campaignID uint32 + err := s.server.db.QueryRow(` + SELECT ce.campaign_id FROM campaign_rewards ce + JOIN event_quests eq ON ce.item_id = eq.quest_id + WHERE eq.id = $1 + `, pkt.QuestID).Scan(&campaignID) + if err == nil { + _, err = s.server.db.Exec(`INSERT INTO campaign_quest (campaign_id, character_id) VALUES ($1, $2)`, campaignID, s.charID) + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + } + } doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } diff --git a/server/channelserver/handlers_items.go b/server/channelserver/handlers_items.go index 83ab57b5b..caa1bf868 100644 --- a/server/channelserver/handlers_items.go +++ b/server/channelserver/handlers_items.go @@ -9,11 +9,6 @@ import ( "go.uber.org/zap" ) -func handleMsgMhfTransferItem(s *Session, p mhfpacket.MHFPacket) { - pkt := p.(*mhfpacket.MsgMhfTransferItem) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) -} - func handleMsgMhfEnumeratePrice(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumeratePrice) bf := byteframe.NewByteFrame() diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 9847b1d28..93226ae40 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -313,7 +313,34 @@ func makeEventQuest(s *Session, eq EventQuest) ([]byte, error) { } bf.WriteUint8(eq.QuestType) if eq.QuestType == QuestTypeSpecialTool { - bf.WriteBool(false) + var stamps, required int + var deadline time.Time + err := s.server.db.QueryRow(`SELECT COUNT(*) FROM campaign_state WHERE campaign_id = ( + SELECT campaign_id + FROM campaign_rewards + WHERE item_type = 9 + AND item_id = $1 + LIMIT 1 + ) AND character_id = $2`, eq.QuestID, s.charID).Scan(&stamps) + if err != nil { + bf.WriteBool(false) + } else { + err = s.server.db.QueryRow(`SELECT stamps, end_time + FROM campaigns + WHERE id = ( + SELECT campaign_id + FROM campaign_rewards + WHERE item_type = 9 + AND item_id = $1 + LIMIT 1 + )`, eq.QuestID).Scan(&required, &deadline) + required = campaignRequiredStamps(required) + if err == nil && stamps >= required && deadline.After(time.Now()) { + bf.WriteBool(true) + } else { + bf.WriteBool(false) + } + } } else { bf.WriteBool(true) } diff --git a/server/migrations/seed/CampaignDemo.sql b/server/migrations/seed/CampaignDemo.sql new file mode 100644 index 000000000..343504328 --- /dev/null +++ b/server/migrations/seed/CampaignDemo.sql @@ -0,0 +1,5169 @@ +BEGIN; + +INSERT INTO + public.campaigns ( + id, + min_hr, + max_hr, + min_sr, + max_sr, + min_gr, + max_gr, + reward_type, + stamps, + receive_type, + background_id, + start_time, + end_time, + title, + reward, + link, + code_prefix + ) +VALUES + ( + 921805910, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ガイド娘の差し入れ', + 'ガイド娘の差し入れ', + 'http://www.mhf-z.jp/', + 'SCSC' + ), ( + 142209682, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'VISAクエスト【ベイルZP】', + 'VISAクエスト【ベイルZP】', + 'http://www.mhf-z.jp/', + 'VC10' + ), ( + 488594222, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '推奨PC特典トゥールム', + '推奨PC特典トゥールム', + 'http://www.mhf-z.jp', + 'TOUR' + ), ( + 649144304, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'VISAクエスト【ベイルGP】', + 'VISAクエスト【ベイルGP】', + 'http://www.mhf-z.jp', + 'VC09' + ), ( + 421484974, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '新・狩友紹介特典【紹介】', + '新・狩友紹介特典【紹介】', + 'http://www.mhf-z.jp', + 'SFR1' + ), ( + 730957531, + 100, + 999, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '新・狩友紹介特典【HR100・複数】', + '新・狩友紹介特典【HR100・複数】', + 'http://www.mhf-z.jp', + 'SFR7' + ), ( + 865537514, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'G-Tune特典G-Tuneソード', + 'GTUNE生産券×1', + 'http://www.mhf-z.jp', + 'GT01' + ), ( + 488594158, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'VISAクエスト【ベイルGS】', + 'VISAクエスト【ベイルGS】', + 'http://www.mhf-z.jp', + 'VC08' + ), ( + 699557165, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'VISAクエスト【ベイルHS】', + 'VISAクエスト【ベイルHS】', + 'http://www.mhf-z.jp', + 'VC07' + ), ( + 766535101, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'はじめての狩猟セット【蒼】', + 'はじめての狩猟セット【蒼】', + 'http://www.mhf-z.jp', + 'HSSG' + ), ( + 919840278, + -1, + -1, + -1, + -1, + 1, + 999, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'レア素材獲得クエスト[GR1]', + 'レア素材獲得クエスト[GR1]', + 'http://www.mhf-z.jp', + 'RAQ8' + ), ( + 747709809, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 10, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「ゴスペル風の服」', + 'プーギー服「ゴスペル風の服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG08' + ), ( + 257005183, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'スリートキット生産券一式', + 'スリートキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'SRTK' + ), ( + 649274608, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ステノキット生産券一式', + 'ステノキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'STNK' + ), ( + 680601073, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'エディオキット生産券一式', + 'エディオキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'EDEK' + ), ( + 142209810, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ガリトスキット生産券一式', + 'ガリトスキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'GLSK' + ), ( + 140111954, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 10, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「パリアっぽい服」', + 'プーギー服「パリアっぽい服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG10' + ), ( + 225604757, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 10, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「釣り上げそうな服」', + 'プーギー服「釣り上げそうな服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG12' + ), ( + 970837204, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパックG第1弾', + 'ブースターパックG第1弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BGK1' + ), ( + 647465687, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'Fate/stay night生産券一式', + 'Fate/stay night生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'FSNK' + ), ( + 615934211, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '初音ミクキット生産券一式', + '初音ミクキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'HMKK' + ), ( + 477754130, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'G強化券', + 'G強化券×10', + 'http://members.mhf-z.jp/topic/payment/', + 'GUGK' + ), ( + 477131813, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '伊達政宗ノ装束生産券一式', + '伊達政宗ノ装束生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'BDMK' + ), ( + 919839894, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '真田幸村ノ装束生産券一式', + '真田幸村ノ装束生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'BSYK' + ), ( + 410645266, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'VISAクエスト【ベイルHC】', + 'VISAクエスト【ベイルHC】', + 'http://www.mhf-z.jp', + 'VC06' + ), ( + 769511124, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'VISAクエスト【ベイルF】', + 'VISAクエスト【ベイルF】', + 'http://www.mhf-z.jp', + 'VC04' + ), ( + 697509361, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'VISAクエスト【ベイルFZ】', + 'VISAクエスト【ベイルFZ】', + 'http://www.mhf-z.jp', + 'VC05' + ), ( + 1037946068, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'SF25周年記念キット生産券一式', + 'SF25周年記念キット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'SFAK' + ), ( + 615803171, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'グロリアキット生産券一式', + 'グロリアキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'GLRK' + ), ( + 257005151, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '鬼武者キット生産券一式', + '鬼武者キット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'NMSK' + ), ( + 209318802, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'クロースキット生産券一式', + 'クロースキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'CLTK' + ), ( + 664111863, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'テクストキット生産券一式', + 'テクストキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'TEKK' + ), ( + 597101930, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ファランキット生産券一式', + 'ファランキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'FRNK' + ), ( + 494917916, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'アージェキット生産券一式', + 'アージェキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'ARJK' + ), ( + 477262885, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ガイド娘のお助けパック第5弾', + 'ガイド娘のお助けパック第5弾', + 'http://members.mhf-z.jp/topic/payment/', + 'GG5L' + ), ( + 584295574, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第15弾', + 'ブースターパック第15弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BK15' + ), ( + 615934227, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'レイストキット生産券一式', + 'レイストキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'RESK' + ), ( + 865438535, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 18, + NOW(), + NOW() + INTERVAL '24 hours', + 'ドスパラPC特典ドスパライズ', + 'ドスパライズ', + 'http://www.mhf-z.jp', + 'DP01' + ), ( + 209318162, + 300, + 999, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'レア素材獲得クエスト[HR300]', + 'レア素材獲得クエスト[HR300]', + 'http://www.mhf-z.jp', + 'RAQ7' + ), ( + 427809564, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '秘伝書コース', + '秘伝書コース購入者プレゼント', + 'http://members.mhf-z.jp/topic/payment/', + 'HDNP' + ), ( + 769510612, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターピアス第4弾', + 'ブースターピアス第4弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BUP4' + ), ( + 632580403, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第14弾', + 'ブースターパック第14弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BK14' + ), ( + 697509345, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ガイド娘のお助けパック第4弾', + 'ガイド娘のお助けパック第4弾', + 'http://members.mhf-z.jp/topic/payment/', + 'GG4L' + ), ( + 477754258, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'シエナキット生産券一式', + 'シエナキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'SENK' + ), ( + 982746827, + 11, + 999, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '狩友紹介特典【HR11】', + '狩友紹介特典【HR11】', + 'http://www.mhf-z.jp', + 'FRS2' + ), ( + 427809180, + 31, + 999, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '狩友紹介特典【HR31】', + '狩友紹介特典【HR31】', + 'http://www.mhf-z.jp', + 'FRS3' + ), ( + 326425369, + 51, + 999, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '狩友紹介特典【HR51】', + '狩友紹介特典【HR51】', + 'http://www.mhf-z.jp', + 'FRS4' + ), ( + 932646762, + 71, + 999, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '狩友紹介特典【HR71】', + '狩友紹介特典【HR71】', + 'http://www.mhf-z.jp', + 'FRS5' + ), ( + 664242887, + 100, + 999, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '狩友紹介特典【HR100】', + '狩友紹介特典【HR100】', + 'http://www.mhf-z.jp', + 'FRS6' + ), ( + 324377496, + 100, + 999, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '狩友紹介特典【HR100・複数】', + '狩友紹介特典【HR100・複数】', + 'http://www.mhf-z.jp', + 'FRS7' + ), ( + 488593646, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '狩友紹介特典【紹介】', + '狩友紹介特典【紹介】', + 'http://www.mhf-z.jp', + 'FRS1' + ), ( + 917579440, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ガイド娘のお助けパック第3弾', + 'ガイド娘のお助けパック第3弾', + 'http://members.mhf-z.jp/topic/payment/', + 'GG3L' + ), ( + 1032922465, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第13弾', + 'ブースターパック第13弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BK13' + ), ( + 410775890, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ターボパック第6弾', + 'ターボパック第6弾', + 'http://members.mhf-z.jp/topic/payment/', + 'TPK6' + ), ( + 190027375, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターピアス第3弾', + 'ブースターピアス第3弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BUP3' + ), ( + 704499284, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'カウチュキット生産券一式', + 'カウチュキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'CULK' + ), ( + 749757837, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'VISA引換券交換【30日】', + 'VISA引換券交換【30日】', + 'http://www.mhf-z.jp', + 'VT30' + ), ( + 41343673, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'パッケージ引換券交換【30日】', + 'パッケージ引換券交換【30日】', + 'http://www.mhf-z.jp', + 'PT30' + ), ( + 664080362, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'パッケージ引換券交換【60日】', + 'パッケージ引換券交換【60日】', + 'http://www.mhf-z.jp', + 'PT60' + ), ( + 582034480, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'はじめての狩猟セット【紅】', + 'はじめての狩猟セット【紅】', + 'http://www.mhf-z.jp', + 'HSSD' + ), ( + 884238483, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ガイド娘のお助けパック第2弾', + 'ガイド娘のお助けパック第2弾', + 'http://members.mhf-z.jp/topic/payment/', + 'GG2L' + ), ( + 125278872, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ヴァンパイアキット生産券一式', + 'ヴァンパイアキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'VAMK' + ), ( + 848792567, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'トラスキット生産券一式', + 'トラスキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'TRSK' + ), ( + 852600342, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターピアス第2弾', + 'ブースターピアス第2弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BUP2' + ), ( + 426931253, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第12弾', + 'ブースターパック第12弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BK12' + ), ( + 582034992, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '推奨PC特典マグネストーン', + '推奨PC特典マグネストーン', + 'http://www.mhf-z.jp', + 'RPC1' + ), ( + 919708822, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 10, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「レインボウな服」', + 'プーギー服「レインボウな服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG4A' + ), ( + 477885266, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第11弾', + 'ブースターパック第11弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BK11' + ), ( + 1032922449, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'マイストキット生産券一式', + 'マイストキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'MAIK' + ), ( + 190027359, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ターボパック第5弾', + 'ターボパック第5弾', + 'http://members.mhf-z.jp/topic/payment/', + 'TPK5' + ), ( + 917578800, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターピアス', + 'ブースターピアス', + 'http://members.mhf-z.jp/topic/payment/', + 'BUP1' + ), ( + 651273238, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ガイド娘のお助けパック', + 'ガイド娘のお助けパック', + 'http://members.mhf-z.jp/topic/payment/', + 'GGHL' + ), ( + 157276444, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '蘭陀キット生産券一式', + '蘭陀キット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'RANK' + ), ( + 664079850, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'スキルカフP セット', + 'スキルカフP セット', + 'http://members.mhf-z.jp/topic/payment/', + 'SC2K' + ), ( + 490559854, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第10弾', + 'ブースターパック第10弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BK10' + ), ( + 1066502091, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'スパIVキット第2弾生産券一式', + 'スパIVキット第2弾生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'SU2K' + ), ( + 766666125, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 10, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'カシラの差し入れ', + 'カシラの差し入れ', + 'http://www.mhf-z.jp', + 'SASB' + ), ( + 917579312, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 10, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '教官見習ネコの差し入れ', + '教官見習ネコの差し入れ', + 'http://www.mhf-z.jp', + 'SASA' + ), ( + 58169496, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'レア素材獲得クエスト[HR100]', + 'レア素材獲得クエスト[HR100]', + 'http://www.mhf-z.jp', + 'RAQ6' + ), ( + 57989801, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'レア素材獲得クエスト[HR31]', + 'レア素材獲得クエスト[HR31]', + 'http://www.mhf-g.jp', + 'RAQ3' + ), ( + 865406314, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'レア素材獲得クエスト[HR51]', + 'レア素材獲得クエスト[HR51]', + 'http://www.mhf-z.jp', + 'RAQ4' + ), ( + 848792551, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'レア素材獲得クエスト[HR71]', + 'レア素材獲得クエスト[HR71]', + 'http://www.mhf-z.jp', + 'RAQ5' + ), ( + 865438711, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ターボパック第4弾', + 'ターボパック第4弾', + 'http://members.mhf-z.jp/topic/payment/', + 'TPK4' + ), ( + 596970858, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第9弾', + 'ブースターパック第9弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BPK9' + ), ( + 57989769, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'バーニーキット生産券一式', + 'バーニーキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'BUKT' + ), ( + 884238467, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 10, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'マイトレポイント10P', + 'マイトレポイント10P', + 'http://www.mhf-z.jp', + 'MYTP' + ), ( + 125278360, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'スパIVキット生産券一式', + 'スパIVキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'S4KT' + ), ( + 766666173, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ゴルトキット生産券一式', + 'ゴルトキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'GLKT' + ), ( + 58169880, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ターボパックN第2弾', + 'ターボパックN第2弾', + 'http://members.mhf-z.jp/topic/payment/', + 'TPN2' + ), ( + 58120841, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第8弾', + 'ブースターパック第8弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BPK8' + ), ( + 848661495, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'リゲリアキット生産券一式', + 'リゲリアキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'RGKT' + ), ( + 865406954, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'クレールキット生産券一式', + 'クレールキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'CLKT' + ), ( + 901015731, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'シャランキット生産券一式', + 'シャランキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'SAKT' + ), ( + 702533268, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 10, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「アクラっぽい服」', + 'プーギー服「アクラっぽい服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG07' + ), ( + 584164886, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 10, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「美味しそうな服」', + 'プーギー服「美味しそうな服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG13' + ), ( + 425712412, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ターボパック第3弾', + 'ターボパック第3弾', + 'http://members.mhf-z.jp/topic/payment/', + 'TPK3' + ), ( + 749888957, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'きんねこぎんねこキット生産券一式', + 'きんねこぎんねこキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'GSKT' + ), ( + 1066633211, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第7弾', + 'ブースターパック第7弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BPK7' + ), ( + 702532628, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'アリストキット生産券一式', + 'アリストキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'ASKT' + ), ( + 764487025, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第6弾', + 'ブースターパック第6弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BPK6' + ), ( + 714180459, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第5弾', + 'ブースターパック第5弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BPK5' + ), ( + 492820700, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ターボパック第2弾', + 'ターボパック第2弾', + 'http://members.mhf-z.jp/topic/payment/', + 'TPK2' + ), ( + 225604741, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ターボパックN', + 'ターボパックN', + 'http://members.mhf-z.jp/topic/payment/', + 'TPN1' + ), ( + 865438551, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'スキルカフPセット', + 'スキルカフPセット', + 'http://members.mhf-z.jp/topic/payment/', + 'SCP1' + ), ( + 391617368, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'イメチェンサービス', + 'イメチェンサービス', + 'http://members.mhf-z.jp/topic/payment/', + 'IMCH' + ), ( + 309779081, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'メレティキット生産券一式', + 'メレティキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'MTKT' + ), ( + 649143728, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'フェルムキット生産券一式', + 'フェルムキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'FLKT' + ), ( + 123182040, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'レアルキット生産券一式', + 'レアルキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'RLKT' + ), ( + 766534669, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'アルマキット生産券一式', + 'アルマキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'APK1' + ), ( + 901015555, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'イクスキット生産券一式', + 'イクスキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'EXKT' + ), ( + 919708950, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'リアンキット生産券一式', + 'リアンキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'LEKT' + ), ( + 666307882, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'マギサ/ウィザーキット生産券一式', + 'マギサ/ウィザーキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'MGWZ' + ), ( + 766665773, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + '星祭/七夕キット生産券一式', + '星祭/七夕キット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'HTKT' + ), ( + 582035248, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プロミスキット生産券一式', + 'プロミスキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'PRMS' + ), ( + 173119487, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ホワイトメタルキット生産券一式', + 'ホワイトメタルキット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'WMTL' + ), ( + 766534701, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'しろねこ服キット生産券一式', + 'しろねこ服キット生産券一式', + 'http://members.mhf-z.jp/topic/payment/', + 'SRNK' + ), ( + 747709777, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ターボパック第1弾', + 'ターボパック第1弾', + 'http://members.mhf-z.jp/topic/payment/', + 'TPK1' + ), ( + 189896703, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第4弾', + 'ブースターパック第4弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BPK4' + ), ( + 848792439, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第3弾', + 'ブースターパック第3弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BPK3' + ), ( + 970968596, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック第2弾', + 'ブースターパック第2弾', + 'http://members.mhf-z.jp/topic/payment/', + 'BPK2' + ), ( + 425711708, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'ブースターパック', + 'ブースターパック', + 'http://members.mhf-z.jp/topic/payment/', + 'BPAC' + ), ( + 867634602, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「悪戯しそうな服」', + 'プーギー服「悪戯しそうな服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG11' + ), ( + 714180427, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「ベルっぽい服」', + 'プーギー服「ベルっぽい服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG09' + ), ( + 309648009, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「アスール風の服」', + 'プーギー服「アスール風の服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG06' + ), ( + 391616984, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「エスピっぽい服」', + 'プーギー服「エスピっぽい服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG04' + ), ( + 208827525, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「コムラダ風の服」', + 'プーギー服「コムラダ風の服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG05' + ), ( + 326556329, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「ヒプっぽい服」', + 'プーギー服「ヒプっぽい服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG02' + ), ( + 934743978, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「ヴォルっぽい服」', + 'プーギー服「ヴォルっぽい服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG03' + ), ( + 224385244, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'プーギー服「野生的な服」', + 'プーギー服「野生的な服」', + 'http://members.mhf-z.jp/topic/payment/', + 'PG01' + ), ( + 884369427, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 10, + 41, + NOW(), + NOW() + INTERVAL '24 hours', + 'マイトレポイント30P', + 'マイトレポイント30P', + 'http://www.mhf-z.jp', + 'S3P2' + ), ( + 867634474, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 10, + 57, + NOW(), + NOW() + INTERVAL '24 hours', + '便利アイテムセット【入門】', + '便利アイテムセット【入門】', + 'http://www.mhf-z.jp', + 'BITM' + ), ( + 848792423, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 10, + 58, + NOW(), + NOW() + INTERVAL '24 hours', + '便利アイテムセット【達人】', + '便利アイテムセット【達人】', + 'http://www.mhf-z.jp', + 'EITM' + ), ( + 208696469, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'VISAクエスト【ゴシック】', + 'VISA生産券獲得クエスト', + 'http://www.mhf-z.jp', + 'VC01' + ), ( + 584165270, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'VISAクエスト【ゴシックF】', + 'VISA生産券獲得クエスト', + 'http://www.mhf-z.jp', + 'VC02' + ), ( + 901146643, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'VISAクエスト【ベイル】', + 'VISA生産券獲得クエスト', + 'http://www.mhf-z.jp', + 'VC03' + ), ( + 492821212, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'MHF VISAカード入会特典', + 'MHF VISAカード入会特典', + 'http://www.mhf-z.jp', + 'VG03' + ), ( + 901015571, + -1, + -1, + -1, + -1, + -1, + -1, + 2, + 0, + 0, + 12, + NOW(), + NOW() + INTERVAL '24 hours', + 'レア素材獲得クエスト[HR11]', + 'レア素材獲得クエスト[HR11]', + 'http://www.mhf-z.jp', + 'RAQ2' + ), ( + 1038077588, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 5, + NOW(), + NOW() + INTERVAL '24 hours', + 'ポルタチケット配布所', + '換金用アイテム:ポルタチケット', + 'http://www.mhf-z.jp', + 'PTC1' + ), ( + 190027775, + -1, + -1, + -1, + -1, + -1, + -1, + 1, + 0, + 0, + 44, + NOW(), + NOW() + INTERVAL '24 hours', + 'パタパタメラルー配布所', + '家具:パタパタメラルー', + 'http://www.mhf-z.jp', + 'PATA' + ); + +INSERT INTO + public.campaign_categories (id, type, title, description) +VALUES + ( + 1, + 0, + 'イベント・キャンペーン', + '各種~C04イベント~C00用のイベントコードや、各 +種~C04キャンペーン~C00で入手できるイベントコ +ードを入力することができます。' + ), ( + 2, + 0, + 'パッケージ特典', + '~C11プレミアムパッケージ~C00など、各種~C04パッ +ケージ~C00に付属されているイベントコード +を入力することができます。' + ), ( + 3, + 0, + '関連グッズ付属特典', + '攻略本やゲームパッドなど、各種~C04MHF関 +連商品~C00に付属されているイベントコード +を入力することができます。' + ), ( + 5, + 0, + 'その他', + '複数の手段で入手できるイベントコード +や不具合のアイテム補償用などのイベン +トコードを入力することができます。' + ), ( + 6, + 1, + 'プレミアムキット・オリジナル', + 'アイテム販売商品~C11プレミアムキットシ +リーズ【オリジナルキット】~C00のイベン +トコードを入力することができます。' + ), ( + 7, + 1, + 'プレミアムキット・パッケージ', + 'アイテム販売商品~C11プレミアムキットシ +リーズ【パッケージキット】~C00のイベン +トコードを入力することができます。' + ), ( + 8, + 1, + 'ブースターパック', + 'アイテム販売商品~C11ブースターパック~C00の +イベントコードを入力することができま +す。' + ), ( + 9, + 1, + 'ターボパック', + 'アイテム販売商品~C11ターボパック~C00のイベ +ントコードを入力することができます。' + ), ( + 10, + 1, + 'マイトレプーギー服', + 'アイテム販売商品やパッケージに付属し +ている~C11マイトレプーギー服~C00のイベント +コードを入力することができます。' + ), ( + 11, + 1, + 'その他の商品', + 'アイテム販売商品~C11スキルカフPセット~C00や +~C11イメチェンサービス~C00などのイベントコ +ードを入力することができます。' + ); + +INSERT INTO + public.campaign_category_links (campaign_id, category_id) +VALUES + (921805910, 1), + (142209682, 3), + (488594222, 1), + (488594222, 3), + (649144304, 3), + (421484974, 1), + (730957531, 1), + (865537514, 3), + (488594158, 3), + (699557165, 3), + (766535101, 1), + (766535101, 3), + (919840278, 3), + (919840278, 5), + (747709809, 10), + (257005183, 7), + (649274608, 7), + (680601073, 7), + (142209810, 7), + (140111954, 10), + (225604757, 10), + (970837204, 8), + (647465687, 6), + (615934211, 6), + (477754130, 11), + (477131813, 6), + (919839894, 6), + (410645266, 3), + (769511124, 3), + (697509361, 3), + (1037946068, 6), + (615803171, 6), + (257005151, 6), + (209318802, 6), + (664111863, 7), + (597101930, 7), + (494917916, 7), + (477262885, 11), + (584295574, 8), + (615934227, 6), + (865438535, 3), + (209318162, 1), + (209318162, 5), + (427809564, 11), + (769510612, 8), + (632580403, 8), + (697509345, 11), + (477754258, 6), + (982746827, 1), + (427809180, 1), + (326425369, 1), + (932646762, 1), + (664242887, 1), + (324377496, 1), + (488593646, 1), + (917579440, 11), + (1032922465, 8), + (410775890, 9), + (190027375, 8), + (704499284, 6), + (749757837, 1), + (749757837, 3), + (41343673, 2), + (664080362, 2), + (582034480, 3), + (884238483, 11), + (125278872, 6), + (848792567, 6), + (852600342, 8), + (426931253, 8), + (582034992, 3), + (919708822, 10), + (477885266, 8), + (1032922449, 6), + (190027359, 9), + (917578800, 8), + (651273238, 11), + (157276444, 6), + (664079850, 11), + (490559854, 8), + (1066502091, 6), + (766666125, 1), + (766666125, 2), + (766666125, 5), + (766666125, 11), + (917579312, 1), + (917579312, 2), + (917579312, 5), + (917579312, 11), + (58169496, 1), + (58169496, 2), + (58169496, 5), + (57989801, 1), + (57989801, 2), + (57989801, 5), + (865406314, 1), + (865406314, 2), + (865406314, 5), + (848792551, 1), + (848792551, 2), + (848792551, 5), + (865438711, 9), + (596970858, 8), + (57989769, 6), + (884238467, 1), + (884238467, 5), + (884238467, 11), + (125278360, 6), + (766666173, 7), + (58169880, 9), + (58120841, 8), + (848661495, 6), + (865406954, 7), + (901015731, 7), + (702533268, 10), + (584164886, 10), + (425712412, 9), + (749888957, 7), + (1066633211, 8), + (702532628, 6), + (764487025, 8), + (714180459, 8), + (492820700, 9), + (225604741, 9), + (865438551, 11), + (391617368, 11), + (309779081, 6), + (649143728, 6), + (123182040, 6), + (766534669, 6), + (901015555, 7), + (919708950, 7), + (666307882, 6), + (766665773, 7), + (582035248, 7), + (173119487, 7), + (766534701, 7), + (747709777, 9), + (189896703, 8), + (848792439, 8), + (970968596, 8), + (425711708, 8), + (867634602, 10), + (714180427, 10), + (309648009, 10), + (391616984, 10), + (208827525, 10), + (326556329, 10), + (934743978, 10), + (224385244, 10), + (884369427, 1), + (884369427, 2), + (884369427, 5), + (884369427, 11), + (867634474, 5), + (867634474, 11), + (848792423, 5), + (848792423, 11), + (208696469, 1), + (208696469, 3), + (584165270, 1), + (584165270, 3), + (901146643, 1), + (901146643, 3), + (492821212, 1), + (492821212, 3), + (901015571, 1), + (901015571, 2), + (901015571, 5), + (1038077588, 1), + (1038077588, 5), + (190027775, 1), + (190027775, 5); + +INSERT INTO + public.campaign_rewards ( + campaign_id, + item_type, + quantity, + item_id + ) +VALUES + ( + 410645266, + 9, + 0, + 40161 + ), ( + 884238467, + 14, + 10, + 0 + ), ( + 747709809, + 15, + 1, + 16 + ), ( + 140111954, + 15, + 1, + 19 + ), ( + 225604757, + 15, + 1, + 26 + ), ( + 919708822, + 15, + 1, + 28 + ), ( + 702533268, + 15, + 1, + 11 + ), ( + 584164886, + 15, + 1, + 25 + ), ( + 867634602, + 15, + 1, + 21 + ), ( + 714180427, + 15, + 1, + 15 + ), ( + 309648009, + 15, + 1, + 12 + ), ( + 391616984, + 15, + 1, + 7 + ), ( + 208827525, + 15, + 1, + 8 + ), ( + 326556329, + 15, + 1, + 5 + ), ( + 934743978, + 15, + 1, + 6 + ), ( + 224385244, + 15, + 1, + 4 + ), ( + 697509361, + 9, + 0, + 40143 + ), ( + 769511124, + 9, + 0, + 40141 + ), ( + 901146643, + 9, + 0, + 40081 + ), ( + 584165270, + 9, + 0, + 40080 + ), ( + 208696469, + 9, + 0, + 40079 + ), ( + 492821212, + 7, + 110, + 1859 + ), ( + 208696469, + 9, + 0, + 40079 + ), ( + 492821212, + 7, + 110, + 1859 + ), ( + 190027775, + 8, + 1, + 96 + ), ( + 884369427, + 14, + 30, + 0 + ), ( + 57989769, + 7, + 1, + 3617 + ), ( + 57989769, + 7, + 1, + 3618 + ), ( + 57989769, + 7, + 1, + 3622 + ), ( + 57989769, + 7, + 1, + 3623 + ), ( + 57989769, + 7, + 1, + 3624 + ), ( + 57989769, + 7, + 1, + 3625 + ), ( + 57989769, + 7, + 1, + 3626 + ), ( + 57989769, + 7, + 1, + 3627 + ), ( + 57989769, + 7, + 2, + 3631 + ), ( + 57989769, + 7, + 2, + 3632 + ), ( + 57989769, + 7, + 2, + 3633 + ), ( + 57989769, + 7, + 2, + 3634 + ), ( + 57989769, + 7, + 2, + 3635 + ), ( + 173119487, + 7, + 1, + 1767 + ), ( + 173119487, + 7, + 1, + 1759 + ), ( + 173119487, + 7, + 1, + 1760 + ), ( + 173119487, + 7, + 1, + 1776 + ), ( + 173119487, + 7, + 1, + 1777 + ), ( + 173119487, + 7, + 1, + 1778 + ), ( + 173119487, + 7, + 1, + 1779 + ), ( + 173119487, + 7, + 1, + 1780 + ), ( + 173119487, + 7, + 1, + 1781 + ), ( + 173119487, + 7, + 1, + 1806 + ), ( + 173119487, + 7, + 1, + 1807 + ), ( + 582035248, + 7, + 1, + 1460 + ), ( + 582035248, + 7, + 1, + 1761 + ), ( + 582035248, + 7, + 1, + 1762 + ), ( + 582035248, + 7, + 1, + 1461 + ), ( + 582035248, + 7, + 1, + 1462 + ), ( + 582035248, + 7, + 1, + 1464 + ), ( + 582035248, + 7, + 1, + 1463 + ), ( + 582035248, + 7, + 1, + 1465 + ), ( + 582035248, + 7, + 1, + 1466 + ), ( + 766665773, + 7, + 1, + 1532 + ), ( + 766665773, + 7, + 1, + 1084 + ), ( + 766665773, + 7, + 1, + 2020 + ), ( + 766665773, + 7, + 1, + 2019 + ), ( + 766665773, + 7, + 5, + 1533 + ), ( + 766665773, + 7, + 5, + 1534 + ), ( + 766665773, + 7, + 1, + 1535 + ), ( + 766665773, + 7, + 1, + 1074 + ), ( + 919708950, + 7, + 1, + 1614 + ), ( + 919708950, + 7, + 1, + 1615 + ), ( + 919708950, + 7, + 1, + 1616 + ), ( + 919708950, + 7, + 1, + 1617 + ), ( + 919708950, + 7, + 1, + 1618 + ), ( + 919708950, + 7, + 1, + 1619 + ), ( + 919708950, + 7, + 1, + 1620 + ), ( + 919708950, + 7, + 1, + 1621 + ), ( + 919708950, + 7, + 2, + 1622 + ), ( + 919708950, + 7, + 2, + 1623 + ), ( + 919708950, + 7, + 2, + 1624 + ), ( + 919708950, + 7, + 2, + 1625 + ), ( + 919708950, + 7, + 2, + 1626 + ), ( + 901015555, + 7, + 1, + 1765 + ), ( + 901015555, + 7, + 1, + 1766 + ), ( + 901015555, + 7, + 1, + 1763 + ), ( + 901015555, + 7, + 1, + 1764 + ), ( + 901015555, + 7, + 2, + 1769 + ), ( + 901015555, + 7, + 2, + 1770 + ), ( + 901015555, + 7, + 2, + 1771 + ), ( + 901015555, + 7, + 2, + 1772 + ), ( + 901015555, + 7, + 2, + 1773 + ), ( + 749888957, + 7, + 1, + 2972 + ), ( + 749888957, + 7, + 1, + 2973 + ), ( + 749888957, + 7, + 1, + 2983 + ), ( + 749888957, + 7, + 1, + 2984 + ), ( + 749888957, + 7, + 1, + 2985 + ), ( + 749888957, + 7, + 1, + 2986 + ), ( + 749888957, + 7, + 1, + 2987 + ), ( + 749888957, + 7, + 1, + 2988 + ), ( + 749888957, + 7, + 2, + 3012 + ), ( + 749888957, + 7, + 2, + 3013 + ), ( + 749888957, + 7, + 2, + 3014 + ), ( + 749888957, + 7, + 2, + 3015 + ), ( + 749888957, + 7, + 2, + 3016 + ), ( + 749888957, + 7, + 2, + 3017 + ), ( + 749888957, + 7, + 2, + 3018 + ), ( + 749888957, + 7, + 2, + 3019 + ), ( + 749888957, + 7, + 2, + 3020 + ), ( + 749888957, + 7, + 2, + 3021 + ), ( + 865406954, + 7, + 1, + 2015 + ), ( + 865406954, + 7, + 1, + 2016 + ), ( + 865406954, + 7, + 1, + 2017 + ), ( + 865406954, + 7, + 1, + 2018 + ), ( + 865406954, + 7, + 2, + 2026 + ), ( + 865406954, + 7, + 2, + 2027 + ), ( + 865406954, + 7, + 2, + 2028 + ), ( + 865406954, + 7, + 2, + 2029 + ), ( + 865406954, + 7, + 2, + 2030 + ), ( + 766666173, + 7, + 1, + 2099 + ), ( + 766666173, + 7, + 1, + 2100 + ), ( + 766666173, + 7, + 1, + 2101 + ), ( + 766666173, + 7, + 1, + 2102 + ), ( + 766666173, + 7, + 1, + 2105 + ), ( + 766666173, + 7, + 1, + 2106 + ), ( + 766666173, + 7, + 1, + 2107 + ), ( + 766666173, + 7, + 1, + 2108 + ), ( + 766666173, + 7, + 1, + 2109 + ), ( + 766666173, + 7, + 1, + 2110 + ), ( + 766666173, + 7, + 2, + 2121 + ), ( + 766666173, + 7, + 2, + 2122 + ), ( + 766666173, + 7, + 2, + 2123 + ), ( + 766666173, + 7, + 2, + 2124 + ), ( + 766666173, + 7, + 2, + 2125 + ), ( + 664111863, + 7, + 1, + 2561 + ), ( + 664111863, + 7, + 1, + 2562 + ), ( + 664111863, + 7, + 1, + 2564 + ), ( + 664111863, + 7, + 1, + 2563 + ), ( + 664111863, + 7, + 1, + 2567 + ), ( + 664111863, + 7, + 1, + 2568 + ), ( + 664111863, + 7, + 1, + 2569 + ), ( + 664111863, + 7, + 1, + 2570 + ), ( + 664111863, + 7, + 1, + 2571 + ), ( + 664111863, + 7, + 1, + 2572 + ), ( + 664111863, + 7, + 2, + 2578 + ), ( + 664111863, + 7, + 2, + 2579 + ), ( + 664111863, + 7, + 2, + 2580 + ), ( + 664111863, + 7, + 2, + 2581 + ), ( + 664111863, + 7, + 2, + 2582 + ), ( + 664111863, + 7, + 2, + 2583 + ), ( + 664111863, + 7, + 2, + 2584 + ), ( + 664111863, + 7, + 2, + 2585 + ), ( + 664111863, + 7, + 2, + 2586 + ), ( + 664111863, + 7, + 2, + 2587 + ), ( + 664111863, + 7, + 2, + 2583 + ), ( + 664111863, + 7, + 2, + 2584 + ), ( + 664111863, + 7, + 2, + 2585 + ), ( + 664111863, + 7, + 2, + 2586 + ), ( + 664111863, + 7, + 2, + 2587 + ), ( + 597101930, + 7, + 1, + 2968 + ), ( + 597101930, + 7, + 1, + 2969 + ), ( + 597101930, + 7, + 1, + 2970 + ), ( + 597101930, + 7, + 1, + 2971 + ), ( + 597101930, + 7, + 1, + 2977 + ), ( + 597101930, + 7, + 1, + 2978 + ), ( + 597101930, + 7, + 1, + 2979 + ), ( + 597101930, + 7, + 1, + 6398 + ), ( + 597101930, + 7, + 1, + 2980 + ), ( + 597101930, + 7, + 1, + 2981 + ), ( + 597101930, + 7, + 1, + 2982 + ), ( + 597101930, + 7, + 1, + 6399 + ), ( + 597101930, + 7, + 2, + 3007 + ), ( + 597101930, + 7, + 2, + 3008 + ), ( + 597101930, + 7, + 2, + 3009 + ), ( + 597101930, + 7, + 2, + 3010 + ), ( + 597101930, + 7, + 2, + 3011 + ), ( + 666307882, + 7, + 1, + 1231 + ), ( + 666307882, + 7, + 1, + 1230 + ), ( + 666307882, + 7, + 1, + 1232 + ), ( + 666307882, + 7, + 2, + 1233 + ), ( + 666307882, + 7, + 2, + 1234 + ), ( + 666307882, + 7, + 2, + 1235 + ), ( + 666307882, + 7, + 2, + 1236 + ), ( + 666307882, + 7, + 2, + 1237 + ), ( + 766534669, + 7, + 1, + 1708 + ), ( + 766534669, + 7, + 1, + 1709 + ), ( + 766534669, + 7, + 1, + 1713 + ), ( + 766534669, + 7, + 1, + 1714 + ), ( + 766534669, + 7, + 1, + 1715 + ), ( + 766534669, + 7, + 4, + 1718 + ), ( + 766534669, + 7, + 2, + 1719 + ), ( + 766534669, + 7, + 2, + 1720 + ), ( + 766534669, + 7, + 2, + 1721 + ), ( + 766534669, + 7, + 2, + 1722 + ), ( + 901015731, + 7, + 1, + 1821 + ), ( + 901015731, + 7, + 1, + 1822 + ), ( + 901015731, + 7, + 1, + 1820 + ), ( + 901015731, + 7, + 1, + 1819 + ), ( + 901015731, + 7, + 1, + 1828 + ), ( + 901015731, + 7, + 1, + 1829 + ), ( + 901015731, + 7, + 2, + 1836 + ), ( + 901015731, + 7, + 2, + 1837 + ), ( + 901015731, + 7, + 2, + 1838 + ), ( + 901015731, + 7, + 2, + 1839 + ), ( + 901015731, + 7, + 2, + 1840 + ), ( + 123182040, + 7, + 1, + 1826 + ), ( + 123182040, + 7, + 1, + 1827 + ), ( + 123182040, + 7, + 1, + 1830 + ), ( + 123182040, + 7, + 1, + 1831 + ), ( + 123182040, + 7, + 1, + 1832 + ), ( + 123182040, + 7, + 1, + 1833 + ), ( + 123182040, + 7, + 1, + 1834 + ), ( + 123182040, + 7, + 1, + 1835 + ), ( + 123182040, + 7, + 2, + 1841 + ), ( + 123182040, + 7, + 2, + 1842 + ), ( + 123182040, + 7, + 2, + 1843 + ), ( + 123182040, + 7, + 2, + 1844 + ), ( + 123182040, + 7, + 2, + 1845 + ), ( + 649143728, + 7, + 1, + 2013 + ), ( + 649143728, + 7, + 1, + 2014 + ), ( + 649143728, + 7, + 1, + 2011 + ), ( + 649143728, + 7, + 1, + 2012 + ), ( + 649143728, + 7, + 2, + 2021 + ), ( + 649143728, + 7, + 2, + 2022 + ), ( + 649143728, + 7, + 2, + 2023 + ), ( + 649143728, + 7, + 2, + 2024 + ), ( + 649143728, + 7, + 2, + 2025 + ), ( + 309779081, + 7, + 1, + 2097 + ), ( + 309779081, + 7, + 1, + 2098 + ), ( + 309779081, + 7, + 1, + 2103 + ), ( + 309779081, + 7, + 1, + 2104 + ), ( + 309779081, + 7, + 2, + 2116 + ), ( + 309779081, + 7, + 2, + 2117 + ), ( + 309779081, + 7, + 2, + 2118 + ), ( + 309779081, + 7, + 2, + 2119 + ), ( + 309779081, + 7, + 2, + 2120 + ), ( + 702532628, + 7, + 1, + 2559 + ), ( + 702532628, + 7, + 1, + 2560 + ), ( + 702532628, + 7, + 1, + 2565 + ), ( + 702532628, + 7, + 1, + 2566 + ), ( + 702532628, + 7, + 2, + 2573 + ), ( + 702532628, + 7, + 2, + 2574 + ), ( + 702532628, + 7, + 2, + 2575 + ), ( + 702532628, + 7, + 2, + 2576 + ), ( + 702532628, + 7, + 2, + 2577 + ), ( + 848792567, + 7, + 1, + 4784 + ), ( + 848792567, + 7, + 1, + 4783 + ), ( + 848792567, + 7, + 1, + 4785 + ), ( + 848792567, + 7, + 1, + 4786 + ), ( + 848792567, + 7, + 2, + 4787 + ), ( + 848792567, + 7, + 2, + 4788 + ), ( + 848792567, + 7, + 2, + 4789 + ), ( + 848792567, + 7, + 2, + 4790 + ), ( + 848792567, + 7, + 2, + 4791 + ), ( + 848661495, + 7, + 1, + 3252 + ), ( + 848661495, + 7, + 1, + 3251 + ), ( + 848661495, + 7, + 1, + 3249 + ), ( + 848661495, + 7, + 1, + 3250 + ), ( + 848661495, + 7, + 2, + 3263 + ), ( + 848661495, + 7, + 2, + 3264 + ), ( + 848661495, + 7, + 2, + 3265 + ), ( + 848661495, + 7, + 2, + 3266 + ), ( + 848661495, + 7, + 2, + 3267 + ), ( + 704499284, + 7, + 1, + 5133 + ), ( + 704499284, + 7, + 1, + 5134 + ), ( + 704499284, + 7, + 1, + 5135 + ), ( + 704499284, + 7, + 1, + 5136 + ), ( + 704499284, + 7, + 2, + 5139 + ), ( + 704499284, + 7, + 2, + 5140 + ), ( + 704499284, + 7, + 2, + 5141 + ), ( + 704499284, + 7, + 2, + 5142 + ), ( + 704499284, + 7, + 2, + 5143 + ), ( + 157276444, + 7, + 1, + 4078 + ), ( + 157276444, + 7, + 1, + 4079 + ), ( + 157276444, + 7, + 1, + 4076 + ), ( + 157276444, + 7, + 1, + 4077 + ), ( + 157276444, + 7, + 2, + 4080 + ), ( + 157276444, + 7, + 2, + 4081 + ), ( + 157276444, + 7, + 2, + 4082 + ), ( + 157276444, + 7, + 2, + 4083 + ), ( + 157276444, + 7, + 2, + 4084 + ), ( + 209318802, + 7, + 1, + 6422 + ), ( + 209318802, + 7, + 1, + 6423 + ), ( + 209318802, + 7, + 1, + 6420 + ), ( + 209318802, + 7, + 1, + 6421 + ), ( + 209318802, + 7, + 1, + 6424 + ), ( + 209318802, + 7, + 1, + 6425 + ), ( + 209318802, + 7, + 2, + 6426 + ), ( + 209318802, + 7, + 2, + 6427 + ), ( + 209318802, + 7, + 2, + 6428 + ), ( + 209318802, + 7, + 2, + 6429 + ), ( + 209318802, + 7, + 2, + 6430 + ), ( + 494917916, + 7, + 2, + 2583 + ), ( + 494917916, + 7, + 2, + 2584 + ), ( + 494917916, + 7, + 2, + 2585 + ), ( + 494917916, + 7, + 2, + 2586 + ), ( + 494917916, + 7, + 2, + 2587 + ), ( + 477754258, + 7, + 1, + 5626 + ), ( + 477754258, + 7, + 1, + 5627 + ), ( + 477754258, + 7, + 1, + 5628 + ), ( + 477754258, + 7, + 1, + 5629 + ), ( + 477754258, + 7, + 1, + 5630 + ), ( + 477754258, + 7, + 1, + 5631 + ), ( + 477754258, + 7, + 1, + 5632 + ), ( + 477754258, + 7, + 1, + 5633 + ), ( + 477754258, + 7, + 1, + 5634 + ), ( + 477754258, + 7, + 1, + 5635 + ), ( + 477754258, + 7, + 2, + 5636 + ), ( + 477754258, + 7, + 2, + 5637 + ), ( + 477754258, + 7, + 2, + 5638 + ), ( + 477754258, + 7, + 2, + 5639 + ), ( + 477754258, + 7, + 2, + 5640 + ), ( + 257005151, + 7, + 1, + 6403 + ), ( + 257005151, + 7, + 1, + 6404 + ), ( + 257005151, + 7, + 1, + 6405 + ), ( + 257005151, + 7, + 1, + 6406 + ), ( + 257005151, + 7, + 1, + 6407 + ), ( + 257005151, + 7, + 1, + 6408 + ), ( + 257005151, + 7, + 1, + 6409 + ), ( + 257005151, + 7, + 1, + 6410 + ), ( + 257005151, + 7, + 1, + 6411 + ), ( + 257005151, + 7, + 1, + 6412 + ), ( + 257005151, + 7, + 1, + 6413 + ), ( + 257005151, + 7, + 1, + 6414 + ), ( + 257005151, + 7, + 2, + 6415 + ), ( + 257005151, + 7, + 2, + 6416 + ), ( + 257005151, + 7, + 2, + 6417 + ), ( + 257005151, + 7, + 2, + 6418 + ), ( + 257005151, + 7, + 2, + 6419 + ), ( + 615803171, + 7, + 1, + 6476 + ), ( + 615803171, + 7, + 1, + 6477 + ), ( + 615803171, + 7, + 1, + 6478 + ), ( + 615803171, + 7, + 1, + 6479 + ), ( + 615803171, + 7, + 1, + 6480 + ), ( + 615803171, + 7, + 1, + 6481 + ), ( + 615803171, + 7, + 1, + 6482 + ), ( + 615803171, + 7, + 1, + 6483 + ), ( + 615803171, + 7, + 1, + 6484 + ), ( + 615803171, + 7, + 1, + 6485 + ), ( + 615803171, + 7, + 1, + 6486 + ), ( + 615803171, + 7, + 1, + 6487 + ), ( + 615803171, + 7, + 2, + 6438 + ), ( + 615803171, + 7, + 2, + 6439 + ), ( + 615803171, + 7, + 2, + 6440 + ), ( + 615803171, + 7, + 2, + 6441 + ), ( + 615803171, + 7, + 2, + 6442 + ), ( + 125278360, + 7, + 2, + 3586 + ), ( + 125278360, + 7, + 2, + 3587 + ), ( + 125278360, + 7, + 2, + 3588 + ), ( + 125278360, + 7, + 2, + 3589 + ), ( + 125278360, + 7, + 2, + 3590 + ), ( + 1066502091, + 7, + 2, + 4042 + ), ( + 1066502091, + 7, + 2, + 4043 + ), ( + 1066502091, + 7, + 2, + 4044 + ), ( + 1066502091, + 7, + 2, + 4045 + ), ( + 1066502091, + 7, + 2, + 4046 + ), ( + 1037946068, + 7, + 2, + 6443 + ), ( + 1037946068, + 7, + 2, + 6444 + ), ( + 1037946068, + 7, + 2, + 6445 + ), ( + 1037946068, + 7, + 2, + 6446 + ), ( + 1037946068, + 7, + 2, + 6447 + ), ( + 919839894, + 7, + 1, + 7188 + ), ( + 919839894, + 7, + 1, + 7189 + ), ( + 919839894, + 7, + 1, + 7190 + ), ( + 919839894, + 7, + 1, + 7191 + ), ( + 919839894, + 7, + 2, + 7192 + ), ( + 919839894, + 7, + 2, + 7193 + ), ( + 919839894, + 7, + 2, + 7194 + ), ( + 919839894, + 7, + 2, + 7195 + ), ( + 919839894, + 7, + 2, + 7196 + ), ( + 477131813, + 7, + 1, + 7215 + ), ( + 477131813, + 7, + 1, + 7216 + ), ( + 477131813, + 7, + 1, + 7217 + ), ( + 477131813, + 7, + 1, + 7218 + ), ( + 477131813, + 7, + 2, + 7093 + ), ( + 477131813, + 7, + 2, + 7094 + ), ( + 477131813, + 7, + 2, + 7095 + ), ( + 477131813, + 7, + 2, + 7096 + ), ( + 477131813, + 7, + 2, + 7097 + ), ( + 615934211, + 7, + 1, + 7206 + ), ( + 615934211, + 7, + 1, + 7207 + ), ( + 615934211, + 7, + 1, + 7208 + ), ( + 615934211, + 7, + 1, + 7209 + ), ( + 615934211, + 7, + 2, + 7210 + ), ( + 615934211, + 7, + 2, + 7211 + ), ( + 615934211, + 7, + 2, + 7212 + ), ( + 615934211, + 7, + 2, + 7213 + ), ( + 615934211, + 7, + 2, + 7214 + ), ( + 647465687, + 7, + 1, + 7197 + ), ( + 647465687, + 7, + 1, + 7198 + ), ( + 647465687, + 7, + 1, + 7199 + ), ( + 647465687, + 7, + 1, + 7200 + ), ( + 647465687, + 7, + 2, + 7201 + ), ( + 647465687, + 7, + 2, + 7202 + ), ( + 647465687, + 7, + 2, + 7203 + ), ( + 647465687, + 7, + 2, + 7204 + ), ( + 647465687, + 7, + 2, + 7205 + ), ( + 257005183, + 7, + 1, + 3254 + ), ( + 257005183, + 7, + 1, + 3253 + ), ( + 257005183, + 7, + 1, + 3255 + ), ( + 257005183, + 7, + 1, + 3256 + ), ( + 257005183, + 7, + 1, + 3257 + ), ( + 257005183, + 7, + 1, + 3258 + ), ( + 257005183, + 7, + 1, + 3259 + ), ( + 257005183, + 7, + 1, + 6396 + ), ( + 257005183, + 7, + 1, + 3260 + ), ( + 257005183, + 7, + 1, + 3261 + ), ( + 257005183, + 7, + 1, + 3262 + ), ( + 257005183, + 7, + 1, + 6397 + ), ( + 257005183, + 7, + 2, + 3273 + ), ( + 257005183, + 7, + 2, + 3274 + ), ( + 257005183, + 7, + 2, + 3275 + ), ( + 257005183, + 7, + 2, + 3276 + ), ( + 257005183, + 7, + 2, + 3277 + ), ( + 257005183, + 7, + 2, + 3278 + ), ( + 257005183, + 7, + 2, + 3279 + ), ( + 257005183, + 7, + 2, + 3280 + ), ( + 257005183, + 7, + 2, + 3281 + ), ( + 257005183, + 7, + 2, + 3282 + ), ( + 257005183, + 7, + 2, + 7447 + ), ( + 257005183, + 7, + 2, + 7448 + ), ( + 257005183, + 7, + 2, + 8881 + ), ( + 257005183, + 7, + 2, + 8882 + ), ( + 649274608, + 7, + 1, + 3607 + ), ( + 649274608, + 7, + 1, + 3608 + ), ( + 649274608, + 7, + 1, + 3593 + ), ( + 649274608, + 7, + 1, + 3594 + ), ( + 649274608, + 7, + 1, + 3595 + ), ( + 649274608, + 7, + 1, + 3596 + ), ( + 649274608, + 7, + 2, + 3597 + ), ( + 649274608, + 7, + 2, + 3598 + ), ( + 649274608, + 7, + 2, + 3599 + ), ( + 649274608, + 7, + 2, + 3600 + ), ( + 649274608, + 7, + 2, + 3601 + ), ( + 649274608, + 7, + 2, + 3602 + ), ( + 649274608, + 7, + 2, + 3603 + ), ( + 649274608, + 7, + 2, + 3604 + ), ( + 649274608, + 7, + 2, + 3605 + ), ( + 649274608, + 7, + 2, + 3606 + ), ( + 680601073, + 7, + 1, + 4014 + ), ( + 680601073, + 7, + 1, + 4015 + ), ( + 680601073, + 7, + 1, + 4016 + ), ( + 680601073, + 7, + 1, + 4017 + ), ( + 680601073, + 7, + 1, + 4018 + ), ( + 680601073, + 7, + 1, + 4019 + ), ( + 680601073, + 7, + 1, + 4020 + ), ( + 680601073, + 7, + 1, + 4021 + ), ( + 680601073, + 7, + 1, + 4022 + ), ( + 680601073, + 7, + 1, + 4023 + ), ( + 680601073, + 7, + 2, + 4024 + ), ( + 680601073, + 7, + 2, + 4025 + ), ( + 680601073, + 7, + 2, + 4026 + ), ( + 680601073, + 7, + 2, + 4027 + ), ( + 680601073, + 7, + 2, + 4028 + ), ( + 680601073, + 7, + 2, + 4029 + ), ( + 680601073, + 7, + 2, + 4030 + ), ( + 680601073, + 7, + 2, + 4031 + ), ( + 680601073, + 7, + 2, + 4032 + ), ( + 680601073, + 7, + 2, + 4033 + ), ( + 142209810, + 7, + 1, + 4803 + ), ( + 142209810, + 7, + 1, + 4804 + ), ( + 142209810, + 7, + 1, + 4805 + ), ( + 142209810, + 7, + 1, + 4806 + ), ( + 142209810, + 7, + 1, + 4807 + ), ( + 142209810, + 7, + 1, + 4808 + ), ( + 142209810, + 7, + 1, + 4809 + ), ( + 142209810, + 7, + 1, + 4810 + ), ( + 142209810, + 7, + 1, + 4811 + ), ( + 142209810, + 7, + 1, + 4812 + ), ( + 142209810, + 7, + 2, + 4813 + ), ( + 142209810, + 7, + 2, + 4814 + ), ( + 142209810, + 7, + 2, + 4815 + ), ( + 142209810, + 7, + 2, + 4816 + ), ( + 142209810, + 7, + 2, + 4817 + ), ( + 142209810, + 7, + 2, + 4818 + ), ( + 142209810, + 7, + 2, + 4819 + ), ( + 142209810, + 7, + 2, + 4820 + ), ( + 142209810, + 7, + 2, + 4821 + ), ( + 142209810, + 7, + 2, + 4822 + ); + +END; diff --git a/server/migrations/sql/0010_campaign.sql b/server/migrations/sql/0010_campaign.sql new file mode 100644 index 000000000..b6c2a4b69 --- /dev/null +++ b/server/migrations/sql/0010_campaign.sql @@ -0,0 +1,69 @@ +BEGIN; + +CREATE TABLE IF NOT EXISTS public.campaigns ( + id INTEGER PRIMARY KEY, + min_hr INTEGER, + max_hr INTEGER, + min_sr INTEGER, + max_sr INTEGER, + min_gr INTEGER, + max_gr INTEGER, + reward_type INTEGER, + stamps INTEGER, + receive_type INTEGER, + background_id INTEGER, + start_time TIMESTAMP WITH TIME ZONE, + end_time TIMESTAMP WITH TIME ZONE, + title TEXT, + reward TEXT, + link TEXT, + code_prefix TEXT +); + +CREATE TABLE IF NOT EXISTS public.campaign_categories ( + id SERIAL PRIMARY KEY, + type INTEGER, + title TEXT, + description TEXT +); + +CREATE TABLE IF NOT EXISTS public.campaign_category_links ( + id SERIAL PRIMARY KEY, + campaign_id INTEGER REFERENCES public.campaigns(id) ON DELETE CASCADE, + category_id INTEGER REFERENCES public.campaign_categories(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS public.campaign_rewards ( + id SERIAL PRIMARY KEY, + campaign_id INTEGER REFERENCES public.campaigns(id) ON DELETE CASCADE, + item_type INTEGER, + quantity INTEGER, + item_id INTEGER +); + +CREATE TABLE IF NOT EXISTS public.campaign_rewards_claimed ( + character_id INTEGER REFERENCES public.characters(id) ON DELETE CASCADE, + reward_id INTEGER REFERENCES public.campaign_rewards(id) ON DELETE CASCADE, + PRIMARY KEY (character_id, reward_id) +); + +CREATE TABLE IF NOT EXISTS public.campaign_state ( + id SERIAL PRIMARY KEY, + campaign_id INTEGER REFERENCES public.campaigns(id) ON DELETE CASCADE, + character_id INTEGER REFERENCES public.characters(id) ON DELETE CASCADE, + code TEXT +); + +CREATE TABLE IF NOT EXISTS public.campaign_codes ( + code TEXT PRIMARY KEY, + campaign_id INTEGER REFERENCES public.campaigns(id) ON DELETE CASCADE, + multi BOOLEAN NOT NULL DEFAULT FALSE +); + +CREATE TABLE IF NOT EXISTS public.campaign_quest ( + campaign_id INTEGER REFERENCES public.campaigns(id) ON DELETE CASCADE, + character_id INTEGER REFERENCES public.characters(id) ON DELETE CASCADE, + PRIMARY KEY (campaign_id, character_id) +); + +END; From 90d9b7915a000aa9f8e428c0705771a70947546e Mon Sep 17 00:00:00 2001 From: Houmgaor Date: Fri, 20 Mar 2026 11:26:40 +0100 Subject: [PATCH 2/3] fix(tests): update packet field names after campaign RE renaming --- network/mhfpacket/msg_batch_parse_test.go | 2 +- network/mhfpacket/msg_build_test.go | 38 ++++++++++---------- network/mhfpacket/msg_parse_coverage_test.go | 4 +-- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/network/mhfpacket/msg_batch_parse_test.go b/network/mhfpacket/msg_batch_parse_test.go index ea5225900..9dc23038e 100644 --- a/network/mhfpacket/msg_batch_parse_test.go +++ b/network/mhfpacket/msg_batch_parse_test.go @@ -420,7 +420,7 @@ func TestBatchParseMultiField(t *testing.T) { if err := pkt.Parse(bf, ctx); err != nil { t.Fatal(err) } - if pkt.Unk0 != 2 || pkt.Unk1 != 3 || pkt.Unk2 != 4 { + if pkt.QuestID != 2 || pkt.ItemType != 3 || pkt.Quantity != 4 { t.Error("field mismatch") } }) diff --git a/network/mhfpacket/msg_build_test.go b/network/mhfpacket/msg_build_test.go index 18e938e53..d572bee87 100644 --- a/network/mhfpacket/msg_build_test.go +++ b/network/mhfpacket/msg_build_test.go @@ -515,8 +515,8 @@ func TestBuildParseStateCampaign(t *testing.T) { if parsed.CampaignID != tt.campaignID { t.Errorf("CampaignID = %d, want %d", parsed.CampaignID, tt.campaignID) } - if parsed.Unk1 != tt.unk1 { - t.Errorf("Unk1 = %d, want %d", parsed.Unk1, tt.unk1) + if parsed.NullPadding != tt.unk1 { + t.Errorf("NullPadding = %d, want %d", parsed.NullPadding, tt.unk1) } }) } @@ -526,15 +526,14 @@ func TestBuildParseStateCampaign(t *testing.T) { // Build is NOT IMPLEMENTED, so we manually write the binary representation. func TestBuildParseApplyCampaign(t *testing.T) { tests := []struct { - name string - ackHandle uint32 - unk0 uint32 - unk1 uint16 - unk2 []byte + name string + ackHandle uint32 + campaignID uint32 + code string }{ - {"typical", 0x55667788, 5, 10, make([]byte, 16)}, - {"zero", 0, 0, 0, make([]byte, 16)}, - {"max", 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF, make([]byte, 16)}, + {"typical", 0x55667788, 5, "TESTCODE"}, + {"zero", 0, 0, ""}, + {"max", 0xFFFFFFFF, 0xFFFFFFFF, "MAXCODE"}, } ctx := &clientctx.ClientContext{RealClientMode: cfg.ZZ} @@ -542,9 +541,11 @@ func TestBuildParseApplyCampaign(t *testing.T) { t.Run(tt.name, func(t *testing.T) { bf := byteframe.NewByteFrame() bf.WriteUint32(tt.ackHandle) - bf.WriteUint32(tt.unk0) - bf.WriteUint16(tt.unk1) - bf.WriteBytes(tt.unk2) + bf.WriteUint32(tt.campaignID) + bf.WriteUint16(0) // zeroed + codeBytes := make([]byte, 16) + copy(codeBytes, []byte(tt.code)) + bf.WriteBytes(codeBytes) _, _ = bf.Seek(0, io.SeekStart) parsed := &MsgMhfApplyCampaign{} @@ -555,14 +556,11 @@ func TestBuildParseApplyCampaign(t *testing.T) { if parsed.AckHandle != tt.ackHandle { t.Errorf("AckHandle = 0x%X, want 0x%X", parsed.AckHandle, tt.ackHandle) } - if parsed.Unk0 != tt.unk0 { - t.Errorf("Unk0 = %d, want %d", parsed.Unk0, tt.unk0) + if parsed.CampaignID != tt.campaignID { + t.Errorf("CampaignID = %d, want %d", parsed.CampaignID, tt.campaignID) } - if parsed.Unk1 != tt.unk1 { - t.Errorf("Unk1 = %d, want %d", parsed.Unk1, tt.unk1) - } - if len(parsed.Unk2) != len(tt.unk2) { - t.Errorf("Unk2 len = %d, want %d", len(parsed.Unk2), len(tt.unk2)) + if parsed.Code != tt.code { + t.Errorf("Code = %q, want %q", parsed.Code, tt.code) } }) } diff --git a/network/mhfpacket/msg_parse_coverage_test.go b/network/mhfpacket/msg_parse_coverage_test.go index 974089cef..2dcb42d46 100644 --- a/network/mhfpacket/msg_parse_coverage_test.go +++ b/network/mhfpacket/msg_parse_coverage_test.go @@ -102,8 +102,8 @@ func TestParseCoverage_VariableLength(t *testing.T) { if err := pkt.Parse(parsed, ctx); err != nil { t.Errorf("Parse() error: %v", err) } - if len(pkt.Unk1) != 2 { - t.Errorf("expected 2 items, got %d", len(pkt.Unk1)) + if len(pkt.RewardIDs) != 2 { + t.Errorf("expected 2 items, got %d", len(pkt.RewardIDs)) } }) From 793a4b4e038840a440deddfa52a21c1dacbdb81a Mon Sep 17 00:00:00 2001 From: Houmgaor Date: Fri, 20 Mar 2026 11:31:59 +0100 Subject: [PATCH 3/3] fix(migrations): remove BEGIN/END from 0010_campaign.sql Migration runner wraps each file in its own transaction via db.Begin(). Having an explicit BEGIN/END inside caused 'unexpected transaction status idle'. Other migrations use no transaction wrapper. --- server/migrations/sql/0010_campaign.sql | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/server/migrations/sql/0010_campaign.sql b/server/migrations/sql/0010_campaign.sql index b6c2a4b69..84cba9f80 100644 --- a/server/migrations/sql/0010_campaign.sql +++ b/server/migrations/sql/0010_campaign.sql @@ -1,5 +1,4 @@ -BEGIN; - +-- Campaign / Event Tent system tables. CREATE TABLE IF NOT EXISTS public.campaigns ( id INTEGER PRIMARY KEY, min_hr INTEGER, @@ -65,5 +64,3 @@ CREATE TABLE IF NOT EXISTS public.campaign_quest ( character_id INTEGER REFERENCES public.characters(id) ON DELETE CASCADE, PRIMARY KEY (campaign_id, character_id) ); - -END;