473 lines
13 KiB
Go
473 lines
13 KiB
Go
package arena
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"go_dreamfactory/comm"
|
|
"go_dreamfactory/lego/core"
|
|
"go_dreamfactory/lego/sys/log"
|
|
"go_dreamfactory/lego/sys/mgo"
|
|
"go_dreamfactory/lego/utils/container/id"
|
|
"go_dreamfactory/modules"
|
|
"go_dreamfactory/pb"
|
|
"go_dreamfactory/sys/configure"
|
|
cfg "go_dreamfactory/sys/configure/structs"
|
|
"go_dreamfactory/sys/db"
|
|
"math"
|
|
"math/rand"
|
|
"time"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
"go.mongodb.org/mongo-driver/x/bsonx"
|
|
)
|
|
|
|
// /竞技场 数据组件
|
|
type modelArena struct {
|
|
modules.MCompModel
|
|
module *Arena
|
|
}
|
|
|
|
// 组件初始化接口
|
|
func (this *modelArena) Init(service core.IService, module core.IModule, comp core.IModuleComp, opt core.IModuleOptions) (err error) {
|
|
this.TableName = comm.TableArena
|
|
this.MCompModel.Init(service, module, comp, opt)
|
|
this.module = module.(*Arena)
|
|
//创建uid索引
|
|
if _, err = this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{
|
|
Keys: bsonx.Doc{
|
|
{Key: "uid", Value: bsonx.Int32(1)},
|
|
},
|
|
}); err != nil {
|
|
return
|
|
}
|
|
_, err = this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{
|
|
Keys: bson.M{"loc": "2dsphere"},
|
|
})
|
|
return
|
|
}
|
|
|
|
// 查询用户装备数据
|
|
func (this *modelArena) queryPlayerInfo(uId string) (result *pb.DBArenaUser, err error) {
|
|
result = &pb.DBArenaUser{}
|
|
if err = this.Get(uId, result); err != nil && err != mgo.MongodbNil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// 查询用户装备数据
|
|
func (this *modelArena) queryPlayers(uIds []string) (result []*pb.DBArenaUser, err error) {
|
|
result = make([]*pb.DBArenaUser, 0)
|
|
if _, err = this.Gets(uIds, &result); err != nil && err != mgo.MongodbNil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// 查询用户装备数据
|
|
func (this *modelArena) queryArenaPlayer(uId string) (result *pb.ArenaPlayer, err error) {
|
|
temp := &pb.DBArenaUser{}
|
|
if err = this.Get(uId, temp); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
result = &pb.ArenaPlayer{
|
|
Uid: temp.Uid,
|
|
Name: temp.Name,
|
|
Avatar: temp.Avatar,
|
|
Lv: temp.Lv,
|
|
Dan: temp.Dan,
|
|
Integral: temp.Integral,
|
|
Defend: temp.Defend,
|
|
Isai: false,
|
|
}
|
|
return
|
|
}
|
|
|
|
// 查询用户英雄数据
|
|
func (this *modelArena) queryUserHeros(uid string, heroids []string) (results []*pb.DBHero, err error) {
|
|
var (
|
|
model *db.DBModel
|
|
)
|
|
if model, err = this.module.GetDBModelByUid(uid, comm.TableHero); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
results = make([]*pb.DBHero, 0)
|
|
if err = model.GetListObjs(uid, heroids, &results); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// /保存用户竞技场信息
|
|
func (this *modelArena) updateArenaUserInfo(info *pb.DBArenaUser) (err error) {
|
|
var (
|
|
dan int32
|
|
)
|
|
if dan, err = this.computedan(info.Integral); err != nil {
|
|
return
|
|
}
|
|
info.Dan = dan
|
|
this.Change(info.Uid, map[string]interface{}{
|
|
"integral": info.Integral,
|
|
"dan": dan,
|
|
"rank": info.Rank,
|
|
// "ticket": info.Ticket,
|
|
"buynum": info.Buynum,
|
|
"lastrtickettime": info.Lastrtickettime,
|
|
"attack": info.Attack,
|
|
"defend": info.Defend,
|
|
"streak": info.Streak,
|
|
"record": info.Record,
|
|
"attackwinuum": info.Attackwinuum,
|
|
"attacktotaluum": info.Attacktotaluum,
|
|
"defendwinuum": info.Defendwinuum,
|
|
"defendtotaluum": info.Defendtotaluum,
|
|
"loc": []float64{float64(dan), float64(rand.Int31n(100)) / 1000.0},
|
|
"isdef": info.Isdef,
|
|
"name": info.Name,
|
|
"avatar": info.Avatar,
|
|
"lv": info.Lv,
|
|
})
|
|
return
|
|
}
|
|
|
|
func (this *modelArena) modifyIntegral(uid string, integral int32) (err error) {
|
|
var (
|
|
dan int32
|
|
player *pb.ArenaPlayer
|
|
)
|
|
if dan, err = this.computedan(integral); err != nil {
|
|
return
|
|
}
|
|
player = &pb.ArenaPlayer{Uid: uid, Integral: integral}
|
|
if err = this.module.modelRank.updateArenaRank(player); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
this.Change(uid, map[string]interface{}{
|
|
"integral": integral,
|
|
"dan": dan,
|
|
"rank": player.Rank,
|
|
})
|
|
return
|
|
}
|
|
|
|
func (this *modelArena) computedan(integral int32) (dan int32, err error) {
|
|
var (
|
|
active *cfg.GameArenaActiveRewardData
|
|
)
|
|
|
|
if active, err = this.module.configure.getActiveReward(integral); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
dan = active.LvId
|
|
return
|
|
}
|
|
|
|
//获取目标去陪数据
|
|
// func (this *modelArena) matchePlayer(integral int32) (results []*pb.DBArenaUser, err error) {
|
|
// var (
|
|
// cursor *mongo.Cursor
|
|
// )
|
|
// project := bson.M{"$project": bson.M{
|
|
// "diff": bson.M{
|
|
// "$abs": bson.M{"$subtract": bson.A{integral, "$start"}},
|
|
// },
|
|
// }}
|
|
// if cursor, err = this.DBModel.DB.Aggregate(comm.TableArena, bson.A{project}); err != nil {
|
|
// this.module.Errorln(err)
|
|
// return
|
|
// } else {
|
|
// for cursor.Next(context.Background()) {
|
|
// temp := &pb.DBArenaUser{}
|
|
// if err = cursor.Decode(temp); err != nil {
|
|
// this.module.Errorln(err)
|
|
// return
|
|
// }
|
|
// }
|
|
// }
|
|
// return
|
|
// }
|
|
|
|
// 匹配机器人
|
|
func (this *modelArena) matcheAI(dan, num int32) (results []*pb.ArenaPlayer, err error) {
|
|
var (
|
|
active *cfg.GameArenaActiveRewardData
|
|
ais []*cfg.GameArenaRobotData
|
|
formats []*cfg.GameMonsterFormatData
|
|
// monst *cfg.GameMonsterData
|
|
rank []int32
|
|
targets []int32
|
|
)
|
|
if active, err = this.module.configure.getActiveRewardById(dan); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
if ais, err = this.module.configure.getArenaRobot(dan); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
rank = make([]int32, len(ais))
|
|
for i, v := range ais {
|
|
rank[i] = v.Weight
|
|
}
|
|
targets = make([]int32, num)
|
|
for i := 0; i < int(num); i++ {
|
|
index := comm.GetRandW(rank)
|
|
targets[i] = index
|
|
}
|
|
results = make([]*pb.ArenaPlayer, num)
|
|
for i, v := range targets {
|
|
aiconf := ais[v]
|
|
if formats, err = this.module.configure.getMonsterFormat(aiconf.MonsterformatId); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
results[i] = &pb.ArenaPlayer{
|
|
Uid: fmt.Sprintf("ai_%s", id.NewXId()),
|
|
Name: this.randUserName(),
|
|
Avatar: fmt.Sprintf("tx_js_3300%d", rand.Int31n(3)+3),
|
|
Lv: rand.Int31n(10) + 10,
|
|
Dan: dan,
|
|
Integral: int32(rand.Intn(int(active.ScoreUp)-int(active.ScoreLow))) + active.ScoreLow,
|
|
Isai: true,
|
|
Mformatid: aiconf.MonsterformatId,
|
|
Defend: &pb.DBPlayerBattleFormt{
|
|
Leadpos: 0,
|
|
Formt: make([]*pb.DBHero, len(formats)),
|
|
},
|
|
}
|
|
|
|
for i1, v1 := range formats {
|
|
if v1 == nil {
|
|
results[i].Defend.Formt[i1] = nil
|
|
} else {
|
|
if v1.CaptainId == 1 {
|
|
results[i].Defend.Leadpos = int32(i1)
|
|
}
|
|
// if monst, err = this.module.configure.getMonster(v1.Monster); err != nil {
|
|
// this.module.Errorln(err)
|
|
// }
|
|
hero := &pb.DBHero{}
|
|
if hero = this.module.ModuleHero.CreateMonster(fmt.Sprintf("%d", v1.Heroid), v1.Star, v1.Lv); hero == nil {
|
|
err = fmt.Errorf("CreateMonster 失败")
|
|
return
|
|
}
|
|
hero.Property[comm.Hp] = int32(float32(hero.Property[comm.Hp]) * v1.Hppro)
|
|
hero.Property[comm.Atk] = int32(float32(hero.Property[comm.Atk]) * v1.Atkpro)
|
|
hero.Property[comm.Def] = int32(float32(hero.Property[comm.Def]) * v1.Defpro)
|
|
hero.Suits = make([]*pb.DB_EquipmentSuit, 0)
|
|
for _, v := range v1.Equip {
|
|
hero.Suits = append(hero.Suits, &pb.DB_EquipmentSuit{
|
|
Suitid: v,
|
|
Effect: true,
|
|
})
|
|
}
|
|
results[i].Defend.Formt[i1] = hero
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 获取目标去陪数据
|
|
func (this *modelArena) matchePlayer(uid string, dan, num int32) (results []*pb.ArenaPlayer, err error) {
|
|
var (
|
|
cursor *mongo.Cursor
|
|
)
|
|
results = make([]*pb.ArenaPlayer, 0)
|
|
port := []float64{float64(dan), float64(rand.Int31n(100)) / 1000.0}
|
|
if cursor, err = this.DBModel.DB.Find(comm.TableArena, bson.M{
|
|
"isdef": true,
|
|
"uid": bson.M{"$ne": uid},
|
|
"dan": dan,
|
|
"loc": bson.M{
|
|
"$near": bson.M{
|
|
"$geometry": bson.M{"type": "Point", "coordinates": port},
|
|
"$maxDistance": 100000,
|
|
},
|
|
},
|
|
}, options.Find().SetSkip(0).SetLimit(int64(num))); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
} else {
|
|
for cursor.Next(context.Background()) {
|
|
temp := &pb.DBArenaUser{}
|
|
if err = cursor.Decode(temp); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
results = append(results, &pb.ArenaPlayer{
|
|
Uid: temp.Uid,
|
|
Name: temp.Name,
|
|
Avatar: temp.Avatar,
|
|
Lv: temp.Lv,
|
|
Dan: temp.Dan,
|
|
Integral: temp.Integral,
|
|
Defend: temp.Defend,
|
|
})
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 随机用户名
|
|
func (this *modelArena) randUserName() string {
|
|
var s = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*")
|
|
r := rand.New(rand.NewSource(configure.Now().UnixNano() + rand.Int63n(10000)))
|
|
result := []byte("DWA_")
|
|
for i, v := range r.Perm(len(s)) {
|
|
result = append(result, s[v])
|
|
if i == 3 {
|
|
break
|
|
}
|
|
}
|
|
return string(result)
|
|
}
|
|
|
|
func (this *modelArena) getAI(mformatId int32) (ai *pb.ArenaPlayer, err error) {
|
|
var (
|
|
formats []*cfg.GameMonsterFormatData
|
|
// monst *cfg.GameMonsterData
|
|
)
|
|
if formats, err = this.module.configure.getMonsterFormat(mformatId); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
ai = &pb.ArenaPlayer{
|
|
Name: this.randUserName(),
|
|
Isai: true,
|
|
Mformatid: mformatId,
|
|
Defend: &pb.DBPlayerBattleFormt{
|
|
Leadpos: 0,
|
|
Formt: make([]*pb.DBHero, len(formats)),
|
|
},
|
|
}
|
|
for i1, v1 := range formats {
|
|
if v1 == nil {
|
|
ai.Defend.Formt[i1] = nil
|
|
} else {
|
|
// if monst, err = this.module.configure.getMonster(v1.Monster); err != nil {
|
|
// this.module.Errorln(err)
|
|
// }
|
|
hero := &pb.DBHero{}
|
|
if hero = this.module.ModuleHero.CreateMonster(fmt.Sprintf("%d", v1.Heroid), v1.Star, v1.Lv); hero == nil {
|
|
err = fmt.Errorf("CreateMonster 失败")
|
|
return
|
|
}
|
|
hero.Property[comm.Hp] = int32(float32(hero.Property[comm.Hp]) * v1.Hppro)
|
|
hero.Property[comm.Atk] = int32(float32(hero.Property[comm.Atk]) * v1.Atkpro)
|
|
hero.Property[comm.Def] = int32(float32(hero.Property[comm.Def]) * v1.Defpro)
|
|
hero.Suits = make([]*pb.DB_EquipmentSuit, 0)
|
|
for _, v := range v1.Equip {
|
|
hero.Suits = append(hero.Suits, &pb.DB_EquipmentSuit{
|
|
Suitid: v,
|
|
Effect: true,
|
|
})
|
|
}
|
|
ai.Defend.Formt[i1] = hero
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 积分计算
|
|
func (this *modelArena) integralCompute(red, bule *pb.ArenaPlayer, iswin bool) {
|
|
var (
|
|
redactive *cfg.GameArenaActiveRewardData
|
|
buleactive *cfg.GameArenaActiveRewardData
|
|
err error
|
|
)
|
|
if redactive, err = this.module.configure.getActiveRewardById(red.Dan); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
if buleactive, err = this.module.configure.getActiveRewardById(bule.Dan); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
if iswin {
|
|
red.Changeintegral = int32(redactive.KValue * float32(1-1/float32(1+10^(bule.Integral-red.Integral)/400)))
|
|
red.Integral = red.Integral + red.Changeintegral
|
|
bule.Changeintegral = int32(buleactive.KValue * float32(0-1/float32(1+10^(red.Integral-bule.Integral)/400)))
|
|
bule.Integral = bule.Integral + bule.Changeintegral
|
|
} else {
|
|
red.Changeintegral = int32(redactive.KValue * float32(0-1/float32(1+10^(bule.Integral-red.Integral)/400)))
|
|
red.Integral = red.Integral + red.Changeintegral
|
|
bule.Changeintegral = int32(redactive.KValue * float32(1-1/float32(1+10^(red.Integral-bule.Integral)/400)))
|
|
bule.Integral = bule.Integral + bule.Changeintegral
|
|
}
|
|
}
|
|
|
|
func (this *modelArena) recoverTicket(session comm.IUserSession, info *pb.DBArenaUser) {
|
|
var (
|
|
duration time.Duration
|
|
ticketitem *cfg.Gameatn
|
|
ticket int32
|
|
ticketNum int32
|
|
)
|
|
|
|
if ticketitem = this.module.ModuleTools.GetGlobalConf().ArenaTicketCos; ticketitem == nil {
|
|
// code = pb.ErrorCode_ConfigNoFound
|
|
// data = &pb.ErrorData{
|
|
// Title: code.ToString(),
|
|
// Message: comm.NewNotFoundConfErr(moduleName, "global.json", "ArenaTicketCos").Error(),
|
|
// }
|
|
this.module.Error("竞技场配置未找到!", log.Field{Key: "key", Value: "ArenaTicketCos"})
|
|
return
|
|
}
|
|
|
|
global := this.module.ModuleTools.GetGlobalConf()
|
|
ticket = int32(this.module.ModuleItems.QueryItemAmount(info.Uid, ticketitem.T))
|
|
if ticket < global.ArenaTicketMax && info.Lastrtickettime > 0 {
|
|
duration = configure.Now().Sub(time.Unix(info.Lastrtickettime, 0))
|
|
ticketNum = int32(math.Floor(duration.Minutes() / float64(global.ArenaTicketRecoveryTime)))
|
|
if ticketNum > 0 {
|
|
if ticketNum+ticket > global.ArenaTicketMax {
|
|
ticketNum = global.ArenaTicketMax - ticket
|
|
}
|
|
this.module.DispenseRes(session, []*cfg.Gameatn{{A: ticketitem.A, T: ticketitem.T, N: ticketNum}}, true)
|
|
// info.Ticket += ticketNum
|
|
// if info.Ticket > global.ArenaTicketMax {
|
|
// info.Ticket = global.ArenaTicketMax
|
|
// }
|
|
info.Lastrtickettime = time.Unix(info.Lastrtickettime, 0).Add(time.Duration(ticketNum) * time.Minute).Unix()
|
|
}
|
|
}
|
|
}
|
|
|
|
func (this *modelArena) reddot(session comm.IUserSession) bool {
|
|
var (
|
|
info *pb.DBArenaUser
|
|
ticketitem *cfg.Gameatn
|
|
err error
|
|
)
|
|
if info, err = this.queryPlayerInfo(session.GetUserId()); err != nil && err != mgo.MongodbNil {
|
|
return false
|
|
}
|
|
if err == mgo.MongodbNil {
|
|
global := this.module.ModuleTools.GetGlobalConf()
|
|
if global.ArenaTicketMax >= global.ArenaTicketCos.N {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
if ticketitem = this.module.ModuleTools.GetGlobalConf().ArenaTicketCos; ticketitem == nil {
|
|
this.module.Error("竞技场配置未找到!", log.Field{Key: "key", Value: "ArenaTicketCos"})
|
|
return false
|
|
}
|
|
ticket := int32(this.module.ModuleItems.QueryItemAmount(info.Uid, ticketitem.T))
|
|
if ticket > this.module.ModuleTools.GetGlobalConf().ArenaTicketCos.N {
|
|
return true
|
|
}
|
|
return false
|
|
}
|