ro-webgl-server/server/roserver/game/model/role_battle_attr.go

3137 lines
94 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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{})
}