1210 lines
38 KiB
Go
1210 lines
38 KiB
Go
package hero
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"errors"
|
|
"fmt"
|
|
"go_dreamfactory/comm"
|
|
"go_dreamfactory/lego/core"
|
|
"go_dreamfactory/lego/sys/log"
|
|
"go_dreamfactory/lego/sys/redis"
|
|
"go_dreamfactory/modules"
|
|
"go_dreamfactory/pb"
|
|
cfg "go_dreamfactory/sys/configure/structs"
|
|
"go_dreamfactory/sys/db"
|
|
"go_dreamfactory/utils"
|
|
"math"
|
|
"math/big"
|
|
"reflect"
|
|
"strconv"
|
|
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/x/bsonx"
|
|
)
|
|
|
|
type ModelHero struct {
|
|
modules.MCompModel
|
|
module *Hero
|
|
}
|
|
|
|
func (this *ModelHero) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) {
|
|
this.TableName = comm.TableHero
|
|
err = this.MCompModel.Init(service, module, comp, options)
|
|
this.module = module.(*Hero)
|
|
// 通过uid创建索引
|
|
this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{
|
|
Keys: bsonx.Doc{{Key: "uid", Value: bsonx.Int32(1)}},
|
|
})
|
|
return
|
|
}
|
|
func (p *ModelHero) cloneTags(tags map[int32]int32) map[int32]int32 {
|
|
cloneTags := make(map[int32]int32)
|
|
for k, v := range tags {
|
|
cloneTags[k] = v
|
|
}
|
|
return cloneTags
|
|
}
|
|
|
|
// 计算英雄战力
|
|
func (this *ModelHero) calFigthValue(hero *pb.DBHero) (addValue int32, err error) {
|
|
var (
|
|
skillValue int32 // 技能战力
|
|
baseValue int32 // 基础战力
|
|
heroCfg *cfg.GameHeroData //英雄配置
|
|
tmpHero *pb.DBHero
|
|
preValue int32
|
|
skillpos *cfg.GameFightingSkilllvData
|
|
skilllv *cfg.GameFightingSkilllvData
|
|
skillStar *cfg.GameFightingSkillStarData
|
|
)
|
|
tmpHero = new(pb.DBHero)
|
|
*tmpHero = *hero // 克隆一个对象
|
|
tmpHero.Property = this.cloneTags(hero.Property)
|
|
tmpHero.AddProperty = this.cloneTags(hero.AddProperty)
|
|
tmpHero.JuexProperty = this.cloneTags(hero.JuexProperty)
|
|
tmpHero.HoroscopeProperty = this.cloneTags(hero.HoroscopeProperty)
|
|
tmpHero.TalentProperty = this.cloneTags(hero.TalentProperty)
|
|
preValue = hero.Fightvalue
|
|
if heroCfg, err = this.module.configure.GetHeroConfig(tmpHero.HeroID); err != nil {
|
|
return
|
|
}
|
|
|
|
for k, v := range tmpHero.Property {
|
|
switch k {
|
|
case cfg.GamePropertyType_Base_MaxHp_Per:
|
|
tmpHero.Property[cfg.GamePropertyType_Base_MaxHp_Per] = 0
|
|
tmpHero.Property[cfg.GamePropertyType_Base_MaxHp_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_MaxHp_Base])))
|
|
case cfg.GamePropertyType_Base_Atk_Per:
|
|
tmpHero.Property[cfg.GamePropertyType_Base_Atk_Per] = 0
|
|
tmpHero.Property[cfg.GamePropertyType_Base_Atk_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Atk_Base])))
|
|
case cfg.GamePropertyType_Base_Def_Per:
|
|
tmpHero.Property[cfg.GamePropertyType_Base_Def_Per] = 0
|
|
tmpHero.Property[cfg.GamePropertyType_Base_Def_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Def_Base])))
|
|
case cfg.GamePropertyType_Base_Speed_Per:
|
|
tmpHero.Property[cfg.GamePropertyType_Base_Speed_Per] = 0
|
|
tmpHero.Property[cfg.GamePropertyType_Base_Speed_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Speed_Base])))
|
|
}
|
|
}
|
|
|
|
for k, v := range tmpHero.AddProperty {
|
|
switch k {
|
|
case cfg.GamePropertyType_Base_MaxHp_Per:
|
|
tmpHero.AddProperty[cfg.GamePropertyType_Base_MaxHp_Per] = 0
|
|
tmpHero.AddProperty[cfg.GamePropertyType_Base_MaxHp_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_MaxHp_Base])))
|
|
case cfg.GamePropertyType_Base_Atk_Per:
|
|
tmpHero.AddProperty[cfg.GamePropertyType_Base_Atk_Per] = 0
|
|
tmpHero.AddProperty[cfg.GamePropertyType_Base_Atk_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Atk_Base])))
|
|
case cfg.GamePropertyType_Base_Def_Per:
|
|
tmpHero.AddProperty[cfg.GamePropertyType_Base_Def_Per] = 0
|
|
tmpHero.AddProperty[cfg.GamePropertyType_Base_Def_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Def_Base])))
|
|
case cfg.GamePropertyType_Base_Speed_Per:
|
|
tmpHero.AddProperty[cfg.GamePropertyType_Base_Speed_Per] = 0
|
|
tmpHero.AddProperty[cfg.GamePropertyType_Base_Speed_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Speed_Base])))
|
|
}
|
|
}
|
|
|
|
for k, v := range tmpHero.JuexProperty {
|
|
switch k {
|
|
case cfg.GamePropertyType_Base_MaxHp_Per:
|
|
tmpHero.JuexProperty[cfg.GamePropertyType_Base_MaxHp_Per] = 0
|
|
tmpHero.JuexProperty[cfg.GamePropertyType_Base_MaxHp_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_MaxHp_Base])))
|
|
case cfg.GamePropertyType_Base_Atk_Per:
|
|
tmpHero.JuexProperty[cfg.GamePropertyType_Base_Atk_Per] = 0
|
|
tmpHero.JuexProperty[cfg.GamePropertyType_Base_Atk_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Atk_Base])))
|
|
case cfg.GamePropertyType_Base_Def_Per:
|
|
tmpHero.JuexProperty[cfg.GamePropertyType_Base_Def_Per] = 0
|
|
tmpHero.JuexProperty[cfg.GamePropertyType_Base_Def_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Def_Base])))
|
|
case cfg.GamePropertyType_Base_Speed_Per:
|
|
tmpHero.JuexProperty[cfg.GamePropertyType_Base_Speed_Per] = 0
|
|
tmpHero.JuexProperty[cfg.GamePropertyType_Base_Speed_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Speed_Base])))
|
|
}
|
|
}
|
|
|
|
for k, v := range tmpHero.HoroscopeProperty {
|
|
switch k {
|
|
case cfg.GamePropertyType_Base_MaxHp_Per:
|
|
tmpHero.HoroscopeProperty[cfg.GamePropertyType_Base_MaxHp_Per] = 0
|
|
tmpHero.HoroscopeProperty[cfg.GamePropertyType_Base_MaxHp_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_MaxHp_Base])))
|
|
case cfg.GamePropertyType_Base_Atk_Per:
|
|
tmpHero.HoroscopeProperty[cfg.GamePropertyType_Base_Atk_Per] = 0
|
|
tmpHero.HoroscopeProperty[cfg.GamePropertyType_Base_Atk_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Atk_Base])))
|
|
case cfg.GamePropertyType_Base_Def_Per:
|
|
tmpHero.HoroscopeProperty[cfg.GamePropertyType_Base_Def_Per] = 0
|
|
tmpHero.HoroscopeProperty[cfg.GamePropertyType_Base_Def_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Def_Base])))
|
|
case cfg.GamePropertyType_Base_Speed_Per:
|
|
tmpHero.HoroscopeProperty[cfg.GamePropertyType_Base_Speed_Per] = 0
|
|
tmpHero.HoroscopeProperty[cfg.GamePropertyType_Base_Speed_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Speed_Base])))
|
|
}
|
|
}
|
|
|
|
for k, v := range tmpHero.TalentProperty {
|
|
switch k {
|
|
case cfg.GamePropertyType_Base_MaxHp_Per:
|
|
tmpHero.TalentProperty[cfg.GamePropertyType_Base_MaxHp_Per] = 0
|
|
tmpHero.TalentProperty[cfg.GamePropertyType_Base_MaxHp_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_MaxHp_Base])))
|
|
case cfg.GamePropertyType_Base_Atk_Per:
|
|
tmpHero.TalentProperty[cfg.GamePropertyType_Base_Atk_Per] = 0
|
|
tmpHero.TalentProperty[cfg.GamePropertyType_Base_Atk_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Atk_Base])))
|
|
case cfg.GamePropertyType_Base_Def_Per:
|
|
tmpHero.TalentProperty[cfg.GamePropertyType_Base_Def_Per] = 0
|
|
tmpHero.TalentProperty[cfg.GamePropertyType_Base_Def_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Def_Base])))
|
|
case cfg.GamePropertyType_Base_Speed_Per:
|
|
tmpHero.TalentProperty[cfg.GamePropertyType_Base_Speed_Per] = 0
|
|
tmpHero.TalentProperty[cfg.GamePropertyType_Base_Speed_Base] += int32(math.Floor((float64(v) / 1000) * float64(tmpHero.Property[cfg.GamePropertyType_Base_Speed_Base])))
|
|
}
|
|
}
|
|
|
|
// 属性汇总
|
|
for k, v := range tmpHero.TalentProperty {
|
|
tmpHero.Property[k] += v
|
|
}
|
|
for k, v := range tmpHero.HoroscopeProperty {
|
|
tmpHero.Property[k] += v
|
|
}
|
|
for k, v := range tmpHero.JuexProperty {
|
|
tmpHero.Property[k] += v
|
|
}
|
|
for k, v := range tmpHero.AddProperty {
|
|
tmpHero.Property[k] += v
|
|
}
|
|
|
|
// 算基础属性
|
|
for k, v := range this.module.configure.GetGameFightingCapacityData() {
|
|
if _, ok := tmpHero.Property[k]; ok {
|
|
baseValue += tmpHero.Property[k] * v / 1000
|
|
}
|
|
}
|
|
|
|
for pos, v := range tmpHero.NormalSkill {
|
|
if skillpos, err = this.module.configure.GetGameFightingSkilllv(int32(pos + 1)); err == nil {
|
|
if skilllv, err = this.module.configure.GetGameFightingSkilllv(v.SkillLv); err == nil {
|
|
skillValue += skillpos.Value * skilllv.Value / 1000
|
|
} else {
|
|
return
|
|
}
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
|
|
// 乘以星级系数
|
|
if skillStar, err = this.module.configure.GetGameFightingSkillStar(heroCfg.Star); err == nil {
|
|
skillValue = skillValue * skillStar.Value / 1000
|
|
}
|
|
|
|
hero.Fightvalue = skillValue + baseValue
|
|
addValue = hero.Fightvalue - preValue
|
|
return
|
|
}
|
|
|
|
// 初始化英雄
|
|
func (this *ModelHero) InitHero(uid string, heroCfgId string) (newHero *pb.DBHero, err error) {
|
|
var (
|
|
heroCfg *cfg.GameHeroData
|
|
)
|
|
if heroCfg, err = this.module.configure.GetHeroConfig(heroCfgId); err != nil {
|
|
return
|
|
}
|
|
objId := primitive.NewObjectID().Hex()
|
|
newHero = &pb.DBHero{
|
|
Id: objId,
|
|
Uid: uid,
|
|
HeroID: heroCfg.Hid,
|
|
Star: heroCfg.Star, //初始星级
|
|
Lv: 1, //初始等级
|
|
Block: false, //未锁定
|
|
CardType: heroCfg.Type, //卡片类型
|
|
Skins: []int32{},
|
|
EquipID: make([]string, 8), //初始装备
|
|
AddProperty: make(map[int32]int32),
|
|
Property: make(map[int32]int32),
|
|
JuexProperty: make(map[int32]int32),
|
|
TalentProperty: make(map[int32]int32),
|
|
HoroscopeProperty: make(map[int32]int32),
|
|
Fetters: make(map[int32]int32),
|
|
ExclusiveProperty: make(map[int32]int32),
|
|
ExclusiveSkill: make([]*pb.SkillData, 0),
|
|
Lvreward: make(map[int32]bool),
|
|
Awakenreward: make(map[int32]bool),
|
|
}
|
|
this.initHeroSkill(newHero)
|
|
err = this.PropertyCompute(newHero)
|
|
|
|
return
|
|
}
|
|
|
|
// 初始化英雄技能
|
|
func (this *ModelHero) initHeroSkill(hero *pb.DBHero) []*pb.SkillData {
|
|
heroCfg, _ := this.module.configure.GetHeroConfig(hero.HeroID)
|
|
|
|
if heroCfg != nil {
|
|
if heroCfg.Skill != 0 {
|
|
hero.CaptainSkill = heroCfg.Skill
|
|
}
|
|
|
|
skills := []*pb.SkillData{}
|
|
if heroCfg.Skill1 != 0 {
|
|
skills = append(skills, &pb.SkillData{SkillID: heroCfg.Skill1, SkillLv: 1})
|
|
}
|
|
if heroCfg.Skill2 != 0 {
|
|
skills = append(skills, &pb.SkillData{SkillID: heroCfg.Skill2, SkillLv: 1})
|
|
}
|
|
if heroCfg.Skill3 != 0 {
|
|
skills = append(skills, &pb.SkillData{SkillID: heroCfg.Skill3, SkillLv: 1})
|
|
}
|
|
if heroCfg.Skill4 != 0 {
|
|
skills = append(skills, &pb.SkillData{SkillID: heroCfg.Skill4, SkillLv: 1})
|
|
}
|
|
if heroCfg.Skill5 != 0 {
|
|
skills = append(skills, &pb.SkillData{SkillID: heroCfg.Skill5, SkillLv: 1})
|
|
}
|
|
if heroCfg.Skill6 != 0 {
|
|
skills = append(skills, &pb.SkillData{SkillID: heroCfg.Skill6, SkillLv: 1})
|
|
}
|
|
hero.NormalSkill = skills
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// 创建一个指定的英雄
|
|
func (this *ModelHero) gmCreateSpecialHero(uid string, heroCfgId string) (hero *pb.DBHero, err error) {
|
|
list := this.getHeroList(uid)
|
|
for _, v := range list {
|
|
if v.HeroID == heroCfgId {
|
|
hero = v
|
|
return
|
|
}
|
|
}
|
|
hero, err = this.InitHero(uid, heroCfgId)
|
|
if err == nil {
|
|
if err = this.AddList(uid, hero.Id, hero); err != nil {
|
|
this.module.Errorf("%v", err)
|
|
return
|
|
}
|
|
this.module.moduleFetter.AddHeroFetterData(uid, heroCfgId)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 拷贝一个指针对象
|
|
func (this *ModelHero) copyPoint(m *pb.DBHero) *pb.DBHero {
|
|
vt := reflect.TypeOf(m).Elem()
|
|
newoby := reflect.New(vt)
|
|
newoby.Elem().Set(reflect.ValueOf(m).Elem())
|
|
return newoby.Interface().(*pb.DBHero)
|
|
}
|
|
|
|
// 克隆一个英雄
|
|
// 调用此方法前注意有使用map 切片等指针类型数据是 克隆完成后自行初始化这个指针对象
|
|
func (this *ModelHero) CloneNewHero(uid string, hero *pb.DBHero) (newHero *pb.DBHero) {
|
|
newHero = new(pb.DBHero)
|
|
*newHero = *hero //*this.copyPoint(hero)
|
|
newHero.Id = primitive.NewObjectID().Hex()
|
|
this.AddList(newHero.Uid, newHero.Id, newHero)
|
|
|
|
// 星座图属性计算
|
|
this.module.moduleHoroscope.ComputeHeroNumeric(uid, hero)
|
|
return
|
|
}
|
|
|
|
// 初始化可叠加的英雄
|
|
func (this *ModelHero) initHeroOverlying(uid string, heroCfgId string, count int32) (hero *pb.DBHero, err error) {
|
|
var (
|
|
model *db.DBModel
|
|
)
|
|
hero, err = this.InitHero(uid, heroCfgId)
|
|
if err == nil {
|
|
if this.module.IsCross() {
|
|
if model, err = this.module.GetDBModelByUid(uid, this.TableName); err != nil {
|
|
this.module.Errorln(err)
|
|
} else {
|
|
if err = model.AddList(uid, hero.Id, hero); err != nil {
|
|
this.module.Errorf("err:%v", err)
|
|
}
|
|
}
|
|
} else {
|
|
if err = this.AddList(uid, hero.Id, hero); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 获取一个英雄(参数唯一objID)
|
|
func (this *ModelHero) getOneHero(uid, heroId string) *pb.DBHero {
|
|
var (
|
|
err error
|
|
model *db.DBModel
|
|
)
|
|
hero := &pb.DBHero{}
|
|
if this.module.IsCross() {
|
|
if model, err = this.module.GetDBModelByUid(uid, this.TableName); err != nil {
|
|
this.module.Errorln(err)
|
|
} else {
|
|
if err = model.GetListObj(uid, heroId, hero); err != nil {
|
|
this.module.Errorf("err:%v", err)
|
|
}
|
|
}
|
|
} else {
|
|
if err = this.GetListObj(uid, heroId, hero); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
}
|
|
return hero
|
|
}
|
|
|
|
// 获取一个英雄(参数唯一objID)
|
|
func (this *ModelHero) getHeros(uid string, heroIds []string) (heros []*pb.DBHero, err error) {
|
|
heros = make([]*pb.DBHero, 0)
|
|
if err = this.GetListObjs(uid, heroIds, &heros); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// 消耗英雄卡
|
|
func (this *ModelHero) consumeHeroCard(uid string, hero *pb.DBHero) (err error) {
|
|
|
|
if hero == nil {
|
|
err = errors.New("hero no exist")
|
|
return
|
|
}
|
|
|
|
if err := this.DelListlds(uid, []string{hero.Id}); err != nil {
|
|
this.module.Errorf("%v", err)
|
|
}
|
|
this.module.Debugf("删除卡牌uid:%s,卡牌ID:%s", uid, hero.Id)
|
|
return
|
|
}
|
|
|
|
// 获取玩家的英雄列表
|
|
func (this *ModelHero) getHeroList(uid string) []*pb.DBHero {
|
|
var (
|
|
err error
|
|
model *db.DBModel
|
|
heroes []*pb.DBHero
|
|
)
|
|
if this.module.IsCross() {
|
|
if model, err = this.module.GetDBModelByUid(uid, this.TableName); err != nil {
|
|
this.module.Errorln(err)
|
|
} else {
|
|
if err = model.GetList(uid, &heroes); err != nil {
|
|
this.module.Errorf("err:%v", err)
|
|
}
|
|
}
|
|
} else {
|
|
if err := this.GetList(uid, &heroes); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
}
|
|
return heroes
|
|
}
|
|
|
|
// 重置觉醒属性
|
|
func (this *ModelHero) resetJuexingProperty(hero *pb.DBHero) (err error) {
|
|
var (
|
|
awakenData *cfg.GameHeroAwakenData
|
|
)
|
|
hero.JuexProperty = make(map[int32]int32)
|
|
for i := 1; i <= int(hero.JuexingLv); i++ {
|
|
if awakenData, err = this.module.configure.GetHeroAwakenConfig(hero.HeroID, int32(i)); err == nil {
|
|
for _, v := range awakenData.Phasebonus {
|
|
hero.JuexProperty[v.A] += int32(v.N)
|
|
}
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 设置装备属性
|
|
func (this *ModelHero) setEquipProperty(hero *pb.DBHero, equip []*pb.DB_Equipment) {
|
|
|
|
addProperty := make(map[int32]int32) //副属性
|
|
equipSkill := make([]*pb.SkillData, 0)
|
|
for i, v := range equip {
|
|
if v == nil {
|
|
continue
|
|
}
|
|
hero.EquipID[i] = v.Id
|
|
addProperty[v.MainEntry.AttrName] += v.MainEntry.Value //主属性
|
|
if v.Inscribe == hero.Id { //铭刻生效
|
|
addProperty[v.MainEntry.AttrName] += v.Inscribevalue
|
|
}
|
|
for _, v := range v.AdverbEntry {
|
|
addProperty[v.AttrName] += v.Value + v.EnchValue //附加属性
|
|
}
|
|
if v.Adverbskill != nil {
|
|
for _, v := range v.Adverbskill {
|
|
equipSkill = append(equipSkill, &pb.SkillData{
|
|
SkillID: v.SkillId,
|
|
SkillLv: v.Lv,
|
|
})
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
for _, v := range hero.Suits {
|
|
if v.Effect {
|
|
if configure, err := this.module.configure.GetEquipsuit(v.Suitid); err != nil {
|
|
this.module.Errorln(err)
|
|
} else {
|
|
for _, v := range configure.SetBonuses {
|
|
addProperty[v.A] += v.N
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
this.mergeAddProperty(hero.Uid, hero, addProperty, equipSkill)
|
|
}
|
|
|
|
// 设置装备属性
|
|
func (this *ModelHero) setExclusiveProperty(hero *pb.DBHero, exw *pb.DB_Exclusive) {
|
|
|
|
addProperty := make(map[int32]int32) //副属性
|
|
equipSkill := make([]*pb.SkillData, 0)
|
|
hero.Exclusiveid = exw.Id
|
|
|
|
for k, v := range exw.Property {
|
|
addProperty[k] = v //附加属性
|
|
}
|
|
hero.ExclusiveProperty = addProperty
|
|
if exw.Commonskill != 0 {
|
|
equipSkill = append(equipSkill, &pb.SkillData{
|
|
SkillID: exw.Commonskill,
|
|
SkillLv: 1,
|
|
})
|
|
}
|
|
if exw.Exclusiveskill != 0 {
|
|
equipSkill = append(equipSkill, &pb.SkillData{
|
|
SkillID: exw.Exclusiveskill,
|
|
SkillLv: 1,
|
|
})
|
|
}
|
|
hero.ExclusiveSkill = equipSkill
|
|
this.calFigthValue(hero)
|
|
if err := this.ChangeList(hero.Uid, hero.Id, map[string]interface{}{
|
|
"exclusiveid": hero.Exclusiveid,
|
|
"exclusiveProperty": hero.ExclusiveProperty,
|
|
"exclusiveSkill": hero.ExclusiveSkill,
|
|
}); err != nil {
|
|
this.module.Errorf("mergeAddProperty err %v", err)
|
|
}
|
|
}
|
|
|
|
// 设置装备
|
|
func (this *ModelHero) setEquipment(uid string, hero *pb.DBHero) (newHero *pb.DBHero, err error) {
|
|
if len(hero.EquipID) == 0 {
|
|
return
|
|
}
|
|
|
|
update := make(map[string]interface{})
|
|
update["suits"] = hero.Suits
|
|
update["equipID"] = hero.EquipID
|
|
if err = this.ChangeList(hero.Uid, hero.Id, update); err != nil {
|
|
this.module.Errorf("%v", err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// 合并附加属性
|
|
func (this *ModelHero) mergeAddProperty(uid string, hero *pb.DBHero, data map[int32]int32, skills []*pb.SkillData) {
|
|
hero.AddProperty = data
|
|
|
|
this.calFigthValue(hero)
|
|
if err := this.ChangeList(uid, hero.Id, map[string]interface{}{
|
|
"addProperty": data,
|
|
"equipSkill": skills,
|
|
"fightvalue": hero.Fightvalue,
|
|
"suits": hero.Suits,
|
|
"equipID": hero.EquipID,
|
|
}); err != nil {
|
|
this.module.Errorf("mergeAddProperty err %v", err)
|
|
}
|
|
}
|
|
|
|
func (this *ModelHero) StarAtkAddition(star int32) (addValue float32, err error) {
|
|
var (
|
|
starCfg *cfg.GameHeroStargrowData
|
|
cfg *cfg.GameHeroLevelupData
|
|
)
|
|
for i := 1; i <= int(star); i++ {
|
|
if starCfg, err = this.module.configure.GetHeroStar(int32(i)); err == nil {
|
|
if cfg, err = this.module.configure.GetHeroLv(starCfg.Level); err == nil {
|
|
addValue += cfg.Atk * starCfg.StarupAtk / 1000.0
|
|
} else {
|
|
return
|
|
}
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *ModelHero) StarDefAddition(star int32) (addValue float32, err error) {
|
|
var (
|
|
starCfg *cfg.GameHeroStargrowData
|
|
cfg *cfg.GameHeroLevelupData
|
|
)
|
|
for i := 1; i <= int(star); i++ {
|
|
if starCfg, err = this.module.configure.GetHeroStar(int32(i)); err == nil {
|
|
if cfg, err = this.module.configure.GetHeroLv(starCfg.Level); err == nil {
|
|
addValue += cfg.Def * starCfg.StarupDef / 1000.0
|
|
} else {
|
|
return
|
|
}
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *ModelHero) StarHpAddition(star int32) (addValue float32, err error) {
|
|
var (
|
|
starCfg *cfg.GameHeroStargrowData
|
|
cfg *cfg.GameHeroLevelupData
|
|
)
|
|
for i := 1; i <= int(star); i++ {
|
|
if starCfg, err = this.module.configure.GetHeroStar(int32(i)); err == nil {
|
|
if cfg, err = this.module.configure.GetHeroLv(starCfg.Level); err == nil {
|
|
addValue += cfg.Hp * starCfg.StarupHp / 1000.0
|
|
} else {
|
|
return
|
|
}
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 属性计算 基础属性
|
|
// 英雄基础属性 + 英雄等级基础属性 * 英雄成长系数 + 英雄星级对应等级属性 * 英雄品质系数
|
|
func (this *ModelHero) PropertyCompute(hero *pb.DBHero) (err error) {
|
|
var (
|
|
growCfg *cfg.GameHeroLevelgrowData
|
|
lvCfg *cfg.GameHeroLevelupData
|
|
atk float32
|
|
def float32
|
|
hp float32
|
|
)
|
|
growCfg, err = this.module.configure.GetHeroLvgrow(hero.HeroID)
|
|
if err != nil {
|
|
this.module.Debugf("hero propertyCompute Configure Info err:heroid :%s, herolv:=%d,heroStar:%d,", hero.HeroID, hero.Lv, hero.Star)
|
|
return
|
|
}
|
|
lvCfg, err = this.module.configure.GetHeroLv(hero.Lv)
|
|
if err != nil {
|
|
this.module.Debugf("hero propertyCompute Configure Info err:heroid :%s, herolv:=%d,heroStar:%d,", hero.HeroID, hero.Lv, hero.Star)
|
|
return
|
|
}
|
|
atk, err = this.StarAtkAddition(hero.Star)
|
|
if err != nil {
|
|
return
|
|
}
|
|
def, err = this.StarDefAddition(hero.Star)
|
|
if err != nil {
|
|
return
|
|
}
|
|
hp, err = this.StarHpAddition(hero.Star)
|
|
if err != nil {
|
|
return
|
|
}
|
|
atk = (atk + lvCfg.Atk + float32(growCfg.Atk)) * (growCfg.Atkgrow / 1000.0)
|
|
def = (def + lvCfg.Def + float32(growCfg.Def)) * (growCfg.Defgrow / 1000.0)
|
|
hp = (hp + lvCfg.Hp + float32(growCfg.Hp)) * (growCfg.Hpgrow / 1000.0)
|
|
speed := growCfg.Speed
|
|
hero.Property = map[int32]int32{
|
|
cfg.GamePropertyType_Base_MaxHp_Base: int32(math.Floor(float64(hp))),
|
|
cfg.GamePropertyType_Base_Atk_Base: int32(math.Floor(float64(atk))),
|
|
cfg.GamePropertyType_Base_Def_Base: int32(math.Floor(float64(def))),
|
|
cfg.GamePropertyType_Base_Speed_Base: int32(math.Floor(float64(speed))),
|
|
cfg.GamePropertyType_Base_Crit_Base: int32(growCfg.Cri), //暴击
|
|
cfg.GamePropertyType_Base_CritDam_Base: int32(growCfg.Cridam), //暴击伤害
|
|
cfg.GamePropertyType_Base_EffectHit_Base: int32(growCfg.Effhit), //效果命中
|
|
cfg.GamePropertyType_Base_EffectResist_Base: int32(growCfg.Effre), //效果抵抗
|
|
cfg.GamePropertyType_LostHold: int32(growCfg.Losthold), //失手率%
|
|
cfg.GamePropertyType_UnderStand: int32(growCfg.Understand), //会心率%
|
|
cfg.GamePropertyType_DamRe: int32(growCfg.Damre), //伤害减免%
|
|
cfg.GamePropertyType_CauseDam: int32(growCfg.Causedam), //伤害提升%
|
|
cfg.GamePropertyType_TreAdd: int32(growCfg.Treadd), //治疗加成%
|
|
cfg.GamePropertyType_BeTreAdd: int32(growCfg.Betreadd), //受疗加成%
|
|
cfg.GamePropertyType_SuckBlood_Per: int32(growCfg.Suckblood), //吸血加成%
|
|
}
|
|
|
|
if hero.Id != "" { // objID 为空表示是怪物对象 不享受天赋属性加成
|
|
this.resetTalentProperty(hero)
|
|
this.module.moduleHoroscope.ComputeHeroNumeric(hero.Uid, hero)
|
|
}
|
|
err = this.resetJuexingProperty(hero)
|
|
if err != nil {
|
|
return
|
|
}
|
|
_, err = this.calFigthValue(hero)
|
|
return
|
|
}
|
|
|
|
func (this *ModelHero) cleanData(uid string) {
|
|
userList := this.module.GetHeroList(uid)
|
|
for _, v := range userList {
|
|
if err := this.DelListlds(uid, []string{v.Id}); err != nil {
|
|
this.module.Errorf("cleanData err:%v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (this *ModelHero) AddCardExp(session comm.IUserSession, heros []*pb.DBHero, exp int32, model *db.DBModel) (curAddExp map[string]int32, award []*cfg.Gameatn, errdata *pb.ErrorData) {
|
|
var (
|
|
tasks []*pb.BuriedParam
|
|
changeupdate map[string]interface{} = make(map[string]interface{})
|
|
maxlvhero *pb.DBHero
|
|
err error
|
|
)
|
|
curAddExp = make(map[string]int32, len(heros))
|
|
for _, hero := range heros {
|
|
var (
|
|
user *pb.DBUser
|
|
expConf *cfg.GamePlayerlvData
|
|
heroconf *cfg.GameHeroData
|
|
preLv int32 //加经验之前的等级
|
|
curExp int32 // 加经验之后的经验
|
|
curLv int32 // 加经验之后的等级
|
|
update map[string]interface{} // 属性变化
|
|
)
|
|
if hero == nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_HeroNoExist,
|
|
Title: pb.ErrorCode_HeroNoExist.ToString(),
|
|
}
|
|
return
|
|
}
|
|
if hero.HeroID == "" { // 这里出bug了
|
|
this.module.Errorf("获取英雄数据出问题.玩家id:%s 英雄对象:%v", session.GetUserId(), hero)
|
|
continue
|
|
}
|
|
update = make(map[string]interface{}, 0)
|
|
curExp = hero.Exp
|
|
curLv = hero.Lv
|
|
preLv = curLv
|
|
var maxLv int32 // 校验等级达到上限
|
|
if maxLv, err = this.module.configure.GetHeroMaxLv(hero.Star); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ConfigNoFound,
|
|
Message: fmt.Sprintf("cid:%s id:%s err:%s", hero.HeroID, hero.Id, err.Error()),
|
|
}
|
|
return
|
|
}
|
|
// 校验玩家等级
|
|
if user, err = this.module.GetUserForSession(session); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
if expConf, err = this.module.configure.GetPlayerlvConf(user.Lv); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ConfigNoFound,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
if maxLv > expConf.HeroLv {
|
|
maxLv = expConf.HeroLv // 英雄最大等级限制
|
|
}
|
|
_data, _ := this.module.configure.GetHeroLv(curLv)
|
|
if _data == nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ConfigNoFound,
|
|
Title: pb.ErrorCode_ConfigNoFound.ToString(),
|
|
}
|
|
return
|
|
}
|
|
if heroconf, err = this.module.configure.GetHeroConfig(hero.HeroID); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ConfigNoFound,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
var maxExp int32
|
|
maxExp = _data.Heroexp
|
|
if maxLv <= curLv && curExp >= maxExp { // 加经验之前校验是否达到最大等级
|
|
curAddExp[hero.Id] = 0
|
|
this.module.Debugf("英雄已经满级 不需要升级heroid:%s,addexp:%d", hero.Id, exp)
|
|
return
|
|
}
|
|
var fullexp int32 // 溢出的经验
|
|
curExp += exp // 先把经验加上
|
|
for { // 死循环判断一键升级
|
|
if _data.Heroexp == 0 {
|
|
fullexp = (curExp - maxExp)
|
|
//curAddExp[hero.Id] = exp - (curExp - maxExp) // 减去超过部分的经验
|
|
curExp = 0
|
|
break
|
|
}
|
|
maxExp = _data.Heroexp
|
|
if maxLv <= curLv && curExp >= maxExp { // 设置最大经验和等级
|
|
fullexp = (curExp - maxExp)
|
|
//curAddExp[hero.Id] = exp - (curExp - maxExp) // 减去超过部分的经验
|
|
curLv = maxLv
|
|
curExp = maxExp
|
|
break
|
|
}
|
|
if maxExp > curExp { // 经验不够升级则不能执行升级操作
|
|
break
|
|
} else { // 升级操作
|
|
curExp -= maxExp
|
|
curLv += 1 // 经验够了 那么等级+1
|
|
|
|
_data, _ = this.module.configure.GetHeroLv(curLv)
|
|
if _data == nil { // 等级加失败了 回到原来的等级
|
|
fullexp = (curExp - maxExp)
|
|
curLv -= 1
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if curAddExp[hero.Id] == 0 {
|
|
curAddExp[hero.Id] = exp // 真正加的经验
|
|
} else {
|
|
curAddExp[hero.Id] = (exp - fullexp)
|
|
}
|
|
|
|
this.module.Debugf("add hero exp :old lv:%d,old exp:%d,new lv:%d,new exp:%d,addexp:%d", hero.Lv, hero.Exp, curLv, curExp, exp)
|
|
update["lv"] = curLv
|
|
update["exp"] = curExp
|
|
|
|
hero.Lv = curLv
|
|
hero.Exp = curExp
|
|
if curLv-preLv > 0 { // 升级了 统计任务
|
|
if maxlvhero == nil || curLv > maxlvhero.Lv {
|
|
maxlvhero = hero
|
|
}
|
|
this.PropertyCompute(hero)
|
|
update["property"] = hero.Property
|
|
update["horoscopeProperty"] = hero.HoroscopeProperty
|
|
update["talentProperty"] = hero.TalentProperty
|
|
update["juexProperty"] = hero.JuexProperty
|
|
update["fightvalue"] = hero.Fightvalue
|
|
|
|
}
|
|
changeupdate[hero.Id] = update
|
|
if curLv-preLv > 0 { // 升级了 统计任务
|
|
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype147, utils.ToInt32(hero.HeroID), curLv-preLv))
|
|
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype113, curLv))
|
|
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype4, hero.Lv, utils.ToInt32(hero.HeroID)))
|
|
tasks = append(tasks, comm.GetBuriedParam2(comm.Rtype23, hero.HeroID, hero.Star, hero.Lv))
|
|
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype24, curLv-preLv))
|
|
// szTask = append(szTask, comm.GetBuriedParam(comm.Rtype29, 1, hero.Lv, utils.ToInt32(hero.HeroID)))
|
|
tasks = append(tasks, comm.GetBuriedParam2(comm.Rtype23, hero.HeroID, hero.Star, hero.Lv))
|
|
tasks = append(tasks, comm.GetBuriedParam2(comm.Rtype32, hero.HeroID, heroconf.Color, hero.Lv))
|
|
//xx英雄满级、共鸣、觉醒至最高状态
|
|
nextAwaken, _ := this.module.configure.GetHeroAwakenConfig(hero.HeroID, hero.JuexingLv+1)
|
|
if nextAwaken == nil { // 达到满级觉醒
|
|
var maxlv int32
|
|
if maxlv, err = this.module.configure.GetHeroMaxLv(hero.Star); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ConfigNoFound,
|
|
Title: pb.ErrorCode_ConfigNoFound.ToString(),
|
|
Message: fmt.Sprintf("cid:%s id:%s err:%s", hero.HeroID, hero.Id, err.Error()),
|
|
}
|
|
return
|
|
}
|
|
if hero.Lv == maxlv {
|
|
var _l int32
|
|
talent, err := this.module.modelTalent.GetHerotalent(session.GetUserId())
|
|
if err == nil {
|
|
for _, v := range talent {
|
|
if v.HeroId == hero.HeroID {
|
|
_l = int32(len(v.Talent))
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if maxlv, e := this.module.configure.GetHeroTalentMaxLv(hero.HeroID); e == nil {
|
|
if maxlv == _l {
|
|
tasks = append(tasks, comm.GetBuriedParam2(comm.Rtype37, hero.HeroID, heroconf.Color))
|
|
tasks = append(tasks, comm.GetBuriedParam2(comm.Rtype38, hero.HeroID))
|
|
iHeroId, _ := strconv.Atoi(hero.HeroID)
|
|
tasks = append(tasks, comm.GetBuriedParam2(comm.Rtype243, hero.HeroID, int32(iHeroId)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tasks = append(tasks, comm.GetBuriedParam2(comm.Rtype111, hero.HeroID, hero.Lv))
|
|
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype112, 1, hero.Lv))
|
|
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype113, hero.Lv))
|
|
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype33, 1, 1, hero.Lv))
|
|
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype118, hero.Lv, hero.JuexingLv))
|
|
}
|
|
}
|
|
|
|
if model != nil {
|
|
if err := model.ChangeLists(session.GetUserId(), changeupdate); err != nil {
|
|
this.module.Errorln(err)
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Title: pb.ErrorCode_DBError.ToString(),
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
} else {
|
|
if err := this.ChangeLists(session.GetUserId(), changeupdate); err != nil {
|
|
this.module.Errorln(err)
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Title: pb.ErrorCode_DBError.ToString(),
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
}
|
|
award = make([]*cfg.Gameatn, 0)
|
|
go this.module.AsynHandleSession(session.Clone(), func(session comm.IUserSession) {
|
|
if maxlvhero != nil {
|
|
this.module.passon.HeroUpLv(session, maxlvhero.HeroID, maxlvhero.Lv)
|
|
}
|
|
this.module.ModuleBuried.TriggerBuried(session, tasks...)
|
|
|
|
})
|
|
return
|
|
}
|
|
|
|
// 玩家离线 清除缓存
|
|
func (this *ModelHero) RemoveUserHeroInfo(uid string) (err error) {
|
|
//star := configure.Now()
|
|
this.BatchDelLists(uid)
|
|
//this.moduleHero.Debugf("=====%d,", time.Since(star).Milliseconds())
|
|
return
|
|
}
|
|
|
|
// 通过卡池的权重 获取英雄
|
|
func (this *ModelHero) GetRandHeroIdBypool(sz []int32) int32 {
|
|
|
|
if len(sz) > 0 {
|
|
var _totalW int64 // 总权重
|
|
var _tmpW int64 // 临时权重
|
|
for _, v := range sz {
|
|
_totalW += int64(v)
|
|
}
|
|
// 随机权重
|
|
n, _ := rand.Int(rand.Reader, big.NewInt(_totalW))
|
|
for i, v := range sz {
|
|
_tmpW += int64(v)
|
|
if n.Int64() < _tmpW { // 种族保底卡池命中
|
|
return int32(i)
|
|
}
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// 初始化怪物属性
|
|
func (this *ModelHero) InitMonsterHero(heroCfgId string, star, lv int32) *pb.DBHero {
|
|
heroCfg, _ := this.module.configure.GetHeroConfig(heroCfgId)
|
|
|
|
if heroCfg == nil {
|
|
this.module.Errorf("%v hero not found from config %v", heroCfgId)
|
|
return nil
|
|
}
|
|
|
|
newHero := &pb.DBHero{
|
|
HeroID: heroCfg.Hid,
|
|
Star: star, //初始星级
|
|
Lv: lv, //初始等级
|
|
Block: false, //未锁定
|
|
CardType: heroCfg.Type, //卡片类型
|
|
Skins: []int32{},
|
|
EquipID: make([]string, 8), //初始装备
|
|
AddProperty: make(map[int32]int32),
|
|
Property: make(map[int32]int32),
|
|
JuexProperty: make(map[int32]int32),
|
|
TalentProperty: make(map[int32]int32),
|
|
HoroscopeProperty: make(map[int32]int32),
|
|
}
|
|
this.initHeroSkill(newHero)
|
|
this.PropertyCompute(newHero)
|
|
|
|
return newHero
|
|
}
|
|
|
|
// 设置天赋属性
|
|
func (this *ModelHero) setTalentProperty(hero *pb.DBHero, conf *cfg.GameHeroTalentData) {
|
|
if conf == nil || hero == nil {
|
|
return
|
|
}
|
|
if hero.TalentProperty == nil {
|
|
hero.TalentProperty = make(map[int32]int32)
|
|
}
|
|
|
|
hero.TalentProperty[conf.Attr.A] += conf.Attr.N
|
|
|
|
_heroMap := make(map[string]interface{}, 0)
|
|
|
|
_heroMap["talentProperty"] = hero.TalentProperty
|
|
this.module.modelHero.calFigthValue(hero)
|
|
_heroMap["fightvalue"] = hero.Fightvalue
|
|
if err := this.ChangeList(hero.Uid, hero.Id, _heroMap); err != nil {
|
|
this.module.Errorf("mergeenegryProperty err %v", err)
|
|
}
|
|
}
|
|
|
|
// 重置天赋属性
|
|
func (this *ModelHero) cleanTalentProperty(hero *pb.DBHero) {
|
|
if hero == nil {
|
|
return
|
|
}
|
|
hero.TalentProperty = map[int32]int32{}
|
|
hero.Talentskill = make([]*pb.SkillData, 0) // 重置技能
|
|
_heroMap := make(map[string]interface{}, 0)
|
|
_heroMap["talentProperty"] = hero.TalentProperty
|
|
_heroMap["talentskill"] = hero.Talentskill
|
|
if err := this.ChangeList(hero.Uid, hero.Id, _heroMap); err != nil {
|
|
this.module.Errorf("mergeenegryProperty err %v", err)
|
|
}
|
|
}
|
|
|
|
// 重新计算天赋加成 attr hp atk def cri speed
|
|
func (this *ModelHero) resetTalentProperty(hero *pb.DBHero) {
|
|
|
|
if hero == nil {
|
|
return
|
|
}
|
|
if rst, err := this.module.modelTalent.GetHerotalent(hero.Uid); err == nil {
|
|
for _, v := range rst {
|
|
if v.HeroId == hero.HeroID { // 找到对应的英雄
|
|
for k := range v.Talent {
|
|
if conf, _ := this.module.configure.GetHeroTalent(k); conf != nil { //获取天赋
|
|
hero.TalentProperty[conf.Attr.A] = conf.Attr.N
|
|
}
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 校验当前技能是否是满级
|
|
func (this *ModelHero) checkHeroAllSkillMax(hero *pb.DBHero) bool {
|
|
for _, v := range hero.NormalSkill {
|
|
if this.module.configure.GetHeroSkillMaxLvConfig(uint32(v.SkillID)) > v.SkillLv {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
func (this *ModelHero) SetHeroFetterProperty(hero *pb.DBHero, attr []*cfg.Gameatr) {
|
|
if hero == nil || len(attr) == 0 {
|
|
return
|
|
}
|
|
if hero.Fetters == nil {
|
|
hero.Fetters = make(map[int32]int32, 0)
|
|
}
|
|
for _, key := range attr {
|
|
hero.Fetters[key.A] += key.N
|
|
}
|
|
}
|
|
|
|
func (this *ModelHero) CheckDrawCardRes(session comm.IUserSession, drawConf *cfg.GameDrawPoolData, consume int32, drawCount int32) (costRes []*cfg.Gameatn, errdata *pb.ErrorData) {
|
|
if consume == 0 { // 消耗A
|
|
if drawCount == 1 {
|
|
costRes = drawConf.ConsumeA // 单抽消耗
|
|
} else {
|
|
costRes = drawConf.ConsumeA10 // 十连消耗
|
|
}
|
|
} else { // 消耗B
|
|
if drawCount == 1 {
|
|
costRes = drawConf.ConsumeB // 单抽消耗
|
|
} else {
|
|
costRes = drawConf.ConsumeB10 // 十连消耗
|
|
}
|
|
}
|
|
|
|
if errdata = this.module.CheckRes(session, costRes); errdata != nil { // 消耗数量不足直接返回
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// 模拟获得英雄 (bImitate : true 表示模拟获得 并不发英雄)
|
|
func (this *ModelHero) ImitateHeros(session comm.IUserSession, cids []string, bImitate bool) (addres [][]*cfg.Gameatn, add []*pb.DBHero, err error) {
|
|
var (
|
|
szCard map[string]int32
|
|
bChange bool
|
|
hero *pb.DBHero
|
|
tasks []*pb.BuriedParam
|
|
)
|
|
szCard = make(map[string]int32)
|
|
heros := make([]*pb.DBHero, 0)
|
|
uid := session.GetUserId()
|
|
list := this.module.ModuleTools.GetGlobalConf().Moonshopmoney
|
|
if list == nil {
|
|
return
|
|
}
|
|
rst, err := this.module.ModuleUser.GetUserExpand(session.GetUserId())
|
|
if err != nil {
|
|
return
|
|
}
|
|
lock, _ := this.userlock(session.GetUserId())
|
|
err = lock.Lock()
|
|
if err != nil {
|
|
this.module.Error("创建英雄分布式锁失效 err!", log.Field{Key: "uid", Value: uid}, log.Field{Key: "err", Value: err.Error()})
|
|
return
|
|
}
|
|
defer lock.Unlock()
|
|
heros = this.module.modelHero.getHeroList(uid)
|
|
for _, heroCfgId := range cids {
|
|
var (
|
|
res []*cfg.Gameatn
|
|
)
|
|
|
|
heroCfg, _ := this.module.configure.GetHeroConfig(heroCfgId)
|
|
bFirst := true
|
|
if heroCfg == nil {
|
|
err = errors.New("not found hero configID")
|
|
this.module.Errorf("not found hero configID:%s", heroCfgId)
|
|
return
|
|
}
|
|
szCard[heroCfgId] += 1 //统计卡片数量
|
|
for _, obj := range heros {
|
|
if obj.HeroID == heroCfgId {
|
|
hero = obj
|
|
bFirst = false
|
|
res = append(res, &cfg.Gameatn{
|
|
A: "hero",
|
|
T: obj.HeroID,
|
|
N: 0,
|
|
})
|
|
break
|
|
}
|
|
}
|
|
|
|
if bFirst { // 没有当前英雄
|
|
if bImitate {
|
|
// 模拟英雄不用真实数据
|
|
hero = &pb.DBHero{
|
|
HeroID: heroCfgId,
|
|
}
|
|
//hero = this.InitHero(uid, heroCfgId)
|
|
} else {
|
|
hero, err = this.initHeroOverlying(uid, heroCfgId, 1)
|
|
}
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
res = append(res, &cfg.Gameatn{
|
|
A: "hero",
|
|
T: hero.HeroID,
|
|
N: 1,
|
|
})
|
|
heros = append(heros, hero)
|
|
add = append(add, hero)
|
|
}
|
|
|
|
// 转碎片处理
|
|
bAdd := false
|
|
//守护之星 获得
|
|
if heroCfg.Herofragnum > 0 {
|
|
if v, ok := rst.Herofrag[hero.HeroID]; !ok {
|
|
rst.Herofrag[hero.HeroID] = 1
|
|
bAdd = true
|
|
bChange = true
|
|
} else if heroCfg.Herofragnum > v {
|
|
rst.Herofrag[hero.HeroID] += 1
|
|
bAdd = true
|
|
bChange = true
|
|
}
|
|
}
|
|
if bAdd {
|
|
res = append(res, heroCfg.Herofrag...)
|
|
} else {
|
|
for pos, v := range list {
|
|
if int32(pos)+3 == heroCfg.Star && v > 0 {
|
|
|
|
res = append(res, &cfg.Gameatn{
|
|
A: "attr",
|
|
T: "moongold",
|
|
N: v,
|
|
})
|
|
break
|
|
}
|
|
}
|
|
}
|
|
bAdd = false // 初始化
|
|
// expitem 获得
|
|
if heroCfg.Expitemnum > 0 {
|
|
if v, ok := rst.Expitem[hero.HeroID]; ok {
|
|
if heroCfg.Expitemnum > v {
|
|
rst.Expitem[hero.HeroID] += 1
|
|
bAdd = true
|
|
bChange = true
|
|
}
|
|
} else {
|
|
rst.Expitem[hero.HeroID] = 1
|
|
bAdd = true
|
|
bChange = true
|
|
}
|
|
}
|
|
if bAdd {
|
|
res = append(res, heroCfg.Expitem...)
|
|
}
|
|
addres = append(addres, res)
|
|
}
|
|
if !bImitate {
|
|
var szAddHero []string
|
|
for _, v := range add {
|
|
if cfg, err := this.module.configure.GetHeroConfig(v.HeroID); err == nil {
|
|
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype228, cfg.Star))
|
|
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype1, 1, utils.ToInt32(v.HeroID)))
|
|
tasks = append(tasks, comm.GetBuriedParam2(comm.Rtype30, v.HeroID, cfg.Color))
|
|
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype31, 1, cfg.Color))
|
|
szAddHero = append(szAddHero, v.HeroID)
|
|
}
|
|
|
|
}
|
|
if len(add) > 0 {
|
|
session.SendMsg("hero", "change", &pb.HeroChangePush{List: add})
|
|
}
|
|
|
|
if db.IsCross() {
|
|
go this.module.moduleFetter.SendRpcAddHero(session.GetUserId(), szAddHero, session.GetServiecTag())
|
|
} else {
|
|
go this.module.moduleFetter.AddHerosFetterData(session.GetUserId(), szAddHero)
|
|
}
|
|
go this.module.AsynHandleSession(session.Clone(), func(session comm.IUserSession) {
|
|
this.module.ModuleEntertain.AddXxlCard(session, szCard, true)
|
|
if len(tasks) > 0 {
|
|
this.module.ModuleBuried.TriggerBuried(session, tasks...)
|
|
}
|
|
})
|
|
if bChange {
|
|
this.module.ModuleUser.ChangeUserExpand(session.GetUserId(), map[string]interface{}{
|
|
"herofrag": rst.Herofrag,
|
|
"expitem": rst.Expitem,
|
|
})
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 分布式锁
|
|
func (this *ModelHero) userlock(id string) (result *redis.RedisMutex, err error) {
|
|
return this.module.modelHero.Redis.NewRedisMutex(fmt.Sprintf("%s-herolock:%s", this.module.modelHero.DBModel.ServiceId, id))
|
|
}
|