fix&feat(niuniu): 修复已知问题,添加新玩法牛牛商店 (#974)

This commit is contained in:
宇~ 2024-09-26 15:30:16 +08:00 committed by GitHub
parent 7d5c770398
commit 3cffc36dec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 475 additions and 63 deletions

View File

@ -1035,10 +1035,18 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 打胶 - [x] 打胶
- [x] 使用[道具名称]打胶
- [x] jj[@xxx] - [x] jj[@xxx]
- [x] 使用[道具名称]jj[@xxx]
- [x] 赎牛牛 - [x] 赎牛牛
- [x] 牛牛商店
- [x] 牛牛背包
- [x] 注册牛牛 - [x] 注册牛牛
- [x] 注销牛牛 - [x] 注销牛牛

View File

@ -24,16 +24,25 @@ type lastLength struct {
Length float64 Length float64
} }
type propsCount struct {
Count int
TimeLimit time.Time
}
var ( var (
en = control.AutoRegister(&ctrl.Options[*zero.Ctx]{ en = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false, DisableOnDefault: false,
Brief: "牛牛大作战", Brief: "牛牛大作战",
Help: "- 打胶\n" + Help: "- 打胶\n" +
"- 赎牛牛 cd30分钟\n" + "- 使用[道具名称]打胶\n" +
"- jj@xxx\n" +
"- 使用[道具名称]jj@xxx\n" +
"- 注册牛牛\n" + "- 注册牛牛\n" +
"- 赎牛牛(cd:45分钟)\n" +
"- 牛牛商店\n" +
"- 牛牛背包\n" +
"- 注销牛牛\n" + "- 注销牛牛\n" +
"- 查看我的牛牛\n" + "- 查看我的牛牛\n" +
"- jj@xxx\n" +
"- 牛子长度排行\n" + "- 牛子长度排行\n" +
"- 牛子深度排行\n", "- 牛子深度排行\n",
PrivateDataFolder: "niuniu", PrivateDataFolder: "niuniu",
@ -41,46 +50,149 @@ var (
dajiaoLimiter = rate.NewManager[string](time.Second*90, 1) dajiaoLimiter = rate.NewManager[string](time.Second*90, 1)
jjLimiter = rate.NewManager[string](time.Second*150, 1) jjLimiter = rate.NewManager[string](time.Second*150, 1)
jjCount = syncx.Map[string, *lastLength]{} jjCount = syncx.Map[string, *lastLength]{}
prop = syncx.Map[string, *propsCount]{}
) )
func init() { func init() {
en.OnFullMatch("牛牛背包", zero.OnlyGroup, getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
niu, err := db.findNiuNiu(gid, uid)
if err != nil {
ctx.SendChain(message.Text("你还没有牛牛呢快去注册一个吧!"))
return
}
ctx.SendChain(message.Text("当前牛牛背包如下",
"\n伟哥:", niu.WeiGe,
"\n媚药:", niu.Philter,
"\n击剑神器:", niu.Artifact,
"\n击剑神稽:", niu.ShenJi))
})
en.OnFullMatch("牛牛商店", zero.OnlyGroup, getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
if _, err := db.findNiuNiu(gid, uid); err != nil {
ctx.SendChain(message.Text("你还没有牛牛呢快去注册一个吧!"))
return
}
var messages message.Message
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text("牛牛商店当前售卖的物品如下")))
messages = append(messages,
ctxext.FakeSenderForwardNode(ctx,
message.Text("商品1\n商品名:伟哥\n商品价格:300ATRI币\n商品描述:可以让你打胶每次都增长有效5次")))
messages = append(messages,
ctxext.FakeSenderForwardNode(ctx,
message.Text("商品2\n商品名:媚药\n商品价格:300ATRI币\n商品描述:可以让你打胶每次都减少有效5次")))
messages = append(messages,
ctxext.FakeSenderForwardNode(ctx,
message.Text("商品3\n商品名:击剑神器\n商品价格:500ATRI币\n商品描述:可以让你每次击剑都立于不败之地有效2次")))
messages = append(messages,
ctxext.FakeSenderForwardNode(ctx,
message.Text("商品4\n商品名:击剑神稽\n商品价格:500ATRI币\n商品描述:可以让你每次击剑都失败有效2次")))
if id := ctx.Send(messages).ID(); id == 0 {
ctx.Send(message.Text("发送商店失败"))
return
}
ctx.SendChain(message.Text("输入对应序号进行购买商品"))
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.CheckUser(uid), zero.CheckGroup(gid), zero.RegexRule(`^(\d+)$`)).Repeat()
defer cancel()
timer := time.NewTimer(120 * time.Second)
answer := ""
defer timer.Stop()
for {
select {
case <-timer.C:
ctx.SendChain(message.At(uid), message.Text("超时,已自动取消"))
return
case r := <-recv:
answer = r.Event.Message.String()
n, err := strconv.Atoi(answer)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
info, err := db.findNiuNiu(gid, uid)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
u, money, err := purchaseItem(n, info)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if wallet.GetWalletOf(uid) < money {
ctx.SendChain(message.Text("你还没有足够的ATRI币呢,不能购买"))
return
}
if err = wallet.InsertWalletOf(uid, -money); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if err = db.insertNiuNiu(u, gid); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("购买成功!"))
return
}
}
})
en.OnFullMatch("赎牛牛", zero.OnlyGroup, getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) { en.OnFullMatch("赎牛牛", zero.OnlyGroup, getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
uid := ctx.Event.UserID uid := ctx.Event.UserID
last, ok := jjCount.Load(fmt.Sprintf("%d_%d", gid, uid)) last, ok := jjCount.Load(fmt.Sprintf("%d_%d", gid, uid))
if !ok { if !ok {
ctx.SendChain(message.Text("你还没有被厥呢")) ctx.SendChain(message.Text("你还没有被厥呢"))
return return
} }
if time.Since(last.TimeLimit) > time.Minute*30 {
if time.Since(last.TimeLimit) > time.Minute*45 {
ctx.SendChain(message.Text("时间已经过期了,牛牛已被收回!")) ctx.SendChain(message.Text("时间已经过期了,牛牛已被收回!"))
jjCount.Delete(fmt.Sprintf("%d_%d", gid, uid)) jjCount.Delete(fmt.Sprintf("%d_%d", gid, uid))
return return
} }
if last.Count < 6 { if last.Count < 6 {
ctx.SendChain(message.Text("你还没有被厥够6次呢,不能赎牛牛")) ctx.SendChain(message.Text("你还没有被厥够6次呢,不能赎牛牛"))
return return
} }
money := wallet.GetWalletOf(uid) money := wallet.GetWalletOf(uid)
if money < 100 { if money < 150 {
ctx.SendChain(message.Text("赎牛牛需要100ATRI币快去赚钱吧")) ctx.SendChain(message.Text("赎牛牛需要150ATRI币快去赚钱吧"))
return return
} }
err := wallet.InsertWalletOf(uid, -100)
if err := wallet.InsertWalletOf(uid, -150); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
niuniu, err := db.findNiuNiu(gid, uid)
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR:", err)) ctx.SendChain(message.Text("ERROR:", err))
return return
} }
u := &userInfo{
UID: uid, niuniu.Length = last.Length
Length: last.Length,
UserCount: 0, if err = db.insertNiuNiu(&niuniu, gid); err != nil {
}
err = db.insertniuniu(u, gid)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err)) ctx.SendChain(message.Text("ERROR:", err))
return return
} }
jjCount.Delete(fmt.Sprintf("%d_%d", gid, uid)) jjCount.Delete(fmt.Sprintf("%d_%d", gid, uid))
ctx.SendChain(message.At(uid), message.Text(fmt.Sprintf("恭喜你!成功赎回牛牛,当前长度为:%.2fcm", last.Length))) ctx.SendChain(message.At(uid), message.Text(fmt.Sprintf("恭喜你!成功赎回牛牛,当前长度为:%.2fcm", last.Length)))
}) })
@ -133,11 +245,12 @@ func init() {
en.OnFullMatch("查看我的牛牛", getdb, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) { en.OnFullMatch("查看我的牛牛", getdb, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
uid := ctx.Event.UserID uid := ctx.Event.UserID
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
niuniu, err := db.findniuniu(gid, uid) i, err := db.findNiuNiu(gid, uid)
if err != nil { if err != nil {
ctx.SendChain(message.Text("你还没有牛牛呢不能查看!")) ctx.SendChain(message.Text("你还没有牛牛呢不能查看!"))
return return
} }
niuniu := i.Length
var result strings.Builder var result strings.Builder
sexLong := "长" sexLong := "长"
sex := "♂️" sex := "♂️"
@ -155,7 +268,7 @@ func init() {
sex, sexLong, niuniu, niuniuList.ranking(niuniu, uid), generateRandomString(niuniu))) sex, sexLong, niuniu, niuniuList.ranking(niuniu, uid), generateRandomString(niuniu)))
ctx.SendChain(message.At(uid), message.Text(&result)) ctx.SendChain(message.At(uid), message.Text(&result))
}) })
en.OnFullMatchGroup([]string{"dj", "打胶"}, zero.OnlyGroup, en.OnRegex(`^(?:.*使用(.*))??打胶$`, zero.OnlyGroup,
getdb).SetBlock(true).Limit(func(ctx *zero.Ctx) *rate.Limiter { getdb).SetBlock(true).Limit(func(ctx *zero.Ctx) *rate.Limiter {
lt := dajiaoLimiter.Load(fmt.Sprintf("%d_%d", ctx.Event.GroupID, ctx.Event.UserID)) lt := dajiaoLimiter.Load(fmt.Sprintf("%d_%d", ctx.Event.GroupID, ctx.Event.UserID))
ctx.State["dajiao_last_touch"] = lt.LastTouch() ctx.State["dajiao_last_touch"] = lt.LastTouch()
@ -172,19 +285,22 @@ func init() {
// 获取群号和用户ID // 获取群号和用户ID
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
uid := ctx.Event.UserID uid := ctx.Event.UserID
niuniu, err := db.findniuniu(gid, uid) t := fmt.Sprintf("%d_%d", gid, uid)
fiancee := ctx.State["regex_matched"].([]string)
updateMap(t, false)
niuniu, err := db.findNiuNiu(gid, uid)
if err != nil { if err != nil {
ctx.SendChain(message.Text("请先注册牛牛!")) ctx.SendChain(message.Text("请先注册牛牛!"))
dajiaoLimiter.Delete(fmt.Sprintf("%d_%d", gid, uid)) dajiaoLimiter.Delete(fmt.Sprintf("%d_%d", gid, uid))
return return
} }
messages, f := generateRandomStingTwo(niuniu) messages, u, err := processNiuniuAction(t, &niuniu, fiancee[1])
u := userInfo{ if err != nil {
UID: uid, ctx.SendChain(message.Text(err))
Length: f, return
} }
ctx.SendChain(message.Text(messages)) ctx.SendChain(message.Text(messages))
if err = db.insertniuniu(&u, gid); err != nil { if err = db.insertNiuNiu(&u, gid); err != nil {
ctx.SendChain(message.Text("ERROR:", err)) ctx.SendChain(message.Text("ERROR:", err))
return return
} }
@ -192,7 +308,7 @@ func init() {
en.OnFullMatch("注册牛牛", zero.OnlyGroup, getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) { en.OnFullMatch("注册牛牛", zero.OnlyGroup, getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
uid := ctx.Event.UserID uid := ctx.Event.UserID
if _, err := db.findniuniu(gid, uid); err == nil { if _, err := db.findNiuNiu(gid, uid); err == nil {
ctx.SendChain(message.Text("你已经注册过了")) ctx.SendChain(message.Text("你已经注册过了"))
return return
} }
@ -204,23 +320,23 @@ func init() {
UserCount: 0, UserCount: 0,
} }
// 添加数据进入表 // 添加数据进入表
err := db.insertniuniu(&u, gid) if err := db.insertNiuNiu(&u, gid); err != nil {
if err != nil {
err = db.createGIDTable(gid) if err = db.createGIDTable(gid); err != nil {
if err != nil {
ctx.SendChain(message.Text("ERROR:", err)) ctx.SendChain(message.Text("ERROR:", err))
return return
} }
err = db.insertniuniu(&u, gid)
if err != nil { if err = db.insertNiuNiu(&u, gid); err != nil {
ctx.SendChain(message.Text("ERROR:", err)) ctx.SendChain(message.Text("ERROR:", err))
return return
} }
} }
ctx.SendChain(message.Reply(ctx.Event.GroupID), ctx.SendChain(message.Reply(ctx.Event.GroupID),
message.Text("注册成功,你的牛牛现在有", u.Length, "cm")) message.Text("注册成功,你的牛牛现在有", u.Length, "cm"))
}) })
en.OnRegex(`^jj\s?(\[CQ:at,(?:\S*,)?qq=(\d+)(?:,\S*)?\]|(\d+))$`, getdb, en.OnRegex(`^(?:.*使用(.*))??jj\s?(\[CQ:at,(?:\S*,)?qq=(\d+)(?:,\S*)?\]|(\d+))$`, getdb,
zero.OnlyGroup).SetBlock(true).Limit(func(ctx *zero.Ctx) *rate.Limiter { zero.OnlyGroup).SetBlock(true).Limit(func(ctx *zero.Ctx) *rate.Limiter {
lt := jjLimiter.Load(fmt.Sprintf("%d_%d", ctx.Event.GroupID, ctx.Event.UserID)) lt := jjLimiter.Load(fmt.Sprintf("%d_%d", ctx.Event.GroupID, ctx.Event.UserID))
ctx.State["jj_last_touch"] = lt.LastTouch() ctx.State["jj_last_touch"] = lt.LastTouch()
@ -236,50 +352,58 @@ func init() {
}, },
).Handle(func(ctx *zero.Ctx) { ).Handle(func(ctx *zero.Ctx) {
fiancee := ctx.State["regex_matched"].([]string) fiancee := ctx.State["regex_matched"].([]string)
adduser, err := strconv.ParseInt(fiancee[2]+fiancee[3], 10, 64) adduser, err := strconv.ParseInt(fiancee[3]+fiancee[4], 10, 64)
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR:", err)) ctx.SendChain(message.Text("ERROR:", err))
return return
} }
uid := ctx.Event.UserID uid := ctx.Event.UserID
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
myniuniu, err := db.findniuniu(gid, uid) t := fmt.Sprintf("%d_%d", gid, uid)
updateMap(t, false)
myniuniu, err := db.findNiuNiu(gid, uid)
if err != nil { if err != nil {
ctx.SendChain(message.Text("你还没有牛牛快去注册一个吧!")) ctx.SendChain(message.Text("你还没有牛牛快去注册一个吧!"))
jjLimiter.Delete(fmt.Sprintf("%d_%d", gid, uid)) jjLimiter.Delete(t)
return return
} }
adduserniuniu, err := db.findniuniu(gid, adduser) adduserniuniu, err := db.findNiuNiu(gid, adduser)
if err != nil { if err != nil {
ctx.SendChain(message.At(uid), message.Text("对方还没有牛牛呢,不能🤺")) ctx.SendChain(message.At(uid), message.Text("对方还没有牛牛呢,不能🤺"))
jjLimiter.Delete(fmt.Sprintf("%d_%d", gid, uid)) jjLimiter.Delete(t)
return return
} }
if uid == adduser { if uid == adduser {
ctx.SendChain(message.Text("你要和谁🤺?你自己吗?")) ctx.SendChain(message.Text("你要和谁🤺?你自己吗?"))
jjLimiter.Delete(fmt.Sprintf("%d_%d", gid, uid)) jjLimiter.Delete(t)
return return
} }
fencingResult, f, f1 := fencing(myniuniu, adduserniuniu) fencingResult, f1, u, err := processJJuAction(&myniuniu, &adduserniuniu, t, fiancee[1])
err = db.insertniuniu(&userInfo{UID: uid, Length: f, UserCount: 0}, gid)
if err != nil { if err != nil {
ctx.SendChain(message.Text(err))
return
}
if err = db.insertNiuNiu(&u, gid); err != nil {
ctx.SendChain(message.Text("ERROR:", err)) ctx.SendChain(message.Text("ERROR:", err))
return return
} }
err = db.insertniuniu(&userInfo{UID: adduser, Length: f1, UserCount: 0}, gid)
if err != nil { if err = db.insertNiuNiu(&userInfo{UID: adduser, Length: f1}, gid); err != nil {
ctx.SendChain(message.Text("ERROR:", err)) ctx.SendChain(message.Text("ERROR:", err))
return return
} }
ctx.SendChain(message.At(uid), message.Text(" ", fencingResult)) ctx.SendChain(message.At(uid), message.Text(" ", fencingResult))
j := fmt.Sprintf("%d_%d", gid, adduser) j := fmt.Sprintf("%d_%d", gid, adduser)
count, ok := jjCount.Load(j) count, ok := jjCount.Load(j)
var c lastLength var c lastLength
// 按照第一次jj时的时间计算超过45分钟则重置
if !ok { if !ok {
c = lastLength{ c = lastLength{
TimeLimit: time.Now(), TimeLimit: time.Now(),
Count: 1, Count: 1,
Length: adduserniuniu, Length: adduserniuniu.Length,
} }
} else { } else {
c = lastLength{ c = lastLength{
@ -287,11 +411,20 @@ func init() {
Count: count.Count + 1, Count: count.Count + 1,
Length: count.Length, Length: count.Length,
} }
if time.Since(c.TimeLimit) > time.Minute*45 {
c = lastLength{
TimeLimit: time.Now(),
Count: 1,
Length: adduserniuniu.Length,
} }
}
}
jjCount.Store(j, &c) jjCount.Store(j, &c)
if c.Count > 5 { if c.Count > 5 {
ctx.SendChain(message.Text(randomChoice([]string{fmt.Sprintf("你们太厉害了,对方已经被你们打了%d次了你们可以继续找他🤺", c.Count), ctx.SendChain(message.Text(randomChoice([]string{fmt.Sprintf("你们太厉害了,对方已经被你们打了%d次了你们可以继续找他🤺", c.Count),
"你们不要再找ta🤺啦"}))) "你们不要再找ta🤺啦"})))
// 保证只发生一次
if c.Count < 7 { if c.Count < 7 {
id := ctx.SendPrivateMessage(adduser, id := ctx.SendPrivateMessage(adduser,
message.Text(fmt.Sprintf("你在%d群里已经被厥冒烟了快去群里赎回你原本的牛牛!\n发送:`赎牛牛`即可!", gid))) message.Text(fmt.Sprintf("你在%d群里已经被厥冒烟了快去群里赎回你原本的牛牛!\n发送:`赎牛牛`即可!", gid)))
@ -300,11 +433,12 @@ func init() {
} }
} }
} }
}) })
en.OnFullMatch("注销牛牛", getdb, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) { en.OnFullMatch("注销牛牛", getdb, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
uid := ctx.Event.UserID uid := ctx.Event.UserID
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
_, err := db.findniuniu(gid, uid) _, err := db.findNiuNiu(gid, uid)
if err != nil { if err != nil {
ctx.SendChain(message.Text("你还没有牛牛呢,咋的你想凭空造一个啊")) ctx.SendChain(message.Text("你还没有牛牛呢,咋的你想凭空造一个啊"))
return return
@ -321,3 +455,30 @@ func init() {
func randomChoice(options []string) string { func randomChoice(options []string) string {
return options[rand.Intn(len(options))] return options[rand.Intn(len(options))]
} }
func updateMap(t string, d bool) {
value, ok := prop.Load(t)
if value == nil {
return
}
if !d {
if time.Since(value.TimeLimit) > time.Minute*8 {
prop.Delete(t)
}
return
}
if ok {
prop.Store(t, &propsCount{
Count: value.Count + 1,
TimeLimit: value.TimeLimit,
})
} else {
prop.Store(t, &propsCount{
Count: 1,
TimeLimit: time.Now(),
})
}
if time.Since(value.TimeLimit) > time.Minute*8 {
prop.Delete(t)
}
}

View File

@ -2,6 +2,8 @@
package niuniu package niuniu
import ( import (
"fmt"
"math"
"math/rand" "math/rand"
"sort" "sort"
"strconv" "strconv"
@ -23,6 +25,10 @@ type userInfo struct {
UID int64 UID int64
Length float64 Length float64
UserCount int UserCount int
WeiGe int // 伟哥
Philter int // 媚药
Artifact int // 击剑神器
ShenJi int // 击剑神稽
} }
type users []*userInfo type users []*userInfo
@ -40,6 +46,84 @@ var (
}) })
) )
// useWeiGe 使用道具伟哥
func (u *userInfo) useWeiGe() (string, float64) {
niuniu := u.Length
reduce := math.Abs(hitGlue(niuniu))
niuniu += reduce
return randomChoice([]string{
fmt.Sprintf("哈哈,你这一用道具,牛牛就像是被激发了潜能,增加了%.2fcm!看来今天是个大日子呢!", reduce),
fmt.Sprintf("你这是用了什么神奇的道具?牛牛竟然增加了%.2fcm,简直是牛气冲天!", reduce),
fmt.Sprintf("使用道具后,你的牛牛就像是开启了加速模式,一下增加了%.2fcm,这成长速度让人惊叹!", reduce),
}), niuniu
}
// usePhilter 使用道具媚药
func (u *userInfo) usePhilter() (string, float64) {
niuniu := u.Length
reduce := math.Abs(hitGlue(niuniu))
niuniu -= reduce
return randomChoice([]string{
fmt.Sprintf("你使用媚药,咿呀咿呀一下使当前长度发生了一些变化,当前长度%.2f", niuniu),
fmt.Sprintf("看来你追求的是‘微观之美’,故意使用道具让牛牛凹进去了%.2fcm", reduce),
fmt.Sprintf("缩小奇迹’在你身上发生了,牛牛凹进去了%.2fcm,你的选择真是独特!", reduce),
}), niuniu
}
// useArtifact 使用道具击剑神器
func (u *userInfo) useArtifact(adduserniuniu float64) (string, float64, float64) {
myLength := u.Length
difference := myLength - adduserniuniu
var (
change float64
)
if difference > 0 {
change = hitGlue(myLength + adduserniuniu)
} else {
change = hitGlue((myLength + adduserniuniu) / 2)
}
myLength += change
return randomChoice([]string{
fmt.Sprintf("凭借神秘道具的力量,你让对方在你的长度面前俯首称臣!你的长度增加了%.2fcm,当前长度达到了%.2fcm", change, myLength),
fmt.Sprintf("神器在手,天下我有!你使用道具后,长度猛增%.2fcm,现在的总长度是%.2fcm,无人能敌!", change, myLength),
fmt.Sprintf("这就是道具的魔力!你轻松增加了%.2fcm,让对手望尘莫及,当前长度为%.2fcm", change, myLength),
fmt.Sprintf("道具一出,谁与争锋!你的长度因道具而增长%.2fcm,现在的长度是%.2fcm,霸气尽显!", change, myLength),
fmt.Sprintf("使用道具的你,如同获得神助!你的长度增长了%.2fcm,达到%.2fcm的惊人长度,胜利自然到手!", change, myLength),
}), myLength, adduserniuniu - change/1.3
}
// useShenJi 使用道具击剑神稽
func (u *userInfo) useShenJi(adduserniuniu float64) (string, float64, float64) {
myLength := u.Length
difference := myLength - adduserniuniu
var (
change float64
)
if difference > 0 {
change = hitGlue(myLength + adduserniuniu)
} else {
change = hitGlue((myLength + adduserniuniu) / 2)
}
myLength -= change
var r string
if myLength > 0 {
r = randomChoice([]string{
fmt.Sprintf("哦吼!?看来你的牛牛因为使用了神秘道具而缩水了呢🤣🤣🤣!缩小了%.2fcm", change),
fmt.Sprintf("哈哈,看来这个道具有点儿调皮,让你的长度缩水了%.2fcm!现在你的长度是%.2fcm,下次可得小心使用哦!", change, myLength),
fmt.Sprintf("使用道具后,你的牛牛似乎有点儿害羞,缩水了%.2fcm!现在的长度是%.2fcm,希望下次它能挺直腰板!", change, myLength),
fmt.Sprintf("哎呀,这个道具的效果有点儿意外,你的长度减少了%.2fcm,现在只有%.2fcm了!下次选道具可得睁大眼睛!", change, myLength),
})
} else {
r = randomChoice([]string{
fmt.Sprintf("哦哟,小姐姐真是玩得一手好游戏,使用道具后数值又降低了%.2fcm,小巧得更显魅力!", change),
fmt.Sprintf("看来小姐姐喜欢更加精致的风格,使用道具后,数值减少了%.2fcm,更加迷人了!", change),
fmt.Sprintf("小姐姐的每一次变化都让人惊喜,使用道具后,数值减少了%.2fcm,更加优雅动人!", change),
fmt.Sprintf("小姐姐这是在展示什么是真正的精致小巧,使用道具后,数值减少了%.2fcm,美得不可方物!", change),
})
}
return r, myLength, adduserniuniu + 0.7*change
}
func (m users) positive() users { func (m users) positive() users {
var m1 []*userInfo var m1 []*userInfo
for _, i2 := range m { for _, i2 := range m {
@ -93,15 +177,17 @@ func (db *model) createGIDTable(gid int64) error {
return db.sql.Create(strconv.FormatInt(gid, 10), &userInfo{}) return db.sql.Create(strconv.FormatInt(gid, 10), &userInfo{})
} }
func (db *model) findniuniu(gid, uid int64) (float64, error) { // findNiuNiu 返回一个用户的牛牛信息
func (db *model) findNiuNiu(gid, uid int64) (userInfo, error) {
db.RLock() db.RLock()
defer db.RUnlock() defer db.RUnlock()
u := userInfo{} u := userInfo{}
err := db.sql.Find(strconv.FormatInt(gid, 10), &u, "where UID = "+strconv.FormatInt(uid, 10)) err := db.sql.Find(strconv.FormatInt(gid, 10), &u, "where UID = "+strconv.FormatInt(uid, 10))
return u.Length, err return u, err
} }
func (db *model) insertniuniu(u *userInfo, gid int64) error { // insertNiuNiu 更新一个用户的牛牛信息
func (db *model) insertNiuNiu(u *userInfo, gid int64) error {
db.Lock() db.Lock()
defer db.Unlock() defer db.Unlock()
return db.sql.Insert(strconv.FormatInt(gid, 10), u) return db.sql.Insert(strconv.FormatInt(gid, 10), u)

View File

@ -2,12 +2,152 @@
package niuniu package niuniu
import ( import (
"errors"
"fmt" "fmt"
"math" "math"
"math/rand" "math/rand"
"time" "time"
) )
func createUserInfoByProps(props string, niuniu *userInfo) (userInfo, error) {
var (
err error
)
switch props {
case "伟哥":
if niuniu.WeiGe > 0 {
niuniu.WeiGe--
} else {
err = errors.New("你还没有伟哥呢,不能使用")
}
case "媚药":
if niuniu.Philter > 0 {
niuniu.Philter--
} else {
err = errors.New("你还没有媚药呢,不能使用")
}
case "击剑神器":
if niuniu.Artifact > 0 {
niuniu.Artifact--
} else {
err = errors.New("你还没有击剑神器呢,不能使用")
}
case "击剑神稽":
if niuniu.ShenJi > 0 {
niuniu.ShenJi--
} else {
err = errors.New("你还没有击剑神稽呢,不能使用")
}
default:
err = errors.New("道具不存在")
}
return *niuniu, err
}
// 接收值依次是 自己和被jj用户的信息 一个包含gid和uid的字符串 道具名称
// 返回值依次是 要发生的消息 被jj用户的niuniu 用户的信息 错误信息
func processJJuAction(myniuniu, adduserniuniu *userInfo, t string, props string) (string, float64, userInfo, error) {
var (
fencingResult string
f float64
f1 float64
u userInfo
err error
)
v, ok := prop.Load(t)
if props != "" {
if props != "击剑神器" && props != "击剑神稽" {
return "", 0, userInfo{}, errors.New("道具不存在")
}
u, err = createUserInfoByProps(props, myniuniu)
if err != nil {
return "", 0, userInfo{}, err
}
}
switch {
case ok && v.Count > 1 && time.Since(v.TimeLimit) < time.Minute*8:
fencingResult, f, f1 = fencing(myniuniu.Length, adduserniuniu.Length)
u.Length = f
errMessage := fmt.Sprintf("你使用道具次数太快了,此次道具不会生效,等待%d再来吧", time.Minute*8-time.Since(v.TimeLimit))
err = errors.New(errMessage)
case myniuniu.ShenJi-u.ShenJi != 0:
fencingResult, f, f1 = myniuniu.useShenJi(adduserniuniu.Length)
u.Length = f
updateMap(t, true)
case myniuniu.Artifact-u.Artifact != 0:
fencingResult, f, f1 = myniuniu.useArtifact(adduserniuniu.Length)
u.Length = f
updateMap(t, true)
default:
fencingResult, f, f1 = fencing(myniuniu.Length, adduserniuniu.Length)
u.Length = f
}
return fencingResult, f1, u, err
}
func processNiuniuAction(t string, niuniu *userInfo, props string) (string, userInfo, error) {
var (
messages string
f float64
u userInfo
err error
)
load, ok := prop.Load(t)
if props != "" {
if props != "伟哥" && props != "媚药" {
return "", u, errors.New("道具不存在")
}
u, err = createUserInfoByProps(props, niuniu)
if err != nil {
return "", userInfo{}, err
}
}
switch {
case ok && load.Count > 1 && time.Since(load.TimeLimit) < time.Minute*8:
messages, f = generateRandomStingTwo(niuniu.Length)
u.Length = f
u.UID = niuniu.UID
errMessage := fmt.Sprintf("你使用道具次数太快了,此次道具不会生效,等待%d再来吧", time.Minute*8-time.Since(load.TimeLimit))
err = errors.New(errMessage)
case niuniu.WeiGe-u.WeiGe != 0:
messages, f = niuniu.useWeiGe()
u.Length = f
updateMap(t, true)
case niuniu.Philter-u.Philter != 0:
messages, f = niuniu.usePhilter()
u.Length = f
updateMap(t, true)
default:
messages, f = generateRandomStingTwo(niuniu.Length)
u.Length = f
u.UID = niuniu.UID
}
return messages, u, err
}
func purchaseItem(n int, info userInfo) (*userInfo, int, error) {
var (
money int
err error
)
switch n {
case 1:
money = 300
info.WeiGe += 5
case 2:
money = 300
info.Philter += 5
case 3:
money = 500
info.Artifact += 2
case 4:
money = 500
info.ShenJi += 2
default:
err = errors.New("无效的选择")
}
return &info, money, err
}
func generateRandomStingTwo(niuniu float64) (string, float64) { func generateRandomStingTwo(niuniu float64) (string, float64) {
probability := rand.Intn(100 + 1) probability := rand.Intn(100 + 1)
reduce := math.Abs(hitGlue(niuniu)) reduce := math.Abs(hitGlue(niuniu))
@ -31,14 +171,13 @@ func generateRandomStingTwo(niuniu float64) (string, float64) {
fmt.Sprintf("你突发恶疾!你的牛牛凹进去了%.2fcm", reduce), fmt.Sprintf("你突发恶疾!你的牛牛凹进去了%.2fcm", reduce),
fmt.Sprintf("笑死,你因为打🦶过度导致牛牛凹进去了%.2fcm!🤣🤣🤣", reduce), fmt.Sprintf("笑死,你因为打🦶过度导致牛牛凹进去了%.2fcm!🤣🤣🤣", reduce),
}), niuniu }), niuniu
} else { }
return randomChoice([]string{ return randomChoice([]string{
fmt.Sprintf("阿哦,你过度打🦶,牛牛缩短%.2fcm了呢!", reduce), fmt.Sprintf("阿哦,你过度打🦶,牛牛缩短%.2fcm了呢!", reduce),
fmt.Sprintf("你的牛牛变长了很多,你很激动地继续打🦶,然后牛牛缩短了%.2fcm呢!", reduce), fmt.Sprintf("你的牛牛变长了很多,你很激动地继续打🦶,然后牛牛缩短了%.2fcm呢!", reduce),
fmt.Sprintf("小打怡情,大打伤身,强打灰飞烟灭!你过度打🦶,牛牛缩短了%.2fcm捏!", reduce), fmt.Sprintf("小打怡情,大打伤身,强打灰飞烟灭!你过度打🦶,牛牛缩短了%.2fcm捏!", reduce),
}), niuniu }), niuniu
} }
}
} }
func generateRandomString(niuniu float64) string { func generateRandomString(niuniu float64) string {
@ -99,7 +238,6 @@ func generateRandomString(niuniu float64) string {
// fencing 击剑对决逻辑返回对决结果和myLength的变化值 // fencing 击剑对决逻辑返回对决结果和myLength的变化值
func fencing(myLength, oppoLength float64) (string, float64, float64) { func fencing(myLength, oppoLength float64) (string, float64, float64) {
lossLimit := 0.25
devourLimit := 0.27 devourLimit := 0.27
probability := rand.Intn(100) + 1 probability := rand.Intn(100) + 1
@ -107,26 +245,28 @@ func fencing(myLength, oppoLength float64) (string, float64, float64) {
switch { switch {
case oppoLength <= -100 && myLength > 0 && 10 < probability && probability <= 20: case oppoLength <= -100 && myLength > 0 && 10 < probability && probability <= 20:
oppoLength *= 0.85 oppoLength *= 0.85
change := math.Min(math.Abs(lossLimit*myLength), math.Abs(1.5*myLength)) change := hitGlue(oppoLength) + rand.Float64()*math.Log2(math.Abs(0.5*(myLength+oppoLength)))
myLength += change myLength = change
return fmt.Sprintf("对方身为魅魔诱惑了你,你同化成魅魔!当前长度%.2fcm", -myLength), -myLength, oppoLength return fmt.Sprintf("对方身为魅魔诱惑了你,你同化成魅魔!当前长度%.2fcm", -myLength), -myLength, oppoLength
case oppoLength >= 100 && myLength > 0 && 10 < probability && probability <= 20: case oppoLength >= 100 && myLength > 0 && 10 < probability && probability <= 20:
oppoLength *= 0.85 oppoLength *= 0.85
change := math.Min(math.Abs(devourLimit*myLength), math.Abs(1.5*myLength)) change := math.Min(math.Abs(devourLimit*myLength), math.Abs(1.5*myLength))
myLength += change myLength += change
return fmt.Sprintf("对方以牛头人的荣誉摧毁了你的牛牛!当前长度%.2fcm", myLength-oppoLength), myLength - oppoLength, oppoLength return fmt.Sprintf("对方以牛头人的荣誉摧毁了你的牛牛!当前长度%.2fcm", myLength), myLength, oppoLength
case myLength <= -100 && oppoLength > 0 && 10 < probability && probability <= 20: case myLength <= -100 && oppoLength > 0 && 10 < probability && probability <= 20:
myLength *= 0.85 myLength *= 0.85
change := oppoLength * 0.7 change := hitGlue(myLength+oppoLength) + rand.Float64()*math.Log2(math.Abs(0.5*(myLength+oppoLength)))
oppoLength -= change oppoLength -= change
myLength -= change myLength -= change
return fmt.Sprintf("你身为魅魔诱惑了对方,吞噬了对方部分长度!当前长度%.2fcm", myLength), myLength, oppoLength return fmt.Sprintf("你身为魅魔诱惑了对方,吞噬了对方部分长度!当前长度%.2fcm", myLength), myLength, oppoLength
case myLength >= 100 && oppoLength > 0 && 10 < probability && probability <= 20: case myLength >= 100 && oppoLength > 0 && 10 < probability && probability <= 20:
myLength *= 0.85 myLength -= oppoLength
oppoLength -= 0.8 * myLength oppoLength = 0.01
return fmt.Sprintf("你以牛头人的荣誉摧毁了对方的牛牛!当前长度%.2fcm", myLength), myLength, oppoLength return fmt.Sprintf("你以牛头人的荣誉摧毁了对方的牛牛!当前长度%.2fcm", myLength), myLength, oppoLength
default: default:
return determineResultBySkill(myLength, oppoLength) return determineResultBySkill(myLength, oppoLength)
} }
@ -146,7 +286,7 @@ func calculateWinProbability(heightA, heightB float64) float64 {
if heightA > heightB { if heightA > heightB {
pA = 0.7 + 0.2*(heightA-heightB)/heightA pA = 0.7 + 0.2*(heightA-heightB)/heightA
} else { } else {
pA = 0.6 - 0.2*(heightB-heightA)/heightB pA = 0.7 - 0.2*(heightB-heightA)/heightB
} }
heightRatio := math.Max(heightA, heightB) / math.Min(heightA, heightB) heightRatio := math.Max(heightA, heightB) / math.Min(heightA, heightB)
reductionRate := 0.1 * (heightRatio - 1) reductionRate := 0.1 * (heightRatio - 1)
@ -165,6 +305,7 @@ func applySkill(myLength, oppoLength float64, increaseLength1 bool) (string, flo
return fmt.Sprintf("哦吼!?你的牛牛在长大欸!长大了%.2fcm", reduce), myLength, oppoLength return fmt.Sprintf("哦吼!?你的牛牛在长大欸!长大了%.2fcm", reduce), myLength, oppoLength
} }
return fmt.Sprintf("你以绝对的长度让对方屈服了呢!你的长度增加%.2fcm,当前长度%.2fcm", reduce, myLength), myLength, oppoLength return fmt.Sprintf("你以绝对的长度让对方屈服了呢!你的长度增加%.2fcm,当前长度%.2fcm", reduce, myLength), myLength, oppoLength
} }
myLength -= reduce myLength -= reduce
oppoLength += 0.8 * reduce oppoLength += 0.8 * reduce
@ -172,17 +313,33 @@ func applySkill(myLength, oppoLength float64, increaseLength1 bool) (string, flo
return fmt.Sprintf("哦吼!?看来你的牛牛因为击剑而凹进去了呢🤣🤣🤣!凹进去了%.2fcm", reduce), myLength, oppoLength return fmt.Sprintf("哦吼!?看来你的牛牛因为击剑而凹进去了呢🤣🤣🤣!凹进去了%.2fcm", reduce), myLength, oppoLength
} }
return fmt.Sprintf("对方以绝对的长度让你屈服了呢!你的长度减少%.2fcm,当前长度%.2fcm", reduce, myLength), myLength, oppoLength return fmt.Sprintf("对方以绝对的长度让你屈服了呢!你的长度减少%.2fcm,当前长度%.2fcm", reduce, myLength), myLength, oppoLength
} }
// fence // fence
func fence(rd float64) float64 { func fence(rd float64) float64 {
rd -= float64(time.Now().UnixNano() % 10) r := hitGlue(rd)*2 + rand.Float64()*math.Log2(rd)
if rd > 1000000 { if rand.Intn(2) == 1 {
return rd - rand.Float64()*rd return rd - rand.Float64()*r
} }
return float64(int(rd * rand.Float64())) return float64(int(r * rand.Float64()))
} }
func hitGlue(l float64) float64 { func hitGlue(l float64) float64 {
return rand.Float64() * math.Log2(l) / 2 if l == 0 {
l = 0.1
}
l = math.Abs(l)
switch {
case l > 1 && l <= 10:
return rand.Float64() * math.Log2(l*2)
case 10 < l && l <= 100:
return rand.Float64() * math.Log2(l*1.5)
case 100 < l && l <= 1000:
return rand.Float64() * (math.Log10(l*1.5) * 2)
case l > 1000:
return rand.Float64() * (math.Log10(l) * 2)
default:
return rand.Float64()
}
} }