go_dreamfactory/modules/hero/model_hero.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)
}
}
}