1087 lines
30 KiB
Go
1087 lines
30 KiB
Go
package entertainment
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"errors"
|
|
"fmt"
|
|
"go_dreamfactory/comm"
|
|
"go_dreamfactory/lego/sys/event"
|
|
"go_dreamfactory/lego/sys/timewheel"
|
|
"go_dreamfactory/pb"
|
|
"go_dreamfactory/sys/configure"
|
|
cfg "go_dreamfactory/sys/configure/structs"
|
|
"math/big"
|
|
"time"
|
|
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
const (
|
|
MaxPs = 2 // 最大体力
|
|
)
|
|
|
|
//游戏房间
|
|
type Room struct {
|
|
Id string // 房间id
|
|
szSession []comm.IUserSession
|
|
player1 *pb.PlayerData // 玩家1
|
|
player2 *pb.PlayerData // 玩家2
|
|
chessboard *MapData // 地图数据
|
|
module *Entertainment
|
|
round int32 // 当前轮数
|
|
closeRoomTimer *timewheel.Task //房间解散倒计时定时器
|
|
curPower string // 当前操作的玩家
|
|
NexPower string // 下一个操作的玩家
|
|
MaxRound int32 // 最大回合数
|
|
rd1 bool // 玩家1 是否准备
|
|
rd2 bool // 玩家2 是否准备
|
|
Status int32 //房间游戏状态 0未开始 1 已开始 2 已结束
|
|
RoomType int32 // 房间类型 1 是好友创房 0对战 2 AI 对战
|
|
MaxTime int32 // 操作时间
|
|
Playtype int32 //当前房间玩法
|
|
offline string // 谁离线
|
|
}
|
|
|
|
func (this *Room) CloseRoomTimeOut(task *timewheel.Task, args ...interface{}) {
|
|
this.module.Errorf("解散房间超时+++++%d\n", time.Now().Unix()) //倒计时结束还没结束基本是游戏异常 直接清理房间
|
|
this.Status = 2 // 游戏解散
|
|
this.ModifyUserRoomInfoData()
|
|
}
|
|
|
|
// 随机一个玩法
|
|
func (this *Room) RandomPlayType() (itype int32) {
|
|
|
|
var weight []int32 // 权重
|
|
// 开始随机玩法
|
|
list := this.module.configure.GetGameConsumeIntegral()
|
|
for _, v := range list {
|
|
weight = append(weight, v.Weight)
|
|
}
|
|
itype = list[comm.GetRandW(weight)].Key
|
|
|
|
return
|
|
}
|
|
|
|
func (this *Room) InitRoom(module *Entertainment, p1 *pb.PlayerData, p2 *pb.PlayerData, itype int32) (room *Room, err error) {
|
|
this.module = module
|
|
this.chessboard = new(MapData)
|
|
if itype == -1 {
|
|
this.Playtype = this.RandomPlayType()
|
|
} else {
|
|
if itype == 0 {
|
|
itype = 1 // 测试数据 后面删
|
|
}
|
|
this.Playtype = itype
|
|
// 校验类型
|
|
if _, err = this.module.configure.GetGameConsumeIntegralByKey(this.Playtype); err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
this.chessboard.InitMap(module, this.Playtype) // 初始化棋盘
|
|
if s1, ok := this.module.GetUserSession(p1.Userinfo.Uid); !ok {
|
|
this.module.PutUserSession(s1)
|
|
} else {
|
|
this.szSession = append(this.szSession, s1.Clone())
|
|
}
|
|
|
|
if p2.Userinfo.Uid != "999" { // 是否是机器人
|
|
if s2, ok := this.module.GetUserSession(p2.Userinfo.Uid); !ok {
|
|
this.module.PutUserSession(s2)
|
|
} else {
|
|
this.szSession = append(this.szSession, s2.Clone())
|
|
}
|
|
} else {
|
|
this.RoomType = 2
|
|
}
|
|
this.MaxRound = module.ModuleTools.GetGlobalConf().ConsumeRounds
|
|
room = &Room{
|
|
Id: primitive.NewObjectID().Hex(),
|
|
szSession: this.szSession,
|
|
player1: p1,
|
|
player2: p2,
|
|
chessboard: this.chessboard,
|
|
module: module,
|
|
round: 1,
|
|
MaxRound: this.MaxRound,
|
|
Status: 0,
|
|
Playtype: this.Playtype,
|
|
RoomType: this.RoomType,
|
|
}
|
|
|
|
if err = this.module.SendMsgSyncToSession(string(this.module.GetType()), "enterroom", &pb.EntertainEnterRoomPush{
|
|
Rooid: room.Id,
|
|
Servepath: fmt.Sprintf("%s/%s", this.module.service.GetType(), this.module.service.GetId()),
|
|
User1: room.player1,
|
|
User2: room.player2,
|
|
Itype: itype,
|
|
}, this.szSession...); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// AI 操作了
|
|
|
|
func (this *Room) ReceiveMessage(session comm.IUserSession, stype string, msg proto.Message) (errdata *pb.ErrorData) {
|
|
switch stype {
|
|
case "operator": // 操作消息
|
|
var (
|
|
curScore int32 // 该次操作的得分
|
|
oid1 int32 // 唯一id
|
|
oid2 int32
|
|
color int32 // 校验消除的颜色
|
|
bAddPs bool
|
|
curPlayer *pb.PlayerData
|
|
)
|
|
var szMap []*pb.MapData
|
|
req := msg.(*pb.EntertainOperatorReq)
|
|
if session.GetUserId() != this.curPower { // 校验是不是你的权限
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoPower,
|
|
Title: pb.ErrorCode_EntertainNoPower.ToString(),
|
|
}
|
|
return
|
|
}
|
|
if this.curPower == this.player1.Userinfo.Uid {
|
|
color = 1
|
|
curPlayer = this.player1
|
|
} else {
|
|
color = 2
|
|
curPlayer = this.player2
|
|
}
|
|
if req.Itype == "cardskill" { //释放技能
|
|
if errdata = this.UserSkillUp(color, req.Curid); errdata != nil {
|
|
return
|
|
}
|
|
return
|
|
} else if req.Itype != "swap" { //玩家卡牌技能
|
|
if conf, err := this.module.configure.GetGamePlaySkill(req.Itype); err == nil {
|
|
if curPlayer.Skill[conf.Key] <= 0 {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoSkillCard, // 技能卡不足
|
|
Title: pb.ErrorCode_EntertainNoSkillCard.ToString(),
|
|
}
|
|
return
|
|
}
|
|
curPlayer.Skill[conf.Key] -= 1
|
|
if errdata = this.UserCardSkill(curPlayer, color, conf.Key, req.Curid); errdata != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
if req.Itype == "swap" && req.Curid == 0 && req.Targetid == 0 {
|
|
if this.curPower == this.player1.Userinfo.Uid {
|
|
this.NexPower = this.player2.Userinfo.Uid
|
|
this.player2.Ps = 2
|
|
this.player1.Ps = 0
|
|
}
|
|
if this.curPower == this.player2.Userinfo.Uid {
|
|
this.NexPower = this.player1.Userinfo.Uid
|
|
this.player1.Ps = 2
|
|
this.player2.Ps = 0
|
|
}
|
|
} else {
|
|
bCanChange := false
|
|
oid1 = this.chessboard.Plat[req.Curid].Oid
|
|
oid2 = this.chessboard.Plat[req.Targetid].Oid
|
|
if b, m := this.chessboard.CheckSpecialElemChange(req.Curid, req.Targetid, color); !b {
|
|
// 交换元素
|
|
if b = this.chessboard.SwapGirde(req.Curid, req.Targetid); !b { // 交换格子
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainCantSwap, // 不能交换 直接返回
|
|
Title: pb.ErrorCode_EntertainCantSwap.ToString(),
|
|
}
|
|
return
|
|
}
|
|
} else {
|
|
bCanChange = true
|
|
szMap = append(szMap, m...)
|
|
}
|
|
if m, b := this.chessboard.CheckMap(color, true); len(m) > 0 {
|
|
szMap = append(szMap, m...)
|
|
bAddPs = b
|
|
bCanChange = true
|
|
}
|
|
if !bCanChange { // 不能消除
|
|
this.chessboard.SwapGirde(req.Targetid, req.Curid) // 换到原来的位置
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainCantSwap, // 不能交换 直接返回
|
|
Title: pb.ErrorCode_EntertainCantSwap.ToString(),
|
|
}
|
|
return
|
|
}
|
|
|
|
// 校验下次是不是消除
|
|
if !this.chessboard.CheckAndRefreshPlat() {
|
|
this.chessboard.RedsetPlatData()
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.chessboard.GetPalatData(),
|
|
ChangeType: 1,
|
|
})
|
|
}
|
|
if this.curPower == this.player1.Userinfo.Uid { //权限校验
|
|
this.player1.Score += curScore
|
|
this.player1.Ps--
|
|
if bAddPs {
|
|
this.player1.Ps++
|
|
if this.player1.Ps > MaxPs {
|
|
this.player1.Ps = MaxPs
|
|
}
|
|
}
|
|
|
|
if this.player1.Ps <= 0 {
|
|
this.NexPower = this.player2.Userinfo.Uid
|
|
this.player2.Ps = MaxPs
|
|
}
|
|
} else { // this.curPower == this.player2.Uid
|
|
this.player2.Score += curScore
|
|
this.player2.Ps--
|
|
if bAddPs {
|
|
this.player2.Ps++
|
|
if this.player2.Ps > MaxPs {
|
|
this.player2.Ps = MaxPs
|
|
}
|
|
}
|
|
if this.player2.Ps <= 0 {
|
|
this.NexPower = this.player1.Userinfo.Uid
|
|
this.player1.Ps = MaxPs
|
|
}
|
|
}
|
|
for _, v := range szMap { //
|
|
curScore += v.CurSocre
|
|
if color == 1 {
|
|
this.player1.Score += v.CurSocre
|
|
v.CurSocre = this.player1.Score
|
|
this.player1.Energy += v.CurEnergy
|
|
v.CurEnergy = this.player1.Energy
|
|
} else {
|
|
this.player2.Score += v.CurSocre
|
|
v.CurSocre = this.player2.Score
|
|
this.player2.Energy += v.CurEnergy
|
|
v.CurEnergy = this.player2.Energy
|
|
}
|
|
}
|
|
}
|
|
|
|
if this.NexPower == this.player1.Userinfo.Uid && this.NexPower != this.curPower {
|
|
this.round++
|
|
}
|
|
|
|
// 广播消息
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "operatorrst", &pb.EntertainOperatorRstPush{
|
|
Mpadata: szMap,
|
|
Power: this.NexPower,
|
|
Curpower: this.curPower,
|
|
Score: curScore,
|
|
Round: this.round,
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Itype: req.Itype,
|
|
Curid: oid1,
|
|
Targetid: oid2,
|
|
}, this.szSession...); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
if this.round > this.MaxRound { // 游戏结束
|
|
if this.player1.Score == this.player2.Score {
|
|
this.MaxRound += 1 // 增加一回合
|
|
} else {
|
|
this.GameOver(nil)
|
|
}
|
|
return
|
|
}
|
|
// 变更权限
|
|
this.curPower = this.NexPower
|
|
|
|
case "ready":
|
|
var bStartGame bool // 可以开始游戏
|
|
this.NexPower = this.player1.Userinfo.Uid
|
|
this.curPower = this.player1.Userinfo.Uid
|
|
this.player1.Ps = MaxPs
|
|
this.player2.Ps = 0
|
|
if this.RoomType == 2 { // AI对战的话直接开始游戏
|
|
bStartGame = true
|
|
} else {
|
|
if this.player1.Userinfo.Uid == session.GetUserId() {
|
|
this.rd1 = true
|
|
} else if this.player2.Userinfo.Uid == session.GetUserId() {
|
|
this.rd2 = true
|
|
}
|
|
if this.player1.Userinfo.Uid != session.GetUserId() || this.RoomType != 1 { // 房主
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "gameready", &pb.EntertainGameReadyPush{
|
|
P1Ready: this.rd1,
|
|
P2Ready: this.rd2,
|
|
}, this.szSession...); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
}
|
|
if this.rd1 && this.rd2 { // 两个玩家都准备好了 那么就开始游戏
|
|
bStartGame = true
|
|
this.rd1 = false
|
|
this.rd2 = false
|
|
}
|
|
}
|
|
if bStartGame {
|
|
// 初始化规则相关
|
|
if this.RoomType == 2 {
|
|
this.MaxTime = this.module.ModuleTools.GetGlobalConf().ConsumePveTime
|
|
} else {
|
|
this.MaxTime = this.module.ModuleTools.GetGlobalConf().ConsumePvpTime
|
|
}
|
|
|
|
this.Status = 1
|
|
this.round = 1
|
|
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "startgame", &pb.EntertainStartGamePush{
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Mpadata: &pb.MapData{Data: this.chessboard.Plat},
|
|
Power: this.NexPower,
|
|
Round: this.round,
|
|
Roomid: this.Id, // 房间ID
|
|
Playtype: this.Playtype, // 通过权重随机一个玩法
|
|
}, this.szSession...); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
this.ModifyUserRoomInfoData()
|
|
// 游戏开始开启一个定时器 1小时如果还不结束 自动清理
|
|
this.closeRoomTimer = timewheel.Add(time.Hour, this.CloseRoomTimeOut)
|
|
}
|
|
|
|
case "reconnect": // 重连
|
|
this.offline = ""
|
|
session.SendMsg(string(this.module.GetType()), "reconnect", &pb.EntertainReconnectResp{
|
|
Roomid: this.Id,
|
|
Mpadata: &pb.MapData{
|
|
Data: this.chessboard.GetPalatData(),
|
|
CurSocre: 0,
|
|
CurEnergy: 0,
|
|
},
|
|
Power: this.NexPower,
|
|
Curpower: this.curPower,
|
|
Score: 0,
|
|
Round: this.round,
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
})
|
|
case "dissolve": // 房主解散房间
|
|
req := msg.(*pb.EntertainDissolveRoomReq)
|
|
if this.player1.Userinfo.Uid != req.Roomid {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNotMaster, // 不是房主
|
|
Title: pb.ErrorCode_EntertainNotMaster.ToString(),
|
|
}
|
|
return
|
|
}
|
|
// 游戏中不允许解散
|
|
if this.Status == 1 {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainDissolveFailed, // 游戏中不能解散
|
|
Title: pb.ErrorCode_EntertainDissolveFailed.ToString(),
|
|
}
|
|
return
|
|
}
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "dissolvemasterroom", &pb.EntertainDissolveMasterRoomPush{
|
|
Roomid: this.Id,
|
|
}, this.szSession...); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
this.Status = 2
|
|
this.ModifyUserRoomInfoData()
|
|
case "operatorover": // 操作完成 开启一个定时器
|
|
|
|
if this.player1.Userinfo.Uid == session.GetUserId() {
|
|
this.rd1 = true
|
|
} else if this.player2.Userinfo.Uid == session.GetUserId() {
|
|
this.rd2 = true
|
|
}
|
|
if this.RoomType == 2 || this.offline != "" {
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "startimer", &pb.EntertainStarTimerPush{
|
|
Time: this.MaxTime,
|
|
Power: this.curPower,
|
|
}, this.szSession...); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
if this.offline != "" && this.curPower == this.offline {
|
|
this.AutoOperator(this.offline) // 托管
|
|
} else {
|
|
if this.curPower == this.player2.Userinfo.Uid {
|
|
this.AutoOperator(this.curPower)
|
|
}
|
|
}
|
|
} else {
|
|
if this.rd1 && this.rd2 { // 两个玩家都准备好了 那么就开始游戏
|
|
this.rd1 = false
|
|
this.rd2 = false
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "startimer", &pb.EntertainStarTimerPush{
|
|
Time: this.MaxTime,
|
|
Power: this.curPower,
|
|
}, this.szSession...); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
}
|
|
}
|
|
//this.operatetimer = timewheel.Add(time.Second*time.Duration(this.MaxTime), this.operateTimeOut)
|
|
case "offline":
|
|
|
|
req := msg.(*pb.RPCGeneralReqA2)
|
|
fmt.Printf("useroffline: %v\n", req)
|
|
|
|
if this.RoomType == 2 { // AI 对战直接结束
|
|
this.Status = 2 // 解散
|
|
this.ModifyUserRoomInfoData()
|
|
return
|
|
}
|
|
if this.offline == "" {
|
|
this.offline = req.Param2
|
|
// 如果当前权限是自己开启托管
|
|
if this.curPower == this.offline {
|
|
this.AutoOperator(this.offline)
|
|
}
|
|
} else {
|
|
if this.offline != req.Param2 { // 两个都离线 游戏直接结束
|
|
this.Status = 2 // 解散
|
|
this.ModifyUserRoomInfoData()
|
|
}
|
|
}
|
|
|
|
case "surrender":
|
|
if this.Status != 1 { // 不是游戏中 直接返回
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoGamePlayering,
|
|
Title: pb.ErrorCode_EntertainNoGamePlayering.ToString(),
|
|
}
|
|
return
|
|
}
|
|
var winner *pb.PlayerData
|
|
if this.player1.Userinfo.Uid == session.GetUserId() {
|
|
winner = this.player2
|
|
} else {
|
|
winner = this.player1
|
|
}
|
|
this.GameOver(winner)
|
|
}
|
|
return
|
|
}
|
|
|
|
// 游戏结束
|
|
func (this *Room) GameOver(winner *pb.PlayerData) (errdata *pb.ErrorData) {
|
|
var (
|
|
atno []*pb.UserAtno
|
|
winindex int32
|
|
res []*cfg.Gameatn
|
|
lostPlayer *pb.PlayerData // 输的玩家
|
|
box *pb.BoxData // 是否可以获得宝箱奖励
|
|
pl []*pb.XxlPlayer
|
|
winScore int32 // 胜利获得的积分
|
|
lostScore int32 // 失败扣的积分
|
|
bDestruction bool
|
|
)
|
|
if winner == nil {
|
|
if this.player1.Score < this.player2.Score {
|
|
winner = this.player2
|
|
winindex = 1
|
|
} else {
|
|
winner = this.player1
|
|
}
|
|
}
|
|
if this.player1 != winner {
|
|
lostPlayer = this.player1
|
|
} else {
|
|
lostPlayer = this.player2
|
|
}
|
|
if winner.Userinfo.Uid != "999" {
|
|
var (
|
|
list *pb.DBXXLData
|
|
err error
|
|
update map[string]interface{}
|
|
)
|
|
update = make(map[string]interface{})
|
|
if list, err = this.module.model.getEntertainmList(winner.Userinfo.Uid); err != nil {
|
|
return
|
|
}
|
|
if conf, err := this.module.configure.GetGameConsumeintegral(list.Consumeexp); err == nil {
|
|
pro := this.LianShengAdd(list.Liansheng) // 连胜加成
|
|
for _, v := range conf.Rewards {
|
|
if v.A == "attr" && v.T == "consumeexp" {
|
|
list.Consumeexp += int32(v.N*pro) / 1000
|
|
winScore = int32(v.N*pro) / 1000
|
|
update["consumeexp"] = list.Consumeexp
|
|
winner.Consumeexp = list.Consumeexp
|
|
if list.Consumeexp > list.Maxconsumeexp { // 写最高积分
|
|
list.Maxconsumeexp = list.Consumeexp
|
|
update["maxconsumeexp"] = list.Maxconsumeexp
|
|
}
|
|
if list.Maxsocre < winner.Score {
|
|
list.Maxsocre = winner.Score
|
|
update["maxsocre"] = list.Maxsocre
|
|
}
|
|
} else {
|
|
res = append(res, v)
|
|
}
|
|
}
|
|
if errdata, atno = this.module.DispenseAtno(this.szSession[winindex], res, true); errdata != nil {
|
|
return
|
|
}
|
|
this.szSession[winindex].Push()
|
|
}
|
|
|
|
// 修改连胜
|
|
list.Liansheng += 1
|
|
update["liansheng"] = list.Liansheng
|
|
if len(list.Box) < 3 { // 可以获得一个宝箱
|
|
if c, err := this.module.configure.GetGameRandomConsumeBoxConf(); err == nil {
|
|
if c.Color != 0 {
|
|
box = &pb.BoxData{
|
|
Boxid: c.Boxid,
|
|
Opentime: int64(c.Cd) + configure.Now().Unix(),
|
|
}
|
|
list.Box = append(list.Box, box)
|
|
update["box"] = list.Box
|
|
}
|
|
}
|
|
}
|
|
this.module.model.modifyEntertainmList(winner.Userinfo.Uid, update)
|
|
if user, err := this.module.ModuleUser.GetUser(winner.Userinfo.Uid); err == nil {
|
|
|
|
p := &pb.XxlPlayer{
|
|
Uinfo: comm.GetUserBaseInfo(user),
|
|
Maxconsumeexp: list.Maxconsumeexp,
|
|
Consumeexp: list.Consumeexp,
|
|
Maxsocre: list.Maxsocre,
|
|
}
|
|
pl = append(pl, p)
|
|
}
|
|
} else {
|
|
if conf, err := this.module.configure.GetGameConsumeintegral(winner.Consumeexp); err == nil {
|
|
for _, v := range conf.Rewards {
|
|
if v.A == "attr" && v.T == "consumeexp" {
|
|
winScore = v.N
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if lostPlayer.Userinfo.Uid != "999" {
|
|
if conf, err := this.module.configure.GetGameConsumeHero(lostPlayer.Cardid); err == nil {
|
|
update := map[string]interface{}{}
|
|
if list, err := this.module.model.getEntertainmList(lostPlayer.Userinfo.Uid); err == nil {
|
|
if list.Liansheng != 0 {
|
|
list.Liansheng = 0 // 修改连胜
|
|
update["liansheng"] = list.Liansheng
|
|
}
|
|
|
|
if conf.Type != 1 { //卡片类型不为1
|
|
if list.Card[lostPlayer.Cardid] >= 1 { //删除卡片
|
|
var star int32
|
|
for _, v := range this.module.ModuleHero.GetHeroList(lostPlayer.Userinfo.Uid) {
|
|
if v.HeroID == lostPlayer.Cardid {
|
|
star = v.Star
|
|
break
|
|
}
|
|
}
|
|
if c, err := this.module.configure.GetGameConsumeHero(lostPlayer.Cardid); err == nil {
|
|
if len(c.Lost) == 0 { // 容错处理
|
|
bDestruction = false
|
|
} else {
|
|
if star >= int32(len(c.Lost)) {
|
|
star = c.Lost[len(c.Lost)-1]
|
|
} else {
|
|
star = c.Lost[star]
|
|
}
|
|
}
|
|
// 概率验证
|
|
n, _ := rand.Int(rand.Reader, big.NewInt(1000))
|
|
if star > int32(n.Int64()) {
|
|
bDestruction = true
|
|
}
|
|
}
|
|
if bDestruction {
|
|
list.Card[lostPlayer.Cardid] -= 1
|
|
update["card"] = list.Card
|
|
}
|
|
}
|
|
}
|
|
if conf, err := this.module.configure.GetGameConsumeintegral(list.Consumeexp); err == nil { // 战败扣除积分
|
|
for _, v := range conf.Deductrewards {
|
|
if v.A == "attr" && v.T == "consumeexp" {
|
|
lostScore = v.N
|
|
list.Consumeexp -= v.N
|
|
if list.Consumeexp <= 0 {
|
|
list.Consumeexp = 0
|
|
}
|
|
lostPlayer.Consumeexp = list.Consumeexp
|
|
update["consumeexp"] = list.Consumeexp
|
|
}
|
|
}
|
|
}
|
|
if list.Maxsocre < winner.Score { // 单局最大积分
|
|
list.Maxsocre = winner.Score
|
|
update["maxsocre"] = list.Maxsocre
|
|
}
|
|
if len(update) > 0 {
|
|
this.module.model.modifyEntertainmList(lostPlayer.Userinfo.Uid, update)
|
|
}
|
|
if user, err := this.module.ModuleUser.GetUser(winner.Userinfo.Uid); err == nil {
|
|
p := &pb.XxlPlayer{
|
|
Uinfo: comm.GetUserBaseInfo(user),
|
|
Maxconsumeexp: list.Maxconsumeexp,
|
|
Consumeexp: list.Consumeexp,
|
|
Maxsocre: list.Maxsocre,
|
|
}
|
|
pl = append(pl, p)
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if conf, err := this.module.configure.GetGameConsumeintegral(winner.Consumeexp); err == nil {
|
|
for _, v := range conf.Deductrewards {
|
|
if v.A == "attr" && v.T == "consumeexp" {
|
|
lostScore = v.N
|
|
break
|
|
}
|
|
}
|
|
}
|
|
bDestruction = true
|
|
}
|
|
if this.RoomType != 1 { //好友对战无需记录对战记录
|
|
go func() {
|
|
// 更新排行榜数据
|
|
this.module.modelRank.updateXxlRank(pl...)
|
|
// 写记录
|
|
recode1 := &pb.DBXxlRecord{
|
|
Id: primitive.NewObjectID().Hex(),
|
|
P1: this.player1.Userinfo.Uid,
|
|
P2: this.player2.Userinfo.Uid,
|
|
Uinfo1: this.player1.Userinfo,
|
|
Uinfo2: this.player2.Userinfo,
|
|
P1Score: this.player1.Score,
|
|
P2Score: this.player2.Score,
|
|
Win: winner.Userinfo.Uid,
|
|
Winscore: winScore,
|
|
Lostscore: lostScore,
|
|
P1Card: this.player1.Cardid,
|
|
P2Cards: this.player2.Cardid,
|
|
P1Totlascore: this.player1.Consumeexp,
|
|
P2Totlascore: this.player2.Consumeexp,
|
|
Createtime: configure.Now().Unix(),
|
|
}
|
|
this.module.modelRecode.updateXxlRecord(recode1)
|
|
}()
|
|
}
|
|
|
|
// 修改房间状态
|
|
this.Status = 2
|
|
this.module.SendMsgSyncToSession(string(this.module.GetType()), "gameover", &pb.EntertainGameOverPush{
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Mpadata: &pb.MapData{Data: this.chessboard.Plat},
|
|
Power: "",
|
|
Round: this.round,
|
|
Win: winner.Userinfo.Uid,
|
|
Reward: atno,
|
|
Box: box,
|
|
BDestruction: bDestruction,
|
|
}, this.szSession...)
|
|
this.ModifyUserRoomInfoData()
|
|
if this.closeRoomTimer != nil { // 游戏结束 清理定时器
|
|
timewheel.Remove(this.closeRoomTimer)
|
|
this.closeRoomTimer = nil
|
|
}
|
|
this.curPower = ""
|
|
return
|
|
}
|
|
|
|
// 加入房间
|
|
func (this *Room) JoinRoom(module *Entertainment, p *pb.PlayerData) (room *Room, err error) {
|
|
|
|
// 该房间是个空的
|
|
if this.player1 == nil {
|
|
this.player1 = p
|
|
this.module = module
|
|
this.chessboard = new(MapData)
|
|
this.Playtype = this.RandomPlayType()
|
|
this.chessboard.InitMap(module, this.Playtype) // 初始化棋盘
|
|
if s1, ok := this.module.GetUserSession(p.Userinfo.Uid); !ok {
|
|
this.module.PutUserSession(s1)
|
|
} else {
|
|
this.szSession = append(this.szSession, s1.Clone())
|
|
}
|
|
this.Id = p.Userinfo.Uid // 房主ID 作为房间id
|
|
this.RoomType = 1
|
|
this.MaxRound = this.module.ModuleTools.GetGlobalConf().ConsumeRounds
|
|
room = this
|
|
} else if this.player2 == nil {
|
|
//异常处理
|
|
if this.player1.Userinfo.Uid == p.Userinfo.Uid {
|
|
err = errors.New("重复加入")
|
|
}
|
|
this.player2 = p // 玩家2 赋值
|
|
if s1, ok := this.module.GetUserSession(p.Userinfo.Uid); !ok {
|
|
this.module.PutUserSession(s1)
|
|
} else {
|
|
this.szSession = append(this.szSession, s1.Clone())
|
|
}
|
|
// 推送消息
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "joincreateroom", &pb.EntertainJoinCreateRoomPush{
|
|
Roomid: this.Id,
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
}, this.szSession...); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
} else { // 房间满了 加不进来
|
|
err = errors.New("房间已满")
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *Room) LianShengAdd(liansheng int32) (permillage int32) {
|
|
var (
|
|
result []*cfg.GameConsumeTxtData
|
|
err error
|
|
)
|
|
if result, err = this.module.configure.getLianShengReward(); err == nil {
|
|
for pos, v := range result {
|
|
if len(result) > pos+1 {
|
|
if result[pos+1].Winningstreak >= liansheng { // 下一等级小于当前值
|
|
permillage = result[pos].Rewarddata
|
|
return
|
|
}
|
|
} else {
|
|
permillage = v.Rewarddata
|
|
}
|
|
}
|
|
}
|
|
if permillage == 0 {
|
|
permillage = 1
|
|
}
|
|
return
|
|
}
|
|
|
|
// 修改玩家的房间信息
|
|
func (this *Room) ModifyUserRoomInfoData() {
|
|
var (
|
|
roomid string
|
|
path string
|
|
)
|
|
if this.Status == 1 {
|
|
roomid = this.Id
|
|
path = fmt.Sprintf("%s/%s", this.module.service.GetType(), this.module.service.GetId())
|
|
} else {
|
|
event.TriggerEvent(comm.EventCloseRoom, this.Id) // 释放房间
|
|
}
|
|
// 修改房间记录信息
|
|
if this.player1 != nil && this.player1.Userinfo != nil {
|
|
this.module.model.modifyEntertainmList(this.player1.Userinfo.Uid, map[string]interface{}{
|
|
"roomid": roomid,
|
|
"servicePath": path,
|
|
})
|
|
}
|
|
|
|
if this.RoomType != 2 && this.player2 != nil && this.player2.Userinfo != nil {
|
|
this.module.model.modifyEntertainmList(this.player2.Userinfo.Uid, map[string]interface{}{
|
|
"roomid": roomid,
|
|
"servicePath": path,
|
|
})
|
|
}
|
|
return
|
|
}
|
|
|
|
// 自动操作
|
|
func (this *Room) AutoOperator(uid string) {
|
|
var (
|
|
curScore int32
|
|
szMap []*pb.MapData
|
|
bAddPs bool
|
|
oid1 int32
|
|
oid2 int32
|
|
p *pb.PlayerData
|
|
)
|
|
if uid == this.player1.Userinfo.Uid {
|
|
p = this.player1
|
|
} else if uid == this.player2.Userinfo.Uid {
|
|
p = this.player2
|
|
} else {
|
|
this.module.Errorf("cant found user:%s", uid)
|
|
return
|
|
}
|
|
conf, err := this.module.configure.GetGameConsumeHero(p.Cardid)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 交换元素
|
|
if p.Energy >= conf.Skillload {
|
|
var color int32
|
|
if this.curPower == this.player1.Userinfo.Uid {
|
|
color = 1
|
|
} else {
|
|
color = 2
|
|
}
|
|
this.UserSkillUp(color, 0)
|
|
if this.RoomType == 2 && this.curPower == p.Userinfo.Uid {
|
|
this.AutoOperator(this.curPower)
|
|
}
|
|
return
|
|
}
|
|
szMap, oid1, oid2, bAddPs = this.chessboard.AiSwapGirde()
|
|
p.Ps--
|
|
if bAddPs {
|
|
p.Ps++
|
|
if p.Ps > MaxPs {
|
|
p.Ps = MaxPs
|
|
}
|
|
}
|
|
if p.Ps <= 0 { // 权限给下一个人
|
|
this.ChangePower()
|
|
this.round++
|
|
}
|
|
// 校验下次是不是消除
|
|
if !this.chessboard.CheckAndRefreshPlat() {
|
|
this.chessboard.RedsetPlatData()
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.chessboard.GetPalatData(),
|
|
ChangeType: 1,
|
|
})
|
|
}
|
|
for _, v := range szMap {
|
|
curScore += v.CurSocre
|
|
p.Score += v.CurSocre
|
|
v.CurSocre = p.Score
|
|
p.Energy += v.CurEnergy
|
|
v.CurEnergy = p.Energy
|
|
}
|
|
|
|
// 广播消息
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "operatorrst", &pb.EntertainOperatorRstPush{
|
|
Mpadata: szMap,
|
|
Power: this.NexPower,
|
|
Curpower: this.curPower,
|
|
Score: curScore,
|
|
Round: this.round,
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Itype: "swap",
|
|
Curid: oid1,
|
|
Targetid: oid2,
|
|
}, this.szSession...); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
this.curPower = this.NexPower
|
|
if this.round > this.MaxRound { // 游戏结束
|
|
if this.player1.Score == this.player2.Score {
|
|
this.MaxRound += 1 // 增加一回合
|
|
} else {
|
|
this.GameOver(nil)
|
|
}
|
|
return
|
|
}
|
|
|
|
if this.RoomType == 2 && this.curPower == p.Userinfo.Uid {
|
|
this.AutoOperator(this.curPower)
|
|
}
|
|
}
|
|
|
|
// 玩家释放技能
|
|
func (this *Room) UserSkillUp(color int32, curid int32) (errdata *pb.ErrorData) {
|
|
var (
|
|
curScore int32 // 该次操作的得分
|
|
oid1 int32 // 唯一id
|
|
oid2 int32
|
|
)
|
|
var szMap []*pb.MapData
|
|
// 能量校验
|
|
if color == 1 { // 玩家1 放技能
|
|
conf, err := this.module.configure.GetGameConsumeHero(this.player1.Cardid)
|
|
if err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoHeroSkill,
|
|
Title: pb.ErrorCode_EntertainNoHeroSkill.ToString(),
|
|
}
|
|
return
|
|
}
|
|
if this.player1.Energy >= conf.Skillload {
|
|
this.player1.Energy = 0 // 清零
|
|
if _, m := this.chessboard.SkillUp(curid, color, conf.Skilleffect, conf.Skillvalue, true); len(m) > 0 {
|
|
szMap = append(szMap, m...)
|
|
} else {
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.chessboard.GetPalatData(),
|
|
})
|
|
}
|
|
for _, v := range szMap {
|
|
curScore += v.CurSocre
|
|
this.player1.Score += v.CurSocre
|
|
v.CurSocre = this.player1.Score
|
|
}
|
|
|
|
} else {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoEnergy,
|
|
Title: pb.ErrorCode_EntertainNoEnergy.ToString(),
|
|
}
|
|
return
|
|
}
|
|
this.NexPower = this.curPower
|
|
} else {
|
|
conf, err := this.module.configure.GetGameConsumeHero(this.player2.Cardid)
|
|
if err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoHeroSkill,
|
|
Title: pb.ErrorCode_EntertainNoHeroSkill.ToString(),
|
|
}
|
|
return
|
|
}
|
|
if this.player2.Energy >= conf.Skillload {
|
|
this.player2.Energy = 0 // 清零
|
|
if _, m := this.chessboard.SkillUp(curid, color, conf.Skilleffect, conf.Skillvalue, true); len(m) > 0 {
|
|
szMap = append(szMap, m...)
|
|
} else {
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.chessboard.GetPalatData(),
|
|
})
|
|
}
|
|
for _, v := range szMap {
|
|
curScore += v.CurSocre
|
|
this.player2.Score += v.CurSocre
|
|
v.CurSocre = this.player2.Score
|
|
}
|
|
|
|
} else {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoEnergy,
|
|
Title: pb.ErrorCode_EntertainNoEnergy.ToString(),
|
|
}
|
|
return
|
|
}
|
|
this.NexPower = this.curPower
|
|
}
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "operatorrst", &pb.EntertainOperatorRstPush{
|
|
Mpadata: szMap,
|
|
Power: this.NexPower,
|
|
Curpower: this.curPower,
|
|
Score: curScore,
|
|
Round: this.round,
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Itype: "cardskill",
|
|
Curid: oid1,
|
|
Targetid: oid2,
|
|
}, this.szSession...); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// 交换玩家权限
|
|
func (this *Room) ChangePower() {
|
|
if this.curPower == this.player1.Userinfo.Uid {
|
|
this.NexPower = this.player2.Userinfo.Uid
|
|
this.player2.Ps = MaxPs
|
|
this.player1.Ps = 0
|
|
}
|
|
if this.curPower == this.player2.Userinfo.Uid {
|
|
this.NexPower = this.player1.Userinfo.Uid
|
|
this.player1.Ps = MaxPs
|
|
this.player2.Ps = 0
|
|
}
|
|
}
|
|
|
|
// 玩家释放技能
|
|
func (this *Room) UserCardSkill(curPlayer *pb.PlayerData, color int32, skillid string, curid int32) (errdata *pb.ErrorData) {
|
|
var (
|
|
curScore int32 // 该次操作的得分
|
|
oid1 int32 // 唯一id
|
|
oid2 int32
|
|
conf *cfg.GamePlayerSkillData
|
|
err error
|
|
szMap []*pb.MapData
|
|
bAddps bool
|
|
)
|
|
if curid >= int32(len(this.chessboard.Plat)) {
|
|
return
|
|
}
|
|
conf, err = this.module.configure.GetGamePlaySkill(skillid)
|
|
if err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoHeroSkill,
|
|
Title: pb.ErrorCode_EntertainNoHeroSkill.ToString(),
|
|
}
|
|
return
|
|
}
|
|
|
|
if conf.Skilltouch == 101 { // 技能类型为1
|
|
szMap = this.chessboard.HitElem(color, curid)
|
|
} else if conf.Skilltouch == 102 {
|
|
szMap, bAddps = this.chessboard.ShuffleElem()
|
|
} else if conf.Skilltouch == 103 {
|
|
this.chessboard.HitCrossElem(color, curid) // 消除十字
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.chessboard.Plat,
|
|
})
|
|
}
|
|
for _, v := range szMap { //
|
|
curScore += v.CurSocre
|
|
if color == 1 {
|
|
this.player1.Score += v.CurSocre
|
|
v.CurSocre = this.player1.Score
|
|
this.player1.Energy += v.CurEnergy
|
|
v.CurEnergy = this.player1.Energy
|
|
if bAddps {
|
|
this.player1.Ps++
|
|
if this.player1.Ps > 2 {
|
|
this.player1.Ps = 2
|
|
}
|
|
}
|
|
} else {
|
|
this.player2.Score += v.CurSocre
|
|
v.CurSocre = this.player2.Score
|
|
this.player2.Energy += v.CurEnergy
|
|
v.CurEnergy = this.player2.Energy
|
|
if bAddps {
|
|
this.player2.Ps++
|
|
if this.player2.Ps > 2 {
|
|
this.player2.Ps = 2
|
|
}
|
|
}
|
|
}
|
|
v.ChangeType = 1
|
|
}
|
|
this.NexPower = this.curPower
|
|
if conf.Number == 2 { // 只有2类型扣除
|
|
if list, err := this.module.model.getEntertainmList(curPlayer.Userinfo.Uid); err == nil {
|
|
if _, ok := list.Skill[skillid]; ok {
|
|
list.Skill[skillid] -= 1
|
|
if list.Skill[skillid] < 0 {
|
|
list.Skill[skillid] = 0
|
|
}
|
|
this.module.model.modifyEntertainmList(curPlayer.Userinfo.Uid, map[string]interface{}{
|
|
"skill": list.Skill,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "operatorrst", &pb.EntertainOperatorRstPush{
|
|
Mpadata: szMap,
|
|
Power: this.NexPower,
|
|
Curpower: this.curPower,
|
|
Score: curScore,
|
|
Round: this.round,
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Itype: conf.Key,
|
|
Curid: oid1,
|
|
Targetid: oid2,
|
|
}, this.szSession...); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
return
|
|
}
|