3137 lines
94 KiB
Go
3137 lines
94 KiB
Go
package model
|
||
|
||
import (
|
||
"rocommon/util"
|
||
"roserver/baseserver/model"
|
||
"roserver/baseserver/set"
|
||
"roserver/serverproto"
|
||
"sort"
|
||
"time"
|
||
)
|
||
|
||
func (this *Role) GetActorAttr(reqMsg *serverproto.CSActorAttrGetReq) {
|
||
retCode := serverproto.ErrorCode_ERROR_FAIL
|
||
if this.roleBattleAttr != nil {
|
||
retCode = this.roleBattleAttr.GetActorAttr(reqMsg.ActorList, reqMsg.IsAllBattle, true)
|
||
}
|
||
if retCode != serverproto.ErrorCode_ERROR_OK {
|
||
ackMsg := &serverproto.SCActorAttrGetAck{
|
||
Error: int32(retCode),
|
||
}
|
||
this.ReplayGate(ackMsg, true)
|
||
}
|
||
}
|
||
|
||
//属性变更类型
|
||
const (
|
||
Attr_Change_None = 0
|
||
Attr_Change_Fashion = 1 //时装数据变更
|
||
Attr_Change_Card = 2 //卡片
|
||
Attr_Change_Equip = 3 //装备
|
||
Attr_Change_Skill = 4 //技能
|
||
Attr_Change_AddPoint = 5 //属性点
|
||
Attr_Change_Advance = 6 //进阶
|
||
Attr_Change_Strength = 7 //突破
|
||
Attr_Change_Pet = 8 //宠物继承给玩家属性
|
||
Attr_Change_HeadFrame = 9 //头像框添加属性
|
||
Attr_Change_Sake = 10 //收集屋藏品属性
|
||
Attr_Change_Skill_Equip_Slot = 11 //神器槽位属性变更
|
||
Attr_Change_Skill_Equip = 12 //神器槽位属性变更
|
||
Attr_Change_Head = 13 //称号属性
|
||
|
||
Attr_Change_Pet_Base = 20 //宠物自身
|
||
Attr_Change_Pet_Bond = 21 //宠物羁绊属性
|
||
Attr_Change_Pet_Equip = 22 //宠物印记(装备)
|
||
Attr_Change_Pet_Skill = 23 //只涉及到宠物战力变更
|
||
Attr_Change_Pet_Qiyue = 25 //契约属性
|
||
)
|
||
const s_AttrNum = 30
|
||
|
||
type ProfessionData struct {
|
||
hpRate float32
|
||
spRate float32
|
||
atkRate float32
|
||
magicAtkRate float32
|
||
defRate float32
|
||
magicDefRate float32
|
||
hitRate float32
|
||
dodgeRate float32
|
||
critRate float32
|
||
tenacityRate float32
|
||
attackSpeed float32
|
||
}
|
||
type ActorAttr struct {
|
||
attrMag *RoleBattleAttr
|
||
isMainHero bool
|
||
isPet bool
|
||
heroId int32 //英雄动态ID(宠物动态ID)
|
||
heroConfigId int32
|
||
level int32
|
||
advLevel int32
|
||
strengthLevel int32
|
||
changeSetList set.Interface
|
||
pData ProfessionData
|
||
positionValue int32
|
||
|
||
baseStr int32
|
||
baseAgi int32
|
||
baseInt int32
|
||
baseVit int32
|
||
baseDex int32
|
||
baseLuk int32
|
||
|
||
//基础二级属性
|
||
attrs map[serverproto.Attr]float32
|
||
|
||
triggerBuffList map[uint32]*serverproto.TriggerBuffData
|
||
normalSKillList []*serverproto.KeyValueType
|
||
useSkillList []*serverproto.KeyValueType
|
||
|
||
additionalAttrs map[serverproto.Attr]float64
|
||
extendAttrPercent map[serverproto.Attr]float32
|
||
//attrPercent [s_AttrNum]float32
|
||
attrPercent map[serverproto.Attr]float32
|
||
|
||
//hero
|
||
//计算后的属性
|
||
curAddPointAttr map[serverproto.Attr]float32 //属性点
|
||
curFashionAttr map[serverproto.Attr]float32 //时装
|
||
curCardAttr map[serverproto.Attr]float32 //卡片
|
||
curEquipAttr map[serverproto.Attr]float32 //装备
|
||
curAdvanceAttr map[serverproto.Attr]float32 //进阶
|
||
curStrengthAttr map[serverproto.Attr]float32 //强化
|
||
curPetAttr map[serverproto.Attr]float32 //宠物继承给玩家
|
||
curSkillAttr map[serverproto.Attr]float32 //技能升级添加属性
|
||
curHeadFrameAttr map[serverproto.Attr]float32 //头像框解锁添加属性
|
||
curSakeAttr map[serverproto.Attr]float32 //藏品添加属性
|
||
curSkillEquipAttr map[serverproto.Attr]float32 //神器槽位属性
|
||
curHeadAttr map[serverproto.Attr]float32 //称号属性
|
||
//pet
|
||
curPetAttrForPetBase map[serverproto.Attr]float32 //宠物自身base(level + advLevel)
|
||
curPetAttrForPetBond map[serverproto.Attr]float32 //来自宠物羁绊的属性
|
||
curPetAttrForPetEquip map[serverproto.Attr]float32 //来自宠物印记的属性
|
||
curPetAttrForPetQiyue map[serverproto.Attr]float32 //宠物契约继承属性
|
||
|
||
//战力部分
|
||
curAttrFightPower uint64 //根据属性计算的战力
|
||
curSkillFightPower int64 //技能升级添加的战斗力
|
||
curSkillEquipFightPower int64 //神器添加的战斗力
|
||
}
|
||
type PetActorAttr struct {
|
||
//基础二级属性
|
||
attrs map[serverproto.Attr]float32
|
||
additionalAttrs map[serverproto.Attr]float32
|
||
extendAttrPercent map[serverproto.Attr]float32
|
||
//attrPercent [s_AttrNum]float32
|
||
attrPercent map[serverproto.Attr]float32
|
||
|
||
curEquipAttr map[serverproto.Attr]float32 //装备
|
||
}
|
||
|
||
func newActorAttr(mag *RoleBattleAttr, hId int32, heroConfigId int32, level int32, advLevel, strengthLevel int32) *ActorAttr {
|
||
actorAttr := &ActorAttr{
|
||
baseStr: 1,
|
||
baseAgi: 1,
|
||
baseInt: 1,
|
||
baseVit: 1,
|
||
baseDex: 1,
|
||
baseLuk: 1,
|
||
attrMag: mag,
|
||
heroId: hId,
|
||
heroConfigId: heroConfigId,
|
||
level: level,
|
||
|
||
attrs: map[serverproto.Attr]float32{},
|
||
triggerBuffList: map[uint32]*serverproto.TriggerBuffData{},
|
||
|
||
extendAttrPercent: map[serverproto.Attr]float32{},
|
||
additionalAttrs: map[serverproto.Attr]float64{},
|
||
attrPercent: map[serverproto.Attr]float32{},
|
||
|
||
curAddPointAttr: map[serverproto.Attr]float32{},
|
||
curFashionAttr: map[serverproto.Attr]float32{},
|
||
|
||
curEquipAttr: map[serverproto.Attr]float32{},
|
||
curCardAttr: map[serverproto.Attr]float32{},
|
||
curAdvanceAttr: map[serverproto.Attr]float32{},
|
||
curStrengthAttr: map[serverproto.Attr]float32{},
|
||
curPetAttr: map[serverproto.Attr]float32{},
|
||
curSkillAttr: map[serverproto.Attr]float32{},
|
||
curHeadFrameAttr: map[serverproto.Attr]float32{},
|
||
curSakeAttr: map[serverproto.Attr]float32{},
|
||
curSkillEquipAttr: map[serverproto.Attr]float32{},
|
||
curSkillFightPower: -1,
|
||
curSkillEquipFightPower: -1,
|
||
curPetAttrForPetQiyue: map[serverproto.Attr]float32{},
|
||
}
|
||
|
||
actorAttr.changeSetList = set.New(set.NonThreadSafe)
|
||
|
||
if mag.role.GetRoleHero().IsMainHero(hId) {
|
||
actorAttr.isMainHero = true
|
||
actorAttr.initJobAttr()
|
||
} else {
|
||
if parterCfgData, ok := serverproto.ParterCfgLoader[heroConfigId]; ok {
|
||
actorAttr.positionValue = parterCfgData.Position
|
||
}
|
||
}
|
||
actorAttr.resetAttrList(actorAttr.level, advLevel, strengthLevel)
|
||
|
||
return actorAttr
|
||
}
|
||
|
||
func newPetAttr(mag *RoleBattleAttr, petId int32, petConfigId int32, level, advLevel int32) *ActorAttr {
|
||
actorAttr := &ActorAttr{
|
||
attrMag: mag,
|
||
heroId: petId,
|
||
heroConfigId: petConfigId,
|
||
level: level,
|
||
advLevel: advLevel,
|
||
|
||
attrs: map[serverproto.Attr]float32{},
|
||
extendAttrPercent: map[serverproto.Attr]float32{},
|
||
additionalAttrs: map[serverproto.Attr]float64{},
|
||
attrPercent: map[serverproto.Attr]float32{},
|
||
|
||
curEquipAttr: map[serverproto.Attr]float32{},
|
||
curAdvanceAttr: map[serverproto.Attr]float32{},
|
||
|
||
curPetAttrForPetBase: map[serverproto.Attr]float32{},
|
||
curPetAttrForPetBond: map[serverproto.Attr]float32{},
|
||
curPetAttrForPetEquip: map[serverproto.Attr]float32{},
|
||
|
||
curSkillFightPower: -1,
|
||
}
|
||
actorAttr.changeSetList = set.New(set.NonThreadSafe)
|
||
actorAttr.isPet = true
|
||
//actorAttr.initJobAttr()
|
||
//actorAttr.resetAttrList(actorAttr.level, advLevel, 0)
|
||
|
||
return actorAttr
|
||
}
|
||
|
||
func (this *ActorAttr) getRole() *Role {
|
||
return this.attrMag.role
|
||
}
|
||
func (this *ActorAttr) getFormulaValue(paramId int32) float32 {
|
||
if paramData, ok := BattleFormulaList[paramId]; ok {
|
||
return paramData.val
|
||
}
|
||
return 0
|
||
}
|
||
func (this *ActorAttr) initJobAttr() {
|
||
if this.isMainHero {
|
||
if jobData, ok := serverproto.JobCfgLoader[this.heroConfigId]; ok {
|
||
this.pData.hpRate = float32(jobData.HpRate) * 0.0001
|
||
this.pData.spRate = float32(jobData.SpRate) * 0.0001
|
||
this.pData.atkRate = float32(jobData.AtkRate) * 0.0001
|
||
this.pData.magicAtkRate = float32(jobData.MatkRate) * 0.0001
|
||
this.pData.defRate = float32(jobData.DefRate) * 0.0001
|
||
this.pData.magicDefRate = float32(jobData.MdefRate) * 0.0001
|
||
this.pData.hitRate = float32(jobData.HitRate) * 0.0001
|
||
this.pData.dodgeRate = float32(jobData.DodgeRate) * 0.0001
|
||
this.pData.critRate = float32(jobData.CritRate) * 0.0001
|
||
this.pData.tenacityRate = float32(jobData.TenRate) * 0.0001
|
||
this.pData.attackSpeed = float32(jobData.Aspd)
|
||
|
||
this.positionValue = jobData.Position
|
||
}
|
||
} else if this.isPet {
|
||
if jobData, ok := serverproto.PetCfgLoader[this.heroConfigId]; ok {
|
||
this.pData.hpRate = float32(jobData.HpRate) * 0.0001
|
||
this.pData.spRate = float32(jobData.SpRate) * 0.0001
|
||
this.pData.atkRate = float32(jobData.AtkRate) * 0.0001
|
||
this.pData.magicAtkRate = float32(jobData.MatkRate) * 0.0001
|
||
this.pData.defRate = float32(jobData.DefRate) * 0.0001
|
||
this.pData.magicDefRate = float32(jobData.MdefRate) * 0.0001
|
||
this.pData.hitRate = float32(jobData.HitRate) * 0.0001
|
||
this.pData.dodgeRate = float32(jobData.DodgeRate) * 0.0001
|
||
this.pData.critRate = float32(jobData.CritRate) * 0.0001
|
||
this.pData.tenacityRate = float32(jobData.TenRate) * 0.0001
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *ActorAttr) resetAttrList(level int32, advLevel, strengthLevel int32) {
|
||
this.level = level
|
||
this.attrs = map[serverproto.Attr]float32{}
|
||
if this.isMainHero {
|
||
if attrData, ok := model.RoleAttrContainer[level]; ok {
|
||
for _, data := range attrData.AttrSet {
|
||
this.attrs[serverproto.Attr(data.Key)-serverproto.Attr_Life] = float32(data.Value)
|
||
}
|
||
}
|
||
} else if this.isPet {
|
||
if attrData, ok := model.RoleAttrContainer[level]; ok {
|
||
for _, data := range attrData.AttrSet {
|
||
this.attrs[serverproto.Attr(data.Key)-serverproto.Attr_Life] = float32(data.Value)
|
||
}
|
||
}
|
||
} else {
|
||
if attrData, ok := model.PartnerAttrContainer[this.heroConfigId]; ok {
|
||
for _, data := range attrData.AttrSet {
|
||
this.attrs[serverproto.Attr(data.Key)-serverproto.Attr_Life] = float32(data.Value)
|
||
}
|
||
}
|
||
|
||
////进阶属性
|
||
//partnerCfgDta,ok := serverproto.ParterCfgLoader[this.heroConfigId]
|
||
//if ok {
|
||
// progressAttrData,ok := model.ProgressAttrContainer[partnerCfgDta.ParterJob]
|
||
// if ok && advLevel > 0 {
|
||
// for key,val :=range progressAttrData.AttrSet {
|
||
// if key >= this.advLevel && key < advLevel {
|
||
// for k,v := range val {
|
||
// if k < int32(serverproto.Attr_STR_Percent) {
|
||
// this.additionalAttrs[serverproto.Attr(k)] += float32(v)
|
||
// }else{
|
||
// attrId := serverproto.Attr(k)
|
||
// if attrId >= serverproto.Attr_Nature_None_Damage_Percent &&
|
||
// attrId <= serverproto.Attr_VariableSingTime_Percent {
|
||
// this.extendAttrPercent[attrId] += float32(v)
|
||
// }else{
|
||
// this.attrPercent[attrId-serverproto.Attr_STR_Percent] += float32(v)
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
//
|
||
// //突破属性
|
||
// convertAttrData, ok := model.StrengthAttrContainer[partnerCfgDta.ParterJob]
|
||
// if ok && strengthLevel > 0 {
|
||
// for key,val :=range convertAttrData.AttrSet {
|
||
// if key >= this.strengthLevel && key < strengthLevel {
|
||
// for k,v := range val {
|
||
// if k < int32(serverproto.Attr_STR_Percent) {
|
||
// this.additionalAttrs[serverproto.Attr(k)] += float32(v)
|
||
// }else{
|
||
// attrId := serverproto.Attr(k)
|
||
// if attrId >= serverproto.Attr_Nature_None_Damage_Percent &&
|
||
// attrId <= serverproto.Attr_VariableSingTime_Percent {
|
||
// this.extendAttrPercent[attrId] += float32(v)
|
||
// }else{
|
||
// this.attrPercent[attrId-serverproto.Attr_STR_Percent] += float32(v)
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
//}
|
||
this.advLevel = advLevel
|
||
this.strengthLevel = strengthLevel
|
||
}
|
||
}
|
||
func (this *ActorAttr) isFront() bool {
|
||
return this.positionValue <= 3
|
||
}
|
||
|
||
//first
|
||
func (this *ActorAttr) STR() int32 {
|
||
return this.baseStr + int32(this.GetAdditionalAttr(serverproto.Attr_Str))
|
||
}
|
||
func (this *ActorAttr) AGI() int32 {
|
||
return this.baseAgi + int32(this.GetAdditionalAttr(serverproto.Attr_Agi))
|
||
}
|
||
func (this *ActorAttr) INT() int32 {
|
||
return this.baseInt + int32(this.GetAdditionalAttr(serverproto.Attr_Int))
|
||
}
|
||
func (this *ActorAttr) VIT() int32 {
|
||
return this.baseVit + int32(this.GetAdditionalAttr(serverproto.Attr_Vit))
|
||
}
|
||
func (this *ActorAttr) DEX() int32 {
|
||
return this.baseDex + int32(this.GetAdditionalAttr(serverproto.Attr_Dex))
|
||
}
|
||
func (this *ActorAttr) LUK() int32 {
|
||
return this.baseLuk + int32(this.GetAdditionalAttr(serverproto.Attr_Luk))
|
||
}
|
||
|
||
//second
|
||
func (this *ActorAttr) Life() float64 {
|
||
return this.calcSecondAttrForLife(serverproto.Attr_Life)
|
||
}
|
||
func (this *ActorAttr) Sp() float32 {
|
||
return this.calcSecondAttr(serverproto.Attr_Sp)
|
||
}
|
||
func (this *ActorAttr) Attack() float32 {
|
||
return this.calcSecondAttr(serverproto.Attr_Attack)
|
||
}
|
||
func (this *ActorAttr) MinAttack() float32 {
|
||
return this.Attack()
|
||
}
|
||
func (this *ActorAttr) MagicAttack() float32 {
|
||
return this.calcSecondAttr(serverproto.Attr_MagicAttack)
|
||
}
|
||
func (this *ActorAttr) MinMagicAttack() float32 {
|
||
return this.MagicAttack()
|
||
}
|
||
func (this *ActorAttr) Defense() float32 {
|
||
return this.calcSecondAttr(serverproto.Attr_Defense)
|
||
}
|
||
func (this *ActorAttr) MagicDefense() float32 {
|
||
return this.calcSecondAttr(serverproto.Attr_MagicDefense)
|
||
}
|
||
func (this *ActorAttr) Dodge() float32 {
|
||
return this.calcSecondAttr(serverproto.Attr_Dodge)
|
||
}
|
||
func (this *ActorAttr) Hit() float32 {
|
||
return this.calcSecondAttr(serverproto.Attr_Hit)
|
||
}
|
||
func (this *ActorAttr) Crit() float32 {
|
||
return this.calcSecondAttr(serverproto.Attr_Crit)
|
||
}
|
||
func (this *ActorAttr) Ten() float32 {
|
||
return this.calcSecondAttr(serverproto.Attr_Ten)
|
||
}
|
||
func (this *ActorAttr) AttackSpeed() float32 {
|
||
//return this.calcSecondAttr(serverproto.Attr_AttackSpeed)
|
||
p1 := this.getFormulaValue(24)
|
||
p2 := this.getFormulaValue(25)
|
||
//tempSpeed := this.getBaseSecondAttr(serverproto.Attr_AttackSpeed) + this.GetAdditionalAttr(serverproto.Attr_AttackSpeed)
|
||
//tempSpeed *= 1 + this.GetAdditionalAttrPercent(serverproto.Attr_AttackSpeed) + float32(this.AGI())*p1 + float32(this.DEX())*p2
|
||
tempSpeed := this.getBaseSecondAttr(serverproto.Attr_AttackSpeed) + float32(this.GetAdditionalAttr(serverproto.Attr_AttackSpeed))
|
||
tempSpeed += float32(this.AGI())*p1 + float32(this.DEX())*p2
|
||
return tempSpeed
|
||
}
|
||
func (this *ActorAttr) CastAcce() float32 {
|
||
return this.getBaseSecondAttr(serverproto.Attr_CastAcce)
|
||
//return this.calcSecondAttr(serverproto.Attr_CastAcce)
|
||
}
|
||
|
||
//暴击伤害百分比
|
||
func (this *ActorAttr) CritDamagePercent() float32 {
|
||
return this.GetAdditionalAttrPercent(serverproto.Attr_CritDamage_Percent)
|
||
}
|
||
|
||
//忽视物防
|
||
func (this *ActorAttr) Penetration() float32 {
|
||
return this.GetAdditionalAttrPercent(serverproto.Attr_Penetration_Percent)
|
||
}
|
||
|
||
//忽视魔防
|
||
func (this *ActorAttr) MagicPenetration() float32 {
|
||
return this.GetAdditionalAttrPercent(serverproto.Attr_Magic_Penetration_Percent)
|
||
}
|
||
|
||
//防御百分比
|
||
func (this *ActorAttr) DefPercent() float32 {
|
||
return this.GetAdditionalAttrPercent(serverproto.Attr_Defense_Percent)
|
||
}
|
||
|
||
//魔防百分比
|
||
func (this *ActorAttr) MagicDefPercent() float32 {
|
||
return this.GetAdditionalAttrPercent(serverproto.Attr_MagicDefense_Percent)
|
||
}
|
||
|
||
func (this *ActorAttr) baseLife() float32 {
|
||
p0 := this.getFormulaValue(1)
|
||
if this.isMainHero {
|
||
tmpf1 := this.getAttr(serverproto.Attr_Life)
|
||
tmpf2 := this.pData.hpRate
|
||
tmpf3 := 1 + float32(this.VIT())*p0
|
||
return tmpf1 * tmpf2 * tmpf3
|
||
//return this.getAttr(serverproto.Attr_Life) * this.pData.hpRate * (1 + float32(this.VIT())*p0)
|
||
} else {
|
||
//<!--《伙伴生命成长公式》 伙伴基础血量=HP+A*(LV^2-1)+B*(LV-1)-->
|
||
p1 := this.getFormulaValue(31)
|
||
p2 := this.getFormulaValue(32)
|
||
fLevel := float32(this.level)
|
||
tempLife := this.getAttr(serverproto.Attr_Life) + p1*(fLevel*fLevel-1) + p2*(fLevel-1)
|
||
tempLife = tempLife * (1 + float32(this.VIT())*p0)
|
||
return tempLife
|
||
}
|
||
}
|
||
func (this *ActorAttr) baseSp() float32 {
|
||
p0 := this.getFormulaValue(2)
|
||
if this.isMainHero {
|
||
return this.getAttr(serverproto.Attr_Sp) * this.pData.spRate * (1 + float32(this.INT())*p0)
|
||
} else {
|
||
p1 := this.getFormulaValue(33)
|
||
p2 := this.getFormulaValue(34)
|
||
fLevel := float32(this.level)
|
||
tempLife := this.getAttr(serverproto.Attr_Sp) + p1*(fLevel*fLevel-1) + p2*(fLevel-1)
|
||
return tempLife * (1 + float32(this.INT())*p0)
|
||
}
|
||
}
|
||
func (this *ActorAttr) baseAttack() float32 {
|
||
fAttack := this.getAttr(serverproto.Attr_Attack)
|
||
if this.isMainHero {
|
||
fAttack *= this.pData.atkRate
|
||
}
|
||
if this.isFront() { //近战处理
|
||
p1 := this.getFormulaValue(3)
|
||
p2 := this.getFormulaValue(4)
|
||
p3 := this.getFormulaValue(35)
|
||
fStr := float32(this.STR())
|
||
fDex := float32(this.DEX())
|
||
fLuk := float32(this.LUK())
|
||
iStr := int32(fStr * 0.1)
|
||
fAttack += p1*(fStr+p3*fDex+p3*fLuk) + p2*float32(iStr*iStr)
|
||
} else { //远程处理
|
||
p1 := this.getFormulaValue(5)
|
||
p2 := this.getFormulaValue(6)
|
||
p3 := this.getFormulaValue(36)
|
||
fStr := float32(this.STR())
|
||
fDex := float32(this.DEX())
|
||
fLuk := float32(this.LUK())
|
||
iDex := int32(fDex * 0.1)
|
||
fAttack += p1*(fDex+p3*fStr+p3*fLuk) + p2*float32(iDex*iDex)
|
||
}
|
||
return fAttack
|
||
}
|
||
func (this *ActorAttr) baseMagicAttack() float32 {
|
||
p1 := this.getFormulaValue(7)
|
||
p2 := this.getFormulaValue(8)
|
||
fInt := float32(this.INT())
|
||
iInt := int32(fInt * 0.1)
|
||
magicAttack := this.getAttr(serverproto.Attr_MagicAttack)
|
||
if this.isMainHero {
|
||
magicAttack *= this.pData.magicAtkRate
|
||
}
|
||
magicAttack += fInt*p1 + p2*float32(iInt*iInt)
|
||
return magicAttack
|
||
}
|
||
func (this *ActorAttr) baseDefense() float32 {
|
||
p1 := this.getFormulaValue(9)
|
||
defense := this.getAttr(serverproto.Attr_Defense)
|
||
if this.isMainHero {
|
||
defense *= this.pData.defRate
|
||
}
|
||
defense = defense + p1*float32(this.VIT())
|
||
return defense
|
||
}
|
||
func (this *ActorAttr) baseMagicDefense() float32 {
|
||
p1 := this.getFormulaValue(10)
|
||
magicDefense := this.getAttr(serverproto.Attr_MagicDefense)
|
||
if this.isMainHero {
|
||
magicDefense *= this.pData.magicDefRate
|
||
}
|
||
magicDefense = magicDefense + p1*float32(this.INT())
|
||
return magicDefense
|
||
}
|
||
func (this *ActorAttr) baseDodge() float32 {
|
||
p1 := this.getFormulaValue(11)
|
||
dodge := this.getAttr(serverproto.Attr_Dodge)
|
||
if this.isMainHero {
|
||
dodge *= this.pData.dodgeRate
|
||
}
|
||
dodge = dodge + p1*float32(this.AGI())
|
||
return dodge
|
||
}
|
||
func (this *ActorAttr) baseHit() float32 {
|
||
p1 := this.getFormulaValue(12)
|
||
hit := this.getAttr(serverproto.Attr_Hit)
|
||
if this.isMainHero {
|
||
hit *= this.pData.hitRate
|
||
}
|
||
hit = hit + p1*float32(this.DEX())
|
||
return hit
|
||
}
|
||
func (this *ActorAttr) baseCrit() float32 {
|
||
p1 := this.getFormulaValue(13)
|
||
crit := this.getAttr(serverproto.Attr_Crit)
|
||
if this.isMainHero {
|
||
crit *= this.pData.critRate
|
||
}
|
||
crit = crit + p1*float32(this.LUK())
|
||
return crit
|
||
}
|
||
func (this *ActorAttr) baseTen() float32 {
|
||
p1 := this.getFormulaValue(14)
|
||
ten := this.getAttr(serverproto.Attr_Ten)
|
||
if this.isMainHero {
|
||
ten *= this.pData.tenacityRate
|
||
}
|
||
ten = ten + p1*float32(this.LUK())
|
||
return ten
|
||
}
|
||
func (this *ActorAttr) baseAttackSpeed() float32 {
|
||
if this.isMainHero {
|
||
return this.pData.attackSpeed
|
||
} else {
|
||
return this.getAttr(serverproto.Attr_AttackSpeed)
|
||
}
|
||
}
|
||
func (this *ActorAttr) baseCastAcce() float32 {
|
||
p1 := this.getFormulaValue(28)
|
||
return p1 * float32(this.DEX())
|
||
}
|
||
|
||
//获得二级基础属性
|
||
func (this *ActorAttr) getAttr(attrId serverproto.Attr) float32 {
|
||
if attrId < serverproto.Attr_Life {
|
||
return 0
|
||
}
|
||
return this.attrs[attrId-serverproto.Attr_Life]
|
||
}
|
||
func (this *ActorAttr) setBaseFirstAttr(attrId serverproto.Attr, val int32) {
|
||
switch attrId {
|
||
case serverproto.Attr_Str:
|
||
this.baseStr = val
|
||
case serverproto.Attr_Agi:
|
||
this.baseAgi = val
|
||
case serverproto.Attr_Int:
|
||
this.baseInt = val
|
||
case serverproto.Attr_Vit:
|
||
this.baseVit = val
|
||
case serverproto.Attr_Dex:
|
||
this.baseDex = val
|
||
case serverproto.Attr_Luk:
|
||
this.baseLuk = val
|
||
}
|
||
}
|
||
func (this *ActorAttr) getBaseFirstAttr(attrId serverproto.Attr) int32 {
|
||
switch attrId {
|
||
case serverproto.Attr_Str:
|
||
return this.baseStr
|
||
case serverproto.Attr_Agi:
|
||
return this.baseAgi
|
||
case serverproto.Attr_Int:
|
||
return this.baseInt
|
||
case serverproto.Attr_Vit:
|
||
return this.baseVit
|
||
case serverproto.Attr_Dex:
|
||
return this.baseDex
|
||
case serverproto.Attr_Luk:
|
||
return this.baseLuk
|
||
}
|
||
return 0
|
||
}
|
||
func (this *ActorAttr) getBaseSecondAttr(attrId serverproto.Attr) float32 {
|
||
switch attrId {
|
||
case serverproto.Attr_Life:
|
||
return this.baseLife()
|
||
case serverproto.Attr_Sp:
|
||
return this.baseSp()
|
||
case serverproto.Attr_Attack:
|
||
return this.baseAttack()
|
||
case serverproto.Attr_MagicAttack:
|
||
return this.baseMagicAttack()
|
||
case serverproto.Attr_Defense:
|
||
return this.baseDefense()
|
||
case serverproto.Attr_MagicDefense:
|
||
return this.baseMagicDefense()
|
||
case serverproto.Attr_Dodge:
|
||
return this.baseDodge()
|
||
case serverproto.Attr_Hit:
|
||
return this.baseHit()
|
||
case serverproto.Attr_Crit:
|
||
return this.baseCrit()
|
||
case serverproto.Attr_Ten:
|
||
return this.baseTen()
|
||
case serverproto.Attr_AttackSpeed:
|
||
return this.baseAttackSpeed()
|
||
case serverproto.Attr_CastAcce:
|
||
return this.baseCastAcce()
|
||
}
|
||
return 0
|
||
}
|
||
|
||
//life需要处理成64位
|
||
func (this *ActorAttr) calcSecondAttrForLife(attrId serverproto.Attr) float64 {
|
||
if attrId < serverproto.Attr_Life || attrId > serverproto.Attr_CastAcce {
|
||
return 0
|
||
}
|
||
tmpf1 := float64(this.getBaseSecondAttr(attrId))
|
||
tmpf2 := this.GetAdditionalAttr(attrId) * float64(1+this.GetAdditionalAttrPercent(attrId+30)*0.0001)
|
||
return tmpf1 + tmpf2
|
||
}
|
||
func (this *ActorAttr) calcSecondAttr(attrId serverproto.Attr) float32 {
|
||
if attrId < serverproto.Attr_Life || attrId > serverproto.Attr_CastAcce {
|
||
return 0
|
||
}
|
||
tmpf1 := this.getBaseSecondAttr(attrId)
|
||
tmpf2 := this.GetAdditionalAttr(attrId) * float64(1+this.GetAdditionalAttrPercent(attrId+30)*0.0001)
|
||
return tmpf1 + float32(tmpf2)
|
||
}
|
||
func (this *ActorAttr) GetAdditionalAttr(attrId serverproto.Attr) float64 {
|
||
if attrId < serverproto.Attr_Str || attrId > serverproto.Attr_RealHurt {
|
||
return 0
|
||
}
|
||
return this.additionalAttrs[attrId]
|
||
}
|
||
func (this *ActorAttr) SetAdditionalAttr(attrId serverproto.Attr, val float64) {
|
||
if attrId < serverproto.Attr_Str || attrId > serverproto.Attr_RealHurt {
|
||
return
|
||
}
|
||
this.additionalAttrs[attrId] = val
|
||
}
|
||
func (this *ActorAttr) SetAdditionalAttrPercent(attrId serverproto.Attr, val float32) {
|
||
if attrId < serverproto.Attr_STR_Percent {
|
||
return
|
||
}
|
||
if attrId >= serverproto.Attr_Nature_None_Damage_Percent &&
|
||
attrId <= serverproto.Attr_VariableSingTime_Percent {
|
||
this.extendAttrPercent[attrId] = val
|
||
} else {
|
||
this.attrPercent[attrId-serverproto.Attr_STR_Percent] = val
|
||
}
|
||
}
|
||
func (this *ActorAttr) GetAdditionalAttrPercent(attrId serverproto.Attr) float32 {
|
||
if attrId < serverproto.Attr_STR_Percent {
|
||
return 0
|
||
}
|
||
if attrId >= serverproto.Attr_Nature_None_Damage_Percent &&
|
||
attrId <= serverproto.Attr_VariableSingTime_Percent {
|
||
return this.extendAttrPercent[attrId]
|
||
}
|
||
return this.attrPercent[attrId-serverproto.Attr_STR_Percent]
|
||
}
|
||
func (this *ActorAttr) AdditionAttrPercentString() {
|
||
type kvSt struct {
|
||
attrKey serverproto.Attr
|
||
attrVal float64
|
||
}
|
||
var kvList []kvSt
|
||
for key, val := range this.attrPercent {
|
||
util.InfoF("%v=%v", key+serverproto.Attr_STR_Percent, val)
|
||
//kvList = append(kvList, kvSt{attrKey: key + serverproto.Attr_STR_Percent, attrVal: val / 100})
|
||
}
|
||
if this.isPet {
|
||
for key, val := range this.additionalAttrs {
|
||
kvList = append(kvList, kvSt{attrKey: key, attrVal: val})
|
||
}
|
||
}
|
||
util.InfoF("=============")
|
||
for key, val := range this.extendAttrPercent {
|
||
//util.InfoF("%v=%v", key, val/100)
|
||
kvList = append(kvList, kvSt{attrKey: key, attrVal: float64(val)})
|
||
}
|
||
sort.Slice(kvList, func(i, j int) bool {
|
||
return kvList[i].attrKey < kvList[j].attrKey
|
||
})
|
||
for idx := 0; idx < len(kvList); idx++ {
|
||
util.InfoF("%v=%v %v%%", kvList[idx].attrKey, kvList[idx].attrVal, kvList[idx].attrVal/100)
|
||
}
|
||
}
|
||
func (this *ActorAttr) attrPrintString(attrList map[serverproto.Attr]float32) {
|
||
type kvSt struct {
|
||
attrKey serverproto.Attr
|
||
attrVal float32
|
||
}
|
||
var kvList []kvSt
|
||
for key, val := range attrList {
|
||
//util.InfoF("%v=%v", key, val/100)
|
||
kvList = append(kvList, kvSt{attrKey: key, attrVal: val})
|
||
}
|
||
sort.Slice(kvList, func(i, j int) bool {
|
||
return kvList[i].attrKey < kvList[j].attrKey
|
||
})
|
||
for idx := 0; idx < len(kvList); idx++ {
|
||
util.InfoF("%v=%v %v%%", kvList[idx].attrKey, kvList[idx].attrVal, kvList[idx].attrVal/100)
|
||
}
|
||
}
|
||
|
||
func (this *ActorAttr) calcAttr(attrList map[serverproto.Attr]float32, curAttrList map[serverproto.Attr]float32) {
|
||
for key := range attrList {
|
||
deltaValue := attrList[key] - curAttrList[key]
|
||
delete(curAttrList, key)
|
||
if deltaValue == 0 {
|
||
continue
|
||
}
|
||
if key < serverproto.Attr_STR_Percent {
|
||
val := this.GetAdditionalAttr(key) + float64(deltaValue)
|
||
this.SetAdditionalAttr(key, val)
|
||
} else {
|
||
val := this.GetAdditionalAttrPercent(key) + deltaValue
|
||
this.SetAdditionalAttrPercent(key, val)
|
||
}
|
||
}
|
||
|
||
//删除之前有但是现在没有的属性条目
|
||
if len(curAttrList) > 0 {
|
||
for key := range curAttrList {
|
||
deltaValue := -curAttrList[key]
|
||
if key < serverproto.Attr_STR_Percent {
|
||
val := this.GetAdditionalAttr(key) + float64(deltaValue)
|
||
this.SetAdditionalAttr(key, val)
|
||
} else {
|
||
val := this.GetAdditionalAttrPercent(key) + deltaValue
|
||
this.SetAdditionalAttrPercent(key, val)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *ActorAttr) calActorAttr(heroData *serverproto.HeroData, attrList []*serverproto.KeyValueType,
|
||
fashionData *serverproto.FashionData, attrChangeSt AttrChangeST) bool {
|
||
if heroData == nil {
|
||
//玩家自身角色
|
||
heroData = this.getRole().GetRoleHero().GetHero(this.heroId)
|
||
}
|
||
if heroData == nil {
|
||
return false
|
||
}
|
||
|
||
bChange := false
|
||
if this.changeSetList.Size() > 0 {
|
||
//主角英雄
|
||
if this.isMainHero {
|
||
changePoint := this.calcAddPointAttrs(heroData, attrList)
|
||
changeSkill := this.calcSkillAttrs(heroData, attrChangeSt)
|
||
changEquip := this.calcEquipAttrs(heroData)
|
||
//this.calcFashionAttr(fashionData)
|
||
changPet := this.calcPetAttr(heroData, attrChangeSt)
|
||
changeHeadFrame := this.calcHeadFrameAttrs(heroData, attrChangeSt)
|
||
changeSkillEquip := this.calcSkillEquipSlotAttrs(heroData)
|
||
if changePoint || changeSkill || changEquip || changPet || changeHeadFrame || changeSkillEquip {
|
||
bChange = true
|
||
}
|
||
} else {
|
||
changePoint := this.calcAddPointAttrs(heroData, attrList)
|
||
changeSkill := this.calcSkillAttrs(heroData, attrChangeSt)
|
||
changAdv := this.calcAdvanceAttrs(heroData)
|
||
changStr := this.calcStrengthAttr(heroData)
|
||
changEquip := this.calcEquipAttrs(heroData)
|
||
changPet := this.calcPetAttr(heroData, attrChangeSt)
|
||
changeSkillEquip := this.calcSkillEquipSlotAttrs(heroData)
|
||
if changePoint || changeSkill || changAdv || changStr || changEquip || changPet || changeSkillEquip {
|
||
bChange = true
|
||
}
|
||
}
|
||
|
||
changeCard := this.calcCardAttrs(heroData)
|
||
changeFashion := this.calcFashionAttr(fashionData, heroData)
|
||
changeSake := this.calcSakeAttr(heroData)
|
||
changeHead := this.calcHeadAttr(heroData)
|
||
|
||
if changeCard || changeFashion || changeSake || changeHead {
|
||
bChange = true
|
||
}
|
||
}
|
||
|
||
if this.changeSetList.Has(Attr_Change_Skill_Equip) {
|
||
bChange = true
|
||
}
|
||
if bChange {
|
||
ntfAttrType := &serverproto.ActorAttrType{
|
||
IsHeroPet: true,
|
||
ActorId: uint32(heroData.Id),
|
||
}
|
||
//代码优化,避免频繁出现扩容操作
|
||
ntfAttrType.AttrList = make([]*serverproto.KeyValueFloat32, 0, 16)
|
||
this.attrMag.copyAttrToMsg(this, ntfAttrType)
|
||
//计算战力
|
||
heroFightPower := this.calcActorFightPower(ntfAttrType.AttrList)
|
||
this.getRole().GetRoleHero().BattleAttrChange(heroData, ntfAttrType, heroFightPower)
|
||
|
||
if !attrChangeSt.IgnoreNotify {
|
||
ntfMsg := &serverproto.SCActorAttrGetNtf{}
|
||
ntfMsg.ActorAttrList = append(ntfMsg.ActorAttrList, ntfAttrType)
|
||
this.attrMag.role.ReplayGate(ntfMsg, true)
|
||
}
|
||
}
|
||
|
||
return bChange
|
||
}
|
||
|
||
//计算属性
|
||
//属性点加成
|
||
func (this *ActorAttr) calcAddPointAttrs(heroData *serverproto.HeroData, attrList []*serverproto.KeyValueType) bool {
|
||
if heroData == nil {
|
||
return false
|
||
}
|
||
//tmpList := this.changeSetList.List()
|
||
//util.DebugF("tmpList=%v", tmpList)
|
||
if !this.changeSetList.Has(Attr_Change_AddPoint) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_AddPoint)
|
||
|
||
if attrList == nil {
|
||
attrList = heroData.AttrList
|
||
}
|
||
if len(attrList) <= 0 && heroData.BaseLevel <= 0 {
|
||
return false
|
||
}
|
||
|
||
for idx := range attrList {
|
||
key := serverproto.Attr(attrList[idx].Key)
|
||
this.setBaseFirstAttr(key, 1+attrList[idx].Value)
|
||
}
|
||
return true
|
||
}
|
||
|
||
//技能升级添加属性
|
||
func (this *ActorAttr) calcSkillAttrs(heroData *serverproto.HeroData, attrChangeSt AttrChangeST) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Skill) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Skill)
|
||
|
||
attrList := map[serverproto.Attr]float32{}
|
||
//get attr
|
||
if attrChangeSt.BSkillReset {
|
||
//reset
|
||
this.GetSkillAttr(heroData.Skill, attrList, attrChangeSt)
|
||
this.calAttr(this.curSkillAttr, attrList)
|
||
this.curSkillAttr = attrList
|
||
|
||
this.curSkillFightPower = 0
|
||
} else {
|
||
this.GetSkillAttr(heroData.Skill, attrList, attrChangeSt)
|
||
this.calAttr(this.curSkillAttr, attrList)
|
||
this.curSkillAttr = attrList
|
||
|
||
//level up
|
||
//this.GetSkillAttr(heroData.Skill, attrList, attrChangeSt)
|
||
//this.calAttrAdd(this.curSkillAttr, attrList)
|
||
|
||
//fight power
|
||
if this.curSkillFightPower < 0 {
|
||
if this.isPet {
|
||
this.curSkillFightPower =
|
||
int64(this.attrMag.getPetTotalSkillFightPower(this.heroId))
|
||
} else {
|
||
this.curSkillFightPower =
|
||
int64(this.attrMag.getHeroTotalSkillFightPower(this.heroId))
|
||
}
|
||
} else {
|
||
skillCfg, ok := serverproto.SkillCfgLoader[attrChangeSt.SkillCfgId]
|
||
if ok {
|
||
this.curSkillFightPower += int64(skillCfg.AddFight)
|
||
}
|
||
}
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
func (this *ActorAttr) calcHeadFrameAttrs(heroData *serverproto.HeroData, attrChangeSt AttrChangeST) bool {
|
||
if !this.changeSetList.Has(Attr_Change_HeadFrame) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_HeadFrame)
|
||
|
||
attrList := map[serverproto.Attr]float32{}
|
||
//get attr
|
||
if attrChangeSt.HeadFrameId > 0 {
|
||
this.GetHeadFrameAttr(attrList, attrChangeSt)
|
||
if attrChangeSt.BHeadFrameDelete {
|
||
this.calAttrDel(this.curHeadFrameAttr, attrList)
|
||
} else {
|
||
this.calAttrAdd(this.curHeadFrameAttr, attrList)
|
||
}
|
||
} else {
|
||
this.GetHeadFrameAttr(attrList, attrChangeSt)
|
||
this.calAttr(this.curHeadFrameAttr, attrList)
|
||
this.curHeadFrameAttr = attrList
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
//equip
|
||
func (this *ActorAttr) calcEquipAttrs(heroData *serverproto.HeroData) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Equip) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Equip)
|
||
|
||
attrList := map[serverproto.Attr]float32{}
|
||
//get attr
|
||
this.GetEquipAttr(heroData.Slot, attrList)
|
||
|
||
this.calAttr(this.curEquipAttr, attrList)
|
||
this.curEquipAttr = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
//card
|
||
func (this *ActorAttr) calcCardAttrs(heroData *serverproto.HeroData) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Card) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Card)
|
||
|
||
this.triggerBuffList = map[uint32]*serverproto.TriggerBuffData{}
|
||
attrList := map[serverproto.Attr]float32{}
|
||
//get attr
|
||
for _, data := range heroData.Slot.SlotList {
|
||
this.GetCardAttr(data, attrList)
|
||
}
|
||
//card suit attr(卡片祝福属性)
|
||
this.getRole().GetRoleCard().GetCardSuitAttr(heroData, attrList)
|
||
//百分比属性//
|
||
// 下面的代码才是正确的,但是改过来之后影响巨大,所以策划说,这个bug放弃修复。。
|
||
/*
|
||
attrPercentList := map[serverproto.Attr]float32{}
|
||
this.getRole().GetRoleCard().GetCardSuitAttr(heroData, attrPercentList)
|
||
if len(attrPercentList) > 0 {
|
||
for attr := serverproto.Attr_Life; attr <=serverproto.Attr_MagicDefense; attr++ {
|
||
_, ok := attrList[attr]
|
||
if ok {
|
||
_, ok2 := attrPercentList[attr+30]
|
||
if ok2 {
|
||
attrList[attr] += attrList[attr]*attrPercentList[attr+30]/10000
|
||
}
|
||
}
|
||
}
|
||
}
|
||
*/
|
||
|
||
this.calAttr(this.curCardAttr, attrList)
|
||
this.curCardAttr = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
//skill equip
|
||
func (this *ActorAttr) calcSkillEquipSlotAttrs(heroData *serverproto.HeroData) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Skill_Equip_Slot) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Skill_Equip_Slot)
|
||
|
||
if heroData.SkillEquipSlot == nil ||
|
||
heroData.SkillEquipSlot.SlotList == nil {
|
||
return false
|
||
}
|
||
|
||
attrList := map[serverproto.Attr]float32{}
|
||
|
||
//get attr
|
||
for _, data := range heroData.SkillEquipSlot.SlotList {
|
||
if data.SkillEquipId <= 0 {
|
||
continue
|
||
}
|
||
this.GetSkillEquipSlotAttr(data, attrList)
|
||
}
|
||
|
||
this.calAttr(this.curSkillEquipAttr, attrList)
|
||
this.curSkillEquipAttr = attrList
|
||
return true
|
||
}
|
||
|
||
//fashion
|
||
func (this *ActorAttr) calcFashionAttr(fashionData *serverproto.FashionData, heroData *serverproto.HeroData) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Fashion) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Fashion)
|
||
|
||
//attrList := map[serverproto.Attr]float32{}
|
||
//this.GetFashionAttr(fashionData, heroData, attrList)
|
||
//
|
||
//this.calAttr(this.curFashionAttr, attrList)
|
||
//this.curFashionAttr = attrList
|
||
|
||
var heroJobType int32 = 0
|
||
if !this.isMainHero {
|
||
heroCfg, ok := serverproto.ParterCfgLoader[heroData.ConfigId]
|
||
if !ok {
|
||
return false
|
||
}
|
||
heroJobType = heroCfg.JobType
|
||
}
|
||
attrList := map[serverproto.Attr]float32{}
|
||
if attrMapList, ok := this.attrMag.curGlobalFashionAttr[heroJobType]; ok {
|
||
for key, val := range attrMapList {
|
||
attrList[key] += val
|
||
}
|
||
}
|
||
|
||
this.calAttr(this.curFashionAttr, attrList)
|
||
this.curFashionAttr = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
//sake
|
||
func (this *ActorAttr) calcSakeAttr(heroData *serverproto.HeroData) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Sake) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Sake)
|
||
|
||
var heroJobType int32 = 0
|
||
if !this.isMainHero {
|
||
heroCfg, ok := serverproto.ParterCfgLoader[heroData.ConfigId]
|
||
if !ok {
|
||
return false
|
||
}
|
||
heroJobType = heroCfg.JobType
|
||
}
|
||
|
||
attrList := map[serverproto.Attr]float32{}
|
||
if attrMapList, ok := this.attrMag.curGlobalSakeAttr[heroJobType]; ok {
|
||
for key, val := range attrMapList {
|
||
attrList[key] += val
|
||
}
|
||
}
|
||
this.calAttr(this.curSakeAttr, attrList)
|
||
this.curSakeAttr = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
//sake
|
||
func (this *ActorAttr) calcHeadAttr(heroData *serverproto.HeroData) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Head) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Head)
|
||
|
||
if this.attrMag == nil || this.attrMag.role == nil {
|
||
return false
|
||
}
|
||
head := this.attrMag.role.roleHead
|
||
if head == nil {
|
||
return false
|
||
}
|
||
attrList := map[serverproto.Attr]float32{}
|
||
state := int32(Head_Not_Activate)
|
||
for _, data := range head.headData {
|
||
if data.State <= state {
|
||
continue
|
||
}
|
||
db, ok := model.DbHeadData[data.HeadId]
|
||
if !ok {
|
||
continue
|
||
}
|
||
for _, kv := range db.Attr {
|
||
attrList[serverproto.Attr(kv.Key)] += float32(kv.Value)
|
||
}
|
||
}
|
||
this.calAttr(this.curHeadAttr, attrList)
|
||
this.curHeadAttr = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
//hero advance
|
||
func (this *ActorAttr) calcAdvanceAttrs(heroData *serverproto.HeroData) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Advance) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Advance)
|
||
|
||
//get attr
|
||
attrList := map[serverproto.Attr]float32{}
|
||
this.GetAdvanceAttrs(heroData, attrList)
|
||
|
||
this.calAttr(this.curAdvanceAttr, attrList)
|
||
this.curAdvanceAttr = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
//hero strength
|
||
func (this *ActorAttr) calcStrengthAttr(heroData *serverproto.HeroData) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Strength) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Strength)
|
||
|
||
//get attr
|
||
attrList := map[serverproto.Attr]float32{}
|
||
this.GetStrengthAttrs(heroData, attrList)
|
||
|
||
this.calAttr(this.curStrengthAttr, attrList)
|
||
this.curStrengthAttr = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
//pet
|
||
func (this *ActorAttr) calcPetAttr(heroData *serverproto.HeroData, attrChangeSt AttrChangeST) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Pet) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Pet)
|
||
|
||
//get attr
|
||
attrList := map[serverproto.Attr]float32{}
|
||
this.GetPetAttrs(heroData, attrList, attrChangeSt)
|
||
util.DebugF("###hero inherit from pet=%v###", heroData.BattlePetId)
|
||
this.attrPrintString(attrList)
|
||
util.DebugF("###hero inherit from pet###\n")
|
||
|
||
this.calAttr(this.curPetAttr, attrList)
|
||
this.curPetAttr = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
func (this *ActorAttr) calAttr(curAttr map[serverproto.Attr]float32, attrList map[serverproto.Attr]float32) {
|
||
for key := range attrList {
|
||
deltaValue := attrList[key] - curAttr[key]
|
||
delete(curAttr, key)
|
||
if deltaValue == 0 {
|
||
continue
|
||
}
|
||
if key >= serverproto.Attr_Life && key <= serverproto.Attr_RealHurt {
|
||
this.SetAdditionalAttr(key, this.GetAdditionalAttr(key)+float64(deltaValue))
|
||
} else if key >= serverproto.Attr_STR_Percent {
|
||
this.SetAdditionalAttrPercent(key, this.GetAdditionalAttrPercent(key)+deltaValue)
|
||
}
|
||
}
|
||
for key := range curAttr {
|
||
deltaValue := -curAttr[key]
|
||
delete(curAttr, key)
|
||
if deltaValue == 0 {
|
||
continue
|
||
}
|
||
if key >= serverproto.Attr_Life && key <= serverproto.Attr_RealHurt {
|
||
this.SetAdditionalAttr(key, this.GetAdditionalAttr(key)+float64(deltaValue))
|
||
} else if key >= serverproto.Attr_STR_Percent {
|
||
this.SetAdditionalAttrPercent(key, this.GetAdditionalAttrPercent(key)+deltaValue)
|
||
}
|
||
}
|
||
}
|
||
|
||
//直接添加到总属性上
|
||
func (this *ActorAttr) calAttrAdd(curAttr map[serverproto.Attr]float32, attrList map[serverproto.Attr]float32) {
|
||
for key, val := range attrList {
|
||
deltaValue := val
|
||
curAttr[key] += deltaValue
|
||
if key >= serverproto.Attr_Life && key <= serverproto.Attr_RealHurt {
|
||
this.SetAdditionalAttr(key, this.GetAdditionalAttr(key)+float64(deltaValue))
|
||
} else if key >= serverproto.Attr_STR_Percent {
|
||
this.SetAdditionalAttrPercent(key, this.GetAdditionalAttrPercent(key)+deltaValue)
|
||
}
|
||
}
|
||
}
|
||
|
||
//直接减到总属性上
|
||
func (this *ActorAttr) calAttrDel(curAttr map[serverproto.Attr]float32, attrList map[serverproto.Attr]float32) {
|
||
for key, val := range attrList {
|
||
deltaValue := -val
|
||
curAttr[key] += deltaValue
|
||
if key >= serverproto.Attr_Life && key <= serverproto.Attr_RealHurt {
|
||
this.SetAdditionalAttr(key, this.GetAdditionalAttr(key)+float64(deltaValue))
|
||
} else if key >= serverproto.Attr_STR_Percent {
|
||
this.SetAdditionalAttrPercent(key, this.GetAdditionalAttrPercent(key)+deltaValue)
|
||
}
|
||
}
|
||
}
|
||
|
||
//attr copy
|
||
func (this *ActorAttr) calAttrCopy(curAttr map[serverproto.Attr]float32, attrList map[serverproto.Attr]float32) {
|
||
for key, val := range curAttr {
|
||
attrList[key] += val
|
||
}
|
||
}
|
||
|
||
func (this *ActorAttr) GetSkillAttr(roleSkill *serverproto.RoleSkill,
|
||
baseAttrList map[serverproto.Attr]float32, attrChangeSt AttrChangeST) {
|
||
if roleSkill == nil {
|
||
return
|
||
}
|
||
|
||
for _, jobSkillList := range roleSkill.JobSkillList {
|
||
for _, skill := range jobSkillList.UnlockSkillList {
|
||
cfgData, ok := model.ConvertSkillAttr[skill.Key]
|
||
if !ok {
|
||
continue
|
||
}
|
||
for k, valList := range cfgData.AttrList {
|
||
//level
|
||
if k <= skill.Value {
|
||
for idx := 0; idx < len(valList); idx++ {
|
||
baseAttrList[serverproto.Attr(valList[idx].Key)] += float32(valList[idx].Value)
|
||
}
|
||
}
|
||
}
|
||
|
||
//上一阶技能属性
|
||
this.getSkillAttr(skill.Key, baseAttrList)
|
||
}
|
||
}
|
||
return
|
||
//init
|
||
//if len(this.curSkillAttr) <= 0 {
|
||
// for _, jobSkillList := range roleSkill.JobSkillList {
|
||
// for _, skill := range jobSkillList.UnlockSkillList {
|
||
// cfgData, ok := model.ConvertSkillAttr[skill.Key]
|
||
// if !ok {
|
||
// continue
|
||
// }
|
||
// for k, valList := range cfgData.AttrList {
|
||
// //level
|
||
// if k <= skill.Value {
|
||
// for idx := 0; idx < len(valList); idx++ {
|
||
// baseAttrList[serverproto.Attr(valList[idx].Key)] += float32(valList[idx].Value)
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
//} else {
|
||
// if attrChangeSt.SkillCfgId <= 0 || attrChangeSt.OldSkillLevel == attrChangeSt.NewSkillLevel {
|
||
// return
|
||
// }
|
||
//
|
||
// cfgData, ok := model.ConvertSkillAttr[attrChangeSt.SkillCfgId]
|
||
// if !ok {
|
||
// return
|
||
// }
|
||
// for k, valList := range cfgData.AttrList {
|
||
// //level
|
||
// if k > attrChangeSt.OldSkillLevel && k <= attrChangeSt.NewSkillLevel {
|
||
// for idx := 0; idx < len(valList); idx++ {
|
||
// baseAttrList[serverproto.Attr(valList[idx].Key)] += float32(valList[idx].Value)
|
||
// }
|
||
// }
|
||
// }
|
||
//}
|
||
}
|
||
|
||
func (this *ActorAttr) getSkillAttr(skillId int32, baseAttrList map[serverproto.Attr]float32) {
|
||
if this.isMainHero {
|
||
//role
|
||
skillCfg, ok := serverproto.SkillTreeCfgLoader[skillId]
|
||
if !ok || skillCfg.BeforeSkill <= 0 {
|
||
return
|
||
}
|
||
|
||
cfgData, ok := model.ConvertSkillAttr[skillCfg.BeforeSkill]
|
||
if ok {
|
||
beforeSkill, ok := serverproto.SkillTreeCfgLoader[skillCfg.BeforeSkill]
|
||
if ok {
|
||
for k, valList := range cfgData.AttrList {
|
||
//level
|
||
if k <= beforeSkill.MaxLv {
|
||
for idx := 0; idx < len(valList); idx++ {
|
||
baseAttrList[serverproto.Attr(valList[idx].Key)] += float32(valList[idx].Value)
|
||
}
|
||
}
|
||
}
|
||
|
||
this.getSkillAttr(skillCfg.BeforeSkill, baseAttrList)
|
||
}
|
||
}
|
||
} else {
|
||
//partner
|
||
skillCfg, ok := serverproto.ParterSkillTreeCfgLoader[skillId]
|
||
if !ok || skillCfg.BeforeSkill <= 0 {
|
||
return
|
||
}
|
||
|
||
cfgData, ok := model.ConvertSkillAttr[skillCfg.BeforeSkill]
|
||
if ok {
|
||
beforeSkill, ok := serverproto.ParterSkillTreeCfgLoader[skillCfg.BeforeSkill]
|
||
if ok {
|
||
for k, valList := range cfgData.AttrList {
|
||
//level
|
||
if k <= beforeSkill.MaxLv {
|
||
for idx := 0; idx < len(valList); idx++ {
|
||
baseAttrList[serverproto.Attr(valList[idx].Key)] += float32(valList[idx].Value)
|
||
}
|
||
}
|
||
}
|
||
|
||
this.getSkillAttr(skillCfg.BeforeSkill, baseAttrList)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *ActorAttr) GetHeadFrameAttr(baseAttrList map[serverproto.Attr]float32, attrChangeSt AttrChangeST) {
|
||
//init
|
||
if len(this.curHeadFrameAttr) <= 0 || attrChangeSt.HeadFrameId <= 0 {
|
||
nowTime := util.GetTimeSeconds()
|
||
headFrameDataList := this.attrMag.role.GetRoleBase().roleBase.Head_Info.HeadFrameList
|
||
for idx := 0; idx < len(headFrameDataList); idx++ {
|
||
cfgData, ok := model.ConvertHeadFrameAttr[headFrameDataList[idx].HeadFrameId]
|
||
if !ok {
|
||
continue
|
||
}
|
||
if headFrameDataList[idx].HeadFrameTime > 0 && headFrameDataList[idx].HeadFrameTime <= nowTime {
|
||
continue
|
||
}
|
||
for k, v := range cfgData.AttrList {
|
||
baseAttrList[serverproto.Attr(k)] += float32(v)
|
||
}
|
||
}
|
||
} else {
|
||
cfgData, ok := model.ConvertHeadFrameAttr[attrChangeSt.HeadFrameId]
|
||
if !ok {
|
||
return
|
||
}
|
||
for k, v := range cfgData.AttrList {
|
||
baseAttrList[serverproto.Attr(k)] += float32(v)
|
||
}
|
||
}
|
||
}
|
||
|
||
//获取属性
|
||
func (this *ActorAttr) GetEquipAttr(slotData *serverproto.SlotData, baseAttrList map[serverproto.Attr]float32) {
|
||
var suitList = map[int32]int32{}
|
||
//最小精炼等级
|
||
var minRefineLevel int32 = 0
|
||
|
||
//套装处理
|
||
for _, data := range slotData.SlotList {
|
||
if data.EquipId <= 0 {
|
||
continue
|
||
}
|
||
cfgData, ok := model.EquipAttrContainer[data.EquipId]
|
||
if !ok {
|
||
continue
|
||
}
|
||
//套装数量统计
|
||
if cfgData.SuitId > 0 {
|
||
suitList[cfgData.SuitId]++
|
||
}
|
||
if minRefineLevel <= 0 {
|
||
minRefineLevel = data.Level
|
||
} else if data.Level < minRefineLevel {
|
||
minRefineLevel = data.Level
|
||
}
|
||
|
||
var refineDataResult float32 = 0
|
||
refineData, ok := serverproto.EquipRefineCfgLoader[data.Level]
|
||
if ok {
|
||
refineDataResult = float32(refineData.Result)
|
||
}
|
||
for _, data := range cfgData.AttrSet {
|
||
if data.Key <= 0 || data.Value <= 0 {
|
||
continue
|
||
}
|
||
if data.Key < int32(serverproto.Attr_STR_Percent) {
|
||
refineAdd := float32(data.Value) * (refineDataResult + 100) * 0.01
|
||
baseAttrList[serverproto.Attr(data.Key)] += refineAdd
|
||
}
|
||
}
|
||
}
|
||
|
||
//精炼等级全套属性处理
|
||
for i := minRefineLevel; i >= 1; i-- {
|
||
refineData, ok := model.EquipRefineContainer[i]
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
for _, data := range refineData.AttrSet {
|
||
if data.Key >= int32(serverproto.Attr_STR_Percent) {
|
||
baseAttrList[serverproto.Attr(data.Key)] += float32(data.Value)
|
||
}
|
||
}
|
||
}
|
||
|
||
//装备套装属性处理
|
||
for suitId, suitCount := range suitList {
|
||
suitCfgData, ok := model.SuitAttrContainer[suitId]
|
||
if !ok {
|
||
continue
|
||
}
|
||
if suitCount >= 2 {
|
||
for key, value := range suitCfgData.AttrSet[0] {
|
||
baseAttrList[serverproto.Attr(key)] += float32(value)
|
||
}
|
||
}
|
||
if suitCount >= 4 {
|
||
for key, value := range suitCfgData.AttrSet[1] {
|
||
baseAttrList[serverproto.Attr(key)] += float32(value)
|
||
}
|
||
}
|
||
if suitCount >= 6 {
|
||
for key, value := range suitCfgData.AttrSet[2] {
|
||
baseAttrList[serverproto.Attr(key)] += float32(value)
|
||
}
|
||
}
|
||
}
|
||
|
||
//todo... 优化
|
||
for key, value := range baseAttrList {
|
||
if key >= serverproto.Attr_STR_Percent && key <= serverproto.Attr_RealHurt_Percent {
|
||
baseAttrList[key] = value * 0.0001
|
||
}
|
||
}
|
||
for key, value := range baseAttrList {
|
||
if key < serverproto.Attr_STR_Percent {
|
||
baseAttrList[key] = value * (1 + baseAttrList[key+30])
|
||
}
|
||
}
|
||
for key := range baseAttrList {
|
||
if key >= serverproto.Attr_STR_Percent && key <= serverproto.Attr_RealHurt_Percent {
|
||
baseAttrList[key] = 0
|
||
}
|
||
}
|
||
}
|
||
func (this *ActorAttr) GetCardAttr(slotDetail *serverproto.SlotDetailData, baseAttrList map[serverproto.Attr]float32) {
|
||
for _, data := range slotDetail.CardIdList {
|
||
//如果没有找到,要区分一下,这位置的卡片是不是没有放卡片
|
||
if data == 0 {
|
||
continue
|
||
}
|
||
convertData, ok := model.ConvertCardList[data]
|
||
if !ok {
|
||
return
|
||
}
|
||
if len(convertData.AttrList) > 0 {
|
||
for key, value := range convertData.AttrList {
|
||
if key < int32(serverproto.Attr_STR_Percent) {
|
||
baseAttrList[serverproto.Attr(key)] += value
|
||
} else {
|
||
//baseAttrList[serverproto.Attr(key)] += value * 0.0001
|
||
baseAttrList[serverproto.Attr(key)] += value
|
||
}
|
||
}
|
||
}
|
||
if len(convertData.TriggerBuffList) > 0 {
|
||
for _, data := range convertData.TriggerBuffList {
|
||
this.triggerBuffList[data.BuffId] = data
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *ActorAttr) GetSkillEquipSlotAttr(slotDetail *serverproto.SkillEquipSlotDetailData, baseAttrList map[serverproto.Attr]float32) {
|
||
convertData, ok := model.SkillEquipSlotAppendAttrContainer[slotDetail.SlotLevel]
|
||
if !ok {
|
||
return
|
||
}
|
||
var realHealHurt int32 = 0
|
||
if len(convertData) > 0 {
|
||
for key, value := range convertData {
|
||
if key < serverproto.Attr_STR_Percent {
|
||
baseAttrList[key] += value
|
||
if key == serverproto.Attr_RealHurt {
|
||
realHealHurt += int32(value)
|
||
}
|
||
} else {
|
||
//baseAttrList[serverproto.Attr(key)] += value * 0.0001
|
||
baseAttrList[key] += value
|
||
}
|
||
}
|
||
}
|
||
slotDetail.SlotAttrs = []*serverproto.KeyValueType{
|
||
&serverproto.KeyValueType{
|
||
Key: int32(serverproto.Attr_RealHurt), Value: realHealHurt}}
|
||
}
|
||
|
||
func (this *ActorAttr) GetFashionAttr(fashionData *serverproto.FashionData, heroData *serverproto.HeroData, baseAttrList map[serverproto.Attr]float32) {
|
||
if fashionData != nil {
|
||
//// 使用外层传入的系统数据进行计算(其他玩家)
|
||
//for _, fId := range fashionData.FashionUpList {
|
||
// attrDataList, ok := model.FashionAttrContainer[fId]
|
||
// if !ok {
|
||
// continue
|
||
// }
|
||
// for _, attr := range attrDataList.AttrSet {
|
||
// if attr.Key < int32(serverproto.Attr_STR_Percent) {
|
||
// baseAttrList[serverproto.Attr(attr.Key)] += float32(attr.Value)
|
||
// } else {
|
||
// baseAttrList[serverproto.Attr(attr.Key)] += float32(attr.Value) * 0.0001
|
||
// }
|
||
// }
|
||
//}
|
||
} else {
|
||
//玩家自己
|
||
heroCfg, ok := serverproto.ParterCfgLoader[heroData.ConfigId]
|
||
if !ok {
|
||
return
|
||
}
|
||
for _, data := range this.attrMag.role.GetRoleFashion().fashionData {
|
||
//attrDataList, ok := model.FashionAttrContainer[data]
|
||
//if !ok {
|
||
// continue
|
||
//}
|
||
for _, attr := range data.attrs {
|
||
if attr.JobType == 0 && this.attrMag.role.GetRoleHero().IsMainHero(heroData.Id) {
|
||
continue
|
||
}
|
||
if attr.JobType > 0 && attr.JobType != heroCfg.JobType {
|
||
continue
|
||
}
|
||
|
||
if attr.AttrId < int32(serverproto.Attr_STR_Percent) {
|
||
baseAttrList[serverproto.Attr(attr.AttrId)] += float32(attr.Value)
|
||
} else {
|
||
baseAttrList[serverproto.Attr(attr.AttrId)] += float32(attr.Value)
|
||
}
|
||
}
|
||
}
|
||
//套装属性
|
||
if this.attrMag.role.GetRoleHero().IsMainHero(heroData.Id) {
|
||
for idx := 0; idx < len(this.attrMag.role.GetRoleFashion().fashionSuitAttrs); idx++ {
|
||
attrItem := this.attrMag.role.GetRoleFashion().fashionSuitAttrs[idx]
|
||
if attrItem.Key < int32(serverproto.Attr_STR_Percent) {
|
||
baseAttrList[serverproto.Attr(attrItem.Key)] += float32(attrItem.Value)
|
||
} else {
|
||
baseAttrList[serverproto.Attr(attrItem.Key)] += float32(attrItem.Value)
|
||
}
|
||
}
|
||
}
|
||
|
||
//获得就添加属性
|
||
//for _, data := range this.attrMag.role.GetRoleFashion().fashionList {
|
||
// attrDataList, ok := model.FashionAttrContainer[data]
|
||
// if !ok {
|
||
// continue
|
||
// }
|
||
// for _, attr := range attrDataList.AttrSet {
|
||
// if attr.Key < int32(serverproto.Attr_STR_Percent) {
|
||
// baseAttrList[serverproto.Attr(attr.Key)] += float32(attr.Value)
|
||
// } else {
|
||
// baseAttrList[serverproto.Attr(attr.Key)] += float32(attr.Value)
|
||
// }
|
||
// }
|
||
//}
|
||
}
|
||
}
|
||
|
||
//进阶(突破等级上限,角色通过专职来处理)
|
||
func (this *ActorAttr) GetAdvanceAttrs(heroData *serverproto.HeroData, baseAttrList map[serverproto.Attr]float32) {
|
||
if heroData.AdvanceLevel <= 0 {
|
||
return
|
||
}
|
||
partner, ok := serverproto.ParterCfgLoader[heroData.ConfigId]
|
||
if !ok {
|
||
return
|
||
}
|
||
stepCfgData, ok := model.ProgressAttrContainer[partner.ParterJob]
|
||
if !ok {
|
||
util.DebugF("[CalAttr] GetAdvanceAttrs data not found:%v", heroData.ConfigId)
|
||
return
|
||
}
|
||
|
||
for i := 0; i < int(heroData.AdvanceLevel); i++ {
|
||
if stepCfgData.AttrSet[int32(i)] == nil {
|
||
continue
|
||
}
|
||
for key, value := range stepCfgData.AttrSet[int32(i)] {
|
||
baseAttrList[serverproto.Attr(key)] += float32(value)
|
||
}
|
||
}
|
||
}
|
||
|
||
//突破
|
||
func (this *ActorAttr) GetStrengthAttrs(heroData *serverproto.HeroData, baseAttrList map[serverproto.Attr]float32) {
|
||
if heroData.StrengthLevel <= 0 {
|
||
return
|
||
}
|
||
partner, ok := serverproto.ParterCfgLoader[heroData.ConfigId]
|
||
if !ok {
|
||
return
|
||
}
|
||
stepCfgData, ok := model.StrengthAttrContainer[partner.ParterJob]
|
||
if !ok {
|
||
util.DebugF("CalAttr GetStrengthAttrs data not found herocfgid=%v", heroData.ConfigId)
|
||
return
|
||
}
|
||
|
||
for i := 0; i < int(heroData.StrengthLevel); i++ {
|
||
if stepCfgData.AttrSet[int32(i)] == nil {
|
||
continue
|
||
}
|
||
for key, value := range stepCfgData.AttrSet[int32(i)] {
|
||
baseAttrList[serverproto.Attr(key)] += float32(value)
|
||
}
|
||
}
|
||
}
|
||
|
||
//可能是上阵,也可能是下阵
|
||
func (this *ActorAttr) GetPetAttrs(heroData *serverproto.HeroData, baseAttrList map[serverproto.Attr]float32, attrChangeSt AttrChangeST) {
|
||
if heroData.BattlePetId <= 0 {
|
||
return
|
||
}
|
||
|
||
petDataInfo := this.attrMag.role.GetRolePet().getPet(heroData.BattlePetId)
|
||
if petDataInfo == nil {
|
||
return
|
||
}
|
||
petCfg, ok := serverproto.PetCfgLoader[petDataInfo.ConfigId]
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
petActorAttr := this.attrMag.getPetActorAttr(petDataInfo)
|
||
if petActorAttr == nil {
|
||
return
|
||
}
|
||
if len(petActorAttr.curPetAttrForPetBase) <= 0 { //初始化时需要先计算一次
|
||
this.attrMag.calcAttrPet([]*serverproto.PetData{petDataInfo}, attrChangeSt)
|
||
}
|
||
|
||
//base(level + advLevel)
|
||
this.petInheritAttrs(baseAttrList, petActorAttr.curPetAttrForPetBase, petCfg.ConversionRate)
|
||
//宠物羁绊属性
|
||
this.petInheritAttrs(baseAttrList, petActorAttr.curPetAttrForPetBond, petCfg.ConversionRate)
|
||
//宠物印记
|
||
this.petInheritAttrs(baseAttrList, petActorAttr.curPetAttrForPetEquip, petCfg.ConversionRate)
|
||
//宠物契约
|
||
this.petInheritAttrs(baseAttrList, petActorAttr.curPetAttrForPetQiyue, petCfg.ConversionRate)
|
||
}
|
||
func (this *ActorAttr) petInheritAttrs(dst map[serverproto.Attr]float32, src map[serverproto.Attr]float32, rate int32) {
|
||
for k, v := range src {
|
||
bFind := false
|
||
for idx := 0; idx < len(model.GlobalAttrPetNotInheritHeroList); idx++ {
|
||
if model.GlobalAttrPetNotInheritHeroList[idx] == k {
|
||
bFind = true
|
||
break
|
||
}
|
||
}
|
||
if bFind {
|
||
delete(dst, k)
|
||
continue
|
||
}
|
||
dst[k] += v * float32(rate) * 0.0001
|
||
}
|
||
}
|
||
func (this *ActorAttr) petInheritAttrsList(dst map[serverproto.Attr]float32, src []*serverproto.KeyValueFloat32, rate int32) {
|
||
for idx := 0; idx < len(src); idx++ {
|
||
k := serverproto.Attr(src[idx].Key)
|
||
v := src[idx].Value
|
||
|
||
bFind := false
|
||
for idx := 0; idx < len(model.GlobalAttrPetNotInheritHeroList); idx++ {
|
||
if model.GlobalAttrPetNotInheritHeroList[idx] == k {
|
||
bFind = true
|
||
break
|
||
}
|
||
}
|
||
if bFind {
|
||
delete(dst, k)
|
||
continue
|
||
}
|
||
dst[k] += v * float32(rate) * 0.0001
|
||
}
|
||
}
|
||
|
||
func (this *ActorAttr) getPetEquipAttrs(petData *serverproto.PetData, baseAttrList map[serverproto.Attr]float32) {
|
||
var suitList = map[int32]int32{} //[qulity][num]
|
||
for _, data := range petData.SlotEquipList {
|
||
if data.EquipId <= 0 {
|
||
continue
|
||
}
|
||
petEquipData := this.getRole().GetRolePet().GetPetEquip(data.EquipId)
|
||
if petEquipData == nil {
|
||
return
|
||
}
|
||
cfgData, ok := model.ConvertPetEquip[petEquipData.EquipCfgId]
|
||
if !ok {
|
||
return
|
||
}
|
||
levelCfgData, ok := cfgData.LevelUpList[petEquipData.Level]
|
||
if !ok {
|
||
return
|
||
}
|
||
for key, val := range levelCfgData.AttrList {
|
||
baseAttrList[serverproto.Attr(key)] += float32(val)
|
||
}
|
||
|
||
//印记套装
|
||
for idx := 1; idx <= int(cfgData.Quality); idx++ {
|
||
suitList[int32(idx)]++
|
||
}
|
||
//suitList[cfgData.Quality]++
|
||
}
|
||
|
||
//使用套装ID最大的一套(套装属性只针对印记)
|
||
for _, data := range model.ConvertPteEquipSuit {
|
||
bOk := true
|
||
for idx := 0; idx < len(data.ConditionList); idx++ {
|
||
if suitList[data.ConditionList[idx].Key] < data.ConditionList[idx].Value {
|
||
bOk = false
|
||
break
|
||
}
|
||
}
|
||
if bOk {
|
||
for key, val := range data.AttrList {
|
||
baseAttrList[serverproto.Attr(key)] += float32(val)
|
||
}
|
||
break
|
||
}
|
||
}
|
||
|
||
//for key, value := range baseAttrList {
|
||
// if key >= serverproto.Attr_STR_Percent && key <= serverproto.Attr_RealHurt_Percent {
|
||
// baseAttrList[key] = value
|
||
// }
|
||
//}
|
||
//for key, value := range baseAttrList {
|
||
// if key < serverproto.Attr_STR_Percent {
|
||
// baseAttrList[key] = value * (1 + baseAttrList[key+30])
|
||
// }
|
||
//}
|
||
//for key, _ := range baseAttrList {
|
||
// if key >= serverproto.Attr_STR_Percent && key <= serverproto.Attr_RealHurt_Percent {
|
||
// baseAttrList[key] = 0
|
||
// }
|
||
//}
|
||
}
|
||
|
||
func (this *ActorAttr) getPetQiyueAttrs(petData *serverproto.PetData, baseAttrList map[serverproto.Attr]float32) {
|
||
//判断当前宠物是否跟随玩家(下阵后也需要计算)
|
||
//if petData.HeroId <= 0 {
|
||
// return
|
||
//}
|
||
petQiyueCfg, ok := serverproto.PetCfgLoader[petData.ConfigId]
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
heroData := this.getRole().GetRoleHero().GetHero(petData.HeroId)
|
||
if heroData == nil || heroData.PetQiyueData == nil || len(heroData.PetQiyueData.QiyueSlotList) <= 0 {
|
||
return
|
||
}
|
||
//已经下阵但是代码上HeroID还没有重置为0(该宠物应该算没有契约属性)
|
||
if heroData.PetQiyueData.PetId <= 0 {
|
||
return
|
||
}
|
||
|
||
type petAttrTmp struct {
|
||
sameNatureType bool
|
||
contract int32 //继承万分比
|
||
outAttr *serverproto.ActorAttrType
|
||
totalSKillLevel int32
|
||
totalSkillLevelFactor int32
|
||
}
|
||
var petAttrTmpList []*petAttrTmp
|
||
sameNatureTypeNum := 0
|
||
|
||
for idx := 0; idx < len(heroData.PetQiyueData.QiyueSlotList); idx++ {
|
||
slotInfo := heroData.PetQiyueData.QiyueSlotList[idx]
|
||
if slotInfo.PetId > 0 && slotInfo.PetCfgId > 0 {
|
||
slotPetData := this.getRole().GetRolePet().getPet(slotInfo.PetId)
|
||
if slotPetData == nil {
|
||
continue
|
||
}
|
||
petCfg, ok := serverproto.PetCfgLoader[slotPetData.ConfigId]
|
||
if !ok {
|
||
continue
|
||
}
|
||
slotPetAttr := this.attrMag.getPetActorAttr(slotPetData)
|
||
if slotPetAttr == nil {
|
||
continue
|
||
}
|
||
if len(slotPetAttr.curPetAttrForPetBase) <= 0 {
|
||
this.attrMag.calcAttrPet([]*serverproto.PetData{slotPetData}, AttrChangeST{
|
||
ChangePetData: slotPetData,
|
||
IgnoreNotify: true,
|
||
})
|
||
}
|
||
|
||
//相同属性继承百分比处理
|
||
tmpAttr := &petAttrTmp{
|
||
contract: petCfg.Contract,
|
||
outAttr: &serverproto.ActorAttrType{
|
||
ActorId: slotPetData.Id,
|
||
},
|
||
}
|
||
this.attrMag.copyAttrToMsg(slotPetAttr, tmpAttr.outAttr)
|
||
if petCfg.NatureType == petQiyueCfg.NatureType {
|
||
sameNatureTypeNum++
|
||
tmpAttr.sameNatureType = true
|
||
}
|
||
//领悟次数增加百分比
|
||
tmpAttr.totalSKillLevel = this.getRole().GetRolePet().GetPetTotalSkillLevel(slotPetData)
|
||
tmpAttr.totalSkillLevelFactor = petCfg.Understand
|
||
|
||
petAttrTmpList = append(petAttrTmpList, tmpAttr)
|
||
}
|
||
}
|
||
|
||
//契约属性继承
|
||
for idx := 0; idx < len(petAttrTmpList); idx++ {
|
||
pet := petAttrTmpList[idx]
|
||
tmpContract := pet.contract
|
||
if pet.sameNatureType {
|
||
//相同属性百分比
|
||
tmpContract += model.GlobalPetQiyueNatureRate * int32(sameNatureTypeNum)
|
||
}
|
||
//领悟次数增加百分比
|
||
tmpContract += pet.totalSKillLevel * pet.totalSkillLevelFactor
|
||
this.petInheritAttrsList(baseAttrList, pet.outAttr.AttrList, tmpContract)
|
||
}
|
||
}
|
||
|
||
//for pet(宠物自身属性计算)
|
||
func (this *ActorAttr) calPetAttrForPetBase() bool {
|
||
//check is'nt a pet
|
||
if !this.isPet {
|
||
return false
|
||
}
|
||
if !this.changeSetList.Has(Attr_Change_Pet_Base) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Pet_Base)
|
||
|
||
petCfgId := this.heroConfigId
|
||
petCfg, ok := serverproto.PetCfgLoader[petCfgId]
|
||
if !ok {
|
||
return false
|
||
}
|
||
progressData, ok := model.ConvertPetProgress[petCfgId]
|
||
if !ok {
|
||
return false
|
||
}
|
||
|
||
attrList := map[serverproto.Attr]float32{}
|
||
progressLevel := this.level
|
||
if len(model.GlobalPetAdvanceLimit) > 0 {
|
||
if progressLevel >= model.GlobalPetAdvanceLimit[0] {
|
||
progressLevel = model.GlobalPetAdvanceLimit[0]
|
||
}
|
||
}
|
||
var tmpBaseAttrList = map[serverproto.Attr]float32{}
|
||
tmpBaseAttrList[serverproto.Attr(serverproto.Attr_Life)] = float32(petCfg.Hp)
|
||
tmpBaseAttrList[serverproto.Attr(serverproto.Attr_Sp)] = float32(petCfg.Sp)
|
||
tmpBaseAttrList[serverproto.Attr(serverproto.Attr_Attack)] = float32(petCfg.Atk)
|
||
tmpBaseAttrList[serverproto.Attr(serverproto.Attr_MagicAttack)] = float32(petCfg.Matk)
|
||
tmpBaseAttrList[serverproto.Attr(serverproto.Attr_Defense)] = float32(petCfg.Def)
|
||
tmpBaseAttrList[serverproto.Attr(serverproto.Attr_MagicDefense)] = float32(petCfg.Mdef)
|
||
tmpBaseAttrList[serverproto.Attr(serverproto.Attr_Hit)] = float32(petCfg.Hit)
|
||
tmpBaseAttrList[serverproto.Attr(serverproto.Attr_Dodge)] = float32(petCfg.Dodge)
|
||
tmpBaseAttrList[serverproto.Attr(serverproto.Attr_Crit)] = float32(petCfg.Crit)
|
||
tmpBaseAttrList[serverproto.Attr(serverproto.Attr_Ten)] = float32(petCfg.Ten)
|
||
tmpBaseAttrList[serverproto.Attr(serverproto.Attr_AttackSpeed)] = float32(petCfg.AttackSpeed)
|
||
|
||
var tmpBaseRateList = map[serverproto.Attr]float32{}
|
||
tmpBaseRateList[serverproto.Attr(serverproto.Attr_Life)] = float32(petCfg.HpRate) * 0.0001
|
||
tmpBaseRateList[serverproto.Attr(serverproto.Attr_Sp)] = float32(petCfg.SpRate) * 0.0001
|
||
tmpBaseRateList[serverproto.Attr(serverproto.Attr_Attack)] = float32(petCfg.AtkRate) * 0.0001
|
||
tmpBaseRateList[serverproto.Attr(serverproto.Attr_MagicAttack)] = float32(petCfg.MatkRate) * 0.0001
|
||
tmpBaseRateList[serverproto.Attr(serverproto.Attr_Defense)] = float32(petCfg.DefRate) * 0.0001
|
||
tmpBaseRateList[serverproto.Attr(serverproto.Attr_MagicDefense)] = float32(petCfg.MdefRate) * 0.0001
|
||
tmpBaseRateList[serverproto.Attr(serverproto.Attr_Hit)] = float32(petCfg.HitRate) * 0.0001
|
||
tmpBaseRateList[serverproto.Attr(serverproto.Attr_Dodge)] = float32(petCfg.DodgeRate) * 0.0001
|
||
tmpBaseRateList[serverproto.Attr(serverproto.Attr_Crit)] = float32(petCfg.CritRate) * 0.0001
|
||
tmpBaseRateList[serverproto.Attr(serverproto.Attr_Ten)] = float32(petCfg.TenRate) * 0.0001
|
||
for k, v := range tmpBaseAttrList {
|
||
attrList[k] = v + v*float32(progressLevel-1)*tmpBaseRateList[k]
|
||
}
|
||
|
||
for advLevel := 1; advLevel <= int(this.advLevel); advLevel++ {
|
||
if len(model.GlobalPetAdvanceLimit) <= advLevel {
|
||
continue
|
||
}
|
||
for idx := 0; idx < len(progressData.ProgressList); idx++ {
|
||
if progressData.ProgressList[idx].ProgressLevel != int32(advLevel) {
|
||
continue
|
||
}
|
||
//进阶增加属性
|
||
for i := 0; i < len(progressData.ProgressList[idx].AttrList); i++ {
|
||
kv := progressData.ProgressList[idx].AttrList[i]
|
||
attrList[serverproto.Attr(kv.Key)] += float32(kv.Value)
|
||
}
|
||
|
||
//进阶后成长率变更对应的等级属性
|
||
progressLevel = this.level
|
||
if progressLevel >= model.GlobalPetAdvanceLimit[advLevel] {
|
||
progressLevel = model.GlobalPetAdvanceLimit[advLevel]
|
||
}
|
||
progressLevel -= model.GlobalPetAdvanceLimit[advLevel-1]
|
||
for i := 0; i < len(progressData.ProgressList[idx].RateList); i++ {
|
||
rate := progressData.ProgressList[idx].RateList[i]
|
||
attrList[serverproto.Attr(rate.Key)] +=
|
||
tmpBaseAttrList[serverproto.Attr(rate.Key)] * float32(progressLevel) * float32(rate.Value) * 0.0001
|
||
}
|
||
break
|
||
}
|
||
}
|
||
|
||
this.calAttr(this.curPetAttrForPetBase, attrList)
|
||
this.curPetAttrForPetBase = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
func (this *ActorAttr) calPetAttrForPetEquip(petData *serverproto.PetData) bool {
|
||
if !this.isPet {
|
||
return false
|
||
}
|
||
if !this.changeSetList.Has(Attr_Change_Pet_Equip) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Pet_Equip)
|
||
|
||
attrList := map[serverproto.Attr]float32{}
|
||
//get attr
|
||
this.getPetEquipAttrs(petData, attrList)
|
||
|
||
this.calAttr(this.curPetAttrForPetEquip, attrList)
|
||
this.curPetAttrForPetEquip = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
func (this *ActorAttr) calPetAttrForPetBond(petData *serverproto.PetData) bool {
|
||
if !this.isPet {
|
||
return false
|
||
}
|
||
if !this.changeSetList.Has(Attr_Change_Pet_Bond) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Pet_Bond)
|
||
|
||
attrList := map[serverproto.Attr]float32{}
|
||
if this.attrMag.role.GetRolePet().isBattle(petData) {
|
||
for k, v := range this.attrMag.curGlobalPetBondAttr {
|
||
attrList[k] += v
|
||
}
|
||
}
|
||
this.calAttr(this.curPetAttrForPetBond, attrList)
|
||
this.curPetAttrForPetBond = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
func (this *ActorAttr) calPetAttrForPetSkill(petData *serverproto.PetData) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Pet_Skill) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Pet_Skill)
|
||
|
||
return true
|
||
}
|
||
|
||
func (this *ActorAttr) calPetAttrForPetQiyue(petData *serverproto.PetData) bool {
|
||
if !this.changeSetList.Has(Attr_Change_Pet_Qiyue) {
|
||
return false
|
||
}
|
||
this.changeSetList.Remove(Attr_Change_Pet_Qiyue)
|
||
|
||
attrList := map[serverproto.Attr]float32{}
|
||
//get attr
|
||
this.getPetQiyueAttrs(petData, attrList)
|
||
|
||
this.calAttr(this.curPetAttrForPetQiyue, attrList)
|
||
this.curPetAttrForPetQiyue = attrList
|
||
|
||
return true
|
||
}
|
||
|
||
func (this *ActorAttr) calcActorFightPower(attrList []*serverproto.KeyValueFloat32) uint64 {
|
||
var fightPower uint64 = 0
|
||
|
||
//attr fight power
|
||
var jobType int32 = -1
|
||
if this.isPet {
|
||
jobType = this.getRole().GetRolePet().GetPetJobType(uint32(this.heroId))
|
||
} else {
|
||
jobType = this.getRole().GetRoleHero().GetHeroJobType(this.heroId)
|
||
}
|
||
|
||
if jobType < 0 {
|
||
return fightPower
|
||
}
|
||
jobCfgData, ok := model.ConvertFightPower[jobType]
|
||
if !ok {
|
||
return fightPower
|
||
}
|
||
for _, attr := range attrList {
|
||
if attr.Key <= 0 || attr.Value <= 0 {
|
||
continue
|
||
}
|
||
|
||
if fightCof, ok := jobCfgData[attr.Key]; ok {
|
||
if fightCof >= 0 {
|
||
fightPower += uint64(int32(attr.Value) * fightCof)
|
||
}
|
||
}
|
||
}
|
||
this.curAttrFightPower = uint64(fightPower)
|
||
|
||
//skill fight power
|
||
//初始化技能升级添加战斗力
|
||
if this.isPet {
|
||
this.curSkillFightPower =
|
||
int64(this.attrMag.getPetTotalSkillFightPower(this.heroId))
|
||
} else {
|
||
this.curSkillFightPower =
|
||
int64(this.attrMag.getHeroTotalSkillFightPower(this.heroId))
|
||
}
|
||
//if this.curSkillFightPower < 0 {
|
||
// if this.isPet {
|
||
// this.curSkillFightPower =
|
||
// int64(this.attrMag.getPetTotalSkillFightPower(this.heroId))
|
||
// } else {
|
||
// this.curSkillFightPower =
|
||
// int64(this.attrMag.getHeroTotalSkillFightPower(this.heroId))
|
||
// }
|
||
//}
|
||
|
||
this.curSkillEquipFightPower = int64(this.attrMag.getSkillEquipFightPower(this.heroId))
|
||
|
||
fightPower += uint64(this.curSkillFightPower)
|
||
fightPower += uint64(this.curSkillEquipFightPower)
|
||
|
||
return fightPower
|
||
}
|
||
|
||
//战斗属性计算
|
||
type RoleBattleAttr struct {
|
||
role *Role
|
||
bInitAttrCalc bool //玩家登陆时第一战斗时计算上阵单位属性
|
||
curTotalFightPower uint32 //当前玩家总战力
|
||
|
||
battleHeroActorList map[uint32]*serverproto.ActorData
|
||
//玩家英雄属性列表
|
||
roleActorAttrList map[int32]*ActorAttr
|
||
//玩家宠物属性列表
|
||
rolePetAttrList map[int32]*ActorAttr
|
||
|
||
//时装属性(多个英雄处理,所以这边单独分开)
|
||
curGlobalFashionAttr map[int32]map[serverproto.Attr]float32 //时装 [jobtype][attr][val]
|
||
bInitGlobalFashionAttr bool
|
||
//收集屋藏品属性(多个英雄处理,所以这边单独分开)
|
||
curGlobalSakeAttr map[int32]map[serverproto.Attr]float32 //[jobtype][attr][val]
|
||
bInitGlobalSakeAttr bool
|
||
//宠物羁绊属性(上阵所有宠物处理)
|
||
curGlobalPetBondAttr map[serverproto.Attr]float32 //[attr][val]
|
||
bInitGlobalPetBondAttr bool
|
||
}
|
||
|
||
func newRoleBattleAttr(r *Role) *RoleBattleAttr {
|
||
mag := &RoleBattleAttr{
|
||
role: r,
|
||
}
|
||
|
||
mag.rolePetAttrList = map[int32]*ActorAttr{}
|
||
mag.battleHeroActorList = map[uint32]*serverproto.ActorData{}
|
||
mag.roleActorAttrList = map[int32]*ActorAttr{}
|
||
mag.curGlobalFashionAttr = map[int32]map[serverproto.Attr]float32{}
|
||
mag.curGlobalSakeAttr = map[int32]map[serverproto.Attr]float32{}
|
||
mag.curGlobalPetBondAttr = map[serverproto.Attr]float32{}
|
||
|
||
return mag
|
||
}
|
||
|
||
//hero
|
||
func (this *RoleBattleAttr) getActorAttr(heroData *serverproto.HeroData) *ActorAttr {
|
||
actorAttr, ok := this.roleActorAttrList[heroData.Id]
|
||
if !ok {
|
||
actorAttr = newActorAttr(this, heroData.Id, heroData.ConfigId,
|
||
heroData.BaseLevel, heroData.AdvanceLevel, heroData.StrengthLevel)
|
||
this.roleActorAttrList[heroData.Id] = actorAttr
|
||
|
||
//技能初始化
|
||
this.HeroSkillChange(heroData)
|
||
|
||
actorAttr.changeSetList.Add(
|
||
Attr_Change_Fashion,
|
||
Attr_Change_Card,
|
||
Attr_Change_Equip,
|
||
Attr_Change_AddPoint,
|
||
Attr_Change_Skill,
|
||
Attr_Change_Advance,
|
||
Attr_Change_Strength,
|
||
Attr_Change_Pet,
|
||
Attr_Change_HeadFrame,
|
||
Attr_Change_Sake,
|
||
Attr_Change_Skill_Equip_Slot)
|
||
}
|
||
return actorAttr
|
||
}
|
||
|
||
//pet
|
||
func (this *RoleBattleAttr) getPetActorAttr(petData *serverproto.PetData) *ActorAttr {
|
||
actorAttr, ok := this.rolePetAttrList[int32(petData.Id)]
|
||
if !ok {
|
||
actorAttr = newPetAttr(this, int32(petData.Id), petData.ConfigId,
|
||
petData.Level, int32(petData.AdvanceLevel))
|
||
this.rolePetAttrList[int32(petData.Id)] = actorAttr
|
||
|
||
actorAttr.changeSetList.Add(
|
||
Attr_Change_Pet_Base,
|
||
Attr_Change_Pet_Equip,
|
||
Attr_Change_Pet_Bond,
|
||
Attr_Change_Pet_Qiyue)
|
||
}
|
||
return actorAttr
|
||
}
|
||
|
||
//属性变更
|
||
type AttrChangeST struct {
|
||
IgnoreNotify bool //是否通知客户端属性变更(true不通知)
|
||
FightChangeNotNotify bool
|
||
|
||
ChangeType int
|
||
ForceChangeType int //强制需要重新计算的属性类型
|
||
ChangeHeroData *serverproto.HeroData
|
||
BNotCalc bool //true不计算 false计算
|
||
ChangeJobType []int32 //fashion,sake
|
||
|
||
IsPet bool //true:pet false:hero
|
||
ChangePetData *serverproto.PetData
|
||
|
||
//技能处理
|
||
BSkillReset bool
|
||
SkillCfgId int32
|
||
OldSkillLevel int32
|
||
NewSkillLevel int32
|
||
|
||
//头像框处理
|
||
BHeadFrameDelete bool
|
||
HeadFrameId int32
|
||
}
|
||
|
||
//压制值计算
|
||
type RepressChangeST struct {
|
||
HeroData *serverproto.HeroData
|
||
BReset bool
|
||
SkillCfgId int32
|
||
OldSKillLevel int32
|
||
NewSKillLevel int32
|
||
}
|
||
|
||
//技能变化
|
||
func (this *RoleBattleAttr) HeroSkillChange(heroData *serverproto.HeroData) {
|
||
if heroData == nil {
|
||
return
|
||
}
|
||
actorAttr, ok := this.roleActorAttrList[heroData.Id]
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
if len(actorAttr.normalSKillList) <= 0 {
|
||
for _, skill := range heroData.Skill.SkillList {
|
||
actorAttr.normalSKillList = append(actorAttr.normalSKillList, &serverproto.KeyValueType{
|
||
Key: skill.DefaultSkillId,
|
||
Value: 1,
|
||
})
|
||
actorAttr.useSkillList = append(actorAttr.useSkillList, &serverproto.KeyValueType{
|
||
Key: skill.SkillId,
|
||
Value: skill.Unlock,
|
||
})
|
||
}
|
||
} else {
|
||
actorAttr.useSkillList = actorAttr.useSkillList[:0]
|
||
for _, skill := range heroData.Skill.SkillList {
|
||
actorAttr.useSkillList = append(actorAttr.useSkillList, &serverproto.KeyValueType{
|
||
Key: skill.SkillId,
|
||
Value: skill.Unlock,
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
//等级属性变更
|
||
func (this *RoleBattleAttr) ResetLevelAttrList(heroData *serverproto.HeroData) {
|
||
if heroData == nil {
|
||
return
|
||
}
|
||
actorAttr := this.getActorAttr(heroData)
|
||
actorAttr.resetAttrList(heroData.BaseLevel, heroData.AdvanceLevel, heroData.StrengthLevel)
|
||
|
||
this.AttrChange(AttrChangeST{
|
||
ChangeType: Attr_Change_AddPoint,
|
||
ChangeHeroData: heroData,
|
||
FightChangeNotNotify: !heroData.IsBattle,
|
||
})
|
||
}
|
||
|
||
//更换职业属性变更
|
||
func (this *RoleBattleAttr) ResetJobAttrList(heroData *serverproto.HeroData) {
|
||
if heroData == nil {
|
||
return
|
||
}
|
||
actorAttr := this.getActorAttr(heroData)
|
||
actorAttr.heroConfigId = heroData.ConfigId
|
||
if actorAttr.isMainHero {
|
||
actorAttr.initJobAttr()
|
||
}
|
||
|
||
actorAttr.resetAttrList(heroData.BaseLevel, heroData.AdvanceLevel, heroData.StrengthLevel)
|
||
this.AttrChange(AttrChangeST{
|
||
ChangeType: Attr_Change_Skill,
|
||
ChangeHeroData: heroData,
|
||
BNotCalc: true,
|
||
})
|
||
this.AttrChange(AttrChangeST{
|
||
ChangeType: Attr_Change_AddPoint,
|
||
ChangeHeroData: heroData,
|
||
})
|
||
}
|
||
|
||
func (this *RoleBattleAttr) PartnerAdvanceAttrList(heroData *serverproto.HeroData) {
|
||
if heroData == nil {
|
||
return
|
||
}
|
||
//actorAttr := this.getActorAttr(heroData)
|
||
|
||
//actorAttr.resetAttrList(heroData.BaseLevel, heroData.AdvanceLevel, heroData.StrengthLevel)
|
||
this.AttrChange(AttrChangeST{
|
||
ChangeType: Attr_Change_Advance,
|
||
ChangeHeroData: heroData,
|
||
})
|
||
}
|
||
|
||
//属性变更唯一对外接口
|
||
func (this *RoleBattleAttr) AttrChange(attrChangeSt AttrChangeST) {
|
||
|
||
if attrChangeSt.IsPet {
|
||
//pet
|
||
this.attrChangePet(attrChangeSt)
|
||
} else {
|
||
//hero
|
||
this.attrChangeHero(attrChangeSt)
|
||
}
|
||
|
||
//判断战力变化
|
||
if !attrChangeSt.FightChangeNotNotify {
|
||
this.checkFightPower(true)
|
||
}
|
||
}
|
||
|
||
func (this *RoleBattleAttr) attrChangeHero(attrChangeSt AttrChangeST) {
|
||
if attrChangeSt.ChangeHeroData == nil {
|
||
return
|
||
}
|
||
|
||
if !this.bInitGlobalFashionAttr {
|
||
this.getFashionAttr(nil)
|
||
}
|
||
if !this.bInitGlobalSakeAttr {
|
||
this.getSakeAttr(nil)
|
||
}
|
||
if !this.bInitGlobalPetBondAttr {
|
||
this.getPetBondAttr()
|
||
}
|
||
|
||
if attrChangeSt.ChangeType == Attr_Change_Fashion || attrChangeSt.ChangeType == Attr_Change_Sake {
|
||
if attrChangeSt.ChangeType == Attr_Change_Fashion {
|
||
this.getFashionAttr(nil)
|
||
} else if attrChangeSt.ChangeType == Attr_Change_Sake {
|
||
this.getSakeAttr(nil)
|
||
}
|
||
|
||
var calHeroList []*serverproto.HeroData
|
||
for idx := 0; idx < len(attrChangeSt.ChangeJobType); idx++ {
|
||
jobType := attrChangeSt.ChangeJobType[idx]
|
||
heroData := this.role.GetRoleHero().GetHeroByJobId(jobType)
|
||
if heroData == nil {
|
||
continue
|
||
}
|
||
|
||
bFind := false
|
||
for k := 0; k < len(calHeroList); k++ {
|
||
if calHeroList[k].Id == heroData.Id {
|
||
bFind = true
|
||
break
|
||
}
|
||
}
|
||
if !bFind {
|
||
actorAttr := this.getActorAttr(heroData)
|
||
if attrChangeSt.ChangeType > Attr_Change_None {
|
||
actorAttr.changeSetList.Add(attrChangeSt.ChangeType)
|
||
}
|
||
calHeroList = append(calHeroList, heroData)
|
||
|
||
if !attrChangeSt.BNotCalc {
|
||
this.calcAttrHero(heroData, AttrChangeST{})
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
actorAttr := this.getActorAttr(attrChangeSt.ChangeHeroData)
|
||
if attrChangeSt.ChangeType > Attr_Change_None {
|
||
actorAttr.changeSetList.Add(attrChangeSt.ChangeType)
|
||
}
|
||
|
||
if !attrChangeSt.BNotCalc {
|
||
this.calcAttrHero(attrChangeSt.ChangeHeroData, attrChangeSt)
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *RoleBattleAttr) attrChangePet(attrChangeSt AttrChangeST) {
|
||
if attrChangeSt.ChangePetData == nil &&
|
||
attrChangeSt.ChangeType != Attr_Change_Pet_Bond {
|
||
return
|
||
}
|
||
|
||
//init attr
|
||
var changePetDataList []*serverproto.PetData
|
||
if attrChangeSt.ChangeType == Attr_Change_Pet_Bond {
|
||
//reset attr
|
||
this.getPetBondAttr()
|
||
this.role.GetRoleHero().GetBattlePetList(&changePetDataList)
|
||
if attrChangeSt.ChangePetData != nil {
|
||
changePetDataList = append(changePetDataList, attrChangeSt.ChangePetData)
|
||
}
|
||
} else {
|
||
if !this.bInitGlobalPetBondAttr {
|
||
this.getPetBondAttr()
|
||
}
|
||
changePetDataList = append(changePetDataList, attrChangeSt.ChangePetData)
|
||
}
|
||
|
||
//battle pet list
|
||
for idx := 0; idx < len(changePetDataList); idx++ {
|
||
petActorAttr := this.getPetActorAttr(changePetDataList[idx])
|
||
if attrChangeSt.ChangeType > Attr_Change_None {
|
||
petActorAttr.changeSetList.Add(attrChangeSt.ChangeType)
|
||
}
|
||
if attrChangeSt.ForceChangeType > Attr_Change_None {
|
||
petActorAttr.changeSetList.Add(attrChangeSt.ForceChangeType)
|
||
}
|
||
}
|
||
if !attrChangeSt.BNotCalc {
|
||
outChangePetDataList := this.calcAttrPet(changePetDataList, attrChangeSt)
|
||
//当前宠物在契约槽内,需要处理契约宠物属性
|
||
//pet for qiyue
|
||
if attrChangeSt.ChangePetData != nil {
|
||
qiyuePetId, bQiyueSlot := this.role.GetRolePet().IsPetInQiyueSlot(attrChangeSt.ChangePetData.Id)
|
||
if bQiyueSlot {
|
||
this.attrChangePet(AttrChangeST{
|
||
IsPet: true,
|
||
ChangePetData: this.role.GetRolePet().getPet(qiyuePetId),
|
||
ChangeType: Attr_Change_Pet_Qiyue,
|
||
FightChangeNotNotify: true,
|
||
})
|
||
}
|
||
}
|
||
|
||
//pet fro hero
|
||
for idx := 0; idx < len(outChangePetDataList); idx++ {
|
||
//出阵宠物属性变更后,玩家属性继承处理
|
||
if this.role.GetRolePet().isBattle(outChangePetDataList[idx]) || outChangePetDataList[idx].HeroId > 0 {
|
||
this.attrChangeHero(AttrChangeST{
|
||
IgnoreNotify: attrChangeSt.IgnoreNotify,
|
||
ChangeHeroData: this.role.GetRoleHero().GetHero(outChangePetDataList[idx].HeroId),
|
||
ChangeType: Attr_Change_Pet,
|
||
})
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *RoleBattleAttr) getHeroFightPower(heroData *serverproto.HeroData) int64 {
|
||
var fightPower int64 = 0
|
||
//battle hero
|
||
this.attrChangeHero(AttrChangeST{
|
||
IgnoreNotify: true,
|
||
ChangeType: Attr_Change_None,
|
||
ChangeHeroData: heroData,
|
||
})
|
||
actorAttr := this.getActorAttr(heroData)
|
||
if actorAttr != nil {
|
||
fightPower += int64(actorAttr.curAttrFightPower)
|
||
fightPower += actorAttr.curSkillFightPower
|
||
fightPower += actorAttr.curSkillEquipFightPower
|
||
}
|
||
return fightPower
|
||
}
|
||
func (this *RoleBattleAttr) getPetFightPower(petData *serverproto.PetData) int64 {
|
||
var fightPower int64 = 0
|
||
this.attrChangePet(AttrChangeST{
|
||
IgnoreNotify: true,
|
||
IsPet: true,
|
||
ChangeType: Attr_Change_None,
|
||
ChangePetData: petData,
|
||
})
|
||
petActorAttr := this.getPetActorAttr(petData)
|
||
if petActorAttr != nil {
|
||
fightPower += int64(petActorAttr.curAttrFightPower)
|
||
fightPower += petActorAttr.curSkillFightPower
|
||
}
|
||
return fightPower
|
||
}
|
||
|
||
//获取当前所有技能对应的战力加成
|
||
func (this *RoleBattleAttr) getHeroTotalSkillFightPower(actorId int32) int32 {
|
||
var fightPower int32 = 0
|
||
heroData := this.role.GetRoleHero().GetHero(actorId)
|
||
if heroData == nil || heroData.Skill == nil {
|
||
return fightPower
|
||
}
|
||
|
||
isMainHero := this.role.GetRoleHero().IsMainHero(actorId)
|
||
|
||
for _, skillList := range heroData.Skill.JobSkillList {
|
||
for _, skill := range skillList.UnlockSkillList {
|
||
skillCfg, ok := serverproto.SkillCfgLoader[skill.Key]
|
||
if !ok {
|
||
continue
|
||
}
|
||
fightPower += skillCfg.AddFight * skill.Value
|
||
|
||
this.getHeroTotalSkillFightPower_1(skill.Key, isMainHero, &fightPower)
|
||
}
|
||
}
|
||
return fightPower
|
||
}
|
||
func (this *RoleBattleAttr) getHeroTotalSkillFightPower_1(skillId int32, isMainHero bool, fightPower *int32) {
|
||
if isMainHero {
|
||
//role
|
||
skillCfg, ok := serverproto.SkillTreeCfgLoader[skillId]
|
||
if !ok || skillCfg.BeforeSkill <= 0 {
|
||
return
|
||
}
|
||
beforeSkill, ok := serverproto.SkillTreeCfgLoader[skillCfg.BeforeSkill]
|
||
if ok {
|
||
beforeSkillCfg, ok := serverproto.SkillCfgLoader[skillCfg.BeforeSkill]
|
||
if ok {
|
||
*fightPower += beforeSkillCfg.AddFight * beforeSkill.MaxLv
|
||
}
|
||
this.getHeroTotalSkillFightPower_1(skillCfg.BeforeSkill, isMainHero, fightPower)
|
||
}
|
||
} else {
|
||
//partner
|
||
skillCfg, ok := serverproto.ParterSkillTreeCfgLoader[skillId]
|
||
if !ok || skillCfg.BeforeSkill <= 0 {
|
||
return
|
||
}
|
||
beforeSkill, ok := serverproto.ParterSkillTreeCfgLoader[skillCfg.BeforeSkill]
|
||
if ok {
|
||
beforeSkillCfg, ok := serverproto.SkillCfgLoader[skillCfg.BeforeSkill]
|
||
if ok {
|
||
*fightPower += beforeSkillCfg.AddFight * beforeSkill.MaxLv
|
||
}
|
||
|
||
this.getHeroTotalSkillFightPower_1(skillCfg.BeforeSkill, isMainHero, fightPower)
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *RoleBattleAttr) getPetTotalSkillFightPower(actorId int32) int32 {
|
||
var fightPower int32 = 0
|
||
petData := this.role.GetRolePet().getPet(uint32(actorId))
|
||
if petData == nil {
|
||
return fightPower
|
||
}
|
||
for _, skill := range petData.SkillList {
|
||
skillCfg, ok := serverproto.SkillCfgLoader[skill.ConfigId]
|
||
if !ok {
|
||
continue
|
||
}
|
||
fightPower += skillCfg.AddFight * skill.Level
|
||
}
|
||
return fightPower
|
||
}
|
||
|
||
func (this *RoleBattleAttr) getSkillEquipFightPower(heroId int32) int32 {
|
||
var fightPower int32 = 0
|
||
hero := this.role.GetRoleHero().GetHero(heroId)
|
||
if hero == nil ||
|
||
hero.SkillEquipSlot == nil ||
|
||
hero.SkillEquipSlot.SlotList == nil {
|
||
return fightPower
|
||
}
|
||
|
||
for _, slotDetail := range hero.SkillEquipSlot.SlotList {
|
||
powerMap, ok := model.SkillEquipAppendFightPowerContainer[slotDetail.SkillEquipConfigId]
|
||
if !ok {
|
||
break
|
||
}
|
||
power, ok1 := powerMap[slotDetail.SkillEquipStarLevel-1]
|
||
if !ok1 {
|
||
break
|
||
}
|
||
fightPower += power
|
||
}
|
||
return fightPower
|
||
}
|
||
|
||
func (this *RoleBattleAttr) checkFightPower(bNotify bool) *serverproto.FightPowerData {
|
||
util.InfoF("uid=%v RoleBattleAttr", this.role.GetUUid())
|
||
|
||
ntfMsg := &serverproto.SCFightPowerChagneNtf{
|
||
Data: &serverproto.FightPowerData{},
|
||
}
|
||
|
||
var heroList []*serverproto.HeroData
|
||
this.role.GetRoleHero().GetBattleHeroList(&heroList)
|
||
var totalFightPower int64 = 0
|
||
for _, heroData := range heroList {
|
||
if !heroData.IsBattle {
|
||
continue
|
||
}
|
||
|
||
heroFightPower := this.getHeroFightPower(heroData)
|
||
var petFightPower int64 = 0
|
||
//battle pet
|
||
if heroData.BattlePetId > 0 {
|
||
petData := this.role.GetRolePet().getPet(heroData.BattlePetId)
|
||
if petData != nil {
|
||
petFightPower = this.getPetFightPower(petData)
|
||
}
|
||
}
|
||
|
||
totalFightPower += heroFightPower / 10
|
||
totalFightPower += petFightPower / 10
|
||
|
||
ntfMsg.Data.SlotFightpower = append(ntfMsg.Data.SlotFightpower,
|
||
&serverproto.SlotFightPower{
|
||
HeroId: heroData.Id,
|
||
HeroFightPower: uint64(heroFightPower / 10),
|
||
PetFightPower: uint64(petFightPower / 10),
|
||
})
|
||
}
|
||
|
||
ntfMsg.Data.TotalFightpower = uint32(totalFightPower)
|
||
this.curTotalFightPower = ntfMsg.Data.TotalFightpower
|
||
this.role.GetRoleBase().SetFightPower(ntfMsg.Data.TotalFightpower)
|
||
TaskMagCheck(this.role, serverproto.TaskType_Eve_Fight_value, int32(ntfMsg.Data.TotalFightpower))
|
||
TaskMagCheck(this.role, serverproto.TaskType_Total_Power, int32(ntfMsg.Data.TotalFightpower))
|
||
if bNotify {
|
||
this.role.ReplayGate(ntfMsg, true)
|
||
util.InfoF("uid=%v SCFightPowerChangeNtf data=%v", this.role.GetUUid(), ntfMsg.Data)
|
||
this.WriteMiaojuFightPowerLog(ntfMsg.Data.TotalFightpower)
|
||
}
|
||
//for _, data := range this.roleActorAttrList {
|
||
// util.DebugF("uid=%v checkFightPower heroid=%v selffight=%v", this.role.GetUUid(), data.heroId, (data.curAttrFightPower+uint64(data.curSkillFightPower))/10)
|
||
//}
|
||
//for _, data := range this.rolePetAttrList {
|
||
// util.DebugF("uid=%v checkFightPower petid=%v selffight=%v", this.role.GetUUid(), data.heroId, (data.curAttrFightPower+uint64(data.curSkillFightPower))/10)
|
||
//}
|
||
//util.DebugF("uid=%v totalFightPower=%v", this.role.GetUUid(), this.curTotalFightPower)
|
||
|
||
return ntfMsg.Data
|
||
}
|
||
|
||
func (this *RoleBattleAttr)WriteMiaojuFightPowerLog(fightPower uint32) {
|
||
fightPowerLog := &MiaojuLogFightPower{
|
||
Properties: FightPower{
|
||
Capability: int(fightPower),
|
||
},
|
||
}
|
||
fightPowerLog.OpenId = this.role.GetLunaAccount()
|
||
fightPowerLog.DistinctId = ""
|
||
fightPowerLog.Type = "user_set"
|
||
fightPowerLog.CurTime = time.Unix(int64(util.GetTimeSeconds()), 0).Format(util.DATE_FORMAT)
|
||
fightPowerLog.Log(this.role)
|
||
}
|
||
|
||
func (this *RoleBattleAttr) syncActorData(out *serverproto.ActorBattleAttr, actorAttr *ActorAttr) {
|
||
return
|
||
out.Str = float32(actorAttr.STR())
|
||
out.Agi = float32(actorAttr.AGI())
|
||
out.Int = float32(actorAttr.INT())
|
||
out.Vit = float32(actorAttr.VIT())
|
||
out.Dex = float32(actorAttr.DEX())
|
||
out.Luk = float32(actorAttr.LUK())
|
||
|
||
//out.Life = actorAttr.Life()
|
||
out.Sp = actorAttr.Sp()
|
||
out.MinAttack = actorAttr.MinAttack()
|
||
out.Attack = actorAttr.Attack()
|
||
out.MinMagicAttack = actorAttr.MinMagicAttack()
|
||
out.MagicAttack = actorAttr.MagicAttack()
|
||
out.Defense = actorAttr.Defense()
|
||
out.MagicDefense = actorAttr.MagicDefense()
|
||
out.Crit = actorAttr.Crit()
|
||
out.CritDamagePercent = actorAttr.CritDamagePercent()
|
||
out.Dodge = actorAttr.Dodge()
|
||
out.Hit = actorAttr.Hit()
|
||
out.Ten = actorAttr.Ten()
|
||
out.AttackSpeed = actorAttr.AttackSpeed()
|
||
//out.RealHurt = actorAttr.GetAdditionalAttr(serverproto.Attr_RealHurt)
|
||
|
||
//attrPrintStr := "\nLife,SP=%v,%v " +
|
||
// "\nAttack,MagicAttack=%v,%v " +
|
||
// "\nDefense,MagicDefense=%v,%v " +
|
||
// "\nHit,Dodge=%v,%v " +
|
||
// "\nCrit,Ten=%v,%v " +
|
||
// "\nAttackSpeed=%v"
|
||
//util.InfoF(attrPrintStr, out.Life, out.Sp,
|
||
// out.MinAttack, out.MagicAttack,
|
||
// out.Defense, out.MagicDefense,
|
||
// out.Hit, out.Dodge,
|
||
// out.Crit, out.Ten,
|
||
// out.AttackSpeed)
|
||
util.InfoF("---------------------------------------------heroId=%v fightpower=%v", actorAttr.heroId, actorAttr.curSkillFightPower+int64(actorAttr.curAttrFightPower))
|
||
util.InfoF("Life,SP=%v,%v", out.Life, out.Sp)
|
||
util.InfoF("Attack,MagicAttack=%v,%v", out.MinAttack, out.MagicAttack)
|
||
util.InfoF("Defense,MagicDefense=%v,%v", out.Defense, out.MagicDefense)
|
||
util.InfoF("Hit,Dodge=%v,%v", out.Hit, out.Dodge)
|
||
util.InfoF("Crit,Ten=%v,%v", out.Crit, out.Ten)
|
||
util.InfoF("AttackSpeed=%v CastAcce=%v", out.AttackSpeed, actorAttr.CastAcce())
|
||
actorAttr.AdditionAttrPercentString()
|
||
util.InfoF("---------------------------------------------end\n\n")
|
||
|
||
out.DefPercent = actorAttr.DefPercent()
|
||
out.MagicDefPercent = actorAttr.MagicDefPercent()
|
||
|
||
//忽视物防
|
||
out.Penetration = actorAttr.Penetration()
|
||
//忽视魔防
|
||
out.MagicPenetration = actorAttr.MagicPenetration()
|
||
|
||
for idx := serverproto.Nature_NatureType_None; idx < serverproto.Nature_NatureType_Dark; idx++ {
|
||
idx1 := serverproto.Attr(int32(serverproto.Attr_Nature_None_Damage_Begin) + int32(idx))
|
||
val1 := actorAttr.GetAdditionalAttrPercent(idx1)
|
||
out.NatureDamagePercent = append(out.NatureDamagePercent, val1)
|
||
|
||
idx2 := serverproto.Attr(int32(serverproto.Attr_Nature_None_AntiDamage_Begin) + int32(idx))
|
||
val2 := actorAttr.GetAdditionalAttrPercent(idx2)
|
||
out.AntiNatureDamagePercent = append(out.AntiNatureDamagePercent, val2)
|
||
}
|
||
|
||
//触发型buff列表
|
||
if len(actorAttr.triggerBuffList) > 0 {
|
||
out.TriggerBuffList = out.TriggerBuffList[:0]
|
||
for _, data := range actorAttr.triggerBuffList {
|
||
out.TriggerBuffList = append(out.TriggerBuffList, data)
|
||
}
|
||
}
|
||
}
|
||
|
||
//时装属性
|
||
func (this *RoleBattleAttr) getFashionAttr(heroData *serverproto.HeroData) {
|
||
if heroData == nil {
|
||
//玩家自身角色
|
||
heroData = this.role.GetRoleHero().GetMainHero()
|
||
if heroData == nil {
|
||
return
|
||
}
|
||
}
|
||
|
||
//heroCfg, ok := serverproto.ParterCfgLoader[heroData.ConfigId]
|
||
//if !ok {
|
||
// return
|
||
//}
|
||
|
||
this.bInitGlobalFashionAttr = true
|
||
var mainRoleAttrJobType int32 = 0
|
||
this.curGlobalFashionAttr = map[int32]map[serverproto.Attr]float32{}
|
||
for _, data := range this.role.GetRoleFashion().fashionData {
|
||
//attrDataList, ok := model.FashionAttrContainer[data]
|
||
//if !ok {
|
||
// continue
|
||
//}
|
||
for _, attr := range data.attrs {
|
||
//if attr.JobType == 0 && this.role.GetRoleHero().IsMainHero(heroData.Id) {
|
||
// continue
|
||
//}
|
||
//if attr.JobType > 0 && attr.JobType != heroCfg.JobType {
|
||
// continue
|
||
//}
|
||
|
||
if _, ok := this.curGlobalFashionAttr[attr.JobType]; !ok {
|
||
this.curGlobalFashionAttr[attr.JobType] = map[serverproto.Attr]float32{}
|
||
}
|
||
this.curGlobalFashionAttr[attr.JobType][serverproto.Attr(attr.AttrId)] += float32(attr.Value)
|
||
}
|
||
}
|
||
//套装属性
|
||
for idx := 0; idx < len(this.role.GetRoleFashion().fashionSuitAttrs); idx++ {
|
||
attr := this.role.GetRoleFashion().fashionSuitAttrs[idx]
|
||
if _, ok := this.curGlobalFashionAttr[mainRoleAttrJobType]; !ok {
|
||
this.curGlobalFashionAttr[mainRoleAttrJobType] = map[serverproto.Attr]float32{}
|
||
}
|
||
this.curGlobalFashionAttr[mainRoleAttrJobType][serverproto.Attr(attr.Key)] += float32(attr.Value)
|
||
}
|
||
}
|
||
|
||
//收集屋藏品属性
|
||
func (this *RoleBattleAttr) getSakeAttr(heroData *serverproto.HeroData) {
|
||
if heroData == nil {
|
||
//玩家自身角色
|
||
heroData = this.role.GetRoleHero().GetMainHero()
|
||
if heroData == nil {
|
||
return
|
||
}
|
||
}
|
||
|
||
this.bInitGlobalSakeAttr = true
|
||
this.curGlobalSakeAttr = map[int32]map[serverproto.Attr]float32{}
|
||
for _, val := range this.role.GetRoleKeepSake().keepSake {
|
||
keepSakeCfg, ok := model.ConvertKeepSake[val.KeepSakeId]
|
||
if !ok {
|
||
continue
|
||
}
|
||
if len(keepSakeCfg.LevelDataList) <= 0 {
|
||
continue
|
||
}
|
||
//level attr
|
||
findIdx := -1
|
||
for key, sakeLevelData := range keepSakeCfg.LevelDataList {
|
||
if sakeLevelData.Level > val.KeepSakeLevel {
|
||
break
|
||
}
|
||
findIdx = key
|
||
}
|
||
if findIdx < 0 {
|
||
continue
|
||
}
|
||
|
||
//jobType add attr
|
||
for idx := 0; idx < len(keepSakeCfg.Job); idx++ {
|
||
jobType := keepSakeCfg.Job[idx]
|
||
if _, ok := this.curGlobalSakeAttr[jobType]; !ok {
|
||
this.curGlobalSakeAttr[jobType] = map[serverproto.Attr]float32{}
|
||
}
|
||
|
||
for k, v := range keepSakeCfg.LevelDataList[findIdx].AddAttr {
|
||
this.curGlobalSakeAttr[jobType][serverproto.Attr(k)] += float32(v)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//宠物羁绊属性
|
||
func (this *RoleBattleAttr) getPetBondAttr() {
|
||
if this.role.GetRolePet() == nil {
|
||
return
|
||
}
|
||
this.bInitGlobalPetBondAttr = true
|
||
this.curGlobalPetBondAttr = map[serverproto.Attr]float32{}
|
||
for _, data := range this.role.GetRolePet().bondList {
|
||
cfgData, ok := model.ConvertBondFight[data.BondCfgId]
|
||
if !ok {
|
||
continue
|
||
}
|
||
if data.PetBondLevel >= 1 {
|
||
for _, val := range cfgData.Attr1List {
|
||
this.curGlobalPetBondAttr[serverproto.Attr(val.Key)] += float32(val.Value)
|
||
}
|
||
}
|
||
if data.PetBondLevel >= 2 {
|
||
for _, val := range cfgData.Attr2List {
|
||
this.curGlobalPetBondAttr[serverproto.Attr(val.Key)] += float32(val.Value)
|
||
}
|
||
}
|
||
if data.PetBondLevel >= 3 {
|
||
for _, val := range cfgData.Attr3List {
|
||
this.curGlobalPetBondAttr[serverproto.Attr(val.Key)] += float32(val.Value)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *RoleBattleAttr) calcAttrHero(heroData *serverproto.HeroData, attrChangeSt AttrChangeST) map[uint32]*serverproto.ActorData {
|
||
//添加之前未初始化的英雄属性数据
|
||
if _, ok := this.roleActorAttrList[heroData.Id]; !ok {
|
||
this.attrChangeHero(AttrChangeST{
|
||
ChangeType: Attr_Change_None,
|
||
ChangeHeroData: heroData,
|
||
BNotCalc: true,
|
||
})
|
||
}
|
||
|
||
if actorAttr, ok := this.roleActorAttrList[heroData.Id]; ok {
|
||
//重新计算属性
|
||
bChange := actorAttr.calActorAttr(heroData, nil, nil, attrChangeSt)
|
||
|
||
actorData, ok := this.battleHeroActorList[uint32(actorAttr.heroId)]
|
||
if !ok {
|
||
actorData = &serverproto.ActorData{
|
||
Id: uint32(actorAttr.heroId),
|
||
IsPlayer: actorAttr.isMainHero,
|
||
BattleAttr: &serverproto.ActorBattleAttr{},
|
||
JobType: uint32(actorAttr.heroConfigId), //主角职业类型/hero配置ID
|
||
}
|
||
}
|
||
//战斗属性同步
|
||
if bChange {
|
||
this.syncActorData(actorData.BattleAttr, actorAttr)
|
||
this.battleHeroActorList[actorData.Id] = actorData
|
||
}
|
||
}
|
||
|
||
tempBattleHeroList := map[uint32]*serverproto.ActorData{}
|
||
tempBattleHeroList[uint32(heroData.Id)] = this.battleHeroActorList[uint32(heroData.Id)]
|
||
return tempBattleHeroList
|
||
}
|
||
|
||
func (this *RoleBattleAttr) calcAttrPet(petList []*serverproto.PetData, attrChangeSt AttrChangeST) (outList []*serverproto.PetData) {
|
||
for _, petData := range petList {
|
||
if _, ok := this.rolePetAttrList[int32(petData.Id)]; !ok {
|
||
this.attrChangePet(AttrChangeST{
|
||
ChangeType: Attr_Change_None,
|
||
ChangePetData: petData,
|
||
BNotCalc: true,
|
||
IsPet: true,
|
||
})
|
||
}
|
||
}
|
||
|
||
ntfMsg := &serverproto.SCActorAttrGetNtf{}
|
||
for idx := 0; idx < len(petList); idx++ {
|
||
if petAttr, ok := this.rolePetAttrList[int32(petList[idx].Id)]; ok {
|
||
//重新计算属性
|
||
petAttr.level = petList[idx].Level
|
||
petAttr.advLevel = int32(petList[idx].AdvanceLevel)
|
||
|
||
//pet base
|
||
changeBase := petAttr.calPetAttrForPetBase()
|
||
//pet equip(宠物印记/套装)
|
||
changePetEquip := petAttr.calPetAttrForPetEquip(petList[idx])
|
||
//pet bond(宠物羁绊)
|
||
changeBond := petAttr.calPetAttrForPetBond(petList[idx])
|
||
//skill for fight power
|
||
changeSkill := petAttr.calPetAttrForPetSkill(petList[idx])
|
||
//宠物契约
|
||
changeQiyue := petAttr.calPetAttrForPetQiyue(petList[idx])
|
||
|
||
if changeBase || changePetEquip || changeBond || changeSkill || changeQiyue {
|
||
actorAttrType := &serverproto.ActorAttrType{
|
||
ActorId: petList[idx].Id,
|
||
}
|
||
this.copyAttrToMsg(petAttr, actorAttrType)
|
||
ntfMsg.ActorAttrList = append(ntfMsg.ActorAttrList, actorAttrType)
|
||
|
||
//pet BattleAttrChange
|
||
//计算战力
|
||
heroFightPower := petAttr.calcActorFightPower(actorAttrType.AttrList)
|
||
this.role.GetRolePet().BattleAttrChange(petList[idx], actorAttrType, heroFightPower)
|
||
|
||
outList = append(outList, petList[idx])
|
||
|
||
//TODO
|
||
//pet equip(stone)
|
||
|
||
util.DebugF("------------------petbase=%v %v", petAttr.heroConfigId, petAttr.heroId)
|
||
petAttr.AdditionAttrPercentString()
|
||
util.DebugF("------------------petbase end\n\n")
|
||
|
||
if len(petAttr.curPetAttrForPetQiyue) > 0 {
|
||
type kvSt struct {
|
||
attrKey serverproto.Attr
|
||
attrVal float32
|
||
}
|
||
var kvList []kvSt
|
||
for key, val := range petAttr.curPetAttrForPetQiyue {
|
||
//util.InfoF("%v=%v", key, val/100)
|
||
kvList = append(kvList, kvSt{attrKey: key, attrVal: val})
|
||
}
|
||
|
||
sort.Slice(kvList, func(i, j int) bool {
|
||
return kvList[i].attrKey < kvList[j].attrKey
|
||
})
|
||
for idx := 0; idx < len(kvList); idx++ {
|
||
util.InfoF("%v=%v %v%%", kvList[idx].attrKey, kvList[idx].attrVal, kvList[idx].attrVal/100)
|
||
}
|
||
util.DebugF("------------------petbase endinherit\n\n")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if !attrChangeSt.IgnoreNotify && len(ntfMsg.ActorAttrList) > 0 {
|
||
this.role.ReplayGate(ntfMsg, true)
|
||
}
|
||
return
|
||
}
|
||
|
||
//计算其他玩家战斗属性
|
||
func (this *RoleBattleAttr) CalcFightRoleInfoAttr(FightInfo *serverproto.FightRoleInfo) map[uint32]*serverproto.ActorData {
|
||
tempBattleHeroList := map[uint32]*serverproto.ActorData{}
|
||
|
||
for _, heroData := range FightInfo.HeroDataList {
|
||
otherActorAttr := newActorAttr(this, heroData.Id, heroData.ConfigId,
|
||
heroData.BaseLevel, heroData.AdvanceLevel, heroData.StrengthLevel)
|
||
if this.role.GetRoleHero().IsMainHero(heroData.Id) {
|
||
otherActorAttr.isMainHero = true
|
||
}
|
||
otherActorAttr.changeSetList.Add(Attr_Change_Fashion, Attr_Change_Card, Attr_Change_Equip,
|
||
Attr_Change_AddPoint, Attr_Change_Advance, Attr_Change_Strength, Attr_Change_Skill_Equip_Slot)
|
||
otherActorAttr.calActorAttr(heroData, FightInfo.AttrList, FightInfo.FashionData, AttrChangeST{})
|
||
|
||
actorData := &serverproto.ActorData{
|
||
Id: uint32(heroData.Id),
|
||
IsPlayer: otherActorAttr.isMainHero,
|
||
BattleAttr: &serverproto.ActorBattleAttr{},
|
||
JobType: uint32(heroData.ConfigId), //主角职业类型/hero配置ID
|
||
}
|
||
this.syncActorData(actorData.BattleAttr, otherActorAttr)
|
||
tempBattleHeroList[actorData.Id] = actorData
|
||
}
|
||
|
||
return tempBattleHeroList
|
||
}
|
||
|
||
//Role
|
||
//获取英雄属性,宠物属性
|
||
func (this *RoleBattleAttr) GetActorAttr(actorList []*serverproto.ActorAttrType,
|
||
isAllBattle bool, bNotify bool) serverproto.ErrorCode {
|
||
|
||
//上阵单位属性(巡游阵容)
|
||
var calActorList []*serverproto.ActorAttrType
|
||
if isAllBattle {
|
||
for _, heroData := range this.role.GetRoleHero().heroList {
|
||
if !heroData.IsBattle {
|
||
continue
|
||
}
|
||
calActorList = append(calActorList, &serverproto.ActorAttrType{
|
||
IsHeroPet: true,
|
||
ActorId: uint32(heroData.Id),
|
||
})
|
||
if heroData.BattlePetId > 0 {
|
||
calActorList = append(calActorList, &serverproto.ActorAttrType{
|
||
ActorId: heroData.BattlePetId,
|
||
})
|
||
}
|
||
}
|
||
|
||
mainHeroData := this.role.GetRoleHero().GetMainHero()
|
||
if mainHeroData != nil {
|
||
calActorList = append(calActorList, &serverproto.ActorAttrType{
|
||
IsHeroPet: true,
|
||
ActorId: uint32(mainHeroData.Id),
|
||
})
|
||
if mainHeroData.BattlePetId > 0 {
|
||
calActorList = append(calActorList, &serverproto.ActorAttrType{
|
||
ActorId: mainHeroData.BattlePetId,
|
||
})
|
||
}
|
||
}
|
||
} else {
|
||
for idx := 0; idx < len(actorList); idx++ {
|
||
calActorList = append(calActorList, actorList[idx])
|
||
if actorList[idx].IsHeroPet {
|
||
//hero
|
||
heroData := this.role.GetRoleHero().GetHero(int32(actorList[idx].ActorId))
|
||
if heroData != nil && heroData.BattlePetId > 0 {
|
||
calActorList = append(calActorList, &serverproto.ActorAttrType{
|
||
ActorId: heroData.BattlePetId,
|
||
})
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//cal attr
|
||
for idx := 0; idx < len(actorList); idx++ {
|
||
if actorList[idx].IsHeroPet {
|
||
//hero
|
||
heroData := this.role.GetRoleHero().GetHero(int32(actorList[idx].ActorId))
|
||
if heroData == nil {
|
||
continue
|
||
}
|
||
//cal attr
|
||
this.attrChangeHero(AttrChangeST{
|
||
IgnoreNotify: true,
|
||
ChangeType: Attr_Change_None,
|
||
ChangeHeroData: heroData,
|
||
})
|
||
//copy attr
|
||
actorAttr := this.getActorAttr(heroData)
|
||
this.copyAttrToMsg(actorAttr, actorList[idx])
|
||
} else {
|
||
//pet
|
||
petData := this.role.GetRolePet().getPet(actorList[idx].ActorId)
|
||
if petData == nil {
|
||
continue
|
||
}
|
||
//cal attr
|
||
this.attrChangePet(AttrChangeST{
|
||
IgnoreNotify: true,
|
||
IsPet: true,
|
||
ChangeType: Attr_Change_None,
|
||
ChangePetData: petData,
|
||
})
|
||
//copy attr
|
||
actorAttr := this.getPetActorAttr(petData)
|
||
this.copyAttrToMsg(actorAttr, actorList[idx])
|
||
}
|
||
}
|
||
|
||
if bNotify {
|
||
if this.bInitAttrCalc {
|
||
ackMsg := &serverproto.SCActorAttrGetAck{}
|
||
ackMsg.ActorAttrList = actorList
|
||
this.role.ReplayGate(ackMsg, true)
|
||
} else {
|
||
this.bInitAttrCalc = true
|
||
ntfMsg := &serverproto.SCActorAttrGetNtf{}
|
||
ntfMsg.ActorAttrList = actorList
|
||
this.role.ReplayGate(ntfMsg, true)
|
||
}
|
||
}
|
||
|
||
return serverproto.ErrorCode_ERROR_OK
|
||
}
|
||
|
||
//获取actor契约属性
|
||
//如果是宠物,则获取契约材料宠物给到契约宠物生成的属性
|
||
//如果是英雄,则获取契约宠物继承到英雄的属性
|
||
func (this *RoleBattleAttr) GetActorQiyueAttr(actorList []*serverproto.ActorAttrType) {
|
||
for idx := 0; idx < len(actorList); idx++ {
|
||
if actorList[idx].IsHeroPet {
|
||
//TODO
|
||
// 暂时没有用到
|
||
} else {
|
||
//pet
|
||
petData := this.role.GetRolePet().getPet(actorList[idx].ActorId)
|
||
if petData == nil {
|
||
continue
|
||
}
|
||
//cal attr
|
||
this.attrChangePet(AttrChangeST{
|
||
IgnoreNotify: true,
|
||
IsPet: true,
|
||
ChangeType: Attr_Change_None,
|
||
ChangePetData: petData,
|
||
})
|
||
actorAttr := this.getPetActorAttr(petData)
|
||
for key, val := range actorAttr.curPetAttrForPetQiyue {
|
||
actorList[idx].AttrList = append(actorList[idx].AttrList, &serverproto.KeyValueFloat32{
|
||
Key: int32(key),
|
||
Value: val,
|
||
})
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *RoleBattleAttr) copyAttrToMsg(actorAttr *ActorAttr, outAttrType *serverproto.ActorAttrType) {
|
||
attrList := map[serverproto.Attr]float32{}
|
||
attrList64 := map[serverproto.Attr]float64{}
|
||
if actorAttr.isPet {
|
||
for key, val := range actorAttr.additionalAttrs {
|
||
attrList64[key] = val
|
||
}
|
||
} else {
|
||
attrList64[serverproto.Attr_Life] = actorAttr.Life()
|
||
attrList[serverproto.Attr_Sp] = actorAttr.Sp()
|
||
attrList[serverproto.Attr_Attack] = actorAttr.MinAttack()
|
||
attrList[serverproto.Attr_MagicAttack] = actorAttr.MinMagicAttack()
|
||
attrList[serverproto.Attr_Defense] = actorAttr.Defense()
|
||
attrList[serverproto.Attr_MagicDefense] = actorAttr.MagicDefense()
|
||
attrList[serverproto.Attr_Crit] = actorAttr.Crit()
|
||
attrList[serverproto.Attr_Dodge] = actorAttr.Dodge()
|
||
attrList[serverproto.Attr_Hit] = actorAttr.Hit()
|
||
attrList[serverproto.Attr_Ten] = actorAttr.Ten()
|
||
attrList[serverproto.Attr_AttackSpeed] = actorAttr.AttackSpeed()
|
||
attrList[serverproto.Attr_CastAcce] = actorAttr.CastAcce() * 1000
|
||
realHurt := actorAttr.GetAdditionalAttr(serverproto.Attr_RealHurt)
|
||
if realHurt > 0 {
|
||
attrList[serverproto.Attr_RealHurt] = float32(realHurt)
|
||
}
|
||
}
|
||
|
||
for key, val := range actorAttr.attrPercent {
|
||
attrList[key+serverproto.Attr_STR_Percent] = val
|
||
}
|
||
for key, val := range actorAttr.extendAttrPercent {
|
||
attrList[key] = val
|
||
}
|
||
|
||
for key, val := range attrList {
|
||
outAttrType.AttrList = append(outAttrType.AttrList, &serverproto.KeyValueFloat32{
|
||
Key: int32(key),
|
||
Value: val,
|
||
})
|
||
}
|
||
for key, val := range attrList64 {
|
||
if key == serverproto.Attr_Life {
|
||
outAttrType.AttrList = append(outAttrType.AttrList, &serverproto.KeyValueFloat32{
|
||
Key: int32(key),
|
||
Value: float32(val),
|
||
Value64: val,
|
||
})
|
||
} else {
|
||
outAttrType.AttrList = append(outAttrType.AttrList, &serverproto.KeyValueFloat32{
|
||
Key: int32(key),
|
||
Value: float32(val),
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *RoleBattleAttr) BattleAttrInit() {
|
||
if !this.bInitAttrCalc {
|
||
this.GetActorAttr(nil, true, true)
|
||
this.bInitAttrCalc = true
|
||
|
||
this.checkFightPower(true)
|
||
}
|
||
}
|
||
|
||
func (this *RoleBattleAttr) CopyData(outData *serverproto.FightPowerData) {
|
||
*outData = *(this.checkFightPower(false))
|
||
|
||
this.role.GetRoleHero().CalRepress(RepressChangeST{})
|
||
}
|