package hero import ( "errors" "fmt" "go_dreamfactory/comm" "go_dreamfactory/lego/core" "go_dreamfactory/modules" "go_dreamfactory/pb" "math" mengine "github.com/dengsgo/math-engine/engine" "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 moduleHero *Hero } func (this *ModelHero) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { err = this.MCompModel.Init(service, module, comp, options) this.moduleHero = module.(*Hero) this.TableName = "hero" // 通过uid创建索引 this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{ Keys: bsonx.Doc{{Key: "uid", Value: bsonx.Int32(1)}}, }) return } //初始化英雄 func (this *ModelHero) initHero(uid string, heroCfgId int32) *pb.DBHero { heroCfg := this.moduleHero.configure.GetHero(heroCfgId) if heroCfg == nil { this.moduleHero.Errorf("%v hero not found from config %v", heroCfgId) return nil } objId := primitive.NewObjectID().Hex() newHero := &pb.DBHero{ Id: objId, Uid: uid, HeroID: heroCfg.Hid, Star: heroCfg.Star, //初始星级 Lv: 1, //初始等级 IsOverlying: true, //是否允许叠加, Block: false, //未锁定 CardType: heroCfg.Type, //卡片类型 Skins: []int32{}, EquipID: make([]string, 6), //初始装备 SameCount: 1, //默认叠加数量 AddProperty: make(map[string]int32), Energy: make(map[int32]int32), Property: make(map[string]int32), } this.initHeroSkill(newHero) return newHero } //初始化英雄技能 func (this *ModelHero) initHeroSkill(hero *pb.DBHero) []*pb.SkillData { heroCfg := this.moduleHero.configure.GetHero(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}) } hero.NormalSkill = skills } return nil } //创建一个指定的英雄 func (this *ModelHero) createOneHero(uid string, heroCfgId int32) (hero *pb.DBHero, err error) { hero = this.initHero(uid, heroCfgId) if hero != nil { if err = this.moduleHero.modelHero.AddList(uid, hero.Id, hero); err != nil { this.moduleHero.Errorf("%v", err) return } } return } //初始化可叠加的英雄 func (this *ModelHero) initHeroOverlying(uid string, heroCfgId, count int32) (hero *pb.DBHero, err error) { hero = this.initHero(uid, heroCfgId) if hero != nil { // 添加图鉴 if result, err1 := this.GetUserExpand(uid); err1 == nil { sz := make(map[int32]bool, 0) for k := range result.GetTujian() { sz[k] = true } if _, ok := result.GetTujian()[heroCfgId]; !ok { sz[heroCfgId] = true initUpdate := map[string]interface{}{ "tujian": sz, } this.ChanageUserExpand(uid, initUpdate) } } hero.SameCount += count if err = this.moduleHero.modelHero.AddList(uid, hero.Id, hero); err != nil { this.moduleHero.Errorf("%v", err) return } } return } //叠加英雄 count叠加数量 func (this *ModelHero) createHeroOverlying(uid string, heroCfgId, count int32) (hero *pb.DBHero, err error) { heroes := this.moduleHero.modelHero.getHeroList(uid) if len(heroes) == 0 { return this.initHeroOverlying(uid, heroCfgId, count) } else { var isExist bool for _, h := range heroes { if h.HeroID == heroCfgId && h.IsOverlying { isExist = true h.SameCount += count data := map[string]interface{}{ "sameCount": h.SameCount, //叠加数 } if err := this.modifyHeroData(uid, h.Id, data); err != nil { return nil, err } } } if !isExist { return this.initHeroOverlying(uid, heroCfgId, count) } } return } //创建多个指定的英雄 heroCfgIds可填入多个英雄ID func (this *ModelHero) createMultiHero(uid string, heroCfgIds ...int32) error { heroes := this.moduleHero.modelHero.getHeroList(uid) if len(heroes) == 0 { for _, v := range heroCfgIds { if _, err := this.createOneHero(uid, v); err != nil { return err } } } else { findHero := func(heroId int32) (*pb.DBHero, bool) { for _, h := range heroes { if h.HeroID == heroId { return h, true } } return nil, false } for _, v := range heroCfgIds { if h, ok := findHero(v); ok { //允许叠加 if h.IsOverlying { h.SameCount++ data := map[string]interface{}{ "sameCount": h.SameCount, //叠加数 } if err := this.modifyHeroData(uid, h.Id, data); err != nil { return err } } else { if _, err := this.createOneHero(uid, v); err != nil { return err } } } else { if _, err := this.createOneHero(uid, v); err != nil { return err } } } } return nil } //获取一个英雄 func (this *ModelHero) getOneHero(uid, heroId string) *pb.DBHero { hero := &pb.DBHero{} err := this.moduleHero.modelHero.GetListObj(uid, heroId, hero) if err != nil { return nil } return hero } //消耗英雄卡 func (this *ModelHero) consumeHeroCard(uid, heroId string, count int32) (hero *pb.DBHero, err error) { if count == 0 { return } hero = this.getOneHero(uid, heroId) if hero == nil { err = errors.New("hero no exist") return } if hero.SameCount < count { err = errors.New("hero card no enough") return } hero.SameCount -= count if hero.SameCount == 0 { if err := this.moduleHero.modelHero.DelListlds(uid, heroId); err != nil { this.moduleHero.Errorf("%v", err) } } else { update := map[string]interface{}{ "sameCount": hero.SameCount, } err = this.modifyHeroData(uid, heroId, update) } this.moduleHero.Debugf("删除一张卡牌uid:%s,卡牌ID:%s", uid, heroId) return } //更新英雄数据 func (this *ModelHero) modifyHeroData(uid, heroId string, data map[string]interface{}) error { if len(data) == 0 { return fmt.Errorf("params len is 0") } return this.moduleHero.modelHero.ChangeList(uid, heroId, data) } //获取玩家的英雄列表 func (this *ModelHero) getHeroList(uid string) []*pb.DBHero { heroes := make([]*pb.DBHero, 0) err := this.GetList(uid, &heroes) if err != nil { return nil } return heroes } // 设置装备属性 func (this *ModelHero) setEquipProperty(hero *pb.DBHero, equip []*pb.DB_Equipment) { property := make(map[string]int32) //主属性 addProperty := make(map[string]int32) //副属性 for i, v := range equip { if v == nil { continue } hero.EquipID[i] = v.Id //主属性 property[v.MainEntry.AttrName] = v.MainEntry.Value //附加属性 for _, v := range v.AdverbEntry { addProperty[v.AttrName] = v.Value } } this.mergeMainProperty(hero.Uid, hero.Uid, property) this.mergeAddProperty(hero.Uid, hero.Uid, addProperty) } //设置装备 func (this *ModelHero) setEquipment(hero *pb.DBHero) (newHero *pb.DBHero, err error) { if len(hero.EquipID) == 0 { return } update := make(map[string]interface{}) if hero.IsOverlying && hero.SameCount > 1 { hero.SameCount -= 1 update["sameCount"] = hero.SameCount update["isOverlying"] = false if err = this.modifyHeroData(hero.Uid, hero.Id, update); err != nil { this.moduleHero.Errorf("%v", err) return } //创建新卡 newHero, err = this.createOneHero(hero.Uid, hero.HeroID) if err != nil { this.moduleHero.Errorf("%v", err) return } newHero.EquipID = hero.EquipID update["suiteId"] = hero.SuiteId update["suiteExtId"] = hero.SuiteExtId update["equipID"] = hero.EquipID update["isoverlying"] = false this.modifyHeroData(newHero.Uid, newHero.Id, update) } else { update["equipID"] = hero.EquipID update["isoverlying"] = false update["suiteId"] = hero.SuiteId update["suiteExtId"] = hero.SuiteExtId this.modifyHeroData(hero.Uid, hero.Id, update) } // 打印 for _, v := range hero.EquipID { this.moduleHero.Debugf("设置装备%s\n", v) } return } //合并属性即属性值累加 func (this *ModelHero) mergeMainProperty(uid, heroId string, data map[string]int32) { hero := this.getOneHero(uid, heroId) if hero == nil { return } hero.Property[comm.Hp] += data[comm.Hp] hero.Property[comm.Atk] += data[comm.Atk] hero.Property[comm.Def] += data[comm.Def] update := map[string]interface{}{ comm.Hp: hero.Property[comm.Hp], comm.Atk: hero.Property[comm.Atk], comm.Def: hero.Property[comm.Def], } if err := this.modifyHeroData(uid, heroId, update); err != nil { this.moduleHero.Errorf("mergeMainProperty err %v", err) } } //合并附加属性 func (this *ModelHero) mergeAddProperty(uid, heroId string, data map[string]int32) { hero := this.getOneHero(uid, heroId) if hero == nil { return } hero.AddProperty[comm.HpPro] += data[comm.HpPro] hero.AddProperty[comm.AtkPro] += data[comm.AtkPro] hero.AddProperty[comm.DefPro] += data[comm.DefPro] update := map[string]interface{}{ comm.HpPro: hero.AddProperty[comm.HpPro], comm.AtkPro: hero.AddProperty[comm.AtkPro], comm.DefPro: hero.AddProperty[comm.DefPro], } if err := this.modifyHeroData(uid, heroId, update); err != nil { this.moduleHero.Errorf("mergeAddProperty err %v", err) } } //属性计算 - 暂时放在modelHero里实现 //英雄基础属性 + 英雄等级基础属性 * 英雄成长系数 + 英雄星级对应等级属性 * 英雄品质系数 func (this *ModelHero) PropertyCompute(uid, heroId string) map[string]int32 { hero := this.getOneHero(uid, heroId) if hero == nil { return nil } //英雄等级基础属性levelup heroLvCfg := this.moduleHero.configure.GetHeroLv(hero.Lv) if heroLvCfg == nil { return nil } //英雄基础配置 newhero heroCfg := this.moduleHero.configure.GetHero(hero.HeroID) if heroCfg == nil { return nil } //品质系数 stargrowCfg := this.moduleHero.configure.GetHeroStar(heroCfg.Star) if stargrowCfg == nil { return nil } //英雄星级对应等级属性 heroStarCfg := this.moduleHero.configure.GetHeroLv(stargrowCfg.Level) if heroStarCfg == nil { return nil } //成长系数 lvGrow := this.moduleHero.configure.GetHeroLvgrow(hero.HeroID) if lvGrow == nil { return nil } curHp := hero.Property[comm.Hp] exprHp := fmt.Sprintf("%v + %v * %v/1000 + %v * %v/1000", (curHp + lvGrow.Hp), heroLvCfg.Hp, lvGrow.Hpgrow, heroStarCfg.Hp, stargrowCfg.StarupHp) hp, _ := mengine.ParseAndExec(exprHp) curAtk := hero.Property[comm.Atk] exprAtk := fmt.Sprintf("%v +%v * %v/1000 + %v * %v/1000", (curAtk + lvGrow.Atk), heroLvCfg.Atk, lvGrow.Atkgrow, heroStarCfg.Atk, stargrowCfg.StarupAtk) atk, _ := mengine.ParseAndExec(exprAtk) curDef := hero.Property[comm.Def] exprDef := fmt.Sprintf("%v +%v * %v/1000 + %v * %v/1000", (curDef + lvGrow.Def), heroLvCfg.Def, lvGrow.Defgrow, heroStarCfg.Def, stargrowCfg.StarupDef) def, _ := mengine.ParseAndExec(exprDef) return map[string]int32{ comm.Hp: int32(math.Floor(hp)), comm.Atk: int32(math.Floor(atk)), comm.Def: int32(math.Floor(def)), } } //推送用户指定英雄属性 func (this *ModelHero) PushHeroProperty(session comm.IUserSession, heroId string) (m map[string]int32, err error) { m = this.PropertyCompute(session.GetUserId(), heroId) update := map[string]interface{}{ "property": m, } if err = this.ChangeList(session.GetUserId(), heroId, update); err != nil { this.moduleHero.Errorf("PushHeroProperty err:%v", err) return } return //session.SendMsg("hero", "property", &pb.HeroPropertyPush{Property: m}) } func (this *ModelHero) cleanData(uid string) { userList := this.moduleHero.GetHeroList(uid) for _, v := range userList { if err := this.moduleHero.modelHero.DelListlds(uid, v.Id); err != nil { this.moduleHero.Errorf("cleanData err:%v", err) } } }