444 lines
12 KiB
Go
444 lines
12 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|