refactor(fight): 重构战斗系统
- 重构了 BattleSkillEntity 结构,改名为 SkillEntity - 优化了 Input 结构,移除了冗余的 Effect 容器 - 调整了 Effect 接口,增加了 SetInput 和 Alive 方法 - 重构了战斗逻辑中的技能使用和效果处理流程 - 优化了代码结构,提高了可读性和可维护性
This commit is contained in:
@@ -72,7 +72,7 @@ type BattleActionI interface {
|
|||||||
// SelectSkillAction 选择技能的战斗动作
|
// SelectSkillAction 选择技能的战斗动作
|
||||||
type SelectSkillAction struct {
|
type SelectSkillAction struct {
|
||||||
PlayerID uint32 // 玩家ID
|
PlayerID uint32 // 玩家ID
|
||||||
Skill *info.BattleSkillEntity // 使用的技能
|
Skill *info.SkillEntity // 使用的技能
|
||||||
PetInfo *info.BattlePetEntity // 使用技能的宠物
|
PetInfo *info.BattlePetEntity // 使用技能的宠物
|
||||||
Attack info.AttackValue
|
Attack info.AttackValue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,32 +13,33 @@ type Effect0 struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 技能命中计算
|
// 技能命中计算
|
||||||
func (this *Effect0) IsHit(attacker, defender *input.Input, skill *info.BattleSkillEntity) {
|
func (this *Effect0) IsHit(opp *input.Input, skill *info.SkillEntity) {
|
||||||
skill.AttackTimeC() //计算命中
|
skill.AttackTimeC() //计算命中
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Effect0) UseSkill(attacker, defender *input.Input) bool {
|
// 比如xx技能无效
|
||||||
|
func (this *Effect0) UseSkill(opp *input.Input, skill *info.SkillEntity) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Effect0) IsCrit(attacker, defender *input.Input, skill *info.BattleSkillEntity) {
|
func (this *Effect0) IsCrit(opp *input.Input, skill *info.SkillEntity) {
|
||||||
skill.Crit = 0
|
skill.Crit = 0
|
||||||
CritRate := utils.Max(skill.CritRate, 1)
|
CritRate := utils.Max(skill.CritRate, 1)
|
||||||
CritRateR := attacker.FightC.GetRand().Int31n(16)
|
CritRateR := this.Input.FightC.GetRand().Int31n(16)
|
||||||
//CritAtkFirst: 先出手时必定致命一击; 默认: 0
|
//CritAtkFirst: 先出手时必定致命一击; 默认: 0
|
||||||
if skill.CritAtkFirst != 0 && attacker.First {
|
if skill.CritAtkFirst != 0 && this.Input.First {
|
||||||
CritRate = 16
|
CritRate = 16
|
||||||
}
|
}
|
||||||
//CritAtkSecond: 后出手时必定致命一击; 默认: 0
|
//CritAtkSecond: 后出手时必定致命一击; 默认: 0
|
||||||
if skill.CritAtkSecond != 0 && !attacker.First {
|
if skill.CritAtkSecond != 0 && !this.Input.First {
|
||||||
CritRate = 16
|
CritRate = 16
|
||||||
}
|
}
|
||||||
// CritSelfHalfHp: 自身体力低于一半时必定致命一击; 默认: 0
|
// CritSelfHalfHp: 自身体力低于一半时必定致命一击; 默认: 0
|
||||||
if skill.CritSelfHalfHp != 0 && (attacker.CurrentPet.HP < int(attacker.CurrentPet.Info.MaxHp)/2) {
|
if skill.CritSelfHalfHp != 0 && (this.Input.CurrentPet.HP < int(this.Input.CurrentPet.Info.MaxHp)/2) {
|
||||||
CritRate = 16
|
CritRate = 16
|
||||||
}
|
}
|
||||||
// CritFoeHalfHp: 对方体力低于一半时必定致命一击; 默认: 0
|
// CritFoeHalfHp: 对方体力低于一半时必定致命一击; 默认: 0
|
||||||
if skill.CritSelfHalfHp != 0 && (defender.CurrentPet.HP < int(defender.CurrentPet.Info.MaxHp)/2) {
|
if skill.CritSelfHalfHp != 0 && (opp.CurrentPet.HP < int(opp.CurrentPet.Info.MaxHp)/2) {
|
||||||
CritRate = 16
|
CritRate = 16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -376,9 +376,9 @@ func (f *FightC) parseskill(attacker, defender *input.Input, id *SelectSkillActi
|
|||||||
temparg = temparg[args:]
|
temparg = temparg[args:]
|
||||||
if t.GetOwner() { //如果取反,说明是给对方添加的回合效果
|
if t.GetOwner() { //如果取反,说明是给对方添加的回合效果
|
||||||
//实际上,owner永远为反,说明是对方给我添加的
|
//实际上,owner永远为反,说明是对方给我添加的
|
||||||
defender.Effect.AddEffect(eff)
|
defender.AddEffect(eff)
|
||||||
} else {
|
} else {
|
||||||
attacker.Effect.AddEffect(eff)
|
attacker.AddEffect(eff)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -409,31 +409,31 @@ func (f *FightC) initAttackers(fattack, sattack BattleActionI) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 处理技能攻击逻辑
|
// 处理技能攻击逻辑
|
||||||
func (f *FightC) processSkillAttack(attacker, defender *input.Input, skill *SelectSkillAction) {
|
func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *SelectSkillAction) {
|
||||||
|
|
||||||
// 记录技能信息
|
// 记录技能信息
|
||||||
attacker.AttackValue.SkillID = uint32(skill.Skill.ID) //获取技能ID
|
attacker.AttackValue.SkillID = uint32(a.Skill.ID) //获取技能ID
|
||||||
|
|
||||||
attacker.Effect.Exec(func(t input.Effect) bool { //计算命中
|
attacker.Exec(func(t input.Effect) bool { //计算命中
|
||||||
|
|
||||||
t.IsHit(attacker, defender, skill.Skill) //相当于先调整基础命中
|
t.IsHit(defender, a.Skill) //相当于先调整基础命中
|
||||||
|
|
||||||
return attacker.AttackTime == 0 //等于0,继续处理
|
return attacker.AttackTime == 0 //等于0,继续处理
|
||||||
})
|
})
|
||||||
defender.Effect.Exec(func(t input.Effect) bool { //计算闪避
|
defender.Exec(func(t input.Effect) bool { //计算闪避
|
||||||
t.TakeHit(attacker, defender, skill.Skill)
|
t.TakeHit(attacker, a.Skill)
|
||||||
|
|
||||||
return attacker.AttackTime > 0 //
|
return attacker.AttackTime > 0 //
|
||||||
})
|
})
|
||||||
attacker.AttackValue.AttackTime = skill.Skill.AttackTime
|
attacker.AttackValue.AttackTime = a.Skill.AttackTime
|
||||||
if attacker.AttackValue.AttackTime > 0 { //如果命中
|
if attacker.AttackValue.AttackTime > 0 { //如果命中
|
||||||
|
f.parseskill(attacker, defender, a) //命中后解析effect
|
||||||
spower := skill.Skill.CalculatePower(defender.CurrentPet)
|
spower := a.Skill.CalculatePower(defender.CurrentPet)
|
||||||
attacker.Damage = spower
|
attacker.Damage = spower
|
||||||
attacker.Effect.Exec(func(t input.Effect) bool { //计算暴击率加成
|
attacker.Exec(func(t input.Effect) bool { //计算暴击率加成
|
||||||
|
|
||||||
t.IsCrit(attacker, defender, skill.Skill)
|
t.IsCrit(defender, a.Skill)
|
||||||
attacker.AttackValue.IsCritical = skill.Skill.Crit
|
attacker.AttackValue.IsCritical = a.Skill.Crit
|
||||||
return attacker.AttackValue.IsCritical == 0
|
return attacker.AttackValue.IsCritical == 0
|
||||||
})
|
})
|
||||||
if attacker.AttackValue.IsCritical == 1 {
|
if attacker.AttackValue.IsCritical == 1 {
|
||||||
@@ -482,20 +482,20 @@ func (f *FightC) enterturn(fattack, sattack BattleActionI) {
|
|||||||
|
|
||||||
//**回合开始前enterturn
|
//**回合开始前enterturn
|
||||||
|
|
||||||
attacker.Effect.Exec(func(t input.Effect) bool { //计算命中
|
attacker.Exec(func(t input.Effect) bool { //计算命中
|
||||||
|
|
||||||
//结算状态
|
//结算状态
|
||||||
t.OnTurnStart(attacker, defender)
|
t.OnTurnStart(defender)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
canuseskill := attacker.Effect.Exec(func(t input.Effect) bool { //计算命中
|
canuseskill := attacker.Exec(func(t input.Effect) bool { //这个是能否使用技能
|
||||||
//结算状态
|
//结算状态
|
||||||
return t.UseSkill(attacker, defender) //返回本身结算,如果false,说明不能使用技能了
|
return t.UseSkill(defender) //返回本身结算,如果false,说明不能使用技能了
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if canuseskill { //可以使用技能
|
if canuseskill { //可以使用技能
|
||||||
f.parseskill(attacker, defender, skill) //解析effect
|
|
||||||
f.processSkillAttack(attacker, defender, skill)
|
f.processSkillAttack(attacker, defender, skill)
|
||||||
|
|
||||||
skill.Skill.Info.PP-- //减少PP
|
skill.Skill.Info.PP-- //减少PP
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ type BattlePetEntity struct {
|
|||||||
Info *model.PetInfo //通过偏移赋值
|
Info *model.PetInfo //通过偏移赋值
|
||||||
|
|
||||||
statusConditions sync.Map // key: StatusCondition, value: int (剩余回合)
|
statusConditions sync.Map // key: StatusCondition, value: int (剩余回合)
|
||||||
Skills [4]*BattleSkillEntity // 技能槽(最多4个技能)
|
Skills [4]*SkillEntity // 技能槽(最多4个技能)
|
||||||
Status StatusDict //精灵的状态
|
Status StatusDict //精灵的状态
|
||||||
//能力提升属性
|
//能力提升属性
|
||||||
Prop PropDict
|
Prop PropDict
|
||||||
@@ -188,7 +188,7 @@ func CreateBattlePetEntity(info *model.PetInfo, rand *rand.Rand) *BattlePetEntit
|
|||||||
ret.Info = info
|
ret.Info = info
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
//todo 技能信息应该每回合进行深拷贝,保证每次的技能效果都是不一样的
|
//todo 技能信息应该每回合进行深拷贝,保证每次的技能效果都是不一样的
|
||||||
ret.Skills[i] = CreateBattleSkillWithInfinity(&info.SkillList[i], rand, ret)
|
ret.Skills[i] = CreateSkill(&info.SkillList[i], rand, ret)
|
||||||
}
|
}
|
||||||
ret.DamageZone = make(map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64) //初始化第一层类型
|
ret.DamageZone = make(map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64) //初始化第一层类型
|
||||||
|
|
||||||
|
|||||||
@@ -32,22 +32,23 @@ var Category = enum.New[struct {
|
|||||||
ALL EnumCategory //任何类型
|
ALL EnumCategory //任何类型
|
||||||
}]()
|
}]()
|
||||||
|
|
||||||
// BattleSkillEntity 战斗技能实体
|
// SkillEntity 战斗技能实体
|
||||||
// 实现了战斗中技能的所有属性和行为,包括PP管理、技能使用、属性获取等
|
// 实现了战斗中技能的所有属性和行为,包括PP管理、技能使用、属性获取等
|
||||||
// 战斗中可以修改技能实体值,比如是否暴击,是否必中等
|
// 战斗中可以修改技能实体值,比如是否暴击,是否必中等
|
||||||
type BattleSkillEntity struct {
|
type SkillEntity struct {
|
||||||
xmlres.Move
|
xmlres.Move
|
||||||
Info *model.SkillInfo
|
Info *model.SkillInfo
|
||||||
|
|
||||||
DamageValue decimal.Decimal // 伤害值
|
DamageValue decimal.Decimal // 伤害值
|
||||||
Rand *rand.Rand
|
Rand *rand.Rand
|
||||||
Pet *BattlePetEntity
|
Pet *BattlePetEntity
|
||||||
|
//MaxValue func(ahp, bhp uint32) decimal.Decimal
|
||||||
Crit uint32
|
Crit uint32
|
||||||
AttackTime uint32
|
AttackTime uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateBattleSkillWithInfinity 创建战斗技能实例(可指定是否无限PP)
|
// CreateSkill 创建战斗技能实例(可指定是否无限PP)
|
||||||
func CreateBattleSkillWithInfinity(skill *model.SkillInfo, rand *rand.Rand, pet *BattlePetEntity) *BattleSkillEntity {
|
func CreateSkill(skill *model.SkillInfo, rand *rand.Rand, pet *BattlePetEntity) *SkillEntity {
|
||||||
//如果PP是-1 ,那就是无限PP
|
//如果PP是-1 ,那就是无限PP
|
||||||
// ID小于10001的视为无效技能
|
// ID小于10001的视为无效技能
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ func CreateBattleSkillWithInfinity(skill *model.SkillInfo, rand *rand.Rand, pet
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ret BattleSkillEntity
|
var ret SkillEntity
|
||||||
ret.Rand = rand
|
ret.Rand = rand
|
||||||
ret.Pet = pet
|
ret.Pet = pet
|
||||||
// 从资源仓库获取技能数据
|
// 从资源仓库获取技能数据
|
||||||
@@ -96,17 +97,17 @@ func strSliceToIntSlice(strs []string) ([]int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CanUse 检查技能是否可以使用(PP是否充足)
|
// CanUse 检查技能是否可以使用(PP是否充足)
|
||||||
func (s *BattleSkillEntity) CanUse() bool {
|
func (s *SkillEntity) CanUse() bool {
|
||||||
return s.Info.PP > 0
|
return s.Info.PP > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取技能类型
|
// 获取技能类型
|
||||||
func (s *BattleSkillEntity) Category() EnumCategory {
|
func (s *SkillEntity) Category() EnumCategory {
|
||||||
return EnumCategory(s.Move.Category)
|
return EnumCategory(s.Move.Category)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取技能属性
|
// 获取技能属性
|
||||||
func (s *BattleSkillEntity) Type() *element.ElementCombination {
|
func (s *SkillEntity) Type() *element.ElementCombination {
|
||||||
ret, _ := element.NewElementCombination(s.Move.Type)
|
ret, _ := element.NewElementCombination(s.Move.Type)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@@ -122,7 +123,7 @@ func (s *BattleSkillEntity) Type() *element.ElementCombination {
|
|||||||
// 解析副作用参数字符串为整数列表
|
// 解析副作用参数字符串为整数列表
|
||||||
|
|
||||||
// 获取技能名称,为空时使用ID
|
// 获取技能名称,为空时使用ID
|
||||||
func getSkillName(move *BattleSkillEntity) string {
|
func getSkillName(move *SkillEntity) string {
|
||||||
if move.Name == "" {
|
if move.Name == "" {
|
||||||
return strconv.FormatInt(int64(move.ID), 10)
|
return strconv.FormatInt(int64(move.ID), 10)
|
||||||
}
|
}
|
||||||
@@ -164,7 +165,7 @@ var DamageC = enum.New[struct {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// 计算是否命中
|
// 计算是否命中
|
||||||
func (s *BattleSkillEntity) AttackTimeC() {
|
func (s *SkillEntity) AttackTimeC() {
|
||||||
s.AttackTime = 0 //先重置上一次的
|
s.AttackTime = 0 //先重置上一次的
|
||||||
if s.MustHit != 0 {
|
if s.MustHit != 0 {
|
||||||
s.AttackTime = 2
|
s.AttackTime = 2
|
||||||
@@ -175,7 +176,7 @@ func (s *BattleSkillEntity) AttackTimeC() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
func (s *BattleSkillEntity) CriticalsameTypeBonus() decimal.Decimal {
|
func (s *SkillEntity) CriticalsameTypeBonus() decimal.Decimal {
|
||||||
|
|
||||||
// 6. 同系加成(属性相同则乘以同系加成倍率,否则1)
|
// 6. 同系加成(属性相同则乘以同系加成倍率,否则1)
|
||||||
sameTypeBonus := decimal.NewFromFloat(1.0)
|
sameTypeBonus := decimal.NewFromFloat(1.0)
|
||||||
@@ -192,7 +193,7 @@ func (s *BattleSkillEntity) CriticalsameTypeBonus() decimal.Decimal {
|
|||||||
return sameTypeBonus
|
return sameTypeBonus
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BattleSkillEntity) criticalrandom() decimal.Decimal {
|
func (s *SkillEntity) criticalrandom() decimal.Decimal {
|
||||||
|
|
||||||
randomnum := s.Rand.Int31n(39) + 217
|
randomnum := s.Rand.Int31n(39) + 217
|
||||||
// 10. 随机倍率,随机值除以255
|
// 10. 随机倍率,随机值除以255
|
||||||
@@ -202,7 +203,7 @@ func (s *BattleSkillEntity) criticalrandom() decimal.Decimal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 计算技能威力
|
// 计算技能威力
|
||||||
func (s *BattleSkillEntity) CalculatePower(deftype *BattlePetEntity) decimal.Decimal {
|
func (s *SkillEntity) CalculatePower(deftype *BattlePetEntity) decimal.Decimal {
|
||||||
|
|
||||||
// 1. 计算等级因子 (level * 0.4 + 2)
|
// 1. 计算等级因子 (level * 0.4 + 2)
|
||||||
levelFactor := decimal.NewFromInt(int64(s.Pet.Info.Level)).
|
levelFactor := decimal.NewFromInt(int64(s.Pet.Info.Level)).
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ type Input struct {
|
|||||||
*info.AttackValue
|
*info.AttackValue
|
||||||
FightC common.FightI
|
FightC common.FightI
|
||||||
// info.BattleActionI
|
// info.BattleActionI
|
||||||
Effect NodeManager //effects容器 技能的
|
Effects []Effect //effects 实际上全局就是effect无限回合 //effects容器 技能的
|
||||||
// Prop NodeManager //属性容器
|
// Prop NodeManager //属性容器
|
||||||
// Status NodeManager //状态容器
|
// Status NodeManager //状态容器
|
||||||
//NewSeIdx NodeManager //全局容器
|
//NewSeIdx NodeManager //全局容器
|
||||||
@@ -29,7 +29,7 @@ type Input struct {
|
|||||||
func NewInput(c common.FightI, p common.PlayerI) *Input {
|
func NewInput(c common.FightI, p common.PlayerI) *Input {
|
||||||
ret := &Input{FightC: c, Player: p}
|
ret := &Input{FightC: c, Player: p}
|
||||||
t := NodeM[1000000]
|
t := NodeM[1000000]
|
||||||
ret.Effect.AddEffect(deepcopy.Copy(t).(Effect)) //添加默认基类,实现继承
|
ret.AddEffect(deepcopy.Copy(t).(Effect)) //添加默认基类,实现继承
|
||||||
p.SetFightC(c) //给玩家设置战斗容器
|
p.SetFightC(c) //给玩家设置战斗容器
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import (
|
|||||||
type Effect interface {
|
type Effect interface {
|
||||||
OnBattleStart() bool //战斗开始
|
OnBattleStart() bool //战斗开始
|
||||||
|
|
||||||
OnTurnStart(attacker, defender *Input) bool //回合开始
|
OnTurnStart(opp *Input) bool //回合开始
|
||||||
|
|
||||||
UseSkill(attacker, defender *Input) bool //使用技能 可以取消用技能节点
|
UseSkill(opp *Input) bool //使用技能 可以取消用技能节点
|
||||||
// OnSkillPP() bool //技能PP减少节点
|
// OnSkillPP() bool //技能PP减少节点
|
||||||
// BeforeMultiHit() bool //多段攻击前
|
// BeforeMultiHit() bool //多段攻击前
|
||||||
// BeforeHit() bool //命中前
|
// BeforeHit() bool //命中前
|
||||||
@@ -19,13 +19,15 @@ type Effect interface {
|
|||||||
// OnBeforeCalculateDamage() bool // 最终伤害计算前触发
|
// OnBeforeCalculateDamage() bool // 最终伤害计算前触发
|
||||||
// OnDamage() bool // 造成伤害时触发
|
// OnDamage() bool // 造成伤害时触发
|
||||||
//使用技能 可以取消用技能节点
|
//使用技能 可以取消用技能节点
|
||||||
|
SetInput(input *Input)
|
||||||
SetArgs(param []int)
|
SetArgs(param []int)
|
||||||
IsCrit(attacker, defender *Input, skill *info.BattleSkillEntity) //是否暴击
|
IsCrit(opp *Input, skill *info.SkillEntity) //是否暴击
|
||||||
CalculateDamage(attacker, defender *Input, skill *info.BattleSkillEntity) //击判定成功且伤害计算前触发
|
CalculateDamage(opp *Input, skill *info.SkillEntity) //击判定成功且伤害计算前触发
|
||||||
|
OnBeforeCalculateDamage(opp *Input, skill *info.SkillEntity) // 最终伤害计算前触发
|
||||||
// Shield() bool // 护盾值变化时触发
|
// Shield() bool // 护盾值变化时触发
|
||||||
// PostDamage() bool // 伤害结算后触发(血量扣除后)
|
// PostDamage() bool // 伤害结算后触发(血量扣除后)
|
||||||
IsHit(attacker, defender *Input, skill *info.BattleSkillEntity) //闪避率计算,,实际上是修改命中的判断
|
IsHit(opp *Input, skill *info.SkillEntity) //闪避率计算,,实际上是修改命中的判断
|
||||||
TakeHit(attacker, defender *Input, skill *info.BattleSkillEntity) //闪避率计算,,实际上是修改命中的判断
|
TakeHit(opp *Input, skill *info.SkillEntity) //闪避率计算,,实际上是修改命中的判断
|
||||||
//() bool // 暴击伤害结算后触发
|
//() bool // 暴击伤害结算后触发
|
||||||
|
|
||||||
// OnHit() bool // 技能命中时触发
|
// OnHit() bool // 技能命中时触发
|
||||||
@@ -65,20 +67,13 @@ type Effect interface {
|
|||||||
Duration(int) int
|
Duration(int) int
|
||||||
ID() int
|
ID() int
|
||||||
GetArgSize() int
|
GetArgSize() int
|
||||||
|
Alive() bool
|
||||||
Stack(int) int
|
Stack(int) int
|
||||||
MaxStack() int
|
MaxStack() int
|
||||||
GetOwner() bool // 技能属主,比如寄生和镇魂歌,属主是对方)
|
GetOwner() bool // 技能属主,比如寄生和镇魂歌,属主是对方)
|
||||||
//GetSkill() *BattleSkillEntity //获得技能ctx
|
//GetSkill() *BattleSkillEntity //获得技能ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================
|
|
||||||
// 容器:存放多个效果
|
|
||||||
// ========================
|
|
||||||
type NodeManager struct {
|
|
||||||
//GlobalEffects []*Effect // 全局常驻/回合/次数效果
|
|
||||||
Effects []Effect //effects 实际上全局就是effect无限回合
|
|
||||||
}
|
|
||||||
|
|
||||||
var NodeM = make(map[int]Effect, 0)
|
var NodeM = make(map[int]Effect, 0)
|
||||||
|
|
||||||
func InitSkillEffect(id int, t Effect) {
|
func InitSkillEffect(id int, t Effect) {
|
||||||
@@ -103,7 +98,7 @@ func getTypeName(v interface{}) string {
|
|||||||
return t.Kind().String()
|
return t.Kind().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NodeManager) AddEffect(e Effect) {
|
func (c *Input) AddEffect(e Effect) {
|
||||||
|
|
||||||
// 如果已有同 ID 的效果,尝试叠加
|
// 如果已有同 ID 的效果,尝试叠加
|
||||||
for _, eff := range c.Effects {
|
for _, eff := range c.Effects {
|
||||||
@@ -116,6 +111,7 @@ func (c *NodeManager) AddEffect(e Effect) {
|
|||||||
|
|
||||||
eff.Duration(eff.Duration(0))
|
eff.Duration(eff.Duration(0))
|
||||||
}
|
}
|
||||||
|
eff.SetInput(c) //设置输入源
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +120,7 @@ func (c *NodeManager) AddEffect(e Effect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
func (c *NodeManager) RemoveEffect(e Effect) {
|
func (c *Input) RemoveEffect(e Effect) {
|
||||||
var remain []Effect
|
var remain []Effect
|
||||||
for _, eff := range c.Effects {
|
for _, eff := range c.Effects {
|
||||||
if eff.ID() != e.ID() {
|
if eff.ID() != e.ID() {
|
||||||
@@ -137,13 +133,12 @@ func (c *NodeManager) RemoveEffect(e Effect) {
|
|||||||
// ForEachEffectBool 遍历所有 Effect,执行“无参数、返回 bool”的方法
|
// ForEachEffectBool 遍历所有 Effect,执行“无参数、返回 bool”的方法
|
||||||
// 参数 fn:接收单个 Effect,返回 bool(如 func(e Effect) bool { return e.OnBattleStart() })
|
// 参数 fn:接收单个 Effect,返回 bool(如 func(e Effect) bool { return e.OnBattleStart() })
|
||||||
// 返回值:所有 Effect 的方法返回值列表
|
// 返回值:所有 Effect 的方法返回值列表
|
||||||
func (c *NodeManager) Exec(fn func(Effect) bool) bool {
|
func (c *Input) Exec(fn func(Effect) bool) bool {
|
||||||
|
|
||||||
var results bool
|
var results bool
|
||||||
// if len(c.Effects) == 0 {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
for _, effect := range c.Effects {
|
for _, effect := range c.Effects {
|
||||||
|
if effect.Alive() {
|
||||||
result := fn(effect)
|
result := fn(effect)
|
||||||
if !result {
|
if !result {
|
||||||
results = result //如果是false,说明存在阻止向下执行的effect,比如免疫能力提升效果
|
results = result //如果是false,说明存在阻止向下执行的effect,比如免疫能力提升效果
|
||||||
@@ -154,11 +149,13 @@ func (c *NodeManager) Exec(fn func(Effect) bool) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
// 消除回合类效果 efftype 输入是消对方的还是自己的,false是自己,true是对方
|
// 消除回合类效果 efftype 输入是消对方的还是自己的,false是自己,true是对方
|
||||||
func (c *NodeManager) CancelTurn(efftype bool) {
|
func (c *Input) CancelTurn(efftype bool) {
|
||||||
|
|
||||||
var remain []Effect
|
var remain []Effect
|
||||||
for _, eff := range c.Effects {
|
for _, eff := range c.Effects {
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ func (this *EffectNode) PreTurnStart() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 回合开始
|
// 回合开始
|
||||||
func (this *EffectNode) OnTurnStart(attacker, defender *input.Input) bool {
|
func (this *EffectNode) OnTurnStart(opp *input.Input) bool {
|
||||||
|
|
||||||
|
//处理异常状态
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,9 +20,8 @@ func (this *EffectNode) OnTurnStart(attacker, defender *input.Input) bool {
|
|||||||
|
|
||||||
func (this *EffectNode) TurnEnd() bool {
|
func (this *EffectNode) TurnEnd() bool {
|
||||||
|
|
||||||
if this.duration != 0 { // 保留 (负数表示永久)
|
if this.duration == 0 { // 保留 (负数表示永久)
|
||||||
//this.GetBattle().Effects[this.GetInput().UserID].AddEffect(this) //重新添加buff到上下文
|
this.NotAlive = true
|
||||||
|
|
||||||
}
|
}
|
||||||
this.duration--
|
this.duration--
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -6,17 +6,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 技能命中计算
|
// 技能命中计算
|
||||||
func (this *EffectNode) IsHit(attacker, defender *input.Input, skill *info.BattleSkillEntity) {
|
func (this *EffectNode) IsHit(opp *input.Input, skill *info.SkillEntity) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 被命中计算,默认直接返回,重写这个来实现闪避率
|
// 被命中计算,默认直接返回,重写这个来实现闪避率
|
||||||
func (this *EffectNode) TakeHit(attacker, defender *input.Input, skill *info.BattleSkillEntity) {
|
func (this *EffectNode) TakeHit(opp *input.Input, skill *info.SkillEntity) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *EffectNode) UseSkill(attacker, defender *input.Input) bool {
|
func (this *EffectNode) UseSkill(opp *input.Input) bool {
|
||||||
return true
|
|
||||||
|
return this.Input.CurrentPet.HP != 0
|
||||||
}
|
}
|
||||||
func (this *EffectNode) OnSkillPP() bool {
|
func (this *EffectNode) OnSkillPP() bool {
|
||||||
panic("not implemented") // TODO: Implement
|
panic("not implemented") // TODO: Implement
|
||||||
@@ -33,7 +34,7 @@ func (this *EffectNode) BeforeHit() bool {
|
|||||||
panic("not implemented") // TODO: Implement
|
panic("not implemented") // TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *EffectNode) OnCritPreDamage() bool {
|
func (this *EffectNode) OnBeforeCalculateDamage(opp *input.Input, skill *info.SkillEntity) {
|
||||||
panic("not implemented") // TODO: Implement
|
panic("not implemented") // TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ func (this *EffectNode) PreDamage() bool {
|
|||||||
panic("not implemented") // TODO: Implement
|
panic("not implemented") // TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *EffectNode) CalculateDamage(attacker, defender *input.Input, skill *info.BattleSkillEntity) {
|
func (this *EffectNode) CalculateDamage(opp *input.Input, skill *info.SkillEntity) {
|
||||||
panic("not implemented") // TODO: Implement
|
panic("not implemented") // TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ func (this *EffectNode) PostDamage() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 正常来说,什么都不做
|
// 正常来说,什么都不做
|
||||||
func (this *EffectNode) IsCrit(attacker, defender *input.Input, skill *info.BattleSkillEntity) {
|
func (this *EffectNode) IsCrit(opp *input.Input, skill *info.SkillEntity) {
|
||||||
//return skill.Crit
|
//return skill.Crit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package node
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/logic/service/fight/input"
|
"blazing/logic/service/fight/input"
|
||||||
"context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 检查,激活,延后
|
// 检查,激活,延后
|
||||||
@@ -10,9 +9,11 @@ import (
|
|||||||
type EffectNode struct {
|
type EffectNode struct {
|
||||||
//Turn int // 当前回合数 ,回合数其实从战斗的上下文中获取
|
//Turn int // 当前回合数 ,回合数其实从战斗的上下文中获取
|
||||||
//本质上Ctx还要传入战斗双方数据来判断是否是本精灵切换
|
//本质上Ctx还要传入战斗双方数据来判断是否是本精灵切换
|
||||||
Ctx context.Context //节点上下文
|
//Ctx context.Context //节点上下文
|
||||||
duration int // 默认为-1 持续回合/次(0 = 即时生效,>0 = 回合数 ,负数是永久) 次数相当于重写回合
|
//次数相当于重写回合
|
||||||
|
duration int // 默认为-1 持续回合/次(0 = 即时生效,>0 = 回合数 ,负数是永久) \
|
||||||
|
|
||||||
|
Input *input.Input
|
||||||
stacks int // 当前层数
|
stacks int // 当前层数
|
||||||
ArgSize int
|
ArgSize int
|
||||||
maxStack int // 最大叠加层数 ,正常都是不允许叠加的,除了衰弱特殊效果 ,异常和能力的叠层
|
maxStack int // 最大叠加层数 ,正常都是不允许叠加的,除了衰弱特殊效果 ,异常和能力的叠层
|
||||||
@@ -21,10 +22,15 @@ type EffectNode struct {
|
|||||||
Success bool // 是否执行成功 成功XXX,失败XXX
|
Success bool // 是否执行成功 成功XXX,失败XXX
|
||||||
arget bool // 传出作用对象,默认0是自身,1是作用于对面
|
arget bool // 传出作用对象,默认0是自身,1是作用于对面
|
||||||
Flag int //过滤掉的战斗类型 pvp pve boss战斗,野怪全部生效
|
Flag int //过滤掉的战斗类型 pvp pve boss战斗,野怪全部生效
|
||||||
Alive bool // 是否失效 effect返回值是否被取消,是否被删除
|
NotAlive bool // 是否失效 effect返回值是否被取消,是否被删除
|
||||||
//增加owner target,如果owner target都为自身,就回合效果结束后再使用回合效果
|
//增加owner target,如果owner target都为自身,就回合效果结束后再使用回合效果
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *EffectNode) Alive() bool {
|
||||||
|
|
||||||
|
return !this.NotAlive
|
||||||
|
|
||||||
|
}
|
||||||
func (this *EffectNode) ID() int {
|
func (this *EffectNode) ID() int {
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@@ -58,10 +64,16 @@ func (this *EffectNode) Duration(t int) int {
|
|||||||
return this.duration
|
return this.duration
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置参数,加上设置输入源
|
||||||
func (this *EffectNode) SetArgs(args []int) {
|
func (this *EffectNode) SetArgs(args []int) {
|
||||||
|
|
||||||
this.SideEffectArgs = args
|
this.SideEffectArgs = args
|
||||||
|
|
||||||
|
}
|
||||||
|
func (this *EffectNode) SetInput(args *input.Input) {
|
||||||
|
this.Input = args
|
||||||
|
|
||||||
}
|
}
|
||||||
func (this *EffectNode) GetArgSize() int {
|
func (this *EffectNode) GetArgSize() int {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user