From 1c57a640026ac5463548b2e10b80ce4bc83f3854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=B9=E6=9F=B3=E7=85=9C?= <101934327+fangliuyu@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:39:17 +0800 Subject: [PATCH] Add files via upload (#774) --- plugin/mcfish/main.go | 88 ++++++++++++++++++++++++++++++++++++++++-- plugin/mcfish/store.go | 83 ++++++++++++++++++++++++++++++--------- 2 files changed, 148 insertions(+), 23 deletions(-) diff --git a/plugin/mcfish/main.go b/plugin/mcfish/main.go index 17775ecbd1..150263db3f 100644 --- a/plugin/mcfish/main.go +++ b/plugin/mcfish/main.go @@ -10,6 +10,7 @@ import ( "time" fcext "github.com/FloatTech/floatbox/ctxext" + "github.com/FloatTech/floatbox/math" sql "github.com/FloatTech/sqlite" ctrl "github.com/FloatTech/zbpctrl" "github.com/FloatTech/zbputils/control" @@ -27,7 +28,7 @@ type fishdb struct { const FishLimit = 50 // version 规则版本号 -const version = "5.4.1" +const version = "5.4.2" // 各物品信息 type jsonInfo struct { @@ -91,6 +92,23 @@ type storeDiscount struct { Discount int } +// buff状态记录 +// buff0: 优惠卷 +type buffInfo struct { + ID int64 + Duration int64 + BuyTimes int `db:"Buff0"` // 购买次数 + Coupon int `db:"Buff1"` // 优惠卷 + SalesPole int `db:"Buff2"` // 卖鱼竿上限 + BuyTing int `db:"Buff3"` // 购买上限 + Buff4 int `db:"Buff4"` // 暂定 + Buff5 int `db:"Buff5"` // 暂定 + Buff6 int `db:"Buff6"` // 暂定 + Buff7 int `db:"Buff7"` // 暂定 + Buff8 int `db:"Buff8"` // 暂定 + Buff9 int `db:"Buff9"` // 暂定 +} + var ( articlesInfo = jsonInfo{} // 物品信息 thingList = make([]string, 0, 100) // 竿列表 @@ -114,7 +132,7 @@ var ( Brief: "钓鱼", Help: "一款钓鱼模拟器\n----------指令----------\n" + "- 钓鱼看板/钓鱼商店\n- 购买xxx\n- 购买xxx [数量]\n- 出售xxx\n- 出售xxx [数量]\n" + - "- 钓鱼背包\n- 装备[xx竿|三叉戟|美西螈]\n- 附魔[诱钓|海之眷顾]\n- 修复鱼竿\n- 合成[xx竿|三叉戟]\n- 消除绑定诅咒\n- 消除绑定诅咒 [数量]\n" + + "- 钓鱼背包\n- 装备[xx竿|三叉戟|美西螈]\n- 附魔[诱钓|海之眷顾]\n- 修复鱼竿\n- 合成[xx竿|三叉戟]\n- 消除[绑定|宝藏]诅咒\n- 消除[绑定|宝藏]诅咒 [数量]\n" + "- 进行钓鱼\n- 进行n次钓鱼\n- 当前装备概率明细\n" + "规则V" + version + ":\n" + "1.每日的商店价格是波动的!!如何最大化收益自己考虑一下喔\n" + @@ -130,7 +148,8 @@ var ( "7.物品BUFF:\n-> 钓鱼佬 : 当背包名字含有'鱼'的物品数量超过100时激活,钓到物品概率提高至90%\n-> 修复大师 : 当背包鱼竿数量超过10时激活,修复物品时耐久百分百继承\n" + "8.合成:\n-> 铁竿 : 3x木竿\n-> 金竿 : 3x铁竿\n-> 钻石竿 : 3x金竿\n-> 下界合金竿 : 3x钻石竿\n-> 三叉戟 : 3x下界合金竿\n注:合成成功率90%,继承附魔等级合/3的等级\n" + "9.杂项:\n-> 无装备的情况下,每人最多可以购买3次100块钱的鱼竿\n-> 默认状态钓鱼上钩概率为60%(理论值!!!)\n-> 附魔的鱼竿会因附魔变得昂贵,每个附魔最高3级\n-> 三叉戟不算鱼竿,修复时可直接满耐久\n" + - "-> 鱼竿数量大于50的不能买东西;\n 鱼竿数量大于30的不能钓鱼;\n 每购/售10次物品获得1层宝藏诅咒;\n 每钓鱼75次获得1本净化书", + "-> 鱼竿数量大于50的不能买东西;\n 鱼竿数量大于30的不能钓鱼;\n 每购/售10次鱼竿获得1层宝藏诅咒;\n 每购买20次物品将获得3次价格减半福利;\n 每钓鱼75次获得1本净化书;\n" + + " 每天最多只可出售5个鱼竿和购买15次物品;", PublicDataFolder: "McFish", }).ApplySingle(ctxext.DefaultSingle) getdb = fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool { @@ -244,7 +263,7 @@ func (sql *fishdb) updateFishInfo(uid int64, number int) (residue int, err error return } -// 更新buff +// 更新诅咒 func (sql *fishdb) updateCurseFor(uid int64, info string, number int) (err error) { if number < 1 { return @@ -694,3 +713,64 @@ func (sql *fishdb) updateStoreInfo(thingInfo store) (err error) { } return sql.db.Insert("store", &thingInfo) } + +// 更新购买次数 +func (sql *fishdb) updateBuyTimeFor(uid int64, add int) (err error) { + sql.Lock() + defer sql.Unlock() + userInfo := buffInfo{ID: uid} + err = sql.db.Create("buff", &userInfo) + if err != nil { + return err + } + _ = sql.db.Find("buff", &userInfo, "where ID = "+strconv.FormatInt(uid, 10)) + userInfo.BuyTimes += add + if userInfo.BuyTimes > 20 { + userInfo.BuyTimes -= 20 + userInfo.Coupon = 3 + } + return sql.db.Insert("buff", &userInfo) +} + +// 使用优惠卷 +func (sql *fishdb) useCouponAt(uid int64, times int) (int, error) { + useTimes := -1 + sql.Lock() + defer sql.Unlock() + userInfo := buffInfo{ID: uid} + err := sql.db.Create("buff", &userInfo) + if err != nil { + return useTimes, err + } + _ = sql.db.Find("buff", &userInfo, "where ID = "+strconv.FormatInt(uid, 10)) + if userInfo.Coupon > 0 { + useTimes = math.Min(userInfo.Coupon, times) + userInfo.Coupon -= useTimes + } + return useTimes, sql.db.Insert("buff", &userInfo) +} + +// 检测上限 +func (sql *fishdb) checkCanSalesFor(uid int64, sales bool) (int, error) { + residue := 0 + sql.Lock() + defer sql.Unlock() + userInfo := buffInfo{ID: uid} + err := sql.db.Create("buff", &userInfo) + if err != nil { + return residue, err + } + _ = sql.db.Find("buff", &userInfo, "where ID = "+strconv.FormatInt(uid, 10)) + if time.Now().Day() != time.Unix(userInfo.Duration, 0).Day() { + userInfo.SalesPole = 0 + userInfo.BuyTing = 0 + } + if sales && userInfo.SalesPole < 5 { + residue = 5 - userInfo.SalesPole + userInfo.SalesPole++ + } else if userInfo.BuyTing < 15 { + residue = 15 - userInfo.SalesPole + userInfo.SalesPole++ + } + return residue, sql.db.Insert("buff", &userInfo) +} diff --git a/plugin/mcfish/store.go b/plugin/mcfish/store.go index 32468a0f25..a7d5935436 100644 --- a/plugin/mcfish/store.go +++ b/plugin/mcfish/store.go @@ -14,17 +14,18 @@ import ( "github.com/FloatTech/gg" "github.com/FloatTech/imgfactory" "github.com/FloatTech/zbputils/control" - "github.com/FloatTech/zbputils/ctxext" "github.com/FloatTech/zbputils/img/text" "github.com/sirupsen/logrus" zero "github.com/wdvxdr1123/ZeroBot" + "github.com/wdvxdr1123/ZeroBot/extension/rate" "github.com/wdvxdr1123/ZeroBot/message" ) var ( - refresh = false - timeNow = 0 - refreshFish = func(ctx *zero.Ctx) bool { + storeLimiter = rate.NewManager[int64](time.Second*3, 1) + refresh = false + timeNow = 0 + refreshFish = func(ctx *zero.Ctx) bool { if refresh && timeNow == time.Now().Day() { return true } @@ -38,8 +39,12 @@ var ( } ) +func limitSet(ctx *zero.Ctx) *rate.Limiter { + return storeLimiter.Load(ctx.Event.UserID) +} + func init() { - engine.OnFullMatchGroup([]string{"钓鱼看板", "钓鱼商店"}, getdb, refreshFish).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) { + engine.OnFullMatchGroup([]string{"钓鱼看板", "钓鱼商店"}, getdb, refreshFish).SetBlock(true).Limit(limitSet).Handle(func(ctx *zero.Ctx) { infos, err := dbdata.getStoreInfo() if err != nil { ctx.SendChain(message.Text("[ERROR at store.go.2]:", err)) @@ -62,9 +67,20 @@ func init() { } ctx.SendChain(message.ImageBytes(pic)) }) - engine.OnRegex(`^出售(`+strings.Join(thingList, "|")+`)\s*(\d*)$`, getdb, refreshFish).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) { + engine.OnRegex(`^出售(`+strings.Join(thingList, "|")+`)\s*(\d*)$`, getdb, refreshFish).SetBlock(true).Limit(limitSet).Handle(func(ctx *zero.Ctx) { uid := ctx.Event.UserID thingName := ctx.State["regex_matched"].([]string)[1] + if strings.Contains(thingName, "竿") { + times, err := dbdata.checkCanSalesFor(uid, true) + if err != nil { + ctx.SendChain(message.Text("[ERROR at store.go.75]:", err)) + return + } + if times <= 0 { + ctx.SendChain(message.Text("出售次数已达到上限,明天再来售卖吧")) + return + } + } number, _ := strconv.Atoi(ctx.State["regex_matched"].([]string)[2]) if number == 0 || strings.Contains(thingName, "竿") { number = 1 @@ -131,8 +147,7 @@ func init() { thing = articles[index] if thing.Number < number { - ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("背包数量不足"))) - return + number = thing.Number } var pice int @@ -178,7 +193,7 @@ func init() { recordInfo := records[0] numberOfRecord := recordInfo.Number if thingName == "唱片" { - numberOfRecord-- + numberOfRecord -= number } if numberOfRecord > 0 { ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("是否使用唱片让价格翻倍?\n回答\"是\"或\"否\""))) @@ -204,6 +219,9 @@ func init() { } if use { pice *= 2 + if thingName == "唱片" { + thing.Number-- + } recordInfo.Number-- err = dbdata.updateUserThingInfo(uid, recordInfo) if err != nil { @@ -280,13 +298,15 @@ func init() { ctx.SendChain(message.Text("[ERROR at store.go.10]:", err)) return } - err = dbdata.updateCurseFor(uid, "sell", 1) - if err != nil { - logrus.Warnln(err) + if strings.Contains(thingName, "竿") { + err = dbdata.updateCurseFor(uid, "sell", 1) + if err != nil { + logrus.Warnln(err) + } } ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("出售成功,你赚到了", pice*number, msg))) }) - engine.OnRegex(`^购买(`+strings.Join(thingList, "|")+`)\s*(\d*)$`, getdb, refreshFish).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) { + engine.OnRegex(`^购买(`+strings.Join(thingList, "|")+`)\s*(\d*)$`, getdb, refreshFish).SetBlock(true).Limit(limitSet).Handle(func(ctx *zero.Ctx) { uid := ctx.Event.UserID numberOfPole, err := dbdata.getNumberFor(uid, "竿") if err != nil { @@ -297,6 +317,15 @@ func init() { ctx.SendChain(message.Text("你有", numberOfPole, "支鱼竿,大于50支的玩家不允许购买东西")) return } + buytimes, err := dbdata.checkCanSalesFor(uid, false) + if err != nil { + ctx.SendChain(message.Text("[ERROR at store.go.75]:", err)) + return + } + if buytimes <= 0 { + ctx.SendChain(message.Text("出售次数已达到上限,明天再来购买吧")) + return + } thingName := ctx.State["regex_matched"].([]string)[1] number, _ := strconv.Atoi(ctx.State["regex_matched"].([]string)[2]) if number == 0 { @@ -407,14 +436,28 @@ func init() { } price := pice[index] * number + msg := "" + times := math.Min(3, number) + coupon, err := dbdata.useCouponAt(uid, times) + if err != nil { + logrus.Warnln(err) + } + if coupon != -1 { + msg += "\n(半价福利还有" + strconv.Itoa(3-coupon) + "次)" + price = pice[index]*(number-coupon) + (pice[index]/2)*coupon + } else { + err = dbdata.updateBuyTimeFor(uid, 1) + if err != nil { + logrus.Warnln(err) + } + } curse, err := dbdata.getNumberFor(uid, "宝藏诅咒") if err != nil { ctx.SendChain(message.Text("[ERROR at store.go.9.3]:", err)) return } - msg := "" if curse != 0 { - msg = "\n(你身上绑定了" + strconv.Itoa(curse) + "层诅咒)" + msg += "\n(你身上绑定了" + strconv.Itoa(curse) + "层诅咒)" price = price * (100 + 10*curse) / 100 } @@ -497,11 +540,13 @@ func init() { ctx.SendChain(message.Text("[ERROR at store.go.14]:", err)) return } - err = dbdata.updateCurseFor(uid, "buy", 1) - if err != nil { - logrus.Warnln(err) + if strings.Contains(thingName, "竿") { + err = dbdata.updateCurseFor(uid, "buy", 1) + if err != nil { + logrus.Warnln(err) + } } - ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("购买成功"))) + ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你用", price, "购买了", number, thingName))) }) }