package caravan import ( "go_dreamfactory/comm" "go_dreamfactory/lego/core" "go_dreamfactory/modules" "go_dreamfactory/pb" "go_dreamfactory/sys/configure" "math" ) type Caravan struct { modules.ModuleBase modelTroll *modelCaravan api *apiComp configure *configureComp } func NewModule() core.IModule { return &Caravan{} } func (this *Caravan) GetType() core.M_Modules { return comm.ModuleTroll } func (this *Caravan) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) { err = this.ModuleBase.Init(service, module, options) return } func (this *Caravan) OnInstallComp() { this.ModuleBase.OnInstallComp() this.api = this.RegisterComp(new(apiComp)).(*apiComp) this.modelTroll = this.RegisterComp(new(modelCaravan)).(*modelCaravan) this.configure = this.RegisterComp(new(configureComp)).(*configureComp) } // 接口信息 func (this *Caravan) ModifyTrollData(uid string, data map[string]interface{}) (code pb.ErrorCode) { err := this.modelTroll.modifyTrollDataByObjId(uid, data) if err != nil { code = pb.ErrorCode_DBError } return } func (this *Caravan) TrollAI(session comm.IUserSession, troll *pb.DBTrollTrain) (code pb.ErrorCode) { var ( sellPrice map[int32]int32 // 出售货物价格 totalGold int32 index int32 update map[string]interface{} rangeId int32 // 增幅ID tarinPos int32 // 火车位置 refreshTime int64 // 刷新时间 ) if troll.Buy == 0 && troll.Sell == 0 { return } update = make(map[string]interface{}) sellPrice = make(map[int32]int32) now := configure.Now().Unix() trainNum := this.configure.GetTrollMaxTraintNum() maxCoefficient := this.configure.GetTrollMaxCoefficientNux() // 增长幅度的最大值 if maxCoefficient == 0 { code = pb.ErrorCode_ConfigNoFound return } rangeId = troll.RangeId tarinPos = troll.TarinPos refreshTime = troll.RefreshTime goods := this.configure.GetTrollAllGoods() for _, v := range goods { sellPrice[v.Id] = v.Goodsprice } sz := this.configure.GetTrollAllTrain() if len(sz) == 0 { this.Errorf("GetTrollAllTrain configure err") // 配置异常 打个日志 return } iCount := this.configure.GetTrollRule(comm.TrollAIBuyCount) for index = 0; ; index++ { if index < tarinPos-1 { // 起始位置 continue } index := int32(index) % trainNum refreshTime += int64(sz[index]) if now >= refreshTime { rangeId = (rangeId % maxCoefficient) + 1 tarinPos = (tarinPos % trainNum) + 1 coefficient := this.configure.GetTrollCoefficient(rangeId) // 获取当前级别的涨幅数据 if coefficient == nil { return } if troll.Sell <= coefficient.Coefficient { // 可以出售 var preGold int32 // 成本价 for _, v := range goods { sellPrice[v.Id] = v.Goodsprice * coefficient.Coefficient / 1000 preGold += troll.Price[v.Id] * troll.Items[v.Id] } // 出售之前算成本 if len(troll.Items) > 0 { sellGold := this.SellAllItem(session.GetUserId(), troll, sellPrice, tarinPos) if sellGold != 0 { if code = this.ModuleUser.AddAttributeValue(session, comm.ResGold, sellGold, true); code != pb.ErrorCode_Success { this.Errorf("玩家 uid:%s 金币不足,获得金币%d", session.GetUserId(), sellGold) } // 一次交易完成做一次结算 } totalGold += sellGold // 计算本次出售赚的金币 if sellGold-preGold > 0 { troll.TotalEarn += int64(sellGold - preGold) } troll.AiCount++ aiMaxCount := this.configure.GetTrollRule(comm.TrollAIBuyCount) if troll.AiCount+troll.SellCount > aiMaxCount { //达到最大交易次数 break } } } else if troll.Buy >= coefficient.Coefficient { // 可以购买 for _, v := range goods { sellPrice[v.Id] = v.Goodsprice * coefficient.Coefficient / 1000 } troll.Shop = make(map[int32]int32) // 买之前清除购买上限 buyGold := this.BuyAllItem(session.GetUserId(), troll, sellPrice, tarinPos) if buyGold != 0 { if code = this.ModuleUser.AddAttributeValue(session, comm.ResGold, buyGold, true); code != pb.ErrorCode_Success { this.Errorf("玩家 uid:%s 金币不足,获得金币%d", session.GetUserId(), buyGold) } } totalGold += buyGold } } else { // 超过当前时间 refreshTime -= int64(sz[index]) break } if index > iCount*maxCoefficient { // ai挂机最大限制 break } } update["shop"] = troll.Shop update["items"] = troll.Items update["price"] = troll.Price update["aiCount"] = troll.AiCount update["gridNum"] = troll.GridNum update["totalEarn"] = troll.TotalEarn if confLv := this.configure.GetTrollLv(troll.GetNpcLv() + 1); confLv != nil { if troll.TotalEarn >= int64(confLv.Money) { troll.NpcLv += 1 // npc levelUp update["npcLv"] = troll.NpcLv } } this.ModifyTrollData(session.GetUserId(), update) return } // 出售所有货物 func (this *Caravan) SellAllItem(uid string, troll *pb.DBTrollTrain, price map[int32]int32, tarinPos int32) (gold int32) { for k, v := range troll.Items { if _, ok := price[k]; ok { gold += price[k] * v } delete(troll.Items, k) // 清除数据 } troll.Price = make(map[int32]int32, 0) // 原来的价格也清除 troll.GridNum = 0 // 清空格子 return } // 可以购买商品 func (this *Caravan) BuyAllItem(uid string, troll *pb.DBTrollTrain, price map[int32]int32, tarinPos int32) (gold int32) { var ( box map[int32]int32 // 盒子 存放可购买的物品 leftGirdNum int32 // 剩余可购买格子数量 costGold int32 buyBox map[int32]int32 // 盒子 存放可购买的物品 ) maxGirdNum := this.configure.GetTrollRule(comm.TrollGridCount) // 获取背包最大格子数量 maxgoods := this.configure.GetTrollRule(comm.TrollItemCount) // 获取单个物品最大上限 20个 leftGirdNum = maxGirdNum - troll.GridNum box = make(map[int32]int32, 0) buyBox = make(map[int32]int32, 0) goods := this.configure.GetTrollAllGoods() for _, v := range goods { for { if leftGirdNum > 0 && troll.Shop[v.Id] < v.Max { leftGirdNum-- troll.Shop[v.Id] += maxgoods box[v.Id] += maxgoods // 加入篮子 } else { break } } // 检查该位置的格子没有补满 full := (troll.Items[v.Id] + box[v.Id]) % maxgoods if full != 0 { box[v.Id] += (maxgoods - full) // 格子补满 } } // 通过金币来校验哪些物品可以买 curGold := this.ModuleUser.QueryAttributeValue(uid, comm.ResGold) for k, v := range box { for i := 0; i < int(v); i++ { //0 1 2 3 curGold -= int64(price[k]) costGold -= price[k] if curGold < 0 { box[k] = int32(i) costGold += price[k] // 返还之前扣的 break } buyBox[k]++ } } if len(buyBox) == 0 { return // 没有可购买的直接返回 } for _, v := range goods { // 计算购买后的平均价格 g := troll.Items[v.Id] * troll.Price[v.Id] g += buyBox[v.Id] * price[v.Id] troll.Items[v.Id] += buyBox[v.Id] if troll.Items[v.Id] != 0 { troll.Price[v.Id] = g / troll.Items[v.Id] } } gold = costGold // 统计格子 troll.GridNum = 0 for _, v := range troll.Items { if v > 0 { troll.GridNum += int32(math.Ceil(float64(v) / float64(maxgoods))) } } return } func (this *Caravan) QueryRankList() (ranks []string, gold []int64, err error) { var ( result []string ) tableName := "trollRank" if result, err = this.modelTroll.Redis.ZRevRange(tableName, 0, comm.MaxRankList).Result(); err != nil { this.Errorln(err) return } ranks = make([]string, 0) for i := 0; i < len(result); i++ { if _d, err := this.modelTroll.Redis.ZScore(tableName, result[i]); err == nil { gold = append(gold, int64(_d)) ranks = append(ranks, result[i]) } } return }