Files
bl/logic/service/fight/input/nodemanger.go

293 lines
7.5 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 input
import (
"blazing/logic/service/fight/info"
"blazing/modules/blazing/model"
"reflect"
"github.com/mohae/deepcopy"
)
type Effect interface {
OnBattleStart() bool //战斗开始
OnTurnStart(opp *Input) //回合开始
UseSkill(opp *Input) bool //使用技能 可以取消用技能节点
SkillUseEnd(opp *Input)
// OnSkillPP() bool //技能PP减少节点
// BeforeMultiHit() bool //多段攻击前
// BeforeHit() bool //命中前
// OnCritPreDamage() bool //暴击判定成功且伤害计算前触发
// PreDamage() bool // 技能伤害计算前触发(增伤 / 减伤等)
// OnBeforeCalculateDamage() bool // 最终伤害计算前触发
// OnDamage() bool // 造成伤害时触发
//使用技能 可以取消用技能节点
SetInput(input *Input)
AfterAttr(t *info.BattlePetEntity) //在获取属性前,比如重写对方属性AfterAttr
BeferAttr(t *info.BattlePetEntity) //在获取属性后,比如视为对方属性
SetArgs(param ...int)
IsCrit(opp *Input, skill *info.SkillEntity) //是否暴击
CalculateDamage(opp *Input, skill *info.SkillEntity) //击判定成功且伤害计算前触发
OnBeforeCalculateDamage(opp *Input, skill *info.SkillEntity) // 最终伤害计算前触发
// Shield() bool // 护盾值变化时触发
// PostDamage() bool // 伤害结算后触发(血量扣除后)
IsHit(opp *Input, skill *info.SkillEntity) //闪避率计算,,实际上是修改命中的判断
TakeHit(opp *Input, skill *info.SkillEntity) //闪避率计算,,实际上是修改命中的判断
//() bool // 暴击伤害结算后触发
OnSkill(opp *Input, skill *info.SkillEntity) //闪避率计算,,实际上是修改命中的判断
// OnHit() bool // 技能命中时触发
// OnMiss() bool // 技能未命中时触发
// AfterAttacked() bool // 被攻击后触发(受击判定)
// SetOwner(bool)
// OnDefeat() bool // 精灵被击败时触发
TurnEnd(opp *Input) //闪避率计算,,实际上是修改命中的判断
// // 堆叠Stack相关触发
// OnStackBefore() bool // 堆叠效果前触发
// OnStack() bool // 堆叠效果触发
// OnBeforeConsumeStack() bool // 消耗堆叠前触发
// OnConsumeStack() bool // 消耗堆叠时触发
// // 治疗相关触发
// OnBeforeHeal() bool // 治疗前触发
// OnHeal() bool // 治疗生效时触发
// // 精灵切换相关触发
// OnSwitchIn() bool // 精灵出战 / 上场时触发
// OnSwitchOut() bool // 精灵下场时触发
// OnOwnerSwitchIn() bool // 所属玩家精灵出战时触发
// OnOwnerSwitchOut() bool // 所属玩家精灵下场时触发
// PreBattleEnd() bool //战斗结束前
// OnBattleEnd() bool //战斗结束
//回合数,然后次数另外维护
Duration(...int) int
Alive() bool
Stack(...int) int
GetMaxStack() int
NotALive()
GetOwner() bool // 技能属主,比如寄生和镇魂歌,属主是对方)
//GetSkill() *BattleSkillEntity //获得技能ctx
}
var NodeM = make(map[int]Effect, 0)
func InitSkillEffect(id int, t Effect) {
NodeM[id+1000000-1] = t
}
func Geteffect(id int) (Effect, bool) {
//todo 获取前GetEffect
ret, ok := NodeM[id]
if ok {
eff := deepcopy.Copy(ret).(Effect)
return eff, ok
}
return nil, false
//todo 获取后GetEffect
}
func InitPropEffect(id int, t Effect) {
NodeM[id+2000000-1] = t
}
// * battle_lv: atk(0), def(1), sp_atk(2), sp_def(3), spd(4), accuracy(5)
// 是否需要真实提升
func (c *Input) GetProp(id int, istue bool) int {
// 获取基础属性值
baseValue := int(c.AttackValue.Prop[id])
// 命中情况直接返回基础值(优先判断)
if id >= 5 {
return baseValue
}
// 处理id < 5的情况
if istue {
return baseValue
}
// 计算实际值(这里可以插入后续优化的函数调用)
realValue := info.CalculateRealValue(int(c.CurrentPet.Info.Prop[id]), baseValue)
// todo: 插入获取后处理函数,例如:
// realValue = postProcessValue(realValue, id, c)
return realValue
}
func InitDamageEffect(id int, t Effect) {
NodeM[id+4000000-1] = t
}
// 1为红伤
func GetDamageEffect(id int) *EffectID {
id1 := id + 4000000
ret, ok := Geteffect(id1)
if ok {
//todo 获取前GetEffect
return &EffectID{
ID: id1,
Effect: ret,
}
//todo 获取后GetEffect
}
return &EffectID{}
}
func (c *Input) GetDamageEffect(id int) int {
id1 := id + 4000000
rer, ok := c.Effects.Load(id1)
if ok {
return rer.Stack()
}
return 0
}
func GetSkillEffect(id int) *EffectID {
id1 := id + 1000000
ret, ok := Geteffect(id1)
if ok {
return &EffectID{
ID: id1,
Effect: ret,
}
}
return &EffectID{}
}
type EffectID struct {
ID int
Effect Effect
}
func GetPropEffect(id int) Effect {
ret, ok := Geteffect(id + 2000000)
if ok {
//todo 获取前GetEffect
return ret
//todo 获取后GetEffect
}
return nil
}
func InitStatusEffect(id int, t Effect) {
NodeM[id+3000000-1] = t
}
func GetStatusEffect(id int) (Effect, bool) {
ret, ok := Geteffect(id + 3000000)
if ok {
//todo 获取前GetEffect
return ret, true
//todo 获取后GetEffect
}
return nil, false
}
func (c *Input) GetStatusEffect(id int) (Effect, bool) {
rer, ok := c.Effects.Load(id + 3000000)
return rer, ok
}
func (c *Input) GetCurrAttr(id int) *model.PetInfo {
//todo 获取前GetEffect
return c.CurrentPet.Info
//todo 获取后GetEffect
}
func getTypeName(v interface{}) string {
// 获取类型信息
t := reflect.TypeOf(v)
// 如果是指针类型,需要先获取其指向的元素类型
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
// 如果是结构体类型,返回其名称
if t.Kind() == reflect.Struct {
return t.Name()
}
// 非结构体类型返回空或对应的类型名
return t.Kind().String()
}
func (c *Input) AddEffect(e *EffectID) {
if e.ID == 0 {
return
}
//todo 免疫
//TODO 先激活
e.Effect.SetInput(c)
// 如果已有同 ID 的效果,尝试叠加
_, ok := c.Effects.Load(e.ID)
if !ok {
// 否则新加入
c.Effects.Store(e.ID, e.Effect)
return
}
c.Effects.Range(func(key int, value Effect) bool {
if e.ID == key {
//设置输入源
if value.Stack() < value.GetMaxStack() { //如果小于最大叠层
value.Stack(value.Stack()) //获取到当前叠层数然后叠加
} else {
//这里,说明是延续回合效果
value.Duration(value.Duration())
}
return false
}
return true
})
}
// ForEachEffectBool 遍历所有 Effect执行“无参数、返回 bool”的方法
// 参数 fn接收单个 Effect返回 bool如 func(e Effect) bool { return e.OnBattleStart() }
// 返回值:所有 Effect 的方法返回值列表
func (c *Input) Exec(fn func(Effect) bool) bool {
c.Effects.Range(func(key int, value Effect) bool {
if value.Alive() {
result := fn(value)
if !result {
return result //如果是false,说明存在阻止向下执行的effect比如免疫能力提升效果
}
}
return true
})
return true
}
// 消除回合类效果 efftype 输入是消对方的还是自己的,false是自己,true是对方
func (c *Input) CancelTurn(efftype bool) {
c.Effects.Range(func(key int, value Effect) bool {
if value.Duration() > 0 { //false是自身,true是对方,反转后为真就是自己的
//slice = append(slice[:i], slice[i+1:]...)
value.NotALive()
}
return true
})
}