mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 05:30:07 +08:00
[新增插件]钓鱼模拟器 (#721)
* Add files via upload * Update README.md * Add files via upload * Add files via upload * Update pole.go * Update pole.go * Update main.go * Add files via upload * Add files via upload * Update main.go * Update pack.go * Add files via upload
This commit is contained in:
parent
6bff62b91b
commit
b7e21fc111
17
README.md
17
README.md
@ -959,6 +959,23 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 吟唱提示[xxxx]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>钓鱼模拟器</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/mcfish"`
|
||||
|
||||
- [x] 钓鱼商店
|
||||
- [x] 购买xxx [数量]
|
||||
- [x] 出售xxx [数量]
|
||||
- [x] 钓鱼背包
|
||||
- [x] 装备[xx竿|三叉戟|美西螈]
|
||||
- [x] 附魔[诱钓|海之眷顾]
|
||||
- [x] 修复鱼竿
|
||||
- [x] 合成[xx竿|三叉戟]
|
||||
- [x] 进行钓鱼
|
||||
- [x] 进行n次钓鱼
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>简易midi音乐制作</summary>
|
||||
|
||||
329
plugin/mcfish/fish.go
Normal file
329
plugin/mcfish/fish.go
Normal file
@ -0,0 +1,329 @@
|
||||
// Package mcfish 钓鱼模拟器
|
||||
package mcfish
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/wallet"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine.OnRegex(`^进行(([1-5]\d|[1-9])次)?钓鱼$`, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
fishNumber := 1
|
||||
info := ctx.State["regex_matched"].([]string)[2]
|
||||
if info != "" {
|
||||
number, err := strconv.Atoi(info)
|
||||
if err != nil || number > FishLimit {
|
||||
ctx.SendChain(message.Text("请输入正确的次数"))
|
||||
return
|
||||
}
|
||||
fishNumber = number
|
||||
}
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.2]:", err))
|
||||
return
|
||||
}
|
||||
if equipInfo == (equip{}) {
|
||||
ok, err := dbdata.checkEquipFor(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.2.1]:", err))
|
||||
return
|
||||
}
|
||||
if !ok {
|
||||
ctx.SendChain(message.At(uid), message.Text("请装备鱼竿后钓鱼", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("你尚未装备鱼竿,是否花费100购买鱼竿?\n回答\"是\"或\"否\""))
|
||||
// 等待用户下一步选择
|
||||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(是|否)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel()
|
||||
buy := false
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("等待超时,取消钓鱼")))
|
||||
return
|
||||
case e := <-recv:
|
||||
nextcmd := e.Event.Message.String()
|
||||
if nextcmd == "否" {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("已取消购买")))
|
||||
return
|
||||
}
|
||||
money := wallet.GetWalletOf(uid)
|
||||
if money < 100 {
|
||||
ctx.SendChain(message.Text("你钱包当前只有", money, "ATRI币,无法完成支付"))
|
||||
return
|
||||
}
|
||||
err = wallet.InsertWalletOf(uid, -100)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.3]:", err))
|
||||
return
|
||||
}
|
||||
equipInfo = equip{
|
||||
ID: uid,
|
||||
Equip: "木竿",
|
||||
Durable: 30,
|
||||
}
|
||||
err = dbdata.updateUserEquip(equipInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.4]:", err))
|
||||
return
|
||||
}
|
||||
err = dbdata.setEquipFor(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.4]:", err))
|
||||
return
|
||||
}
|
||||
buy = true
|
||||
}
|
||||
if buy {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if equipInfo.Durable < fishNumber {
|
||||
fishNumber = equipInfo.Durable
|
||||
}
|
||||
residue, err := dbdata.updateFishInfo(uid, fishNumber)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.1]:", err))
|
||||
return
|
||||
}
|
||||
if residue == 0 {
|
||||
ctx.SendChain(message.Text("今天你已经进行", FishLimit, "次钓鱼了.\n游戏虽好,但请不要沉迷。"))
|
||||
return
|
||||
}
|
||||
fishNumber = residue
|
||||
msg := ""
|
||||
if equipInfo.Equip != "美西螈" {
|
||||
equipInfo.Durable -= fishNumber
|
||||
err = dbdata.updateUserEquip(equipInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5]:", err))
|
||||
return
|
||||
}
|
||||
if equipInfo.Durable < 10 || equipInfo.Durable > 0 {
|
||||
msg = "(你的鱼竿耐久仅剩" + strconv.Itoa(equipInfo.Durable) + ")"
|
||||
} else if equipInfo.Durable <= 0 {
|
||||
msg = "(你的鱼竿耐已销毁)"
|
||||
}
|
||||
} else {
|
||||
fishNmaes, err := dbdata.pickFishFor(uid, fishNumber)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5.1]:", err))
|
||||
return
|
||||
}
|
||||
if len(fishNmaes) == 0 {
|
||||
equipInfo.Durable = 0
|
||||
err = dbdata.updateUserEquip(equipInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5]:", err))
|
||||
}
|
||||
ctx.SendChain(message.Text("美西螈因为没吃到鱼,钓鱼时一直没回来,你失去了美西螈"))
|
||||
return
|
||||
}
|
||||
msg = "(美西螈吃掉了"
|
||||
fishNumber = 0
|
||||
for name, number := range fishNmaes {
|
||||
fishNumber += number
|
||||
msg += strconv.Itoa(number) + name + "、"
|
||||
}
|
||||
msg += ")"
|
||||
}
|
||||
waitTime := 120 / (equipInfo.Induce + 1)
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("你开始去钓鱼了,请耐心等待鱼上钩(预计要", time.Second*time.Duration(waitTime), ")"))
|
||||
timer := time.NewTimer(time.Second * time.Duration(rand.Intn(waitTime)+1))
|
||||
for {
|
||||
<-timer.C
|
||||
timer.Stop()
|
||||
break
|
||||
}
|
||||
// 钓到鱼的范围
|
||||
number, err := dbdata.getNumberFor(uid, "鱼")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5.1]:", err))
|
||||
return
|
||||
}
|
||||
if number > 100 || equipInfo.Equip == "美西螈" { //放大概率
|
||||
probabilities["treasure"] = probabilityLimit{
|
||||
Min: 0,
|
||||
Max: 2,
|
||||
}
|
||||
probabilities["pole"] = probabilityLimit{
|
||||
Min: 2,
|
||||
Max: 10,
|
||||
}
|
||||
probabilities["fish"] = probabilityLimit{
|
||||
Min: 10,
|
||||
Max: 45,
|
||||
}
|
||||
probabilities["waste"] = probabilityLimit{
|
||||
Min: 45,
|
||||
Max: 90,
|
||||
}
|
||||
}
|
||||
for name, info := range probabilities {
|
||||
switch name {
|
||||
case "treasure":
|
||||
info.Max += equipInfo.Favor
|
||||
probabilities[name] = info
|
||||
case "pole":
|
||||
info.Min += equipInfo.Favor
|
||||
info.Max += equipInfo.Favor * 2
|
||||
probabilities[name] = info
|
||||
case "fish":
|
||||
info.Min += equipInfo.Favor * 2
|
||||
info.Max += equipInfo.Favor * 3
|
||||
probabilities[name] = info
|
||||
case "waste":
|
||||
info.Min += equipInfo.Favor * 3
|
||||
probabilities[name] = info
|
||||
}
|
||||
}
|
||||
// 钓鱼结算
|
||||
picName := ""
|
||||
thingNameList := make(map[string]int)
|
||||
for i := fishNumber; i > 0; i-- {
|
||||
thingName := ""
|
||||
typeOfThing := ""
|
||||
number := 1
|
||||
dice := rand.Intn(100)
|
||||
switch {
|
||||
case dice <= probabilities["waste"].Min && dice < probabilities["waste"].Max: // 垃圾
|
||||
typeOfThing = "waste"
|
||||
thingName = wasteList[rand.Intn(len(wasteList))]
|
||||
picName = thingName
|
||||
case dice <= probabilities["treasure"].Min && dice < probabilities["treasure"].Max: // 宝藏
|
||||
dice = rand.Intn(100)
|
||||
switch {
|
||||
case dice <= probabilities["美西螈"].Min && dice < probabilities["美西螈"].Max:
|
||||
typeOfThing = "pole"
|
||||
picName = "美西螈"
|
||||
thingName = "美西螈"
|
||||
case dice <= probabilities["唱片"].Min && dice < probabilities["唱片"].Max:
|
||||
typeOfThing = "article"
|
||||
picName = "唱片"
|
||||
thingName = "唱片"
|
||||
case dice <= probabilities["海之眷顾"].Min && dice < probabilities["海之眷顾"].Max:
|
||||
typeOfThing = "article"
|
||||
picName = "book"
|
||||
thingName = "海之眷顾"
|
||||
default:
|
||||
typeOfThing = "article"
|
||||
picName = "book"
|
||||
thingName = "诱钓"
|
||||
}
|
||||
case dice <= probabilities["pole"].Min && dice < probabilities["pole"].Max: // 宝藏
|
||||
typeOfThing = "pole"
|
||||
dice := rand.Intn(100)
|
||||
switch {
|
||||
case dice <= probabilities["铁竿"].Min && dice < probabilities["铁竿"].Max:
|
||||
thingName = "铁竿"
|
||||
case dice <= probabilities["金竿"].Min && dice < probabilities["金竿"].Max:
|
||||
thingName = "金竿"
|
||||
case dice <= probabilities["钻石竿"].Min && dice < probabilities["钻石竿"].Max:
|
||||
thingName = "钻石竿"
|
||||
case dice <= probabilities["下界合金竿竿竿"].Min && dice < probabilities["下界合金竿竿竿"].Max:
|
||||
thingName = "下界合金竿竿竿"
|
||||
default:
|
||||
thingName = "木竿"
|
||||
}
|
||||
picName = thingName
|
||||
case dice <= probabilities["fish"].Min && dice < probabilities["fish"].Max:
|
||||
typeOfThing = "fish"
|
||||
dice = rand.Intn(100)
|
||||
switch {
|
||||
case dice <= probabilities["墨鱼"].Min && dice < probabilities["墨鱼"].Max:
|
||||
thingName = "墨鱼"
|
||||
case dice <= probabilities["鳕鱼"].Min && dice < probabilities["鳕鱼"].Max:
|
||||
thingName = "鳕鱼"
|
||||
case dice <= probabilities["鲑鱼"].Min && dice < probabilities["鲑鱼"].Max:
|
||||
thingName = "鲑鱼"
|
||||
case dice <= probabilities["热带鱼"].Min && dice < probabilities["热带鱼"].Max:
|
||||
thingName = "热带鱼"
|
||||
case dice <= probabilities["河豚"].Min && dice < probabilities["河豚"].Max:
|
||||
thingName = "河豚"
|
||||
default:
|
||||
thingName = "鹦鹉螺"
|
||||
}
|
||||
picName = thingName
|
||||
default:
|
||||
thingNameList["赛博空气"]++
|
||||
}
|
||||
if thingName != "" {
|
||||
newThing := article{}
|
||||
if strings.Contains(thingName, "竿") {
|
||||
info := strconv.Itoa(rand.Intn(discountList[thingName])+1) +
|
||||
"/" + strconv.Itoa(rand.Intn(10)) + "/" +
|
||||
strconv.Itoa(rand.Intn(3)) + "/" + strconv.Itoa(rand.Intn(2))
|
||||
newThing = article{
|
||||
Duration: time.Now().Unix()*100 + int64(i),
|
||||
Type: typeOfThing,
|
||||
Name: thingName,
|
||||
Number: number,
|
||||
Other: info,
|
||||
}
|
||||
} else {
|
||||
thingInfo, err := dbdata.getUserThingInfo(uid, thingName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.6]:", err))
|
||||
return
|
||||
}
|
||||
if len(thingInfo) == 0 {
|
||||
newThing = article{
|
||||
Duration: time.Now().Unix()*100 + int64(i),
|
||||
Type: typeOfThing,
|
||||
Name: thingName,
|
||||
}
|
||||
} else {
|
||||
newThing = thingInfo[0]
|
||||
}
|
||||
if equipInfo.Equip == "美西螈" && thingName != "美西螈" {
|
||||
number += 2
|
||||
}
|
||||
newThing.Number += number
|
||||
}
|
||||
err = dbdata.updateUserThingInfo(uid, newThing)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.7]:", err))
|
||||
return
|
||||
}
|
||||
thingNameList[thingName] += number
|
||||
}
|
||||
}
|
||||
if len(thingNameList) == 1 {
|
||||
thingName := ""
|
||||
for name := range thingNameList {
|
||||
thingName = name
|
||||
}
|
||||
if picName != "" {
|
||||
pic, err := engine.GetLazyData(picName+".png", false)
|
||||
if err != nil {
|
||||
logrus.Warnln("[mcfish]error:", err)
|
||||
ctx.SendChain(message.At(uid), message.Text("恭喜你钓到了", thingName, "\n", msg))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.At(uid), message.Text("恭喜你钓到了", thingName, "\n", msg), message.ImageBytes(pic))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.At(uid), message.Text("恭喜你钓到了", thingName, "\n", msg))
|
||||
return
|
||||
}
|
||||
msgInfo := make(message.Message, 0, 3+len(thingNameList))
|
||||
msgInfo = append(msgInfo, message.Reply(ctx.Event.MessageID), message.Text("你进行了", fishNumber, "次钓鱼,结果如下:\n"))
|
||||
for name, number := range thingNameList {
|
||||
msgInfo = append(msgInfo, message.Text(name, " : ", number, "\n"))
|
||||
}
|
||||
msgInfo = append(msgInfo, message.Text(msg))
|
||||
ctx.Send(msgInfo)
|
||||
})
|
||||
}
|
||||
586
plugin/mcfish/main.go
Normal file
586
plugin/mcfish/main.go
Normal file
@ -0,0 +1,586 @@
|
||||
// Package mcfish 钓鱼模拟器
|
||||
package mcfish
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
fcext "github.com/FloatTech/floatbox/ctxext"
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
type fishdb struct {
|
||||
db *sql.Sqlite
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// FishLimit 钓鱼次数上限
|
||||
const FishLimit = 50
|
||||
|
||||
// 各物品信息
|
||||
type jsonInfo struct {
|
||||
ZoneInfo []zoneInfo `json:"分类"` // 区域概率
|
||||
ArticleInfo []articleInfo `json:"物品"` // 物品信息
|
||||
}
|
||||
type zoneInfo struct {
|
||||
Name string `json:"类型"` //类型
|
||||
Probability int `json:"概率[0-100)"` // 概率
|
||||
}
|
||||
type articleInfo struct {
|
||||
Name string `json:"名称"` //名称
|
||||
Type string `json:"类型"` // 类型
|
||||
Probability int `json:"概率[0-100),omitempty"` // 概率
|
||||
Durable int `json:"耐久上限,omitempty"` // 耐久
|
||||
Price int `json:"价格"` // 价格
|
||||
}
|
||||
|
||||
type probabilityLimit struct {
|
||||
Min int
|
||||
Max int
|
||||
}
|
||||
|
||||
type equip struct {
|
||||
ID int64 // 用户
|
||||
Equip string // 装备名称
|
||||
Durable int // 耐久
|
||||
Maintenance int // 维修次数
|
||||
Induce int // 诱钓等级
|
||||
Favor int // 眷顾等级
|
||||
}
|
||||
|
||||
type article struct {
|
||||
Duration int64
|
||||
Name string
|
||||
Number int
|
||||
Other string // 耐久/维修次数/诱钓/眷顾
|
||||
Type string
|
||||
}
|
||||
|
||||
type store struct {
|
||||
Duration int64
|
||||
Name string
|
||||
Number int
|
||||
Price int
|
||||
Other string // 耐久/维修次数/诱钓/眷顾
|
||||
Type string
|
||||
}
|
||||
|
||||
type fishState struct {
|
||||
ID int64
|
||||
Duration int64
|
||||
Fish int
|
||||
Equip int
|
||||
}
|
||||
|
||||
type storeDiscount struct {
|
||||
Name string
|
||||
Discount int
|
||||
}
|
||||
|
||||
var (
|
||||
articlesInfo = jsonInfo{} // 物品信息
|
||||
thingList = make([]string, 0, 100) // 竿列表
|
||||
poleList = make([]string, 0, 10) // 竿列表
|
||||
fishList = make([]string, 0, 10) // 鱼列表
|
||||
treasureList = make([]string, 0, 10) // 鱼列表
|
||||
wasteList = make([]string, 0, 10) // 垃圾列表
|
||||
probabilities = make(map[string]probabilityLimit, 50) // 概率分布
|
||||
priceList = make(map[string]int, 50) // 价格分布
|
||||
durationList = make(map[string]int, 50) // 装备耐久分布
|
||||
discountList = make(map[string]int, 50) // 价格波动信息
|
||||
enchantLevel = []string{"0", "Ⅰ", "Ⅱ", "Ⅲ"}
|
||||
dbdata = &fishdb{
|
||||
db: &sql.Sqlite{},
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
engine = control.Register("mcfish", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "钓鱼",
|
||||
Help: "一款钓鱼模拟器\n----------指令----------\n" +
|
||||
"- 钓鱼看板/钓鱼商店\n- 购买xxx\n- 购买xxx [数量]\n- 出售xxx\n- 出售xxx [数量]\n" +
|
||||
"- 钓鱼背包\n- 装备[xx竿|三叉戟|美西螈]\n- 附魔[诱钓|海之眷顾]\n- 修复鱼竿\n- 合成[xx竿|三叉戟]\n" +
|
||||
"- 进行钓鱼\n- 进行n次钓鱼\n" +
|
||||
"规则:\n1.每日的商店价格是波动的!!如何最大化收益自己考虑一下喔\n" +
|
||||
"2.装备信息:\n-> 木竿 : 耐久上限:30 均价:100 上钩概率:0.7%\n-> 铁竿 : 耐久上限:50 均价:300 上钩概率:0.2%\n-> 金竿 : 耐久上限:70 均价700 上钩概率:0.06%\n" +
|
||||
"-> 钻石竿 : 耐久上限:100 均价1500 上钩概率:0.03%\n-> 下界合金竿 : 耐久上限:150 均价3100 上钩概率:0.01%\n-> 三叉戟 : 可使钓的鱼类物品数量变成3 耐久上限:300 均价4000 只能合成和交易\n" +
|
||||
"3.附魔书信息:\n-> 诱钓 : 减少上钩时间. 均价:1000, 上钩概率:0.59%\n-> 海之眷顾 : 增加宝藏上钩概率. 均价:2500, 上钩概率:0.39%\n" +
|
||||
"4.稀有物品:\n-> 唱片 : 出售物品时使用该物品使价格翻倍. 均价:3000, 上钩概率:0.01%\n-> 美西螈 : 可装备,获得隐形[钓鱼佬]buff,并让钓到除鱼竿和美西螈外的物品数量变成3,无耐久上限.不可修复/附魔,每次钓鱼消耗任意一鱼类物品. 均价:3000, 上钩概率:0.01%\n" +
|
||||
"5.鱼类信息:\n-> 鳕鱼 : 均价:10 上钩概率:0.69%\n-> 鲑鱼 : 均价:50 上钩概率:0.2%\n-> 热带鱼 : 均价:100 上钩概率:0.06%\n-> 河豚 : 均价:300 上钩概率:0.03%\n-> 鹦鹉螺 : 均价:500 上钩概率:0.01%\n-> 墨鱼 : 均价:500 上钩概率:0.01%\n" +
|
||||
"6.垃圾:\n-> 均价:10 上钩概率:30%\n" +
|
||||
"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-> 三叉戟不算鱼竿",
|
||||
PublicDataFolder: "McFish",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
getdb = fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
dbdata.db.DBPath = engine.DataFolder() + "fishdata.db"
|
||||
err := dbdata.db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at main.go.1]:", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
)
|
||||
|
||||
func init() {
|
||||
//go func() {
|
||||
_, err := engine.GetLazyData("articlesInfo.json", false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
reader, err := os.Open(engine.DataFolder() + "articlesInfo.json")
|
||||
if err == nil {
|
||||
err = json.NewDecoder(reader).Decode(&articlesInfo)
|
||||
}
|
||||
if err == nil {
|
||||
err = reader.Close()
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
probableList := make([]int, 4)
|
||||
for _, info := range articlesInfo.ZoneInfo {
|
||||
switch info.Name {
|
||||
case "treasure":
|
||||
probableList[0] = info.Probability
|
||||
case "pole":
|
||||
probableList[1] = info.Probability
|
||||
case "fish":
|
||||
probableList[2] = info.Probability
|
||||
case "waste":
|
||||
probableList[3] = info.Probability
|
||||
}
|
||||
}
|
||||
probabilities["treasure"] = probabilityLimit{
|
||||
Min: 0,
|
||||
Max: probableList[0],
|
||||
}
|
||||
probabilities["pole"] = probabilityLimit{
|
||||
Min: probableList[0],
|
||||
Max: probableList[1],
|
||||
}
|
||||
probabilities["fish"] = probabilityLimit{
|
||||
Min: probableList[1],
|
||||
Max: probableList[2],
|
||||
}
|
||||
probabilities["waste"] = probabilityLimit{
|
||||
Min: probableList[2],
|
||||
Max: probableList[3],
|
||||
}
|
||||
min := make(map[string]int, 4)
|
||||
for _, info := range articlesInfo.ArticleInfo {
|
||||
switch {
|
||||
case info.Type == "pole":
|
||||
poleList = append(poleList, info.Name)
|
||||
case info.Type == "fish":
|
||||
fishList = append(fishList, info.Name)
|
||||
case info.Type == "waste":
|
||||
wasteList = append(wasteList, info.Name)
|
||||
case info.Type == "treasure":
|
||||
treasureList = append(treasureList, info.Name)
|
||||
}
|
||||
thingList = append(thingList, info.Name)
|
||||
priceList[info.Name] = info.Price
|
||||
if info.Durable != 0 {
|
||||
durationList[info.Name] = info.Durable
|
||||
}
|
||||
probabilities[info.Name] = probabilityLimit{
|
||||
Min: min[info.Type],
|
||||
Max: min[info.Type] + info.Probability,
|
||||
}
|
||||
min[info.Type] += info.Probability
|
||||
}
|
||||
//}()
|
||||
}
|
||||
|
||||
// 更新上限信息
|
||||
func (sql *fishdb) updateFishInfo(uid int64, number int) (residue int, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := fishState{ID: uid}
|
||||
err = sql.db.Create("fishState", &userInfo)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
_ = sql.db.Find("fishState", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
|
||||
if time.Unix(userInfo.Duration, 0).Day() != time.Now().Day() {
|
||||
userInfo.Fish = 0
|
||||
userInfo.Duration = time.Now().Unix()
|
||||
}
|
||||
if userInfo.Fish >= FishLimit {
|
||||
return 0, nil
|
||||
}
|
||||
residue = number
|
||||
if userInfo.Fish+number > FishLimit {
|
||||
residue = FishLimit - userInfo.Fish
|
||||
number = residue
|
||||
}
|
||||
userInfo.Fish += number
|
||||
err = sql.db.Insert("fishState", &userInfo)
|
||||
return
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/************************装备相关函数***********************/
|
||||
/*********************************************************/
|
||||
|
||||
func (sql *fishdb) checkEquipFor(uid int64) (ok bool, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := fishState{ID: uid}
|
||||
err = sql.db.Create("fishState", &userInfo)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !sql.db.CanFind("fishState", "where ID = "+strconv.FormatInt(uid, 10)) {
|
||||
return true, nil
|
||||
}
|
||||
err = sql.db.Find("fishState", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if userInfo.Equip > 3 {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (sql *fishdb) setEquipFor(uid int64) (err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := fishState{ID: uid}
|
||||
err = sql.db.Create("fishState", &userInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = sql.db.Find("fishState", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userInfo.Equip++
|
||||
return sql.db.Insert("fishState", &userInfo)
|
||||
}
|
||||
|
||||
// 获取装备信息
|
||||
func (sql *fishdb) getUserEquip(uid int64) (userInfo equip, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
err = sql.db.Create("equips", &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !sql.db.CanFind("equips", "where ID = "+strconv.FormatInt(uid, 10)) {
|
||||
return
|
||||
}
|
||||
err = sql.db.Find("equips", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
|
||||
return
|
||||
}
|
||||
|
||||
// 更新装备信息
|
||||
func (sql *fishdb) updateUserEquip(userInfo equip) (err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
err = sql.db.Create("equips", &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if userInfo.Durable == 0 {
|
||||
return sql.db.Del("equips", "where ID = "+strconv.FormatInt(userInfo.ID, 10))
|
||||
}
|
||||
return sql.db.Insert("equips", &userInfo)
|
||||
}
|
||||
|
||||
func (sql *fishdb) pickFishFor(uid int64, number int) (fishNames map[string]int, err error) {
|
||||
fishNames = make(map[string]int, 6)
|
||||
name := strconv.FormatInt(uid, 10) + "Pack"
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := article{}
|
||||
err = sql.db.Create(name, &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count, err := sql.db.Count(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
if !sql.db.CanFind(name, "where Type is 'fish'") {
|
||||
return
|
||||
}
|
||||
fishTypes := make([]article, 0, count)
|
||||
fishInfo := article{}
|
||||
err = sql.db.FindFor(name, &fishInfo, "where Type is 'fish'", func() error {
|
||||
fishTypes = append(fishTypes, fishInfo)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(fishTypes) == 0 {
|
||||
return
|
||||
}
|
||||
max := 0
|
||||
for _, info := range fishTypes {
|
||||
max += info.Number
|
||||
}
|
||||
if max < number {
|
||||
number = max
|
||||
}
|
||||
for i := number; i > 0; i-- {
|
||||
randNumber := rand.Intn(len(fishTypes))
|
||||
fishTypes[randNumber].Number--
|
||||
err = sql.db.Insert(name, &fishTypes[randNumber])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fishNames[fishTypes[randNumber].Name]++
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/************************背包相关函数***********************/
|
||||
/*********************************************************/
|
||||
|
||||
// 获取用户背包信息
|
||||
func (sql *fishdb) getUserPack(uid int64) (thingInfos []article, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := article{}
|
||||
err = sql.db.Create(strconv.FormatInt(uid, 10)+"Pack", &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count, err := sql.db.Count(strconv.FormatInt(uid, 10) + "Pack")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
err = sql.db.FindFor(strconv.FormatInt(uid, 10)+"Pack", &userInfo, "ORDER by Type, Name, Other ASC", func() error {
|
||||
thingInfos = append(thingInfos, userInfo)
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户物品信息
|
||||
func (sql *fishdb) getUserThingInfo(uid int64, thing string) (thingInfos []article, err error) {
|
||||
name := strconv.FormatInt(uid, 10) + "Pack"
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := article{}
|
||||
err = sql.db.Create(name, &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count, err := sql.db.Count(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
if !sql.db.CanFind(name, "where Name = '"+thing+"'") {
|
||||
return
|
||||
}
|
||||
err = sql.db.FindFor(name, &userInfo, "where Name = '"+thing+"'", func() error {
|
||||
thingInfos = append(thingInfos, userInfo)
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 更新用户物品信息
|
||||
func (sql *fishdb) updateUserThingInfo(uid int64, userInfo article) (err error) {
|
||||
name := strconv.FormatInt(uid, 10) + "Pack"
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
err = sql.db.Create(name, &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if userInfo.Number == 0 {
|
||||
return sql.db.Del(name, "where Duration = "+strconv.FormatInt(userInfo.Duration, 10))
|
||||
}
|
||||
return sql.db.Insert(name, &userInfo)
|
||||
}
|
||||
|
||||
// 获取某关键字的数量
|
||||
func (sql *fishdb) getNumberFor(uid int64, thing string) (number int, err error) {
|
||||
name := strconv.FormatInt(uid, 10) + "Pack"
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := article{}
|
||||
err = sql.db.Create(name, &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count, err := sql.db.Count(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
if !sql.db.CanFind(name, "where Name glob '*"+thing+"*'") {
|
||||
return
|
||||
}
|
||||
info := article{}
|
||||
err = sql.db.FindFor(name, &info, "where Name glob '*"+thing+"*'", func() error {
|
||||
number += info.Number
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/************************商店相关函数***********************/
|
||||
/*********************************************************/
|
||||
|
||||
// 刷新商店信息
|
||||
func (sql *fishdb) refreshStroeInfo() (ok bool, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
err = sql.db.Create("stroeDiscount", &storeDiscount{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
lastTime := storeDiscount{}
|
||||
_ = sql.db.Find("stroeDiscount", &lastTime, "where Name = 'lastTime'")
|
||||
refresh := false
|
||||
timeNow := time.Now().Day()
|
||||
if timeNow != lastTime.Discount {
|
||||
lastTime = storeDiscount{
|
||||
Name: "lastTime",
|
||||
Discount: timeNow,
|
||||
}
|
||||
err = sql.db.Insert("stroeDiscount", &lastTime)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
refresh = true
|
||||
}
|
||||
for name := range priceList {
|
||||
thing := storeDiscount{}
|
||||
switch refresh {
|
||||
case true:
|
||||
thingDiscount := 50 + rand.Intn(150)
|
||||
thing = storeDiscount{
|
||||
Name: name,
|
||||
Discount: thingDiscount,
|
||||
}
|
||||
err = sql.db.Insert("stroeDiscount", &thing)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
_ = sql.db.Find("stroeDiscount", &thing, "where Name = '"+name+"'")
|
||||
}
|
||||
if thing.Discount != 0 {
|
||||
discountList[name] = thing.Discount
|
||||
} else {
|
||||
discountList[name] = 100
|
||||
}
|
||||
}
|
||||
if refresh { // 每天调控1种鱼
|
||||
thingInfo := store{}
|
||||
err = sql.db.Create("store", &thingInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fish := fishList[rand.Intn(len(fishList))]
|
||||
_ = sql.db.Find("store", &thingInfo, "where Name = '"+fish+"'")
|
||||
if thingInfo == (store{}) {
|
||||
thingInfo.Duration = time.Now().Unix()
|
||||
thingInfo.Type = "fish"
|
||||
thingInfo.Name = fish
|
||||
thingInfo.Price = priceList[fish] * discountList[fish] / 100
|
||||
}
|
||||
thingInfo.Number += (100 - discountList[fish])
|
||||
if thingInfo.Number < 1 {
|
||||
thingInfo.Number = 1
|
||||
}
|
||||
_ = sql.db.Insert("store", &thingInfo)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 获取商店信息
|
||||
func (sql *fishdb) getStoreInfo() (thingInfos []store, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
thingInfo := store{}
|
||||
err = sql.db.Create("store", &thingInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count, err := sql.db.Count("store")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
err = sql.db.FindFor("store", &thingInfo, "ORDER by Type, Name, Price ASC", func() error {
|
||||
thingInfos = append(thingInfos, thingInfo)
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 获取商店物品信息
|
||||
func (sql *fishdb) getStoreThingInfo(thing string) (thingInfos []store, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
thingInfo := store{}
|
||||
err = sql.db.Create("store", &thingInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count, err := sql.db.Count("store")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
if !sql.db.CanFind("store", "where Name = '"+thing+"'") {
|
||||
return
|
||||
}
|
||||
err = sql.db.FindFor("store", &thingInfo, "where Name = '"+thing+"'", func() error {
|
||||
thingInfos = append(thingInfos, thingInfo)
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 更新商店信息
|
||||
func (sql *fishdb) updateStoreInfo(thingInfo store) (err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
err = sql.db.Create("store", &thingInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if thingInfo.Number == 0 {
|
||||
return sql.db.Del("store", "where Duration = "+strconv.FormatInt(thingInfo.Duration, 10))
|
||||
}
|
||||
return sql.db.Insert("store", &thingInfo)
|
||||
}
|
||||
454
plugin/mcfish/pack.go
Normal file
454
plugin/mcfish/pack.go
Normal file
@ -0,0 +1,454 @@
|
||||
// Package mcfish 钓鱼模拟器
|
||||
package mcfish
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/wallet"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/math"
|
||||
"github.com/FloatTech/gg"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine.OnFullMatch("钓鱼背包", getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pack.go.1]:", err))
|
||||
return
|
||||
}
|
||||
articles, err := dbdata.getUserPack(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pack.go.2]:", err))
|
||||
return
|
||||
}
|
||||
pic, err := drawPackImage(uid, equipInfo, articles)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pack.go.3]:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.ImageBytes(pic))
|
||||
})
|
||||
engine.OnFullMatch("当前装备概率明细", getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pack.go.1]:", err))
|
||||
return
|
||||
}
|
||||
number, err := dbdata.getNumberFor(uid, "鱼")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5.1]:", err))
|
||||
return
|
||||
}
|
||||
msg := make(message.Message, 0, 20+len(thingList))
|
||||
msg = append(msg, message.At(uid), message.Text("\n大类概率:\n"))
|
||||
probableList := make([]int, 4)
|
||||
for _, info := range articlesInfo.ZoneInfo {
|
||||
switch info.Name {
|
||||
case "treasure":
|
||||
probableList[0] = info.Probability
|
||||
case "pole":
|
||||
probableList[1] = info.Probability
|
||||
case "fish":
|
||||
probableList[2] = info.Probability
|
||||
case "waste":
|
||||
probableList[3] = info.Probability
|
||||
}
|
||||
}
|
||||
if number > 100 || equipInfo.Equip == "美西螈" { //放大概率
|
||||
probableList = []int{2, 8, 35, 45}
|
||||
}
|
||||
if equipInfo.Favor > 0 {
|
||||
probableList[0] += equipInfo.Favor
|
||||
probableList[1] += equipInfo.Favor
|
||||
probableList[2] += equipInfo.Favor
|
||||
probableList[3] -= equipInfo.Favor * 3
|
||||
}
|
||||
probable := probableList[0]
|
||||
msg = append(msg, message.Text("宝藏 : ", probableList[0], "%\n"))
|
||||
probable += probableList[1]
|
||||
msg = append(msg, message.Text("鱼竿 : ", probableList[1], "%\n"))
|
||||
probable += probableList[2]
|
||||
msg = append(msg, message.Text("鱼类 : ", probableList[2], "%\n"))
|
||||
probable += probableList[3]
|
||||
msg = append(msg, message.Text("垃圾 : ", probableList[3], "%\n"))
|
||||
msg = append(msg, message.Text("合计 : ", probable, "%\n"))
|
||||
msg = append(msg, message.Text("-----------\n宝藏概率:\n"))
|
||||
for _, name := range treasureList {
|
||||
msg = append(msg, message.Text(name, " : ",
|
||||
strconv.FormatFloat(float64(probabilities[name].Max-probabilities[name].Min)*float64(probableList[0])/100, 'f', 2, 64),
|
||||
"%\n"))
|
||||
}
|
||||
msg = append(msg, message.Text("-----------\n鱼竿概率:\n"))
|
||||
for _, name := range poleList {
|
||||
msg = append(msg, message.Text(name, " : ",
|
||||
strconv.FormatFloat(float64(probabilities[name].Max-probabilities[name].Min)*float64(probableList[1])/100, 'f', 2, 64),
|
||||
"%\n"))
|
||||
}
|
||||
msg = append(msg, message.Text("-----------\n鱼类概率:\n"))
|
||||
for _, name := range fishList {
|
||||
msg = append(msg, message.Text(name, " : ",
|
||||
strconv.FormatFloat(float64(probabilities[name].Max-probabilities[name].Min)*float64(probableList[2])/100, 'f', 2, 64),
|
||||
"%\n"))
|
||||
}
|
||||
msg = append(msg, message.Text("-----------"))
|
||||
ctx.Send(msg)
|
||||
})
|
||||
}
|
||||
|
||||
func drawPackImage(uid int64, equipInfo equip, articles []article) (imagePicByte []byte, err error) {
|
||||
fontdata, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
equipBlock image.Image // 装备信息
|
||||
packBlock image.Image // 背包信息
|
||||
)
|
||||
wg.Add(1)
|
||||
// 绘制ID
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if equipInfo == (equip{}) {
|
||||
equipBlock, err = drawEquipEmptyBlock(fontdata)
|
||||
} else {
|
||||
equipBlock, err = drawEquipInfoBlock(equipInfo, fontdata)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
wg.Add(1)
|
||||
// 绘制基本信息
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if len(articles) == 0 {
|
||||
packBlock, err = drawArticleEmptyBlock(fontdata)
|
||||
} else {
|
||||
packBlock, err = drawArticleInfoBlock(uid, articles, fontdata)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
wg.Wait()
|
||||
if equipBlock == nil || packBlock == nil {
|
||||
err = errors.New("生成图片失败,数据缺失")
|
||||
return
|
||||
}
|
||||
// 计算图片高度
|
||||
backDX := 1020
|
||||
backDY := 10 + equipBlock.Bounds().Dy() + 10 + packBlock.Bounds().Dy() + 10
|
||||
canvas := gg.NewContext(backDX, backDY)
|
||||
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, float64(backDX), float64(backDY))
|
||||
canvas.SetRGBA255(150, 150, 150, 255)
|
||||
canvas.Fill()
|
||||
canvas.DrawRectangle(10, 10, float64(backDX-20), float64(backDY-20))
|
||||
canvas.SetRGBA255(255, 255, 255, 255)
|
||||
canvas.Fill()
|
||||
|
||||
canvas.DrawImage(equipBlock, 10, 10)
|
||||
canvas.DrawImage(packBlock, 10, 10+equipBlock.Bounds().Dy()+10)
|
||||
|
||||
return imgfactory.ToBytes(canvas.Image())
|
||||
}
|
||||
|
||||
// 绘制装备栏区域
|
||||
func drawEquipEmptyBlock(fontdata []byte) (image.Image, error) {
|
||||
canvas := gg.NewContext(1000, 300)
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||||
canvas.SetRGBA255(255, 255, 255, 150)
|
||||
canvas.Fill()
|
||||
// 边框框
|
||||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
canvas.SetColor(color.Black)
|
||||
err := canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textW, textH := canvas.MeasureString("装备信息")
|
||||
canvas.DrawString("装备信息", 10, 10+textH)
|
||||
canvas.DrawLine(10, textH*1.2, textW, textH*1.2)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
if err = canvas.ParseFontFace(fontdata, 50); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas.DrawString("没有装备任何鱼竿", 50, 10+textH*2+50)
|
||||
return canvas.Image(), nil
|
||||
}
|
||||
func drawEquipInfoBlock(equipInfo equip, fontdata []byte) (image.Image, error) {
|
||||
canvas := gg.NewContext(1, 1)
|
||||
err := canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, titleH := canvas.MeasureString("装备信息")
|
||||
err = canvas.ParseFontFace(fontdata, 50)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, textH := canvas.MeasureString("装备信息")
|
||||
|
||||
backDY := math.Max(int(10+titleH*2+(textH*2)*4+10), 300)
|
||||
|
||||
canvas = gg.NewContext(1000, backDY)
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, 1000, float64(backDY))
|
||||
canvas.SetRGBA255(255, 255, 255, 150)
|
||||
canvas.Fill()
|
||||
// 边框框
|
||||
canvas.DrawRectangle(0, 0, 1000, float64(backDY))
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
getAvatar, err := engine.GetLazyData(equipInfo.Equip+".png", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
equipPic, _, err := image.Decode(bytes.NewReader(getAvatar))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
picDy := float64(backDY) - 10 - titleH*2
|
||||
equipPic = imgfactory.Size(equipPic, int(picDy)-10, int(picDy)-10).Image()
|
||||
canvas.DrawImage(equipPic, 10, 10+int(titleH)*2)
|
||||
|
||||
// 放字
|
||||
canvas.SetColor(color.Black)
|
||||
if err = canvas.ParseFontFace(fontdata, 100); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
titleW, titleH := canvas.MeasureString("装备信息")
|
||||
canvas.DrawString("装备信息", 10, 10+titleH*1.2)
|
||||
canvas.DrawLine(10, titleH*1.6, titleW, titleH*1.6)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
textDx := picDy + 10
|
||||
textDy := 10 + titleH*2
|
||||
if err = canvas.ParseFontFace(fontdata, 75); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textW, textH := canvas.MeasureString(equipInfo.Equip)
|
||||
canvas.DrawStringAnchored(equipInfo.Equip, textDx+textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
|
||||
textDy += textH * 1.5
|
||||
if err = canvas.ParseFontFace(fontdata, 50); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textW, textH = canvas.MeasureString("维修次数")
|
||||
durable := strconv.Itoa(equipInfo.Durable)
|
||||
valueW, _ := canvas.MeasureString("100")
|
||||
barW := 1000 - textDx - textW - 10 - valueW - 10
|
||||
|
||||
canvas.DrawStringAnchored("装备耐久", textDx+textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawRectangle(textDx+textW+5, textDy, barW, textH*1.2)
|
||||
canvas.SetRGB255(150, 150, 150)
|
||||
canvas.Fill()
|
||||
canvas.SetRGB255(0, 0, 0)
|
||||
durableW := barW * float64(equipInfo.Durable) / float64(durationList[equipInfo.Equip])
|
||||
canvas.DrawRectangle(textDx+textW+5, textDy, durableW, textH*1.2)
|
||||
canvas.SetRGB255(102, 102, 102)
|
||||
canvas.Fill()
|
||||
canvas.SetColor(color.Black)
|
||||
canvas.DrawStringAnchored(durable, textDx+textW+5+barW+5+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
|
||||
textDy += textH * 2
|
||||
maintenance := strconv.Itoa(equipInfo.Maintenance)
|
||||
canvas.DrawStringAnchored("维修次数", textDx+textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawRectangle(textDx+textW+5, textDy, barW, textH*1.2)
|
||||
canvas.SetRGB255(150, 150, 150)
|
||||
canvas.Fill()
|
||||
canvas.SetRGB255(0, 0, 0)
|
||||
canvas.DrawRectangle(textDx+textW+5, textDy, barW*float64(equipInfo.Maintenance)/10, textH*1.2)
|
||||
canvas.SetRGB255(102, 102, 102)
|
||||
canvas.Fill()
|
||||
canvas.SetColor(color.Black)
|
||||
canvas.DrawStringAnchored(maintenance, textDx+textW+5+barW+5+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
|
||||
textDy += textH * 3
|
||||
canvas.DrawString(" 附魔: 诱钓"+enchantLevel[equipInfo.Induce]+" 海之眷顾"+enchantLevel[equipInfo.Favor], textDx, textDy)
|
||||
return canvas.Image(), nil
|
||||
}
|
||||
|
||||
// 绘制背包信息区域
|
||||
func drawArticleEmptyBlock(fontdata []byte) (image.Image, error) {
|
||||
canvas := gg.NewContext(1000, 300)
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||||
canvas.SetRGBA255(255, 255, 255, 150)
|
||||
canvas.Fill()
|
||||
// 边框框
|
||||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
canvas.SetColor(color.Black)
|
||||
err := canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textW, textH := canvas.MeasureString("背包信息")
|
||||
canvas.DrawString("背包信息", 10, 10+textH*1.2)
|
||||
canvas.DrawLine(10, textH*1.6, textW, textH*1.6)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
if err = canvas.ParseFontFace(fontdata, 50); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas.DrawStringAnchored("背包没有存放任何东西", 500, 10+textH*2+50, 0.5, 0)
|
||||
return canvas.Image(), nil
|
||||
}
|
||||
func drawArticleInfoBlock(uid int64, articles []article, fontdata []byte) (image.Image, error) {
|
||||
canvas := gg.NewContext(1, 1)
|
||||
err := canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
titleW, titleH := canvas.MeasureString("背包信息")
|
||||
front := 45.0
|
||||
err = canvas.ParseFontFace(fontdata, front)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, textH := canvas.MeasureString("高度")
|
||||
|
||||
nameWOfFiest := 0.0
|
||||
nameWOfSecond := 0.0
|
||||
for i, info := range articles {
|
||||
textW, _ := canvas.MeasureString(info.Name + "(" + info.Other + ")")
|
||||
if i%2 == 0 && textW > nameWOfFiest {
|
||||
nameWOfFiest = textW
|
||||
} else if textW > nameWOfSecond {
|
||||
nameWOfSecond = textW
|
||||
}
|
||||
}
|
||||
valueW, _ := canvas.MeasureString("10000")
|
||||
|
||||
if (10+nameWOfFiest+10+valueW+10)+(10+nameWOfSecond+10+valueW+10) > 980 {
|
||||
front = 32.0
|
||||
err = canvas.ParseFontFace(fontdata, front)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, textH = canvas.MeasureString("高度")
|
||||
|
||||
nameWOfFiest = 0
|
||||
nameWOfSecond = 0
|
||||
for i, info := range articles {
|
||||
textW, _ := canvas.MeasureString(info.Name + "(" + info.Other + ")")
|
||||
if i%2 == 0 && textW > nameWOfFiest {
|
||||
nameWOfFiest = textW
|
||||
} else if textW > nameWOfSecond {
|
||||
nameWOfSecond = textW
|
||||
}
|
||||
}
|
||||
valueW, _ = canvas.MeasureString("10000")
|
||||
}
|
||||
wallW := (980 - (10 + nameWOfFiest + 10 + valueW + 10) - (10 + nameWOfSecond + 10 + valueW + 10)) / 2
|
||||
backY := math.Max(10+int(titleH*1.6)+10+int(textH*2)*(math.Ceil(len(articles), 2)+1), 500)
|
||||
canvas = gg.NewContext(1000, backY)
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, 1000, float64(backY))
|
||||
canvas.SetRGBA255(255, 255, 255, 150)
|
||||
canvas.Fill()
|
||||
// 边框框
|
||||
canvas.DrawRectangle(0, 0, 1000, float64(backY))
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
// 放字
|
||||
canvas.SetColor(color.Black)
|
||||
err = canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas.DrawString("背包信息", 10, 10+titleH*1.2)
|
||||
canvas.DrawLine(10, titleH*1.6, titleW, titleH*1.6)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
textDy := 10 + titleH*1.7
|
||||
if err = canvas.ParseFontFace(fontdata, front); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas.SetColor(color.Black)
|
||||
numberOfFish := 0
|
||||
numberOfEquip := 0
|
||||
canvas.DrawStringAnchored("名称", wallW+20+nameWOfFiest/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored("数量", wallW+20+nameWOfFiest+10+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored("名称", wallW+20+nameWOfFiest+10+valueW+10+10+nameWOfSecond/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored("数量", wallW+20+nameWOfFiest+10+valueW+10+10+nameWOfSecond+10+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
textDy += textH * 2
|
||||
for i, info := range articles {
|
||||
name := info.Name
|
||||
if info.Other != "" {
|
||||
if strings.Contains(info.Name, "竿") {
|
||||
numberOfEquip++
|
||||
}
|
||||
name += "(" + info.Other + ")"
|
||||
} else if strings.Contains(name, "鱼") {
|
||||
numberOfFish += info.Number
|
||||
}
|
||||
valueStr := strconv.Itoa(info.Number)
|
||||
if i%2 == 0 {
|
||||
if i != 0 {
|
||||
textDy += textH * 2
|
||||
}
|
||||
canvas.DrawStringAnchored(name, wallW+20+nameWOfFiest/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored(valueStr, wallW+20+nameWOfFiest+10+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
} else {
|
||||
canvas.DrawStringAnchored(name, wallW+20+nameWOfFiest+10+valueW+10+10+nameWOfSecond/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored(valueStr, wallW+20+nameWOfFiest+10+valueW+10+10+nameWOfSecond+10+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
}
|
||||
}
|
||||
if err = canvas.ParseFontFace(fontdata, 30); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textDy = 10
|
||||
text := "钱包余额: " + strconv.Itoa(wallet.GetWalletOf(uid))
|
||||
textW, textH := canvas.MeasureString(text)
|
||||
w, _ := canvas.MeasureString("维修大师[已激活]")
|
||||
if w > textW {
|
||||
textW = w
|
||||
}
|
||||
canvas.DrawStringAnchored(text, 980-textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
textDy += textH * 1.5
|
||||
if numberOfFish > 100 {
|
||||
canvas.DrawStringAnchored("钓鱼佬[已激活]", 980-textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
textDy += textH * 1.5
|
||||
}
|
||||
if numberOfEquip > 10 {
|
||||
canvas.DrawStringAnchored("维修大师[已激活]", 980-textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
}
|
||||
return canvas.Image(), nil
|
||||
}
|
||||
485
plugin/mcfish/pole.go
Normal file
485
plugin/mcfish/pole.go
Normal file
@ -0,0 +1,485 @@
|
||||
// Package mcfish 钓鱼模拟器
|
||||
package mcfish
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine.OnRegex(`^装备(`+strings.Join(poleList, "|")+`)$`, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.1]:", err))
|
||||
return
|
||||
}
|
||||
thingName := ctx.State["regex_matched"].([]string)[1]
|
||||
articles, err := dbdata.getUserThingInfo(uid, thingName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.2]:", err))
|
||||
return
|
||||
}
|
||||
if len(articles) == 0 {
|
||||
ctx.SendChain(message.Text("你的背包不存在该物品"))
|
||||
return
|
||||
}
|
||||
poles := make([]equip, 0, len(articles))
|
||||
if thingName != "美西螈" {
|
||||
for _, info := range articles {
|
||||
poleInfo := strings.Split(info.Other, "/")
|
||||
durable, _ := strconv.Atoi(poleInfo[0])
|
||||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||||
poles = append(poles, equip{
|
||||
ID: uid,
|
||||
Equip: info.Name,
|
||||
Durable: durable,
|
||||
Maintenance: maintenance,
|
||||
Induce: induceLevel,
|
||||
Favor: favorLevel,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
poles = append(poles, equip{
|
||||
ID: uid,
|
||||
Equip: thingName,
|
||||
Durable: 999,
|
||||
})
|
||||
}
|
||||
check := false
|
||||
index := 0
|
||||
if len(poles) > 1 {
|
||||
msg := make(message.Message, 0, 3+len(articles))
|
||||
msg = append(msg, message.Reply(ctx.Event.MessageID), message.Text("找到以下鱼竿:\n"))
|
||||
for i, info := range poles {
|
||||
msg = append(msg, message.Text("[", i, "] ", info.Equip, " : 耐", info.Durable, "/修", info.Maintenance,
|
||||
"/诱", enchantLevel[info.Induce], "/眷顾", enchantLevel[info.Favor], "\n"))
|
||||
}
|
||||
msg = append(msg, message.Text("————————\n输入对应序号进行装备,或回复“取消”取消"))
|
||||
ctx.Send(msg)
|
||||
// 等待用户下一步选择
|
||||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(取消|\d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("等待超时,取消装备"),
|
||||
),
|
||||
)
|
||||
return
|
||||
case e := <-recv:
|
||||
nextcmd := e.Event.Message.String()
|
||||
if nextcmd == "取消" {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("已取消装备"),
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
index, err = strconv.Atoi(nextcmd)
|
||||
if err != nil || index > len(articles)-1 {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入正确的序号"))
|
||||
continue
|
||||
}
|
||||
check = true
|
||||
}
|
||||
if check {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
newEquipInfo := poles[index]
|
||||
packEquip := articles[index]
|
||||
packEquip.Number--
|
||||
err = dbdata.updateUserThingInfo(uid, packEquip)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.3]:", err))
|
||||
return
|
||||
}
|
||||
err = dbdata.updateUserEquip(newEquipInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.3.1]:", err))
|
||||
return
|
||||
}
|
||||
oldthing := article{}
|
||||
if equipInfo != (equip{}) && equipInfo.Equip != "美西螈" {
|
||||
oldthing = article{
|
||||
Duration: time.Now().Unix(),
|
||||
Type: "pole",
|
||||
Name: equipInfo.Equip,
|
||||
Number: 1,
|
||||
Other: strconv.Itoa(equipInfo.Durable) + "/" + strconv.Itoa(equipInfo.Maintenance) + "/" + strconv.Itoa(equipInfo.Induce) + "/" + strconv.Itoa(equipInfo.Favor),
|
||||
}
|
||||
} else if equipInfo.Equip == "美西螈" {
|
||||
articles, err = dbdata.getUserThingInfo(uid, "美西螈")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.3.2]:", err))
|
||||
return
|
||||
}
|
||||
if len(articles) == 0 {
|
||||
oldthing = article{
|
||||
Duration: time.Now().Unix(),
|
||||
Type: "pole",
|
||||
Name: equipInfo.Equip,
|
||||
Number: 1,
|
||||
}
|
||||
} else {
|
||||
oldthing = articles[0]
|
||||
oldthing.Number++
|
||||
}
|
||||
}
|
||||
err = dbdata.updateUserThingInfo(uid, oldthing)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.4]:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("装备成功"),
|
||||
),
|
||||
)
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"修复鱼竿", "维修鱼竿"}, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.5]:", err))
|
||||
return
|
||||
}
|
||||
if equipInfo.Equip == "" || equipInfo.Equip == "美西螈" || equipInfo.Equip == "三叉戟" {
|
||||
ctx.SendChain(message.Text("仅能修复装备中的鱼竿"))
|
||||
return
|
||||
}
|
||||
if equipInfo.Maintenance >= 10 {
|
||||
ctx.SendChain(message.Text("装备的鱼竿已经达到修复上限"))
|
||||
return
|
||||
}
|
||||
articles, err := dbdata.getUserThingInfo(uid, equipInfo.Equip)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.6]:", err))
|
||||
return
|
||||
}
|
||||
if len(articles) == 0 {
|
||||
ctx.SendChain(message.Text("你的背包不存在相同鱼竿进行修复"))
|
||||
return
|
||||
}
|
||||
poles := make([]equip, 0, len(articles))
|
||||
for _, info := range articles {
|
||||
poleInfo := strings.Split(info.Other, "/")
|
||||
durable, _ := strconv.Atoi(poleInfo[0])
|
||||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||||
poles = append(poles, equip{
|
||||
ID: uid,
|
||||
Equip: info.Name,
|
||||
Durable: durable,
|
||||
Maintenance: maintenance,
|
||||
Induce: induceLevel,
|
||||
Favor: favorLevel,
|
||||
})
|
||||
}
|
||||
index := 0
|
||||
check := false
|
||||
if len(articles) > 1 {
|
||||
msg := make(message.Message, 0, 3+len(articles))
|
||||
msg = append(msg, message.Text("找到以下鱼竿:\n"))
|
||||
for i, info := range poles {
|
||||
msg = append(msg, message.Text("[", i, "] ", info.Equip, " : 耐", info.Durable, "/修", info.Maintenance,
|
||||
"/诱", enchantLevel[info.Induce], "/眷顾", enchantLevel[info.Favor], "\n"))
|
||||
}
|
||||
msg = append(msg, message.Text("————————\n输入对应序号进行修复,或回复“取消”取消"))
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, msg...))
|
||||
// 等待用户下一步选择
|
||||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(取消|\d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("等待超时,取消修复"),
|
||||
),
|
||||
)
|
||||
return
|
||||
case e := <-recv:
|
||||
nextcmd := e.Event.Message.String()
|
||||
if nextcmd == "取消" {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("已取消修复"),
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
index, err = strconv.Atoi(nextcmd)
|
||||
if err != nil || index > len(articles)-1 {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入正确的序号"))
|
||||
continue
|
||||
}
|
||||
check = true
|
||||
}
|
||||
if check {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
newEquipInfo := poles[index]
|
||||
number, err := dbdata.getNumberFor(uid, "竿")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5.1]:", err))
|
||||
return
|
||||
}
|
||||
if number <= 10 {
|
||||
number = 8
|
||||
} else {
|
||||
number = 10
|
||||
}
|
||||
equipInfo.Durable += newEquipInfo.Durable * number / 10
|
||||
if equipInfo.Durable > durationList[equipInfo.Equip] {
|
||||
equipInfo.Durable = durationList[equipInfo.Equip]
|
||||
}
|
||||
msg := ""
|
||||
if newEquipInfo.Induce != 0 && rand.Intn(100) < 50 {
|
||||
equipInfo.Induce += newEquipInfo.Induce
|
||||
if equipInfo.Induce > 3 {
|
||||
equipInfo.Induce = 3
|
||||
}
|
||||
msg += ",诱钓等级提升至" + enchantLevel[equipInfo.Induce]
|
||||
}
|
||||
if newEquipInfo.Favor != 0 && rand.Intn(100) < 50 {
|
||||
equipInfo.Favor += newEquipInfo.Favor
|
||||
if equipInfo.Favor > 3 {
|
||||
equipInfo.Favor = 3
|
||||
}
|
||||
msg += ",海之眷顾等级提升至" + enchantLevel[equipInfo.Favor]
|
||||
}
|
||||
thingInfo := articles[index]
|
||||
thingInfo.Number = 0
|
||||
err = dbdata.updateUserThingInfo(uid, thingInfo)
|
||||
if err == nil {
|
||||
equipInfo.Maintenance++
|
||||
err = dbdata.updateUserEquip(equipInfo)
|
||||
}
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.7]:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("鱼竿修复成功,耐久提高至", equipInfo.Durable, msg),
|
||||
),
|
||||
)
|
||||
})
|
||||
engine.OnRegex(`^附魔(诱钓|海之眷顾)$`, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.7]:", err))
|
||||
return
|
||||
}
|
||||
if equipInfo.Equip == "" || equipInfo.Equip == "美西螈" {
|
||||
ctx.SendChain(message.Text("仅可对装备中的进行附魔"))
|
||||
return
|
||||
}
|
||||
book := ctx.State["regex_matched"].([]string)[1]
|
||||
books, err := dbdata.getUserThingInfo(uid, book)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.8]:", err))
|
||||
return
|
||||
}
|
||||
if len(books) == 0 {
|
||||
ctx.SendChain(message.Text("你的背包不存在", book, "进行附魔"))
|
||||
return
|
||||
}
|
||||
bookInfo := books[0]
|
||||
bookInfo.Number--
|
||||
err = dbdata.updateUserThingInfo(uid, bookInfo)
|
||||
number := 0
|
||||
if err == nil {
|
||||
if rand.Intn(100) > 50 {
|
||||
ctx.SendChain(message.Text("附魔失败了"))
|
||||
return
|
||||
}
|
||||
switch book {
|
||||
case "诱钓":
|
||||
equipInfo.Induce++
|
||||
if equipInfo.Induce > 3 {
|
||||
equipInfo.Induce = 3
|
||||
}
|
||||
number = equipInfo.Induce
|
||||
case "海之眷顾":
|
||||
equipInfo.Favor++
|
||||
if equipInfo.Favor > 3 {
|
||||
equipInfo.Favor = 3
|
||||
}
|
||||
number = equipInfo.Favor
|
||||
default:
|
||||
ctx.SendChain(message.Text("附魔失败了"))
|
||||
return
|
||||
}
|
||||
err = dbdata.updateUserEquip(equipInfo)
|
||||
}
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.9]:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("附魔成功,", book, "等级提高至", enchantLevel[number]))
|
||||
})
|
||||
engine.OnRegex(`^合成(.+竿|三叉戟)$`, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
thingList := []string{"木竿", "铁竿", "金竿", "钻石竿", "下界合金竿", "三叉戟"}
|
||||
thingName := ctx.State["regex_matched"].([]string)[1]
|
||||
indexOfMaterial := -1
|
||||
for i, name := range thingList {
|
||||
if thingName == name {
|
||||
indexOfMaterial = (i - 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
if indexOfMaterial < 0 {
|
||||
return
|
||||
}
|
||||
articles, err := dbdata.getUserThingInfo(uid, thingList[indexOfMaterial])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.10]:", err))
|
||||
return
|
||||
}
|
||||
max := len(articles)
|
||||
if max < 3 {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("你的合成材料不足"))
|
||||
return
|
||||
}
|
||||
poles := make([]equip, 0, max)
|
||||
for _, info := range articles {
|
||||
poleInfo := strings.Split(info.Other, "/")
|
||||
durable, _ := strconv.Atoi(poleInfo[0])
|
||||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||||
poles = append(poles, equip{
|
||||
ID: uid,
|
||||
Equip: info.Name,
|
||||
Durable: durable,
|
||||
Maintenance: maintenance,
|
||||
Induce: induceLevel,
|
||||
Favor: favorLevel,
|
||||
})
|
||||
}
|
||||
list := []int{0, 1, 2}
|
||||
check := false
|
||||
if len(articles) > 3 {
|
||||
msg := make(message.Message, 0, 3+len(articles))
|
||||
msg = append(msg, message.Text("找到以下鱼竿:\n"))
|
||||
for i, info := range poles {
|
||||
msg = append(msg, message.Text("[", i, "] ", info.Equip, " : 耐", info.Durable, "/修", info.Maintenance,
|
||||
"/诱", enchantLevel[info.Induce], "/眷顾", enchantLevel[info.Favor], "\n"))
|
||||
}
|
||||
msg = append(msg, message.Text("————————\n输入3个序号进行合成(用空格分割),或回复“取消”取消"))
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, msg...))
|
||||
// 等待用户下一步选择
|
||||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(取消|\d+ \d+ \d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("等待超时,取消合成"),
|
||||
),
|
||||
)
|
||||
return
|
||||
case e := <-recv:
|
||||
nextcmd := e.Event.Message.String()
|
||||
if nextcmd == "取消" {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("已取消合成"),
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
chooseList := strings.Split(nextcmd, " ")
|
||||
if list[0] == list[1] || list[0] == list[2] || list[1] == list[2] {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("[0]请输入正确的序号\n", list))
|
||||
continue
|
||||
}
|
||||
first, err := strconv.Atoi(chooseList[0])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.11.1]:", err))
|
||||
return
|
||||
}
|
||||
second, err := strconv.Atoi(chooseList[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.11.2]:", err))
|
||||
return
|
||||
}
|
||||
third, err := strconv.Atoi(chooseList[2])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.11.3]:", err))
|
||||
return
|
||||
}
|
||||
if first > max || second > max || third > max {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("[", max, "]请输入正确的序号\n", list))
|
||||
continue
|
||||
}
|
||||
list = []int{first, second, third}
|
||||
check = true
|
||||
}
|
||||
if check {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
favorLevel := 0
|
||||
induceLevel := 0
|
||||
for _, index := range list {
|
||||
thingInfo := articles[index]
|
||||
thingInfo.Number = 0
|
||||
err = dbdata.updateUserThingInfo(uid, thingInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.12]:", err))
|
||||
return
|
||||
}
|
||||
favorLevel += poles[index].Favor
|
||||
induceLevel += poles[index].Induce
|
||||
}
|
||||
if rand.Intn(100) >= 90 {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("合成失败,材料已销毁"),
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
attribute := strconv.Itoa(durationList[thingName]) + "/0/" + strconv.Itoa(induceLevel/3) + "/" + strconv.Itoa(favorLevel/3)
|
||||
newthing := article{
|
||||
Duration: time.Now().Unix(),
|
||||
Type: "pole",
|
||||
Name: thingName,
|
||||
Number: 1,
|
||||
Other: attribute,
|
||||
}
|
||||
err = dbdata.updateUserThingInfo(uid, newthing)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.12]:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text(thingName, "合成成功\n属性: ", attribute),
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
593
plugin/mcfish/store.go
Normal file
593
plugin/mcfish/store.go
Normal file
@ -0,0 +1,593 @@
|
||||
// Package mcfish 钓鱼模拟器
|
||||
package mcfish
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/wallet"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/math"
|
||||
"github.com/FloatTech/gg"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
refresh = false
|
||||
timeNow = 0
|
||||
refreshFish = func(ctx *zero.Ctx) bool {
|
||||
if refresh && timeNow == time.Now().Day() {
|
||||
return true
|
||||
}
|
||||
refresh, err := dbdata.refreshStroeInfo()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.1]:", err))
|
||||
return refresh
|
||||
}
|
||||
timeNow = time.Now().Day()
|
||||
return refresh
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine.OnFullMatchGroup([]string{"钓鱼看板", "钓鱼商店"}, getdb, refreshFish).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
infos, err := dbdata.getStoreInfo()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.2]:", err))
|
||||
return
|
||||
}
|
||||
var picImage image.Image
|
||||
if len(infos) == 0 {
|
||||
picImage, err = drawStroeEmptyImage()
|
||||
} else {
|
||||
picImage, err = drawStroeInfoImage(infos)
|
||||
}
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.3]:", err))
|
||||
return
|
||||
}
|
||||
pic, err := imgfactory.ToBytes(picImage)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.4]:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.ImageBytes(pic))
|
||||
})
|
||||
engine.OnRegex(`^出售(`+strings.Join(thingList, "|")+`)\s*(\d*)$`, getdb, refreshFish).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
thingName := ctx.State["regex_matched"].([]string)[1]
|
||||
number, _ := strconv.Atoi(ctx.State["regex_matched"].([]string)[2])
|
||||
if number == 0 {
|
||||
number = 1
|
||||
}
|
||||
articles, err := dbdata.getUserThingInfo(uid, thingName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.5]:", err))
|
||||
return
|
||||
}
|
||||
if len(articles) == 0 {
|
||||
ctx.SendChain(message.Text("你的背包不存在该物品"))
|
||||
return
|
||||
}
|
||||
index := 0
|
||||
thing := article{}
|
||||
if len(articles) > 1 {
|
||||
msg := make(message.Message, 0, 3+len(articles))
|
||||
msg = append(msg, message.Reply(ctx.Event.MessageID), message.Text("找到以下物品:\n"))
|
||||
for i, info := range articles {
|
||||
if info.Other != "" && info.Name != "美西螈" {
|
||||
msg = append(msg, message.Text("[", i, "] ", info.Name, "(", info.Other, ")\n"))
|
||||
} else {
|
||||
msg = append(msg, message.Text(
|
||||
"[", i, "]", info.Name, " 数量: ", info.Number, "\n"))
|
||||
}
|
||||
|
||||
}
|
||||
msg = append(msg, message.Reply(ctx.Event.MessageID), message.Text("————————\n输入对应序号进行装备,或回复“取消”取消"))
|
||||
ctx.Send(msg)
|
||||
// 等待用户下一步选择
|
||||
sell := false
|
||||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(取消|\d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("等待超时,取消出售"),
|
||||
),
|
||||
)
|
||||
return
|
||||
case e := <-recv:
|
||||
nextcmd := e.Event.Message.String()
|
||||
if nextcmd == "取消" {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("已取消出售"),
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
index, err = strconv.Atoi(nextcmd)
|
||||
if err != nil || index > len(articles)-1 {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入正确的序号"))
|
||||
continue
|
||||
}
|
||||
sell = true
|
||||
}
|
||||
if sell {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thing = articles[index]
|
||||
if thing.Number < number {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("背包数量不足")))
|
||||
return
|
||||
}
|
||||
|
||||
var pice int
|
||||
if strings.Contains(thingName, "竿") || thingName == "三叉戟" {
|
||||
poleInfo := strings.Split(articles[index].Other, "/")
|
||||
durable, _ := strconv.Atoi(poleInfo[0])
|
||||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||||
pice = (priceList[thingName] - (durationList[thingName] - durable) - maintenance*2 + induceLevel*600 + favorLevel*1800) * discountList[thingName] / 100
|
||||
} else {
|
||||
pice = priceList[thingName] * discountList[thingName] / 100
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("是否接受商店将以", pice*number*8/10, "收购", number, "个", thingName, "?\n回答\"是\"或\"否\"")))
|
||||
// 等待用户下一步选择
|
||||
recv, cancel1 := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(是|否)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel1()
|
||||
buy := false
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 60):
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("等待超时,取消钓鱼")))
|
||||
return
|
||||
case e := <-recv:
|
||||
nextcmd := e.Event.Message.String()
|
||||
if nextcmd == "否" {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("已取消购买")))
|
||||
return
|
||||
}
|
||||
buy = true
|
||||
}
|
||||
if buy {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
records, err := dbdata.getUserThingInfo(uid, "唱片")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.9.1]:", err))
|
||||
return
|
||||
}
|
||||
if len(records) != 0 {
|
||||
recordInfo := records[0]
|
||||
numberOfRecord := recordInfo.Number
|
||||
if thingName == "唱片" {
|
||||
numberOfRecord--
|
||||
}
|
||||
if numberOfRecord > 0 {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("是否使用唱片让价格翻倍?\n回答\"是\"或\"否\"")))
|
||||
// 等待用户下一步选择
|
||||
recv, cancel2 := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(是|否)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel2()
|
||||
use := false
|
||||
checkTime := false
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 60):
|
||||
checkTime = true
|
||||
case e := <-recv:
|
||||
nextcmd := e.Event.Message.String()
|
||||
if nextcmd == "是" {
|
||||
use = true
|
||||
}
|
||||
checkTime = true
|
||||
}
|
||||
if checkTime {
|
||||
break
|
||||
}
|
||||
}
|
||||
if use {
|
||||
pice *= 2
|
||||
recordInfo.Number--
|
||||
err = dbdata.updateUserThingInfo(uid, recordInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.9.2]:", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
thing.Number -= number
|
||||
err = dbdata.updateUserThingInfo(uid, thing)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.6]:", err))
|
||||
return
|
||||
}
|
||||
newCommodity := store{}
|
||||
if strings.Contains(thingName, "竿") || thingName == "三叉戟" {
|
||||
if pice >= priceList[thingName]*4/5 { // 不值钱的删了
|
||||
newCommodity = store{
|
||||
Duration: time.Now().Unix(),
|
||||
Type: "pole",
|
||||
Name: thingName,
|
||||
Number: 1,
|
||||
Price: pice,
|
||||
Other: thing.Other,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
things, err1 := dbdata.getStoreThingInfo(thingName)
|
||||
if err1 != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.8]:", err1))
|
||||
return
|
||||
}
|
||||
if len(things) == 0 {
|
||||
things = append(things, store{
|
||||
Duration: time.Now().Unix(),
|
||||
Name: thingName,
|
||||
Number: 0,
|
||||
Price: pice,
|
||||
})
|
||||
switch {
|
||||
case thingName == "海之眷顾" || thingName == "诱钓" || thingName == "唱片":
|
||||
things[0].Type = "article"
|
||||
case thingName == "美西螈":
|
||||
things[0].Type = "pole"
|
||||
default:
|
||||
things[0].Type = "fish"
|
||||
}
|
||||
}
|
||||
newCommodity = things[0]
|
||||
newCommodity.Number += number
|
||||
}
|
||||
err = dbdata.updateStoreInfo(newCommodity)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.9]:", err))
|
||||
return
|
||||
}
|
||||
pice = pice * 8 / 10
|
||||
err = wallet.InsertWalletOf(uid, pice*number)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.10]:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("出售成功,你赚到了", pice*number)))
|
||||
})
|
||||
engine.OnRegex(`^购买(`+strings.Join(thingList, "|")+`)\s*(\d*)$`, getdb, refreshFish).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
thingName := ctx.State["regex_matched"].([]string)[1]
|
||||
number, _ := strconv.Atoi(ctx.State["regex_matched"].([]string)[2])
|
||||
if number == 0 {
|
||||
number = 1
|
||||
}
|
||||
thingInfos, err := dbdata.getStoreThingInfo(thingName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.11]:", err))
|
||||
return
|
||||
}
|
||||
if len(thingInfos) == 0 {
|
||||
ctx.SendChain(message.Text("当前商店并没有上架该物品"))
|
||||
return
|
||||
}
|
||||
index := 0
|
||||
pice := make([]int, 0, len(thingInfos))
|
||||
for _, info := range thingInfos {
|
||||
if strings.Contains(thingName, "竿") || thingName == "三叉戟" {
|
||||
poleInfo := strings.Split(info.Other, "/")
|
||||
durable, _ := strconv.Atoi(poleInfo[0])
|
||||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||||
thingPice := (priceList[info.Name] - (durationList[info.Name] - durable) - maintenance*2 + induceLevel*600 + favorLevel*1800) * discountList[info.Name] / 100
|
||||
pice = append(pice, thingPice)
|
||||
} else {
|
||||
thingPice := priceList[info.Name] * discountList[info.Name] / 100
|
||||
pice = append(pice, thingPice)
|
||||
}
|
||||
|
||||
}
|
||||
if len(thingInfos) > 1 {
|
||||
msg := make(message.Message, 0, 3+len(thingInfos))
|
||||
msg = append(msg, message.Text("找到以下物品:\n"))
|
||||
for i, info := range thingInfos {
|
||||
if strings.Contains(thingName, "竿") || thingName == "三叉戟" {
|
||||
msg = append(msg, message.Text(
|
||||
"[", i, "]", info.Name, "(", info.Other, ") 价格:", pice[i], "\n"))
|
||||
} else {
|
||||
msg = append(msg, message.Text(
|
||||
"[", i, "]", info.Name, " 数量:", info.Number, " 价格:", pice[i], "\n"))
|
||||
}
|
||||
|
||||
}
|
||||
msg = append(msg, message.Text("————————\n输入对应序号进行装备,或回复“取消”取消"))
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, msg...))
|
||||
// 等待用户下一步选择
|
||||
sell := false
|
||||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(取消|\d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("等待超时,取消购买"),
|
||||
),
|
||||
)
|
||||
return
|
||||
case e := <-recv:
|
||||
nextcmd := e.Event.Message.String()
|
||||
if nextcmd == "取消" {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("已取消购买"),
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
index, err = strconv.Atoi(nextcmd)
|
||||
if err != nil || index > len(thingInfos)-1 {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入正确的序号"))
|
||||
continue
|
||||
}
|
||||
sell = true
|
||||
}
|
||||
if sell {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thing := thingInfos[index]
|
||||
if thing.Number < number {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("商店数量不足")))
|
||||
return
|
||||
}
|
||||
|
||||
money := wallet.GetWalletOf(uid)
|
||||
if money < pice[index]*number {
|
||||
ctx.SendChain(message.Text("你身上的钱(", money, ")不够支付"))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你确定花费", pice[index]*number, "购买", number, "个", thingName, "?\n回答\"是\"或\"否\"")))
|
||||
// 等待用户下一步选择
|
||||
recv, cancel1 := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(是|否)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel1()
|
||||
buy := false
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 60):
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("等待超时,取消购买")))
|
||||
return
|
||||
case e := <-recv:
|
||||
nextcmd := e.Event.Message.String()
|
||||
if nextcmd == "否" {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("已取消购买")))
|
||||
return
|
||||
}
|
||||
buy = true
|
||||
}
|
||||
if buy {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
thing.Number -= number
|
||||
err = dbdata.updateStoreInfo(thing)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.12]:", err))
|
||||
return
|
||||
}
|
||||
err = wallet.InsertWalletOf(uid, -pice[index]*number)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.13]:", err))
|
||||
return
|
||||
}
|
||||
newCommodity := article{}
|
||||
if strings.Contains(thingName, "竿") || thingName == "三叉戟" {
|
||||
newCommodity = article{
|
||||
Duration: time.Now().Unix(),
|
||||
Type: "pole",
|
||||
Name: thingName,
|
||||
Number: 1,
|
||||
Other: thing.Other,
|
||||
}
|
||||
} else {
|
||||
things, err1 := dbdata.getUserThingInfo(uid, thingName)
|
||||
if err1 != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.15]:", err1))
|
||||
return
|
||||
}
|
||||
if len(things) == 0 {
|
||||
things = append(things, article{
|
||||
Duration: time.Now().Unix(),
|
||||
Name: thingName,
|
||||
Number: 0,
|
||||
})
|
||||
switch {
|
||||
case thingName == "海之眷顾" || thingName == "诱钓" || thingName == "唱片":
|
||||
things[0].Type = "article"
|
||||
case thingName == "美西螈":
|
||||
things[0].Type = "pole"
|
||||
default:
|
||||
things[0].Type = "fish"
|
||||
}
|
||||
}
|
||||
newCommodity = things[0]
|
||||
newCommodity.Number += number
|
||||
}
|
||||
err = dbdata.updateUserThingInfo(uid, newCommodity)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.14]:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("购买成功")))
|
||||
})
|
||||
}
|
||||
|
||||
func drawStroeEmptyImage() (picImage image.Image, err error) {
|
||||
fontdata, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas := gg.NewContext(1000, 300)
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||||
canvas.SetRGBA255(255, 255, 255, 150)
|
||||
canvas.Fill()
|
||||
// 边框框
|
||||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
canvas.SetColor(color.Black)
|
||||
err = canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textW, textH := canvas.MeasureString("价格信息")
|
||||
canvas.DrawString("价格信息", 10, 10+textH*1.2)
|
||||
canvas.DrawLine(10, textH*1.6, textW, textH*1.6)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
if err = canvas.ParseFontFace(fontdata, 50); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas.DrawStringAnchored("当前商店并没有上架任何物品", 500, 10+textH*2+50, 0.5, 0)
|
||||
return canvas.Image(), nil
|
||||
}
|
||||
|
||||
func drawStroeInfoImage(stroeInfo []store) (picImage image.Image, err error) {
|
||||
fontdata, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas := gg.NewContext(1, 1)
|
||||
err = canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
titleW, titleH := canvas.MeasureString("价格信息")
|
||||
|
||||
err = canvas.ParseFontFace(fontdata, 50)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, textH := canvas.MeasureString("高度")
|
||||
nameW, _ := canvas.MeasureString("下界合金竿(100/100/0/0)")
|
||||
numberW, _ := canvas.MeasureString("10000")
|
||||
priceW, _ := canvas.MeasureString("10000")
|
||||
|
||||
bolckW := int(10 + nameW + 50 + numberW + 50 + priceW + 10)
|
||||
backY := 10 + int(titleH*2+10)*2 + 10 + (len(stroeInfo)+len(discountList)/2+2)*int(textH*2) + 10
|
||||
canvas = gg.NewContext(bolckW, math.Max(backY, 500))
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, float64(bolckW), float64(backY))
|
||||
canvas.SetRGBA255(150, 150, 150, 255)
|
||||
canvas.Fill()
|
||||
|
||||
// 放字
|
||||
canvas.SetColor(color.Black)
|
||||
err = canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas.DrawString("今日波动", 10, 10+titleH*1.2)
|
||||
canvas.DrawLine(10, titleH*1.6, titleW, titleH*1.6)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
textDy := 10 + titleH*1.7
|
||||
if err = canvas.ParseFontFace(fontdata, 35); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textDx, textDh := canvas.MeasureString("下界合金竿(均价1000)")
|
||||
valueDx, _ := canvas.MeasureString("+100%")
|
||||
i := 0
|
||||
for name, info := range discountList {
|
||||
text := name + "(均价" + strconv.Itoa(priceList[name]) + ") "
|
||||
|
||||
if i == 2 {
|
||||
i = 0
|
||||
textDy += textDh * 2
|
||||
}
|
||||
canvas.SetColor(color.Black)
|
||||
canvas.DrawStringAnchored(text, 20+(textDx+valueDx+10)*float64(i)+10, textDy+textDh/2, 0, 0.5)
|
||||
if info-100 > 0 {
|
||||
canvas.SetRGBA255(200, 50, 50, 255)
|
||||
text = "+" + strconv.Itoa(info-100) + "%"
|
||||
} else {
|
||||
canvas.SetRGBA255(63, 133, 55, 255)
|
||||
text = strconv.Itoa(info-100) + "%"
|
||||
}
|
||||
canvas.DrawStringAnchored(text, 20+(textDx+valueDx+10)*float64(i)+10+textDx+10, textDy+textDh/2, 0, 0.5)
|
||||
i++
|
||||
}
|
||||
canvas.SetColor(color.Black)
|
||||
textDy += textDh * 2
|
||||
canvas.DrawStringAnchored("注:出售商品将会额外扣除20%的税收,附魔鱼竿请按实际价格", 10, textDy+10+textDh/2, 0, 0.5)
|
||||
|
||||
textDy += textH * 2
|
||||
err = canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas.DrawString("上架内容", 10, textDy+titleH*1.2)
|
||||
canvas.DrawLine(10, textDy+titleH*1.6, titleW, textDy+titleH*1.6)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
textDy += 10 + titleH*1.7
|
||||
if err = canvas.ParseFontFace(fontdata, 50); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
canvas.DrawStringAnchored("名称", 10+nameW/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored("数量", 10+nameW+10+numberW/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored("价格", 10+nameW+10+numberW+50+priceW/2, textDy+textH/2, 0.5, 0.5)
|
||||
|
||||
for _, info := range stroeInfo {
|
||||
textDy += textH * 2
|
||||
name := info.Name
|
||||
if info.Other != "" && info.Name != "美西螈" {
|
||||
name += "(" + info.Other + ")"
|
||||
}
|
||||
numberStr := strconv.Itoa(info.Number)
|
||||
pice := 0
|
||||
if strings.Contains(name, "竿") {
|
||||
poleInfo := strings.Split(info.Other, "/")
|
||||
durable, _ := strconv.Atoi(poleInfo[0])
|
||||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||||
pice = (priceList[info.Name] - (durationList[info.Name] - durable) - maintenance*2 + induceLevel*600 + favorLevel*1800) * discountList[info.Name] / 100
|
||||
} else {
|
||||
pice = priceList[info.Name] * discountList[info.Name] / 100
|
||||
}
|
||||
|
||||
canvas.DrawStringAnchored(name, 10+nameW/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored(numberStr, 10+nameW+10+numberW/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored(strconv.Itoa(pice), 10+nameW+10+numberW+50+priceW/2, textDy+textH/2, 0.5, 0.5)
|
||||
}
|
||||
return canvas.Image(), nil
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user