rewrite shop item enumeration code

This commit is contained in:
wish
2023-02-28 03:55:08 +11:00
parent aecacbaed4
commit 60ab165729
4 changed files with 141 additions and 143 deletions

View File

@@ -0,0 +1,45 @@
BEGIN;
INSERT INTO public.shop_items
(shop_type, shop_id, item_id, cost, quantity, min_hr, min_sr, min_gr, store_level, max_quantity, road_floors, road_fatalis)
VALUES
(8,5,1,30,10,0,0,0,0,10,0,0),
(8,5,2,60,10,0,0,0,0,10,0,0),
(8,5,3,60,10,0,0,0,0,10,0,0),
(8,5,4,30,10,0,0,0,0,10,0,0),
(8,5,5,60,10,0,0,0,0,10,0,0),
(8,5,6,80,10,0,0,0,1,10,0,0),
(8,5,7,80,10,0,0,0,1,10,0,0),
(8,5,8,80,10,0,0,0,1,10,0,0),
(8,5,9,100,10,0,0,0,2,10,0,0),
(8,5,10,100,10,0,0,0,2,10,0,0),
(8,5,11,100,10,0,0,0,2,10,0,0),
(8,5,12,100,10,0,0,0,2,10,0,0),
(8,5,13,100,10,0,0,0,2,10,0,0),
(8,5,14,200,10,0,0,0,2,10,0,0),
(8,5,15,500,10,0,0,0,3,10,0,0),
(8,5,16,1000,10,0,0,0,3,10,0,0),
(8,5,20,30,10,0,0,0,0,10,0,0),
(8,5,21,30,10,0,0,0,0,10,0,0),
(8,5,22,60,10,0,0,0,0,10,0,0),
(8,5,23,60,10,0,0,0,0,10,0,0),
(8,5,24,60,10,0,0,0,0,10,0,0),
(8,5,25,80,10,0,0,0,1,10,0,0),
(8,5,26,80,10,0,0,0,1,10,0,0),
(8,5,27,500,10,0,0,1,3,10,0,0),
(8,5,28,60,10,0,0,0,0,10,0,0),
(8,5,29,60,10,299,0,0,0,10,0,0),
(8,5,30,100,10,0,0,1,3,10,0,0),
(8,5,31,80,10,299,0,0,1,10,0,0),
(8,5,32,80,10,299,0,0,1,10,0,0),
(8,5,33,80,10,299,0,0,1,10,0,0),
(8,7,2209,400,1,299,0,0,2,5,0,0),
(8,7,2208,400,1,299,0,0,2,5,0,0),
(8,7,5113,400,1,299,0,0,2,5,0,0),
(8,7,3571,400,1,299,0,0,2,5,0,0),
(8,7,3572,400,1,299,0,0,2,5,0,0),
(8,7,3738,400,1,299,0,0,2,5,0,0),
(8,7,3737,400,1,299,0,0,2,5,0,0),
(8,7,4399,400,1,299,0,0,2,5,0,0);
END;

View File

@@ -0,0 +1,12 @@
BEGIN;
INSERT INTO public.shop_items
(shop_type, shop_id, item_id, cost, quantity, min_hr, min_sr, min_gr, store_level, max_quantity, road_floors, road_fatalis)
VALUES
(5,5,16516,100,1,0,0,1,0,0,0,0),
(5,5,16517,100,1,0,0,1,0,0,0,0),
(7,0,13190,10,1,0,0,0,0,0,0,0),
(7,0,1662,10,1,0,0,0,0,0,0,0),
(7,0,10179,100,1,0,0,0,0,0,0,0);
END;

View File

@@ -1,39 +1,29 @@
BEGIN;
ALTER TABLE IF EXISTS public.normal_shop_items
RENAME COLUMN itemhash TO id;
DROP TABLE IF EXISTS public.normal_shop_items;
ALTER TABLE IF EXISTS public.normal_shop_items
ALTER COLUMN points TYPE integer;
CREATE TABLE IF NOT EXISTS public.shop_items (
id SERIAL PRIMARY KEY,
shop_type INTEGER,
shop_id INTEGER,
item_id INTEGER,
cost INTEGER,
quantity INTEGER,
min_hr INTEGER,
min_sr INTEGER,
min_gr INTEGER,
store_level INTEGER,
max_quantity INTEGER,
road_floors INTEGER,
road_fatalis INTEGER
);
ALTER TABLE IF EXISTS public.normal_shop_items
RENAME COLUMN points TO cost;
DROP TABLE IF EXISTS public.shop_item_state;
ALTER TABLE IF EXISTS public.normal_shop_items
RENAME COLUMN tradequantity TO quantity;
ALTER TABLE IF EXISTS public.normal_shop_items
RENAME COLUMN rankreqlow TO min_hr;
ALTER TABLE IF EXISTS public.normal_shop_items
RENAME COLUMN rankreqhigh TO min_sr;
ALTER TABLE IF EXISTS public.normal_shop_items
RENAME COLUMN rankreqg TO min_gr;
ALTER TABLE IF EXISTS public.normal_shop_items
RENAME COLUMN storelevelreq TO req_store_level;
ALTER TABLE IF EXISTS public.normal_shop_items
RENAME COLUMN maximumquantity TO max_quantity;
ALTER TABLE IF EXISTS public.normal_shop_items
DROP COLUMN boughtquantity;
ALTER TABLE IF EXISTS public.normal_shop_items
RENAME COLUMN roadfloorsrequired TO road_floors;
ALTER TABLE IF EXISTS public.normal_shop_items
RENAME COLUMN weeklyfataliskills TO road_fatalis;
CREATE TABLE IF NOT EXISTS public.shop_items_bought (
character_id INTEGER,
shop_item_id INTEGER,
bought INTEGER
);
END;

View File

@@ -8,18 +8,18 @@ import (
)
type ShopItem struct {
ID uint32 `db:"id"`
ItemID uint16 `db:"itemid"`
Cost uint32 `db:"cost"`
Quantity uint16 `db:"quantity"`
MinHR uint16 `db:"min_hr"`
MinSR uint16 `db:"min_sr"`
MinGR uint16 `db:"min_gr"`
ReqStoreLevel uint16 `db:"req_store_level"`
MaxQuantity uint16 `db:"max_quantity"`
CharQuantity uint16 `db:"char_quantity"`
RoadFloors uint16 `db:"road_floors"`
RoadFatalis uint16 `db:"road_fatalis"`
ID uint32 `db:"id"`
ItemID uint16 `db:"item_id"`
Cost uint32 `db:"cost"`
Quantity uint16 `db:"quantity"`
MinHR uint16 `db:"min_hr"`
MinSR uint16 `db:"min_sr"`
MinGR uint16 `db:"min_gr"`
StoreLevel uint16 `db:"store_level"`
MaxQuantity uint16 `db:"max_quantity"`
UsedQuantity uint16 `db:"used_quantity"`
RoadFloors uint16 `db:"road_floors"`
RoadFatalis uint16 `db:"road_fatalis"`
}
type Gacha struct {
@@ -67,14 +67,33 @@ func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem) {
bf.WriteUint16(item.MinHR)
bf.WriteUint16(item.MinSR)
bf.WriteUint16(item.MinGR)
bf.WriteUint16(item.ReqStoreLevel)
bf.WriteUint16(item.StoreLevel)
bf.WriteUint16(item.MaxQuantity)
bf.WriteUint16(item.CharQuantity)
bf.WriteUint16(item.UsedQuantity)
bf.WriteUint16(item.RoadFloors)
bf.WriteUint16(item.RoadFatalis)
}
}
func getShopItems(s *Session, shopType uint8, shopID uint32) []ShopItem {
var items []ShopItem
var temp ShopItem
rows, err := s.server.db.Queryx(`SELECT id, item_id, cost, quantity, min_hr, min_sr, min_gr, store_level, max_quantity,
COALESCE((SELECT bought FROM shop_items_bought WHERE shop_item_id=si.id AND character_id=$3), 0) as used_quantity,
road_floors, road_fatalis FROM shop_items si WHERE shop_type=$1 AND shop_id=$2
`, shopType, shopID, s.charID)
if err == nil {
for rows.Next() {
err = rows.StructScan(&temp)
if err != nil {
continue
}
items = append(items, temp)
}
}
return items
}
func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfEnumerateShop)
// Generic Shop IDs
@@ -184,109 +203,41 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
bf.Seek(4, 0)
bf.WriteUint16(entryCount)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
case 3: // Hunting Festival Exchange
bf := byteframe.NewByteFrame()
items := getShopItems(s, pkt.ShopType, pkt.ShopID)
writeShopItems(bf, items)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
case 4: // N Points, 0-6
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
bf := byteframe.NewByteFrame()
items := getShopItems(s, pkt.ShopType, pkt.ShopID)
writeShopItems(bf, items)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
case 5: // GCP->Item, 0-6
switch pkt.ShopID {
case 5:
bf := byteframe.NewByteFrame()
items := []ShopItem{
{ItemID: 16516, Cost: 100, Quantity: 1, MinGR: 1},
{ItemID: 16517, Cost: 100, Quantity: 1, MinGR: 1},
}
writeShopItems(bf, items)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
default:
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
}
bf := byteframe.NewByteFrame()
items := getShopItems(s, pkt.ShopType, pkt.ShopID)
writeShopItems(bf, items)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
case 6: // Gacha coin->Item
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
case 7: // Item->GCP
bf := byteframe.NewByteFrame()
items := []ShopItem{
{ItemID: 13190, Cost: 10, Quantity: 1},
{ItemID: 1662, Cost: 10, Quantity: 1},
{ItemID: 10179, Cost: 100, Quantity: 1},
}
items := getShopItems(s, pkt.ShopType, pkt.ShopID)
writeShopItems(bf, items)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
case 8: // Diva
switch pkt.ShopID {
case 0: // Normal exchange
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
case 5: // GCP skills
bf := byteframe.NewByteFrame()
items := []ShopItem{
{ItemID: 1, Cost: 30, Quantity: 10, MaxQuantity: 10},
{ItemID: 2, Cost: 60, Quantity: 10, MaxQuantity: 10},
{ItemID: 3, Cost: 60, Quantity: 10, MaxQuantity: 10},
{ItemID: 4, Cost: 30, Quantity: 10, MaxQuantity: 10},
{ItemID: 20, Cost: 30, Quantity: 10, MaxQuantity: 10},
{ItemID: 21, Cost: 30, Quantity: 10, MaxQuantity: 10},
{ItemID: 22, Cost: 60, Quantity: 10, MaxQuantity: 10},
{ItemID: 23, Cost: 60, Quantity: 10, MaxQuantity: 10},
{ItemID: 24, Cost: 60, Quantity: 10, MaxQuantity: 10},
{ItemID: 28, Cost: 60, Quantity: 10, MaxQuantity: 10},
{ItemID: 29, Cost: 60, Quantity: 10, MinHR: 299, MaxQuantity: 10},
{ItemID: 5, Cost: 60, Quantity: 10, MaxQuantity: 10},
{ItemID: 6, Cost: 80, Quantity: 10, ReqStoreLevel: 1, MaxQuantity: 10},
{ItemID: 7, Cost: 80, Quantity: 10, ReqStoreLevel: 1, MaxQuantity: 10},
{ItemID: 8, Cost: 80, Quantity: 10, ReqStoreLevel: 1, MaxQuantity: 10},
{ItemID: 25, Cost: 80, Quantity: 10, ReqStoreLevel: 1, MaxQuantity: 10},
{ItemID: 26, Cost: 80, Quantity: 10, ReqStoreLevel: 1, MaxQuantity: 10},
{ItemID: 31, Cost: 80, Quantity: 10, MinHR: 299, ReqStoreLevel: 1, MaxQuantity: 10},
{ItemID: 32, Cost: 80, Quantity: 10, MinHR: 299, ReqStoreLevel: 1, MaxQuantity: 10},
{ItemID: 33, Cost: 80, Quantity: 10, MinHR: 299, ReqStoreLevel: 1, MaxQuantity: 10},
{ItemID: 9, Cost: 100, Quantity: 10, ReqStoreLevel: 2, MaxQuantity: 10},
{ItemID: 10, Cost: 100, Quantity: 10, ReqStoreLevel: 2, MaxQuantity: 10},
{ItemID: 11, Cost: 100, Quantity: 10, ReqStoreLevel: 2, MaxQuantity: 10},
{ItemID: 12, Cost: 100, Quantity: 10, ReqStoreLevel: 2, MaxQuantity: 10},
{ItemID: 13, Cost: 100, Quantity: 10, ReqStoreLevel: 2, MaxQuantity: 10},
{ItemID: 14, Cost: 200, Quantity: 10, ReqStoreLevel: 2, MaxQuantity: 10},
{ItemID: 15, Cost: 500, Quantity: 10, ReqStoreLevel: 3, MaxQuantity: 10},
{ItemID: 16, Cost: 1000, Quantity: 10, ReqStoreLevel: 3, MaxQuantity: 10},
{ItemID: 27, Cost: 500, Quantity: 10, MinGR: 1, ReqStoreLevel: 3, MaxQuantity: 10},
{ItemID: 30, Cost: 100, Quantity: 10, MinHR: 299, ReqStoreLevel: 3, MaxQuantity: 10},
{ItemID: 30, Cost: 100, Quantity: 10, MinGR: 1, ReqStoreLevel: 3, MaxQuantity: 10},
}
writeShopItems(bf, items)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
case 7: // Limited exchange
bf := byteframe.NewByteFrame()
items := []ShopItem{
{ItemID: 2209, Cost: 400, Quantity: 1, MinHR: 299, ReqStoreLevel: 2, MaxQuantity: 5},
{ItemID: 2208, Cost: 400, Quantity: 1, MinHR: 299, ReqStoreLevel: 2, MaxQuantity: 5},
{ItemID: 5113, Cost: 400, Quantity: 1, MinHR: 299, ReqStoreLevel: 2, MaxQuantity: 5},
{ItemID: 3571, Cost: 400, Quantity: 1, MinHR: 299, ReqStoreLevel: 2, MaxQuantity: 5},
{ItemID: 3572, Cost: 400, Quantity: 1, MinHR: 299, ReqStoreLevel: 2, MaxQuantity: 5},
{ItemID: 3738, Cost: 400, Quantity: 1, MinHR: 299, ReqStoreLevel: 2, MaxQuantity: 5},
{ItemID: 3737, Cost: 400, Quantity: 1, MinHR: 299, ReqStoreLevel: 2, MaxQuantity: 5},
{ItemID: 4399, Cost: 400, Quantity: 1, MinHR: 299, ReqStoreLevel: 2, MaxQuantity: 5},
}
writeShopItems(bf, items)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
case 9: // Diva song shop
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
case 10: // Item shop, 0-8
shopEntries, err := s.server.db.Queryx(`SELECT id, itemid, cost, quantity, min_hr, min_sr, min_gr, req_store_level, max_quantity,
COALESCE((SELECT usedquantity FROM shop_item_state WHERE itemhash=nsi.id AND char_id=$3), 0) as char_quantity,
road_floors, road_fatalis FROM normal_shop_items nsi WHERE shoptype=$1 AND shopid=$2
`, pkt.ShopType, pkt.ShopID, s.charID)
if err != nil {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
return
}
bf := byteframe.NewByteFrame()
var items []ShopItem
for shopEntries.Next() {
item := ShopItem{}
err = shopEntries.StructScan(&item)
if err != nil {
continue
}
items = append(items, item)
}
items := getShopItems(s, pkt.ShopType, pkt.ShopID)
writeShopItems(bf, items)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
case 9: // Diva song shop
bf := byteframe.NewByteFrame()
items := getShopItems(s, pkt.ShopType, pkt.ShopID)
writeShopItems(bf, items)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
case 10: // Item shop, 0-8
bf := byteframe.NewByteFrame()
items := getShopItems(s, pkt.ShopType, pkt.ShopID)
writeShopItems(bf, items)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
@@ -302,10 +253,10 @@ func handleMsgMhfAcquireExchangeShop(s *Session, p mhfpacket.MHFPacket) {
continue
}
buyCount := bf.ReadUint32()
s.server.db.Exec(`INSERT INTO shop_item_state (char_id, itemhash, usedquantity)
VALUES ($1,$2,$3) ON CONFLICT (char_id, itemhash)
DO UPDATE SET usedquantity = shop_item_state.usedquantity + $3
WHERE EXCLUDED.char_id=$1 AND EXCLUDED.itemhash=$2
s.server.db.Exec(`INSERT INTO shop_items_bought (character_id, shop_item_id, bought)
VALUES ($1,$2,$3) ON CONFLICT (character_id, shop_item_id)
DO UPDATE SET bought = bought + $3
WHERE EXCLUDED.character_id=$1 AND EXCLUDED.shop_item_id=$2
`, s.charID, itemHash, buyCount)
}
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})