935 lines
29 KiB
Go
935 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
|
|
moduleHero *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.moduleHero = 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.moduleHero.configure.GetHeroConfig(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, 8), //初始装备
|
|
SameCount: 1, //默认叠加数量
|
|
AddProperty: make(map[string]int32),
|
|
Energy: make(map[string]int32),
|
|
Property: make(map[string]int32),
|
|
EnergyProperty: 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) initHeroSkill(hero *pb.DBHero) []*pb.SkillData {
|
|
heroCfg := this.moduleHero.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) createOneHero(uid string, heroCfgId string) (hero *pb.DBHero, err error) {
|
|
hero = this.InitHero(uid, heroCfgId)
|
|
if hero != nil {
|
|
if err = this.AddList(uid, hero.Id, hero); err != nil {
|
|
this.moduleHero.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.moduleHero.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 {
|
|
hero.SameCount = 1 // 新需求 不需要判断叠加
|
|
if this.moduleHero.IsCross() {
|
|
if model, err = this.moduleHero.GetDBModuleByUid(uid, this.TableName, this.Expired); err != nil {
|
|
this.moduleHero.Errorln(err)
|
|
} else {
|
|
if err = model.AddList(uid, hero.Id, hero); err != nil {
|
|
this.moduleHero.Errorf("err:%v", err)
|
|
}
|
|
}
|
|
} else {
|
|
if err = this.AddList(uid, hero.Id, hero); err != nil {
|
|
this.moduleHero.Errorln(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 该方法适用创建初始英雄 叠加英雄 count叠加数量
|
|
func (this *ModelHero) createHeroOverlying(uid string, heroCfgId string, count int32) (hero *pb.DBHero, err error) {
|
|
heros := make([]*pb.DBHero, 0)
|
|
if this.moduleHero.IsCross() {
|
|
if dbModel, err := this.moduleHero.GetDBModuleByUid(uid, this.TableName, this.Expired); err != nil {
|
|
this.moduleHero.Errorln(err)
|
|
|
|
} else {
|
|
if err = dbModel.GetList(uid, &heros); err != nil {
|
|
this.moduleHero.Errorf("err:%v", err)
|
|
}
|
|
}
|
|
} else {
|
|
if err = this.GetList(uid, &heros); err != nil {
|
|
this.moduleHero.Errorf("err:%v", err)
|
|
}
|
|
}
|
|
for _, obj := range heros {
|
|
if obj.HeroID == heroCfgId { // z
|
|
return
|
|
}
|
|
}
|
|
for _, h := range heros {
|
|
if h.HeroID == heroCfgId &&
|
|
h.IsOverlying {
|
|
h.SameCount += count
|
|
data := map[string]interface{}{
|
|
"sameCount": h.SameCount, //叠加数
|
|
}
|
|
hero = h
|
|
|
|
if this.moduleHero.IsCross() {
|
|
if model, err := this.moduleHero.GetDBModuleByUid(uid, this.TableName, this.Expired); err != nil {
|
|
this.moduleHero.Errorln(err)
|
|
} else {
|
|
if err := model.ChangeList(uid, h.Id, data); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
} else {
|
|
if err := this.ChangeList(uid, h.Id, data); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
return this.initHeroOverlying(uid, heroCfgId, count)
|
|
}
|
|
|
|
//获取一个英雄(参数唯一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, count int32) (err error) {
|
|
if count == 0 {
|
|
return
|
|
}
|
|
|
|
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 // 数量-1
|
|
if hero.SameCount == 0 {
|
|
if err := this.DelListlds(uid, hero.Id); err != nil {
|
|
this.moduleHero.Errorf("%v", err)
|
|
}
|
|
} else {
|
|
update := map[string]interface{}{
|
|
"sameCount": hero.SameCount,
|
|
}
|
|
err = this.ChangeList(uid, hero.Id, update)
|
|
}
|
|
this.moduleHero.Debugf("删除%d张卡牌uid:%s,卡牌ID:%s", count, 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 := this.moduleHero.configure.GetHeroAwakenConfig(hero.HeroID, int32(i))
|
|
if awakenData != 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.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) 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) setEnergyProperty(hero *pb.DBHero, star int32) {
|
|
|
|
resonConfig := this.moduleHero.configure.GetHeroResonanceConfig(hero.HeroID, star)
|
|
if resonConfig == nil {
|
|
return
|
|
}
|
|
EnergyProperty := make(map[string]int32) //副属性
|
|
for k, v := range hero.Energy {
|
|
if k == comm.ResonanceHpPro {
|
|
EnergyProperty[comm.Hp] += int32(math.Floor(float64(resonConfig.Hppro*v) / 1000 * float64(hero.Property[comm.Hp])))
|
|
} else if k == comm.ResonanceAtkPro {
|
|
EnergyProperty[comm.Atk] += int32(math.Floor(float64(resonConfig.Atkpro*v) / 1000 * float64(hero.Property[comm.Atk])))
|
|
} else if k == comm.ResonanceDefPro {
|
|
EnergyProperty[comm.Def] += int32(math.Floor(float64(resonConfig.Defpro*v) / 1000 * float64(hero.Property[comm.Def])))
|
|
}
|
|
}
|
|
_heroMap := make(map[string]interface{}, 0)
|
|
_heroMap["enegryProperty"] = EnergyProperty
|
|
if err := this.ChangeList(hero.Uid, hero.Id, _heroMap); err != nil {
|
|
this.moduleHero.Errorf("mergeenegryProperty err %v", err)
|
|
}
|
|
}
|
|
|
|
// 设置装备属性
|
|
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,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
if hero.SuiteId != 0 { //套装
|
|
if configure, err := this.moduleHero.configure.GetEquipsuit(hero.SuiteId); err != nil {
|
|
this.moduleHero.Errorln(err)
|
|
} else {
|
|
for k, v := range configure.SetBonuses {
|
|
addProperty[k] += v
|
|
}
|
|
}
|
|
}
|
|
if hero.SuiteExtId != 0 { //套装
|
|
if configure, err := this.moduleHero.configure.GetEquipsuit(hero.SuiteExtId); err != nil {
|
|
this.moduleHero.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
|
|
}
|
|
var (
|
|
_suiteId int32
|
|
_equipID []string
|
|
_suiteExtId int32
|
|
)
|
|
update := make(map[string]interface{})
|
|
|
|
_suiteId = hero.SuiteId
|
|
_equipID = hero.EquipID
|
|
_suiteExtId = hero.SuiteExtId
|
|
suite1Star := hero.Suite1Star
|
|
suite2Star := hero.Suite2Star
|
|
suite1Lv := hero.Suite1Lv
|
|
suite2Lv := hero.Suite2Lv
|
|
if hero.IsOverlying && hero.SameCount > 1 {
|
|
// 克隆一个新的
|
|
hero.SameCount -= 1
|
|
hero.Suite1Star = 0
|
|
hero.Suite2Star = 0
|
|
hero.Suite1Lv = 0
|
|
hero.Suite2Lv = 0
|
|
hero.SuiteId = 0
|
|
hero.SuiteExtId = 0
|
|
hero.EquipID = make([]string, 8)
|
|
newHero = this.CloneNewHero(uid, hero)
|
|
hero.EquipID = make([]string, 8)
|
|
hero.SameCount = 1
|
|
hero.IsOverlying = false
|
|
update["isoverlying"] = false
|
|
update["sameCount"] = 1
|
|
update["horoscopeProperty"] = hero.HoroscopeProperty
|
|
}
|
|
// 修改装备属性 并更新
|
|
update["suiteId"] = _suiteId
|
|
update["suiteExtId"] = _suiteExtId
|
|
update["equipID"] = _equipID
|
|
update["suite1Star"] = suite1Star
|
|
update["suite2Star"] = suite2Star
|
|
update["suite1Lv"] = suite1Lv
|
|
update["suite2Lv"] = suite2Lv
|
|
|
|
if err = this.ChangeList(hero.Uid, hero.Id, update); err != nil {
|
|
this.moduleHero.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.moduleHero.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.moduleHero.Errorf("mergeAddProperty err %v", err)
|
|
}
|
|
}
|
|
|
|
func (this *ModelHero) StarAtkAddition(star int32) (addValue float32) {
|
|
for i := 1; i <= int(star); i++ {
|
|
starCfg := this.moduleHero.configure.GetHeroStar(int32(i))
|
|
cfg := this.moduleHero.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.moduleHero.configure.GetHeroStar(int32(i))
|
|
cfg := this.moduleHero.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.moduleHero.configure.GetHeroStar(int32(i))
|
|
cfg := this.moduleHero.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.moduleHero.configure.GetHeroLvgrow(hero.HeroID)
|
|
heroCfg := this.moduleHero.configure.GetHeroConfig(hero.HeroID)
|
|
lvCfg := this.moduleHero.configure.GetHeroLv(hero.Lv)
|
|
starCfg := this.moduleHero.configure.GetHeroStar(hero.Star)
|
|
starLvfg := this.moduleHero.configure.GetHeroLv(starCfg.Level)
|
|
if growCfg == nil || heroCfg == nil || lvCfg == nil || starCfg == nil || starLvfg == nil {
|
|
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.Effhit: int32(growCfg.Effhit), //效果命中
|
|
comm.Cridam: int32(growCfg.Cridam), //暴击伤害
|
|
comm.Effre: int32(growCfg.Effre), //效果抵抗
|
|
}
|
|
|
|
if hero.Id != "" { // objID 为空表示是怪物对象 不享受天赋属性加成
|
|
this.resetTalentProperty(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,
|
|
}
|
|
|
|
if err = this.ChangeList(session.GetUserId(), hero.Id, update); err != nil {
|
|
this.moduleHero.Errorf("ChangeHeroProperty err:%v", err)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (this *ModelHero) cleanData(uid string) {
|
|
userList := this.moduleHero.GetHeroList(uid)
|
|
for _, v := range userList {
|
|
if err := this.DelListlds(uid, v.Id); err != nil {
|
|
this.moduleHero.Errorf("cleanData err:%v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (this *ModelHero) AddCardExp(session comm.IUserSession, hero *pb.DBHero, exp int32) (newhero *pb.DBHero, curAddExp int32, code pb.ErrorCode) {
|
|
var (
|
|
preLv int32 //加经验之前的等级
|
|
curExp int32 // 加经验之后的经验
|
|
curLv int32 // 加经验之后的等级
|
|
update map[string]interface{} // 属性变化
|
|
)
|
|
if hero == nil {
|
|
code = pb.ErrorCode_HeroNoExist
|
|
return
|
|
}
|
|
update = make(map[string]interface{}, 0)
|
|
curExp = hero.Exp
|
|
curLv = hero.Lv
|
|
preLv = curLv
|
|
var maxLv int32 // 校验等级达到上限
|
|
maxLv = hero.Star * comm.HeroStarLvRatio
|
|
_data := this.moduleHero.configure.GetHeroLv(curLv)
|
|
if _data != nil {
|
|
var maxExp int32
|
|
maxExp = _data.Heroexp
|
|
if maxLv <= curLv && curExp >= maxExp { // 加经验之前校验是否达到最大等级
|
|
curAddExp = 0 // 已经满级的时候
|
|
code = pb.ErrorCode_HeroMaxLv
|
|
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.moduleHero.configure.GetHeroLv(curLv)
|
|
if _data == nil { // 等级加失败了 回到原来的等级
|
|
curLv -= 1
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if curAddExp != 0 {
|
|
curAddExp = exp // 真正加的经验
|
|
}
|
|
if hero.SameCount > 1 { //有堆叠的情况
|
|
hero.SameCount -= 1
|
|
newhero = this.CloneNewHero(session.GetUserId(), hero) // 克隆一个新的
|
|
}
|
|
this.moduleHero.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
|
|
update["isOverlying"] = false
|
|
update["sameCount"] = 1
|
|
update["horoscopeProperty"] = hero.HoroscopeProperty
|
|
hero.Lv = curLv
|
|
hero.Exp = curExp
|
|
hero.IsOverlying = false
|
|
hero.SameCount = 1
|
|
|
|
if err := this.ChangeList(session.GetUserId(), hero.Id, update); err != nil {
|
|
this.moduleHero.Errorf("add hero exp failed ChangeList %v", err)
|
|
code = pb.ErrorCode_DBError
|
|
}
|
|
if curLv-preLv > 0 { // 升级了 统计任务
|
|
this.ChangeHeroProperty(session, hero) // 重新计算属性值
|
|
// 推送
|
|
this.moduleHero.ModuleRtask.SendToRtask(session, comm.Rtype147, utils.ToInt32(hero.HeroID), curLv-preLv)
|
|
this.moduleHero.ModuleRtask.SendToRtask(session, comm.Rtype113, utils.ToInt32(hero.HeroID), curLv-preLv)
|
|
this.moduleHero.ModuleRtask.SendToRtask(session, comm.Rtype4, utils.ToInt32(hero.HeroID), hero.Lv)
|
|
this.moduleHero.ModuleRtask.SendToRtask(session, comm.Rtype23, 1, hero.Star, hero.Lv)
|
|
this.moduleHero.ModuleRtask.SendToRtask(session, comm.Rtype24, 1)
|
|
this.moduleHero.ModuleRtask.SendToRtask(session, comm.Rtype29, 1, hero.Lv, utils.ToInt32(hero.HeroID))
|
|
cfg := this.moduleHero.configure.GetHeroConfig(hero.HeroID)
|
|
if cfg != nil {
|
|
this.moduleHero.ModuleRtask.SendToRtask(session, comm.Rtype32, 1, cfg.Color, hero.Lv)
|
|
this.moduleHero.ModuleRtask.SendToRtask(session, comm.Rtype36, 1, cfg.Color, cfg.Job, cfg.Race, hero.JuexingLv)
|
|
//xx英雄满级、共鸣、觉醒至最高状态
|
|
nextAwaken := this.moduleHero.configure.GetHeroAwakenConfig(hero.HeroID, hero.JuexingLv+1)
|
|
if nextAwaken == nil { // 达到满级觉醒
|
|
resonConfig := this.moduleHero.configure.GetHeroResonanceConfig(hero.HeroID, cfg.Star)
|
|
if resonConfig != nil && resonConfig.Maxnum == hero.ResonateNum { // 共鸣满
|
|
if hero.Lv == hero.Star*comm.HeroStarLvRatio {
|
|
this.moduleHero.ModuleRtask.SendToRtask(session, comm.Rtype37, 1, cfg.Color)
|
|
this.moduleHero.ModuleRtask.SendToRtask(session, comm.Rtype38, 1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.moduleHero.ModuleRtask.SendToRtask(session, comm.Rtype33, 1, 1, hero.Lv)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 玩家离线 清除缓存
|
|
func (this *ModelHero) RemoveUserHeroInfo(session comm.IUserSession) (err error) {
|
|
this.BatchDelLists(session.GetUserId())
|
|
return
|
|
}
|
|
|
|
func (this *ModelHero) CheckPool(drawCount int32, config *cfg.GameGlobalData) (pools string) {
|
|
if config.BasePool1.S <= drawCount && config.BasePool1.E >= drawCount {
|
|
return config.BasePool1.P
|
|
} else if config.BasePool2.S <= drawCount && config.BasePool2.E >= drawCount {
|
|
return config.BasePool2.P
|
|
} else if config.BasePool3.S <= drawCount && config.BasePool3.E >= drawCount {
|
|
return config.BasePool3.P
|
|
} else if config.BasePool4.S <= drawCount && config.BasePool4.E >= drawCount {
|
|
return config.BasePool4.P
|
|
} else if config.BasePool5.S <= drawCount && config.BasePool5.E >= drawCount {
|
|
return config.BasePool5.P
|
|
} else if config.BasePool6.S <= drawCount && config.BasePool6.E >= drawCount {
|
|
return config.BasePool6.P
|
|
}
|
|
|
|
return config.BasePool7.P
|
|
}
|
|
|
|
// 通数组里的权重随机命中 返回值为数组的下标
|
|
func (this *ModelHero) GetRandW(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) 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.moduleHero.configure.GetHeroConfig(heroCfgId)
|
|
if heroCfg == nil {
|
|
this.moduleHero.Errorf("%v hero not found from config %v", heroCfgId)
|
|
return nil
|
|
}
|
|
|
|
newHero := &pb.DBHero{
|
|
HeroID: heroCfg.Hid,
|
|
Star: star, //初始星级
|
|
Lv: lv, //初始等级
|
|
IsOverlying: true, //是否允许叠加,
|
|
Block: false, //未锁定
|
|
CardType: heroCfg.Type, //卡片类型
|
|
Skins: []int32{},
|
|
EquipID: make([]string, 8), //初始装备
|
|
SameCount: 1, //默认叠加数量
|
|
AddProperty: make(map[string]int32),
|
|
Energy: make(map[string]int32),
|
|
Property: make(map[string]int32),
|
|
EnergyProperty: 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.GameTalentSkillData) {
|
|
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)
|
|
_heroMap["talentProperty"] = hero.TalentProperty
|
|
if err := this.ChangeList(hero.Uid, hero.Id, _heroMap); err != nil {
|
|
this.moduleHero.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.moduleHero.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.moduleHero.modelTalent.GetHerotalent(hero.Uid); err != nil {
|
|
for _, v := range rst {
|
|
if v.HeroId == hero.HeroID { // 找到对应的英雄
|
|
for k := range v.Talent {
|
|
if conf := this.moduleHero.configure.GetHeroTalentSkill(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, err error) {
|
|
heros := make([]*pb.DBHero, 0)
|
|
uid := session.GetUserId()
|
|
if this.moduleHero.IsCross() {
|
|
if dbModel, err := this.moduleHero.GetDBModuleByUid(uid, this.TableName, this.Expired); err != nil {
|
|
this.moduleHero.Errorln(err)
|
|
|
|
} else {
|
|
if err = dbModel.GetList(uid, &heros); err != nil {
|
|
this.moduleHero.Errorf("err:%v", err)
|
|
}
|
|
}
|
|
} else {
|
|
if err = this.GetList(uid, &heros); err != nil {
|
|
this.moduleHero.Errorf("err:%v", err)
|
|
}
|
|
}
|
|
for _, obj := range heros {
|
|
if obj.HeroID == heroCfgId {
|
|
hero = obj
|
|
bFirst = false
|
|
break
|
|
}
|
|
}
|
|
if hero != nil { // 没有当前英雄
|
|
count -= 1
|
|
hero, err = this.initHeroOverlying(uid, heroCfgId, 1)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
// 转碎片处理
|
|
if count > 0 {
|
|
heroCfg := this.moduleHero.configure.GetHeroConfig(heroCfgId)
|
|
if heroCfg != nil {
|
|
res := make([]*cfg.Gameatn, 0)
|
|
for i := 0; i < int(count); i++ {
|
|
res = append(res, heroCfg.Herofrag...)
|
|
}
|
|
this.moduleHero.DispenseRes(session, res, true)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|