405 lines
12 KiB
Go
405 lines
12 KiB
Go
package game
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"server/conf"
|
|
mergeDataCfg "server/conf/merge_data"
|
|
orderCfg "server/conf/order"
|
|
"server/game/mod/item"
|
|
limitedTimeEvent "server/game/mod/limited_time_event"
|
|
"server/game/mod/order"
|
|
"server/game/mod/quest"
|
|
GoUtil "server/game_util"
|
|
"server/msg"
|
|
"sort"
|
|
|
|
"gitea.bywaystudios.com/pet_home/leaf/log"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
type PlayerChessData struct {
|
|
Data msg.ResPlayerChessData
|
|
ColorData msg.ResChessColorData
|
|
}
|
|
|
|
func (p *PlayerChessData) LoadDataFromDB(dwUin interface{}) bool {
|
|
return true
|
|
}
|
|
|
|
func (p *PlayerChessData) Reconnect(b bool) {}
|
|
|
|
func (p *PlayerChessData) SaveDataFromDB(key interface{}) bool {
|
|
return true
|
|
}
|
|
|
|
func (p *PlayerChessData) ResPlayerChessData(player *Player) {
|
|
agent := player.GetAgentByPlayer()
|
|
res := &p.Data
|
|
ChessMod := player.PlayMod.getChessMod()
|
|
res.ChessList = ChessMod.BackData().ChessList
|
|
res.MChessData = ChessMod.ChessMap
|
|
data, _ := proto.Marshal(res)
|
|
G_getGameLogic().PackResInfo(agent, "ResPlayerChessData", data)
|
|
}
|
|
|
|
func (p *PlayerChessData) ResChessColorData(player *Player) {
|
|
agent := player.GetAgentByPlayer()
|
|
data, _ := proto.Marshal(&p.ColorData)
|
|
G_getGameLogic().PackResInfo(agent, "ResChessColorData", data)
|
|
}
|
|
|
|
// 同步棋盘数据
|
|
func (p *PlayerChessData) UpdatePlayerChessData(player *Player, req *msg.UpdatePlayerChessData) error {
|
|
update := req
|
|
lastMap := player.PlayMod.getChessMod().ChessMap
|
|
addChessList, addNewEmit, err := p.HandleChess(player, update.MChessHandle)
|
|
if err != nil {
|
|
res := &msg.ResUpdatePlayerChessData{
|
|
Code: msg.RES_CODE_FAIL,
|
|
Msg: err.Error(),
|
|
}
|
|
handleStr := ""
|
|
sort.Slice(update.MChessHandle, func(i, j int) bool {
|
|
return update.MChessHandle[i].Id < update.MChessHandle[j].Id
|
|
})
|
|
for _, v := range update.MChessHandle {
|
|
handleStr += fmt.Sprintf("%v-%v-%v,", v.Id, v.ChessId, v.Type)
|
|
}
|
|
log.Debug("棋子操作队列错误, %v===%v===%v===%v", handleStr, lastMap, update.MChessData, player.PlayMod.getChessMod().GetChessList())
|
|
player.SendErrClienRes(res)
|
|
return err
|
|
}
|
|
player.PushClientRes(&msg.ResUpdatePlayerChessData{
|
|
Code: msg.RES_CODE_SUCCESS,
|
|
})
|
|
p.Data.MChessData = update.MChessData
|
|
if !p.checkChessEqual(player) {
|
|
res := &msg.ResUpdatePlayerChessData{
|
|
Code: msg.RES_CODE_FAIL,
|
|
Msg: "棋子数据不一致",
|
|
}
|
|
handleStr := ""
|
|
sort.Slice(update.MChessHandle, func(i, j int) bool {
|
|
return update.MChessHandle[i].Id < update.MChessHandle[j].Id
|
|
})
|
|
for _, v := range update.MChessHandle {
|
|
handleStr += fmt.Sprintf("%v-%v-%v,", v.Id, v.ChessId, v.Type)
|
|
}
|
|
log.Debug("棋子数据不一致地图, %v===%v===%v===%v", handleStr, lastMap, update.MChessData, player.PlayMod.getChessMod().GetChessList())
|
|
player.SendErrClienRes(res)
|
|
player.TeLog("outsync_event", map[string]interface{}{
|
|
"outsync_event": "UpdatePlayerChessDataFunc",
|
|
})
|
|
return fmt.Errorf("棋子数据不一致")
|
|
}
|
|
ChessMod := player.PlayMod.getChessMod()
|
|
BaseMod := player.PlayMod.getBaseMod()
|
|
OrderMod := player.PlayMod.getOrderMod()
|
|
ChessMod.ChessMap = update.MChessData
|
|
Update := OrderMod.CreateExtraOrder(addChessList, addNewEmit, ChessMod.GetUnlockChessList(), BaseMod.GetEnergyMul(), BaseMod.GetLevel())
|
|
if Update {
|
|
player.InitOrderItem()
|
|
player.PushClientRes(OrderMod.BackData())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *PlayerChessData) UpdateChessData(player *Player, mChessData map[string]int32) error {
|
|
p.Data.MChessData = mChessData
|
|
if !p.checkChessEqual(player) {
|
|
res := &msg.ResUpdatePlayerChessData{
|
|
Code: msg.RES_CODE_FAIL,
|
|
Msg: "棋子数据不一致",
|
|
}
|
|
log.Debug("棋子数据不一致地图, %v---%v---%v", player.PlayMod.getChessMod().ChessMap, p.Data.MChessData, player.PlayMod.getChessMod().GetChessList())
|
|
player.SendErrClienRes(res)
|
|
player.TeLog("outsync_event", map[string]interface{}{
|
|
"outsync_event": "UpdatePlayerChessDataFunc",
|
|
})
|
|
return fmt.Errorf("棋子数据不一致")
|
|
}
|
|
player.PlayMod.getChessMod().ChessMap = mChessData
|
|
return nil
|
|
}
|
|
|
|
// 检查棋子数据是否一致
|
|
func (p *PlayerChessData) checkChessEqual(player *Player) bool {
|
|
if len(p.Data.MChessData) == 0 && conf.Server.GameName == "Merge_Pet_Local" {
|
|
return true
|
|
}
|
|
chessList := player.PlayMod.getChessMod().GetChessList()
|
|
if len(chessList) != len(p.Data.MChessData) {
|
|
return false
|
|
}
|
|
aCopy := make([]int, 0, len(chessList))
|
|
bCopy := make([]int, 0, len(p.Data.MChessData))
|
|
for _, v := range chessList {
|
|
aCopy = append(aCopy, int(v))
|
|
}
|
|
for _, v := range p.Data.MChessData {
|
|
bCopy = append(bCopy, int(v))
|
|
}
|
|
if SlicesEqual(aCopy, bCopy) {
|
|
return true
|
|
}
|
|
// 找出aCopy多的元素和少的元素
|
|
aMap := make(map[int]int)
|
|
bMap := make(map[int]int)
|
|
|
|
for _, v := range aCopy {
|
|
aMap[v]++
|
|
}
|
|
for _, v := range bCopy {
|
|
bMap[v]++
|
|
}
|
|
|
|
var extra []int
|
|
var missing []int
|
|
|
|
// 找出aCopy多的元素
|
|
for k, v := range aMap {
|
|
if bMap[k] < v {
|
|
for i := 0; i < v-bMap[k]; i++ {
|
|
extra = append(extra, k)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 找出aCopy少的元素
|
|
for k, v := range bMap {
|
|
if aMap[k] < v {
|
|
for i := 0; i < v-aMap[k]; i++ {
|
|
missing = append(missing, k)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(extra) > 0 || len(missing) > 0 {
|
|
log.Debug("棋子数据对比: aCopy多的元素=%v, aCopy少的元素=%v", extra, missing)
|
|
}
|
|
return false
|
|
}
|
|
|
|
// 棋子操作
|
|
func (p *PlayerChessData) HandleChess(player *Player, handle_list []*msg.ChessHandle) ([]int, []int, error) {
|
|
sort.Slice(handle_list, func(i, j int) bool {
|
|
return handle_list[i].Id < handle_list[j].Id
|
|
})
|
|
ChessMod := player.PlayMod.getChessMod()
|
|
BaseMod := player.PlayMod.getBaseMod()
|
|
HandbookMod := player.PlayMod.getHandbookMod()
|
|
var addChessCostEnergy int
|
|
var buyChess int
|
|
limitPush := false // 限时事件推送
|
|
var TriggerList []*quest.Trigger
|
|
var itemList []*item.Item
|
|
var addChessList []int
|
|
var addNewEmit []int
|
|
emitList := ChessMod.GetEmitList()
|
|
for _, v := range handle_list {
|
|
chessId := int(v.ChessId)
|
|
emitId := int(v.Emit)
|
|
switch v.Type {
|
|
case msg.HANDLE_TYPE_ADD: //增加棋子
|
|
err := ChessMod.AddChess(chessId)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
chessType := mergeDataCfg.GetTypeById(chessId)
|
|
addChessList = append(addChessList, chessId)
|
|
if !GoUtil.InArray(emitId, []int{561, 562, 563, 564, 701, 702, 703, 704, 705, 706, 0}) && chessType != "Resource" { // 宝箱生成的棋子不扣体力
|
|
addChessCostEnergy++
|
|
}
|
|
|
|
b := HandbookMod.SetHandbook(chessId) // 添加图鉴
|
|
if b {
|
|
player.TeLog("collection_add", map[string]interface{}{
|
|
"item_id": chessId,
|
|
"item_name": mergeDataCfg.GetNameById(chessId),
|
|
})
|
|
addNewEmit = append(addNewEmit, chessId)
|
|
}
|
|
player.PushClientRes(HandbookMod.BackData())
|
|
case msg.HANDLE_TYPE_COMPOSE: //合成棋子
|
|
newChessId, err := ChessMod.ComposeChess(chessId)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b := HandbookMod.SetHandbook(newChessId) // 添加图鉴
|
|
if b {
|
|
addNewEmit = append(addNewEmit, newChessId)
|
|
}
|
|
addChessList = append(addChessList, newChessId)
|
|
newChessIdLv := mergeDataCfg.GetLvById(newChessId)
|
|
TriggerList = append(TriggerList, &quest.Trigger{Label: quest.TRIGGER_LABEL_MERGELVTIME, A: []interface{}{newChessIdLv}})
|
|
TriggerList = append(TriggerList, &quest.Trigger{Label: quest.TRIGGER_LABEL_MERGETIME})
|
|
player.PushClientRes(HandbookMod.BackData())
|
|
triggerComposeChess(player, newChessId, player.PlayMod.getBaseMod().EnergyMul, player.PlayMod.getChessMod().GetEmitList())
|
|
// 获取活动道具
|
|
ActItem := player.GetActivityItem(GoUtil.Int32ToInt(v.ActType))
|
|
itemList = item.Merge(itemList, ActItem)
|
|
case msg.HANDLE_TYPE_BUY: //购买棋子
|
|
loseGold, err := ChessMod.BuyChess(chessId)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
addChessList = append(addChessList, chessId)
|
|
buyChess += loseGold
|
|
itemList = append(itemList, &item.Item{Id: item.ITEM_STAR_ID, Num: int(-loseGold)})
|
|
case msg.HANDLE_TYPE_SELL: //出售棋子
|
|
items, err := ChessMod.SellChess(chessId)
|
|
if checkChess(chessId, BaseMod.GetEnergyMul(), ChessMod.GetEmitList()) { // 在订单中无法生成的棋子 出售获得原价宠物币
|
|
items = []*item.Item{{Id: item.ITEM_STAR_ID, Num: mergeDataCfg.GetStarById(chessId)}}
|
|
}
|
|
LimitedTimeEventMod := player.PlayMod.getLimitedTimeEventMod()
|
|
chessType := mergeDataCfg.GetTypeById(chessId)
|
|
if LimitedTimeEventMod.CheckExist(limitedTimeEvent.EVENT_TYPE_PAYBACK_DAY) && chessType == "Product" { // 限时活动 返利日
|
|
err = LimitedTimeEventMod.SubPaybackDay()
|
|
if err == nil {
|
|
items = []*item.Item{{Id: item.ITEM_STAR_ID, Num: mergeDataCfg.GetStarById(chessId)}}
|
|
}
|
|
limitPush = true
|
|
}
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
get_star_num := 0
|
|
if len(items) > 0 && items[0].Id == item.ITEM_STAR_ID {
|
|
get_star_num = items[0].Num
|
|
}
|
|
player.TeLog("sell_item", map[string]interface{}{
|
|
"merge_item_id": chessId,
|
|
"product_name": mergeDataCfg.GetNameById(chessId),
|
|
"get_star_num": get_star_num,
|
|
})
|
|
itemList = item.Merge(itemList, items)
|
|
// 获取活动道具
|
|
ActItem := player.GetActivityItem(GoUtil.Int32ToInt(v.ActType))
|
|
itemList = item.Merge(itemList, ActItem)
|
|
case msg.HANDLE_TYPE_REMOVE: //移除棋子
|
|
ChessMod.RemoveChess(chessId)
|
|
}
|
|
|
|
}
|
|
//扣除体力
|
|
energyPow := BaseMod.GetEnergyMul()
|
|
reduceEneny := 0
|
|
if addChessCostEnergy > 0 {
|
|
reduceEneny = int(math.Pow(2, float64(energyPow))) * addChessCostEnergy
|
|
itemList = append(itemList, &item.Item{Id: item.ITEM_ENERGY_ID, Num: -reduceEneny})
|
|
}
|
|
err := player.HandleItem(itemList, msg.ITEM_POP_LABEL_HandleChess.String())
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
newEmitList := ChessMod.GetEmitList()
|
|
var emitProductList []string
|
|
for _, v := range emitList {
|
|
ColorList := mergeDataCfg.GetEmitProduceType(v)
|
|
emitProductList = append(emitProductList, ColorList...)
|
|
}
|
|
var newEmitProductList []string
|
|
for _, v := range newEmitList {
|
|
ColorList := mergeDataCfg.GetEmitProduceType(v)
|
|
newEmitProductList = append(newEmitProductList, ColorList...)
|
|
}
|
|
OrderMod := player.PlayMod.getOrderMod()
|
|
if !GoUtil.SlicesEqualString(emitProductList, newEmitProductList) {
|
|
// 发射器系列变化,重新洗牌
|
|
OrderMod.ResetChessPool()
|
|
}
|
|
|
|
// 限时事件 小猫戏法
|
|
LimitedTimeEventMod := player.PlayMod.getLimitedTimeEventMod()
|
|
if LimitedTimeEventMod.CheckExist(limitedTimeEvent.EVENT_TYPE_CAT_TRICK) {
|
|
LimitedTimeEventMod.AddCatTrickEnergy(reduceEneny)
|
|
limitPush = true
|
|
}
|
|
if limitPush {
|
|
player.PushClientRes(LimitedTimeEventMod.BackData())
|
|
}
|
|
player.QuestTriggerList(TriggerList)
|
|
player.EmitRetireTrigger1()
|
|
player.InitOrderItem()
|
|
player.PushClientRes(ChessMod.BackData())
|
|
player.PlayMod.save()
|
|
return addChessList, addNewEmit, nil
|
|
}
|
|
|
|
func (p *PlayerChessData) ClearData() bool {
|
|
return true
|
|
}
|
|
|
|
func checkChess(chessId, energyMul int, emit []int) bool {
|
|
if len(emit) == 0 {
|
|
return false
|
|
}
|
|
chessIdLv := mergeDataCfg.GetLvById(chessId)
|
|
chessIdType := mergeDataCfg.GetTypeById(chessId)
|
|
if chessIdType != "Product" {
|
|
return false
|
|
}
|
|
chessIdColor := mergeDataCfg.GetColorById(chessId)
|
|
if chessIdColor == "Star" || chessIdColor == "Energy" || chessIdColor == "Diamond" {
|
|
return false
|
|
}
|
|
emitId := 0
|
|
for _, v := range emit {
|
|
ProduceColor := mergeDataCfg.GetEmitProduceType(v)
|
|
if GoUtil.InStringArray(chessIdColor, ProduceColor) {
|
|
emitId = v
|
|
break
|
|
}
|
|
}
|
|
_, max := getChesslvRange(emitId, energyMul, false)
|
|
adjust := mergeDataCfg.GetAdjust(emitId, chessIdColor, energyMul)
|
|
return chessIdLv > max-adjust
|
|
}
|
|
func getChesslvRange(emit int, energyMul int, isCharge bool) (int, int) {
|
|
randEmitLv := mergeDataCfg.GetLvById(emit)
|
|
emitId := mergeDataCfg.GetEmitId(emit)
|
|
randMaxLv := mergeDataCfg.GetMaxLvById(emit)
|
|
randEmitMinLv := mergeDataCfg.GetEmitMinLvById(emitId)
|
|
ratio := mergeDataCfg.GetEmitRatio(emitId)
|
|
m := int(float64(1+randEmitLv-randEmitMinLv) / float64(1+randMaxLv-randEmitMinLv) / ratio * 100)
|
|
if isCharge {
|
|
m += 10
|
|
}
|
|
m = max(1, m)
|
|
m = min(100, m)
|
|
ChessMinLev := orderCfg.GetLvMin(energyMul)
|
|
ChessMaxLev := orderCfg.GetLvMax(energyMul, m)
|
|
return ChessMinLev, ChessMaxLev
|
|
}
|
|
|
|
func triggerComposeChess(player *Player, chessId, energyMul int, emit []int) {
|
|
OrderMod := player.PlayMod.getOrderMod()
|
|
if OrderMod.Step < 12 {
|
|
return
|
|
}
|
|
if !checkChess(chessId, energyMul, emit) {
|
|
return
|
|
}
|
|
ChessMod := player.PlayMod.getChessMod()
|
|
ChessList := ChessMod.GetUnlockChessList()
|
|
chessNum := 0
|
|
for _, v := range ChessList {
|
|
if v == chessId {
|
|
chessNum++
|
|
}
|
|
}
|
|
orderNum := 0
|
|
for _, v := range OrderMod.GetOrderList() {
|
|
if v.Type == order.Clean_Order_type && v.MergeId[0] == chessId {
|
|
orderNum++
|
|
}
|
|
}
|
|
if orderNum >= chessNum {
|
|
return
|
|
}
|
|
OrderMod.CreateCleanOrder2([]int{chessId})
|
|
player.PushClientRes(OrderMod.BackData())
|
|
}
|