go_dreamfactory/modules/hero/model_hero.go
2023-07-04 17:02:26 +08:00

971 lines
29 KiB
Go

package hero
import (
"crypto/rand"
"errors"
"go_dreamfactory/comm"
"go_dreamfactory/lego/core"
"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 (this *ModelHero) InitHero(uid string, heroCfgId string) *pb.DBHero {
heroCfg, _ := this.module.configure.GetHeroConfig(heroCfgId)
if heroCfg == nil {
this.module.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, //初始等级
Block: false, //未锁定
CardType: heroCfg.Type, //卡片类型
Skins: []int32{},
EquipID: make([]string, 8), //初始装备
AddProperty: make(map[string]int32),
Property: make(map[string]int32),
JuexProperty: make(map[string]int32),
TalentProperty: make(map[string]int32),
HoroscopeProperty: make(map[string]int32),
Fetters: make(map[string]int32),
}
this.PropertyCompute(newHero)
this.initHeroSkill(newHero)
return newHero
}
// 初始化英雄技能
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})
}
hero.NormalSkill = skills
}
return nil
}
// 创建一个指定的英雄
func (this *ModelHero) createSpecialHero(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 = this.InitHero(uid, heroCfgId)
if hero != nil {
if err = this.AddList(uid, hero.Id, hero); err != nil {
this.module.Errorf("%v", err)
return
}
}
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 = this.InitHero(uid, heroCfgId)
if hero != 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 {
hero := &pb.DBHero{}
err := this.GetListObj(uid, heroId, hero)
if err != nil {
return nil
}
return hero
}
// 消耗英雄卡
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 {
heroes := make([]*pb.DBHero, 0)
err := this.GetList(uid, &heroes)
if err != nil {
return nil
}
return heroes
}
// 重置觉醒属性
func (this *ModelHero) resetJuexingProperty(hero *pb.DBHero) {
hero.JuexProperty = make(map[string]int32)
for i := 1; i <= int(hero.JuexingLv); i++ {
awakenData, err := this.module.configure.GetHeroAwakenConfig(hero.HeroID, int32(i))
if err == nil {
if len(awakenData.Phasebonus) != 2 {
continue
}
key := awakenData.Phasebonus[0]
value, err := strconv.Atoi(awakenData.Phasebonus[1])
if err != nil {
continue
}
switch key {
case comm.Hp:
hero.JuexProperty[comm.Hp] += int32(value)
case comm.Def:
hero.JuexProperty[comm.Def] += int32(value)
case comm.Atk:
hero.JuexProperty[comm.Atk] += int32(value)
case comm.Speed:
hero.JuexProperty[comm.Speed] += int32(value)
case comm.Cri:
hero.JuexProperty[comm.Cri] += int32(value)
case comm.ResonanceHpPro:
hero.JuexProperty[comm.Hp] += int32(math.Floor((float64(value) / 1000) * float64(hero.Property[comm.Hp])))
case comm.ResonanceAtkPro:
hero.JuexProperty[comm.Atk] += int32(math.Floor((float64(value) / 1000) * float64(hero.Property[comm.Atk])))
case comm.ResonanceDefPro:
hero.JuexProperty[comm.Def] += int32(math.Floor((float64(value) / 1000) * float64(hero.Property[comm.Def])))
default:
this.module.Errorf("unkonw Resonance property:%s", key)
}
}
}
}
// 觉醒
func (this *ModelHero) setJuexingProperty(hero *pb.DBHero, key string, value int32) {
switch key {
case comm.Hp:
hero.JuexProperty[comm.Hp] += value
case comm.Def:
hero.JuexProperty[comm.Def] += value
case comm.Atk:
hero.JuexProperty[comm.Atk] += value
case comm.Speed:
hero.JuexProperty[comm.Speed] += value
case comm.ResonanceHpPro:
hero.JuexProperty[comm.Hp] += int32(math.Floor((float64(value) / 1000) * float64(hero.Property[comm.Hp])))
case comm.ResonanceAtkPro:
hero.JuexProperty[comm.Atk] += int32(math.Floor((float64(value) / 1000) * float64(hero.Property[comm.Atk])))
case comm.ResonanceDefPro:
hero.JuexProperty[comm.Def] += int32(math.Floor((float64(value) / 1000) * float64(hero.Property[comm.Def])))
}
}
// 设置装备属性
func (this *ModelHero) setEquipProperty(hero *pb.DBHero, equip []*pb.DB_Equipment) {
addProperty := make(map[string]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 //主属性
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 k, v := range configure.SetBonuses {
addProperty[k] += v
}
}
}
}
for k, v := range addProperty {
switch k {
case comm.AtkPro:
addProperty[comm.Atk] += int32(math.Floor((float64(v) / 1000) * float64(hero.Property[comm.Atk])))
case comm.DefPro:
addProperty[comm.Def] += int32(math.Floor((float64(v) / 1000) * float64(hero.Property[comm.Def])))
case comm.HpPro:
addProperty[comm.Hp] += int32(math.Floor((float64(v) / 1000) * float64(hero.Property[comm.Hp])))
case comm.SpeedPro:
addProperty[comm.Speed] += int32(math.Floor((float64(v) / 1000) * float64(hero.Property[comm.Speed])))
}
}
this.mergeAddProperty(hero.Uid, hero, addProperty, equipSkill)
}
// 设置装备
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
}
// 合并属性即属性值累加 (data 额外加的属性)
func (this *ModelHero) mergeMainProperty(uid string, hero *pb.DBHero, data map[string]int32) (err error) {
for k, v := range hero.Property {
if v1, ok := data[k]; ok {
v += v1
}
}
if err = this.ChangeList(uid, hero.Id, map[string]interface{}{
"property": hero.Property,
}); err != nil {
this.module.Errorf("mergeMainProperty err %v", err)
}
return
}
// 合并附加属性
func (this *ModelHero) mergeAddProperty(uid string, hero *pb.DBHero, data map[string]int32, skills []*pb.SkillData) {
hero.AddProperty = data
if err := this.ChangeList(uid, hero.Id, map[string]interface{}{
"addProperty": data,
"equipSkill": skills,
}); err != nil {
this.module.Errorf("mergeAddProperty err %v", err)
}
}
func (this *ModelHero) StarAtkAddition(star int32) (addValue float32) {
for i := 1; i <= int(star); i++ {
starCfg := this.module.configure.GetHeroStar(int32(i))
cfg := this.module.configure.GetHeroLv(starCfg.Level)
addValue += cfg.Atk * starCfg.StarupAtk / 1000.0
}
return addValue
}
func (this *ModelHero) StarDefAddition(star int32) (addValue float32) {
for i := 1; i <= int(star); i++ {
starCfg := this.module.configure.GetHeroStar(int32(i))
cfg := this.module.configure.GetHeroLv(starCfg.Level)
addValue += cfg.Def * starCfg.StarupDef / 1000.0
}
return addValue
}
func (this *ModelHero) StarHpAddition(star int32) (addValue float32) {
for i := 1; i <= int(star); i++ {
starCfg := this.module.configure.GetHeroStar(int32(i))
cfg := this.module.configure.GetHeroLv(starCfg.Level)
//this.moduleHero.Debugf("cfg.Atk= %f,starCfg.StarupHp = %f,addValue= %f", cfg.Atk, starCfg.StarupHp, addValue)
addValue += cfg.Hp * starCfg.StarupHp / 1000.0
}
return addValue
}
// 属性计算 基础属性
// 英雄基础属性 + 英雄等级基础属性 * 英雄成长系数 + 英雄星级对应等级属性 * 英雄品质系数
func (this *ModelHero) PropertyCompute(hero *pb.DBHero) {
growCfg := this.module.configure.GetHeroLvgrow(hero.HeroID)
heroCfg, _ := this.module.configure.GetHeroConfig(hero.HeroID)
lvCfg := this.module.configure.GetHeroLv(hero.Lv)
starCfg := this.module.configure.GetHeroStar(hero.Star)
starLvfg := this.module.configure.GetHeroLv(starCfg.Level)
if growCfg == nil || heroCfg == nil || lvCfg == nil || starCfg == nil || starLvfg == nil {
this.module.Debugf("hero PropertyCompute Configure Info err:heroid :%s, herolv:=%d,heroStar:%d,", hero.HeroID, hero.Lv, hero.Star)
return
}
var atk = (this.StarAtkAddition(hero.Star) + lvCfg.Atk + float32(growCfg.Atk)) * (growCfg.Atkgrow / 1000.0)
var def = (this.StarDefAddition(hero.Star) + lvCfg.Def + float32(growCfg.Def)) * (growCfg.Defgrow / 1000.0)
var hp = (this.StarHpAddition(hero.Star) + lvCfg.Hp + float32(growCfg.Hp)) * (growCfg.Hpgrow / 1000.0)
speed := growCfg.Speed
hero.Property = map[string]int32{
comm.Hp: int32(math.Floor(float64(hp))),
comm.Atk: int32(math.Floor(float64(atk))),
comm.Def: int32(math.Floor(float64(def))),
comm.Speed: int32(math.Floor(float64(speed))),
comm.Cri: int32(growCfg.Cri), //暴击
comm.Cridam: int32(growCfg.Cridam), //暴击伤害
comm.Effhit: int32(growCfg.Effhit), //效果命中
comm.Effre: int32(growCfg.Effre), //效果抵抗
comm.LostHold: int32(growCfg.Losthold), //失手率%
comm.UnderStand: int32(growCfg.Understand), //会心率%
comm.DamRe: int32(growCfg.Damre), //伤害减免%
comm.CauseDam: int32(growCfg.Causedam), //伤害提升%
comm.TreAdd: int32(growCfg.Treadd), //治疗加成%
comm.BeTreAdd: int32(growCfg.Betreadd), //受疗加成%
comm.SuckBlood: int32(growCfg.Suckblood), //吸血加成%
}
if hero.Id != "" { // objID 为空表示是怪物对象 不享受天赋属性加成
this.resetTalentProperty(hero)
this.module.moduleHoroscope.ComputeHeroNumeric(hero.Uid, hero)
}
this.resetJuexingProperty(hero)
}
// 重新计算英雄属性
func (this *ModelHero) ChangeHeroProperty(session comm.IUserSession, hero *pb.DBHero) (err error) {
this.PropertyCompute(hero) //重新计算 property 的值
update := map[string]interface{}{
"property": hero.Property,
"talentProperty": hero.TalentProperty,
"juexProperty": hero.JuexProperty,
"horoscopeProperty": hero.HoroscopeProperty,
}
if err = this.ChangeList(session.GetUserId(), hero.Id, update); err != nil {
this.module.Errorf("ChangeHeroProperty err:%v", err)
return
}
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, hero *pb.DBHero, exp int32, model *db.DBModel) (curAddExp int32, errdata *pb.ErrorData) {
var (
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
}
update = make(map[string]interface{}, 0)
curExp = hero.Exp
curLv = hero.Lv
preLv = curLv
var maxLv int32 // 校验等级达到上限
maxLv = this.module.configure.GetHeroMaxLv(hero.Star)
// 校验玩家等级
if _user := this.module.ModuleUser.GetUser(session.GetUserId()); _user != nil {
if expConf := this.module.configure.GetPlayerlvConf(_user.Lv); expConf != nil {
if maxLv > expConf.HeroLv {
maxLv = expConf.HeroLv // 英雄最大等级限制
}
}
}
_data := this.module.configure.GetHeroLv(curLv)
if _data != nil {
var maxExp int32
maxExp = _data.Heroexp
if maxLv <= curLv && curExp >= maxExp { // 加经验之前校验是否达到最大等级
curAddExp = 0 // 已经满级的时候
//code = pb.ErrorCode_HeroMaxLv //
this.module.Debugf("英雄已经满级 不需要升级heroid:%s,addexp:%d", hero.Id, exp)
return
}
curExp += exp // 先把经验加上
for { // 死循环判断一键升级
if _data.Heroexp == 0 {
curAddExp = exp - (curExp - maxExp) // 减去超过部分的经验
curExp = 0
break
}
maxExp = _data.Heroexp
if maxLv <= curLv && curExp >= maxExp { // 设置最大经验和等级
curAddExp = 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 { // 等级加失败了 回到原来的等级
curLv -= 1
break
}
}
}
if curAddExp != 0 {
curAddExp = exp // 真正加的经验
}
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 { // 升级了 统计任务
this.PropertyCompute(hero)
update["property"] = hero.Property
update["horoscopeProperty"] = hero.HoroscopeProperty
update["talentProperty"] = hero.TalentProperty
update["juexProperty"] = hero.JuexProperty
}
if model != nil {
if err := model.ChangeList(session.GetUserId(), hero.Id, update); err != nil {
this.module.Errorf("add hero exp failed ChangeList %v", err)
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Title: pb.ErrorCode_DBError.ToString(),
Message: err.Error(),
}
}
} else {
if err := this.ChangeList(session.GetUserId(), hero.Id, update); err != nil {
this.module.Errorf("add hero exp failed ChangeList %v", err)
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Title: pb.ErrorCode_DBError.ToString(),
Message: err.Error(),
}
}
}
if curLv-preLv > 0 { // 升级了 统计任务
var szTask []*pb.BuriedParam
szTask = append(szTask, comm.GetBuriedParam(comm.Rtype147, utils.ToInt32(hero.HeroID), curLv-preLv))
szTask = append(szTask, comm.GetBuriedParam(comm.Rtype113, curLv-preLv))
szTask = append(szTask, comm.GetBuriedParam(comm.Rtype4, hero.Lv, utils.ToInt32(hero.HeroID)))
szTask = append(szTask, comm.GetBuriedParam2(comm.Rtype23, hero.HeroID, hero.Star, hero.Lv))
szTask = append(szTask, comm.GetBuriedParam(comm.Rtype24, 1))
// szTask = append(szTask, comm.GetBuriedParam(comm.Rtype29, 1, hero.Lv, utils.ToInt32(hero.HeroID)))
szTask = append(szTask, comm.GetBuriedParam2(comm.Rtype23, hero.HeroID, hero.Star, hero.Lv))
if cfg, _ := this.module.configure.GetHeroConfig(hero.HeroID); cfg != nil {
szTask = append(szTask, comm.GetBuriedParam2(comm.Rtype32, hero.HeroID, cfg.Color, hero.Lv))
//xx英雄满级、共鸣、觉醒至最高状态
nextAwaken, _ := this.module.configure.GetHeroAwakenConfig(hero.HeroID, hero.JuexingLv+1)
if nextAwaken == nil { // 达到满级觉醒
if hero.Lv == this.module.configure.GetHeroMaxLv(hero.Star) {
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 this.module.configure.GetHeroTalentMaxLv(hero.HeroID) == _l {
szTask = append(szTask, comm.GetBuriedParam2(comm.Rtype37, hero.HeroID, cfg.Color))
szTask = append(szTask, comm.GetBuriedParam2(comm.Rtype38, hero.HeroID))
}
}
}
}
szTask = append(szTask, comm.GetBuriedParam2(comm.Rtype111, hero.HeroID, hero.Lv))
szTask = append(szTask, comm.GetBuriedParam(comm.Rtype112, 1, hero.Lv))
szTask = append(szTask, comm.GetBuriedParam(comm.Rtype113, hero.Lv))
szTask = append(szTask, comm.GetBuriedParam(comm.Rtype33, 1, 1, hero.Lv))
szTask = append(szTask, comm.GetBuriedParam(comm.Rtype118, hero.Lv, hero.JuexingLv))
go this.module.ModuleBuried.TriggerBuried(session.GetUserId(), szTask...)
}
}
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[string]int32),
Property: make(map[string]int32),
JuexProperty: make(map[string]int32),
TalentProperty: make(map[string]int32),
HoroscopeProperty: make(map[string]int32),
}
this.PropertyCompute(newHero)
this.initHeroSkill(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[string]int32)
}
if conf.Hp != -1 {
if _, ok := hero.TalentProperty[comm.Hp]; ok {
hero.TalentProperty[comm.Hp] += int32(math.Floor((float64(conf.Hp) / 1000) * float64(hero.Property[comm.Hp])))
} else {
hero.TalentProperty[comm.Hp] = int32(math.Floor((float64(conf.Hp) / 1000) * float64(hero.Property[comm.Hp])))
}
}
if conf.Atk != -1 {
if _, ok := hero.TalentProperty[comm.Atk]; ok {
hero.TalentProperty[comm.Atk] += int32(math.Floor((float64(conf.Atk) / 1000) * float64(hero.Property[comm.Atk])))
} else {
hero.TalentProperty[comm.Atk] = int32(math.Floor((float64(conf.Atk) / 1000) * float64(hero.Property[comm.Atk])))
}
}
if conf.Def != -1 {
if _, ok := hero.TalentProperty[comm.Def]; ok {
hero.TalentProperty[comm.Def] += int32(math.Floor((float64(conf.Def) / 1000) * float64(hero.Property[comm.Def])))
} else {
hero.TalentProperty[comm.Def] = int32(math.Floor((float64(conf.Def) / 1000) * float64(hero.Property[comm.Def])))
}
}
if conf.Cri != -1 {
if _, ok := hero.TalentProperty[comm.Cri]; ok {
hero.TalentProperty[comm.Cri] += int32(math.Floor((float64(conf.Cri) / 1000) * float64(hero.Property[comm.Cri])))
} else {
hero.TalentProperty[comm.Cri] = int32(math.Floor((float64(conf.Cri) / 1000) * float64(hero.Property[comm.Cri])))
}
}
if conf.Speed != -1 {
if _, ok := hero.TalentProperty[comm.Speed]; ok {
hero.TalentProperty[comm.Speed] += int32(math.Floor((float64(conf.Speed) / 1000) * float64(hero.Property[comm.Speed])))
} else {
hero.TalentProperty[comm.Speed] = int32(math.Floor((float64(conf.Speed) / 1000) * float64(hero.Property[comm.Speed])))
}
}
_heroMap := make(map[string]interface{}, 0)
if conf.Skill != 0 {
hero.NormalSkill = append(hero.NormalSkill, &pb.SkillData{
SkillID: conf.Skill,
SkillLv: 1,
})
_heroMap["normalSkill"] = hero.NormalSkill
}
_heroMap["talentProperty"] = hero.TalentProperty
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[string]int32{}
_heroMap := make(map[string]interface{}, 0)
_heroMap["talentProperty"] = hero.TalentProperty
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) {
var (
attr [5]int32
)
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 { //获取天赋树
if conf.Hp != -1 {
attr[0] += conf.Hp
}
if conf.Atk != -1 {
attr[1] += conf.Atk
}
if conf.Def != -1 {
attr[2] += conf.Def
}
if conf.Cri != -1 {
attr[3] += conf.Cri
}
if conf.Speed != -1 {
attr[4] += conf.Speed
}
}
}
break
}
}
}
hero.TalentProperty = make(map[string]int32)
for k, v := range attr {
if v != 0 {
switch k {
case 0:
hero.TalentProperty[comm.Hp] = int32(math.Floor((float64(v) / 1000) * float64(hero.Property[comm.Hp])))
case 1:
hero.TalentProperty[comm.Atk] = int32(math.Floor((float64(v) / 1000) * float64(hero.Property[comm.Atk])))
case 2:
hero.TalentProperty[comm.Def] = int32(math.Floor((float64(v) / 1000) * float64(hero.Property[comm.Def])))
case 3:
hero.TalentProperty[comm.Cri] = int32(math.Floor((float64(v) / 1000) * float64(hero.Property[comm.Cri])))
case 4:
hero.TalentProperty[comm.Speed] = int32(math.Floor((float64(v) / 1000) * float64(hero.Property[comm.Speed])))
}
}
}
}
// 创建一条英雄信息,如果有这个英雄 则转换成对应的碎片
func (this *ModelHero) createHero(session comm.IUserSession, heroCfgId string, count int32) (hero *pb.DBHero, bFirst bool, atno []*pb.UserAtno, err error) {
heros := make([]*pb.DBHero, 0)
uid := session.GetUserId()
heroCfg, _ := this.module.configure.GetHeroConfig(heroCfgId)
if heroCfg == nil {
err = errors.New("not found hero configID")
this.module.Errorf("not found hero configID:%s", heroCfgId)
return
}
if this.module.IsCross() {
if dbModel, err1 := this.module.GetDBModelByUid(uid, this.TableName); err1 == nil {
if err = dbModel.GetList(uid, &heros); err != nil {
this.module.Errorf("err:%v", err)
return
}
} else {
this.module.Errorln(err) // 获取跨服对象失败
return
}
} else {
if err = this.GetList(uid, &heros); err != nil {
this.module.Errorf("err:%v", err)
}
}
bFirst = true
for _, obj := range heros {
if obj.HeroID == heroCfgId {
hero = obj
bFirst = false
atno = append(atno, &pb.UserAtno{ // 有英雄的时候 数量给0
A: "hero",
T: hero.HeroID,
N: 0,
O: hero.Id,
})
break
}
}
if bFirst { // 没有当前英雄
count -= 1
hero, err = this.initHeroOverlying(uid, heroCfgId, 1)
if err != nil {
return
}
atno = append(atno, &pb.UserAtno{
A: "hero",
T: hero.HeroID,
N: 1,
O: hero.Id,
})
}
res := make([]*cfg.Gameatn, 0)
rst, err := this.module.ModuleUser.GetUserExpand(session.GetUserId())
if err != nil {
return
}
if rst.Expitem == nil {
rst.Expitem = make(map[string]int32)
}
if rst.Herofrag == nil {
rst.Herofrag = make(map[string]int32)
}
bChange := false
// 转碎片处理
for i := 0; int32(i) < count; i++ {
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...)
for _, v := range heroCfg.Herofrag {
atno = append(atno, &pb.UserAtno{
A: v.A,
T: v.T,
N: v.N,
})
}
} else {
list := this.module.ModuleTools.GetGlobalConf().Moonshopmoney
if list != nil {
for pos, v := range list {
if int32(pos)+3 == heroCfg.Star && v > 0 {
res = append(res, &cfg.Gameatn{
A: "attr",
T: "moongold",
N: v,
})
atno = append(atno, &pb.UserAtno{
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...)
for _, v := range heroCfg.Expitem {
atno = append(atno, &pb.UserAtno{
A: v.A,
T: v.T,
N: v.N,
})
}
}
}
if bChange {
this.module.ModuleUser.ChangeUserExpand(session.GetUserId(), map[string]interface{}{
"herofrag": rst.Herofrag,
"expitem": rst.Expitem,
})
}
if len(res) > 0 { // 资源统一发放
this.module.DispenseRes(session, res, true)
}
return
}
// 校验当前技能是否是满级
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[string]int32, 0)
}
for _, key := range attr {
value := key.N
switch key.A {
case comm.Hp:
hero.Fetters[comm.Hp] += value
case comm.Def:
hero.Fetters[comm.Def] += value
case comm.Atk:
hero.Fetters[comm.Atk] += value
case comm.Speed:
hero.Fetters[comm.Speed] += value
case comm.HpPro:
hero.Fetters[comm.Hp] += int32(math.Floor((float64(value) / 1000) * float64(hero.Property[comm.Hp])))
case comm.AtkPro:
hero.Fetters[comm.Atk] += int32(math.Floor((float64(value) / 1000) * float64(hero.Property[comm.Atk])))
case comm.DefPro:
hero.Fetters[comm.Def] += int32(math.Floor((float64(value) / 1000) * float64(hero.Property[comm.Def])))
default:
this.module.Errorf("unkonw hero fetter property:%v", key)
}
}
}