feat(fight): 实现 boss 战斗中精灵特性的支持与多个新魂印效果

- 在 `fight_boss.go` 中为 Boss 的每只宠物增加了 CatchTime 字段以区分不同精灵,
  并修复了技能特效参数解析的问题。
- 新增多个魂印(NewSeIdx)实现,包括:
  * 无限 PP、伤害倍率控制、命中屏蔽、属性克制、暴击率调整等。
- 调整了部分已有 NewSeIdx 文件中的方法调用方式,统一使用 `ID().GetCatchTime()`
  来判断精灵是否在场。
- 修改了 EffectIDCombiner 的字段访问方式,改为通过 Get/Set 方法操作。
- 优化战斗逻辑,在 NPC 战斗中加入 AI 自动出招机制。
This commit is contained in:
2025-11-26 15:25:10 +08:00
parent f76587f952
commit 0ea1a24419
47 changed files with 518 additions and 102 deletions

View File

@@ -72,7 +72,7 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla
taskid = *bc.TaskID
}
for _, bm := range bc.BossMon {
for i, bm := range bc.BossMon {
mo = model.GenPetInfo(
gconv.Int(processMonID(bm.MonID)), 24, //24个体
@@ -80,17 +80,21 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla
0, //野怪没特性
0,
bm.Lv)
mo.CatchTime = uint32(i)
mo.Hp = uint32(bm.Hp)
mo.MaxHp = uint32(bm.Hp)
moinfo.PetList = append(moinfo.PetList, *mo)
for _, v := range strings.Split(bm.NewSeIdxs, " ") {
idx := gconv.Uint16(v)
eff := xmlres.EffectMAP[int(idx)]
args := strings.Split(eff.Args, " ")
mo.EffectInfo = append(mo.EffectInfo, model.PetEffectInfo{
Idx: gconv.Uint16(v),
Idx: idx,
EID: gconv.Uint16(eff.Eid),
Args: gconv.Ints(args),
})
}
moinfo.PetList = append(moinfo.PetList, *mo)
}
if bc.BossCatchable == 1 {
cancpet = xmlres.PetMAP[int(mo.ID)].CatchRate
@@ -108,11 +112,11 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla
ai := player.NewAI_player(moinfo)
ai.CanCapture = cancpet
ai.Prop[0] = 2
fight.NewFight(c, ai, func(foi *info.FightOverInfo) {
c.Done.Exec(model.MilestoneMode.BOSS, []uint32{c.Info.MapID, data.BossId, uint32(foi.Reason)}, func(results *model.MilestoneEX) uint32 {
if taskid != 0 {
if foi.Reason == 0 && foi.WinnerId == c.Info.UserID {
if results.CheakNoNumber(1) && taskid != 0 { //触发3次奖励
if c.Info.TaskList[taskid-1] != 3 {
c.Info.TaskList[taskid-1] = 3
moinfo.PetList[0].Downgrade(1)
@@ -126,13 +130,12 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla
PetID: PetID,
CaptureTm: newm1.CatchTime,
})
return 1
}
}
return 0
})
}
}
c.Done.Exec(model.MilestoneMode.BOSS, []uint32{c.Info.MapID, data.BossId, uint32(foi.Reason)}, nil)
})

View File

@@ -19,12 +19,20 @@ func (h Controller) SetPetSkill(data *pet.ChangeSkillInfo, c *player.Player) (re
if !ok {
return result, errorcode.ErrorCodes.ErrSystemBusy
}
_, HasSkill, ok := utils.FindWithIndex(onpet.SkillList, func(item model.SkillInfo) bool { //已经存在技能
_, _, ok = utils.FindWithIndex(onpet.SkillList, func(item model.SkillInfo) bool { //已经存在技能
return item.ID == data.ReplaceSkill
})
if ok {
return result, errorcode.ErrorCodes.ErrSystemBusy
}
_, hasskill, ok := utils.FindWithIndex(onpet.SkillList, func(item model.SkillInfo) bool { //已经存在技能
return item.ID == data.HasSkill
})
if !ok {
HasSkill.ID = data.ReplaceSkill
HasSkill.PP = uint32(xmlres.SkillMap[int(HasSkill.ID)].MaxPP)
if ok {
hasskill.ID = data.ReplaceSkill
hasskill.PP = uint32(xmlres.SkillMap[int(hasskill.ID)].MaxPP)
}
return &pet.ChangeSkillOutInfo{
CatchTime: data.CatchTime,

View File

@@ -152,6 +152,8 @@ func (f *FightC) ReadyFight(c common.PlayerI) {
f.Opp.CanCapture = f.Opp.Player.(*player.AI_player).CanCapture
fightStartInfo.Info2.Catchable = 1 //可以捕捉就置1
}
f.Opp.AttackValue.Prop = f.Opp.Player.(*player.AI_player).Prop
fightStartInfo.Info2.Prop = f.Opp.AttackValue.Prop
f.startBattle(fightStartInfo)
default: // PVP战斗需双方都准备完成
if f.checkBothPlayersReady(c) {
@@ -190,10 +192,18 @@ func (f *FightC) checkBothPlayersReady(currentPlayer common.PlayerI) bool {
func (f *FightC) startBattle(startInfo info.FightStartOutboundInfo) {
f.startl.Do(func() {
// 提交战斗循环到战斗池(处理战斗池容量问题)
if err := Fightpool.Submit(f.battleLoop); err != nil {
log.Panic(context.Background(), "战斗循环提交失败", "error", err)
}
f.Broadcast(func(ff *input.Input) {
ff.InitEFFect(&startInfo)
})
f.Broadcast(func(ff *input.Input) {
// 通知双方玩家准备完成,即将开始战斗

View File

@@ -30,7 +30,7 @@ type NewSel1 struct {
func (e *NewSel1) BeferProp(in *input.Ctx, prop, level int8, ptype info.EnumAbilityOpType) bool {
//魂印特性有不在场的情况,绑定时候将精灵和特性绑定
if e.EffectIDCombiner.CatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}

View File

@@ -2,6 +2,7 @@ package effect
import (
"blazing/logic/service/fight/input"
"math"
)
// 10. 无限PP值;
@@ -10,6 +11,19 @@ type NewSel10 struct {
NewSel0
}
func (e *NewSel10) OnSkill() bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().SkillEntity == nil {
return true
}
e.Ctx().SkillEntity.Info.PP = math.MaxInt32
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 10, &NewSel10{})
}

View File

@@ -10,8 +10,9 @@ type NewSel2 struct {
}
func (e *NewSel2) EFFect_Befer(in *input.Input, effEffect input.Effect) bool {
//魂印特性有不在场的情况,绑定时候将精灵和特性绑定
if e.EffectIDCombiner.CatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}

View File

@@ -1,7 +1,10 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"github.com/shopspring/decimal"
)
// 22. 被打时受到直接攻击伤害提高至n倍;a1: n
@@ -10,6 +13,16 @@ type NewSel22 struct {
NewSel0
}
func (e *NewSel22) Damage_DIV_ex(t *info.DamageZone) bool {
//魂印特性有不在场的情况,绑定时候将精灵和特性绑定
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
t.Damage = t.Damage.Mul(decimal.NewFromInt(int64(e.Args()[0])))
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 22, &NewSel22{})
}

View File

@@ -2,6 +2,8 @@ package effect
import (
"blazing/logic/service/fight/input"
"github.com/samber/lo"
)
// 24. 对方用这些技能时, 对自身的命中率为0 (最多8个 / 不要与必中技能一起配置);a1-a8: 有效技能ID
@@ -10,6 +12,27 @@ type NewSel24 struct {
NewSel0
}
func (e *NewSel24) Skill_Hit_ex() bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
// 技能为空时不处理
skill := e.Ctx().SkillEntity
if skill == nil {
return true
}
_, ok := lo.Find(e.Args(), func(item int) bool {
return skill.ID == item
})
if !ok {
return true
}
skill.AttackTime = 0
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 24, &NewSel24{})
}

View File

@@ -1,15 +1,42 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"github.com/shopspring/decimal"
)
// 27. 按一定的属性顺序出招的技能才能对去血a1-a8: mon_type
// TODO: 实现按一定的属性顺序出招的技能才能对去血a1-a8: mon_type的核心逻辑
type NewSel27 struct {
NewSel0
index int
}
func (e *NewSel27) Damage_DIV_ex(t *info.DamageZone) bool {
//魂印特性有不在场的情况,绑定时候将精灵和特性绑定
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().SkillEntity == nil {
return true
}
if e.Args()[e.index] == e.Ctx().SkillEntity.Type {
return true
}
e.index++
if e.index >= len(e.Args()) {
e.index = 0
}
t.Damage = decimal.NewFromInt(0)
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 27, &NewSel27{})
}

View File

@@ -1,7 +1,10 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"github.com/shopspring/decimal"
)
// 28. XX系技能伤害增加n%a1: mon_type, a2: n 百分比)
@@ -10,6 +13,20 @@ type NewSel28 struct {
NewSel0
}
func (e *NewSel28) Damage_ADD(t *info.DamageZone) bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.Type != int(e.Args()[0]) {
return true
}
t.Damage = t.Damage.Add(t.Damage.Mul(decimal.NewFromInt(int64(e.Args()[1]))))
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 28, &NewSel28{})
}

View File

@@ -1,6 +1,8 @@
package effect
import (
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
@@ -10,6 +12,20 @@ type NewSel29 struct {
NewSel0
}
func (e *NewSel29) Action_start(a, b *action.SelectSkillAction) bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
//fmt.Println(e.Ctx().SkillEntity)
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.Category() == info.Category.STATUS {
return true
}
e.Ctx().SkillEntity.Accuracy += e.Args()[0]
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 29, &NewSel29{})
}

View File

@@ -15,11 +15,14 @@ type NewSel3 struct {
func (e *NewSel3) Damage_DIV_ex(t *info.DamageZone) bool {
//魂印特性有不在场的情况,绑定时候将精灵和特性绑定
if e.EffectIDCombiner.CatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
t.Damage = t.Damage.Div(decimal.NewFromInt(int64(e.Args()[0])))
if t.Type == info.DamageType.Red {
reduceRatio := decimal.NewFromInt(100).Sub(decimal.NewFromInt(int64(e.Args()[0]))).Div(decimal.NewFromInt(100))
t.Damage = t.Damage.Mul(reduceRatio)
}
return true
}

View File

@@ -1,15 +0,0 @@
package effect
import (
"blazing/logic/service/fight/input"
)
// 30. 所有技能的致命一击率增加n/16;a1: n 1-16
// TODO: 实现所有技能的致命一击率增加n/16;a1: n 1-16的核心逻辑
type NewSel30 struct {
NewSel0
}
func init() {
input.InitEffect(input.EffectType.NewSel, 30, &NewSel30{})
}

View File

@@ -1,7 +1,10 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"github.com/shopspring/decimal"
)
// 32. 进攻类技能有n%几率秒杀对方;a1: n 千分比)
@@ -10,6 +13,22 @@ type NewSel32 struct {
NewSel0
}
func (e *NewSel32) OnSkill() bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
success, _, _ := e.Input.Player.Roll(e.Args()[0]/10, 100)
if !success {
return true
}
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: decimal.NewFromInt(int64(e.Ctx().Opp.CurrentPet.Info.Hp)),
})
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 32, &NewSel32{})
}

View File

@@ -1,6 +1,7 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
@@ -10,6 +11,28 @@ type NewSel34 struct {
NewSel0
}
func (e *NewSel34) Damage_DIV_ex(t *info.DamageZone) bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
// 2. 技能为空或非物理攻击,不触发
skill := e.Ctx().SkillEntity
if skill == nil {
return true
}
if skill.Category() != info.Category.SPECIAL {
return true
}
// 3. 概率判定Args()[1]为触发概率)
success, _, _ := e.Input.Player.Roll(e.Args()[1], 100)
if !success {
return true
}
e.Ctx().Opp.SetProp(e.Ctx().Our, int8(e.Args()[0]), 1, info.AbilityOpType.SUB)
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 34, &NewSel34{})
}

View File

@@ -1,6 +1,7 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
@@ -10,6 +11,25 @@ type NewSel35 struct {
NewSel0
}
func (e *NewSel35) Damage_DIV_ex(t *info.DamageZone) bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
// 2. 技能为空或非物理攻击,不触发
skill := e.Ctx().SkillEntity
if skill == nil {
return true
}
// 3. 概率判定Args()[1]为触发概率)
success, _, _ := e.Input.Player.Roll(e.Args()[1], 100)
if !success {
return true
}
e.Ctx().Our.SetProp(e.Ctx().Our, int8(e.Args()[0]), 1, info.AbilityOpType.ADD)
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 35, &NewSel35{})
}

View File

@@ -14,7 +14,7 @@ type NewSel4 struct {
func (e *NewSel4) Skill_Use_ex() bool {
//魂印特性有不在场的情况,绑定时候将精灵和特性绑定
if e.EffectIDCombiner.CatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}

View File

@@ -16,7 +16,7 @@ type NewSel5 struct {
func (e *NewSel5) Damage_Lock_ex(t *info.DamageZone) bool {
//魂印特性有不在场的情况,绑定时候将精灵和特性绑定
if e.EffectIDCombiner.CatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().SkillEntity == nil {

View File

@@ -13,7 +13,7 @@ type NewSel6 struct {
func (e *NewSel6) Damage_Lock_ex(t *info.DamageZone) bool {
//魂印特性有不在场的情况,绑定时候将精灵和特性绑定
if e.EffectIDCombiner.CatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().SkillEntity == nil {
@@ -37,7 +37,8 @@ func (e *NewSel6) Damage_Lock_ex(t *info.DamageZone) bool {
statusEffect.SetArgs(e.Ctx().Our) // 目标为对手
// 6. 给对手添加状态
e.Ctx().Opp.AddEffect(e.Ctx().Our, statusEffect)
//然后这里是被动添加,所以对方不能消除
e.Ctx().Opp.AddEffect(e.Ctx().Opp, statusEffect)
return true
}

View File

@@ -1,7 +1,10 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"github.com/shopspring/decimal"
)
// 61. n%几率完全抵挡一次伤害a1: n
@@ -10,6 +13,28 @@ type NewSel61 struct {
NewSel0
}
func (e *NewSel61) Damage_DIV_ex(t *info.DamageZone) bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().SkillEntity == nil {
return true
}
// 3. 概率判定Args()[1]为触发概率)
success, _, _ := e.Input.Player.Roll(e.Args()[0], 100)
if !success {
return true
}
//fmt.Println("Effect46_o", t.Damage)
if t.Type == info.DamageType.Red {
t.Damage = decimal.NewFromInt(0)
}
//fmt.Println("Effect46_n", t.Damage)
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 61, &NewSel61{})
}

View File

@@ -1,7 +1,10 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"github.com/shopspring/decimal"
)
// 62. 物理攻击有n%几率使伤害提高m点a1: n, a2: m
@@ -10,6 +13,24 @@ type NewSel62 struct {
NewSel0
}
func (e *NewSel62) Damage_ADD(t *info.DamageZone) bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.Category() != info.Category.PHYSICAL {
return true
}
success, _, _ := e.Input.Player.Roll(e.Args()[0], 100)
if !success {
return true
}
t.Damage = t.Damage.Add(decimal.NewFromInt(int64(e.Args()[1])))
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 62, &NewSel62{})
}

View File

@@ -1,7 +1,10 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"github.com/shopspring/decimal"
)
// 63. 特殊攻击有n%几率使伤害提高m点a1: n, a2: m
@@ -10,6 +13,24 @@ type NewSel63 struct {
NewSel0
}
func (e *NewSel63) Damage_ADD(t *info.DamageZone) bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.Category() != info.Category.SPECIAL {
return true
}
success, _, _ := e.Input.Player.Roll(e.Args()[0], 100)
if !success {
return true
}
t.Damage = t.Damage.Add(decimal.NewFromInt(int64(e.Args()[1])))
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 63, &NewSel63{})
}

View File

@@ -10,6 +10,19 @@ type NewSel64 struct {
NewSel0
}
func (e *NewSel64) Skill_Hit_ex() bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
// 技能为空时不处理
skill := e.Ctx().SkillEntity
if skill == nil {
return true
}
skill.CritRate -= int(e.Args()[0])
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 64, &NewSel64{})
}

View File

@@ -1,7 +1,10 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"github.com/shopspring/decimal"
)
// 65. 物理攻击或特殊攻击伤害增加m%a1: 1=物理/3=特殊, a2: m
@@ -10,6 +13,21 @@ type NewSel65 struct {
NewSel0
}
func (e *NewSel65) Damage_ADD(t *info.DamageZone) bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.Category() != info.EnumCategory(e.Args()[0]) {
return true
}
t.Damage = t.Damage.Add(t.Damage.Mul(decimal.NewFromInt(int64(e.Args()[1]))))
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 65, &NewSel65{})
}

View File

@@ -1,6 +1,7 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
@@ -10,6 +11,37 @@ type NewSel66 struct {
NewSel0
}
func (e *NewSel66) OnSkill() bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().SkillEntity.Category() != info.Category.PHYSICAL {
return true
}
// n% 触发概率(默认 SideEffectArgs[0]
chance := e.EffectNode.SideEffectArgs[0]
success, _, _ := e.Input.Player.Roll(chance, 100)
if !success {
return true
}
var duration int
// 持续回合
duration = int(e.Input.FightC.GetRand().Int31n(2)) // 默认随机 2~3 回合
duration++
// 获取状态效果
eff := input.Geteffect(input.EffectType.Status, int(e.Args()[1]))
if eff == nil {
return true
}
eff.Duration(duration)
eff.SetArgs(e.Ctx().Our) //输入参数是对方
e.Ctx().Opp.AddEffect(e.Ctx().Our, eff)
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 66, &NewSel66{})
}

View File

@@ -1,6 +1,7 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
@@ -10,6 +11,38 @@ type NewSel67 struct {
NewSel0
}
func (e *NewSel67) OnSkill() bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().SkillEntity.Category() != info.Category.SPECIAL {
return true
}
// n% 触发概率(默认 SideEffectArgs[0]
chance := e.EffectNode.SideEffectArgs[0]
success, _, _ := e.Input.Player.Roll(chance, 100)
if !success {
return true
}
var duration int
// 持续回合
duration = int(e.Input.FightC.GetRand().Int31n(2)) // 默认随机 2~3 回合
duration++
// 获取状态效果
eff := input.Geteffect(input.EffectType.Status, int(e.Args()[1]))
if eff == nil {
return true
}
eff.Duration(duration)
eff.SetArgs(e.Ctx().Our) //输入参数是对方
e.Ctx().Opp.AddEffect(e.Ctx().Our, eff)
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 67, &NewSel67{})
}

View File

@@ -10,6 +10,19 @@ type NewSel7 struct {
NewSel0
}
func (e *NewSel7) Skill_Hit_ex() bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
// 技能为空时不处理
skill := e.Ctx().SkillEntity
if skill == nil {
return true
}
skill.AttackTime -= uint32(e.Args()[0])
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 7, &NewSel7{})
}

View File

@@ -1,15 +0,0 @@
package effect
import (
"blazing/logic/service/fight/input"
)
// 8. 自身的会心一击率为 n/16;a1: n 0-16
// TODO: 实现自身的会心一击率为 n/16;a1: n 0-16的核心逻辑
type NewSel8 struct {
NewSel0
}
func init() {
input.InitEffect(input.EffectType.NewSel, 8, &NewSel8{})
}

View File

@@ -0,0 +1,33 @@
package effect
import (
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
// 30. 所有技能的致命一击率增加n/16;a1: n 1-16
// TODO: 实现所有技能的致命一击率增加n/16;a1: n 1-16的核心逻辑
type NewSel30 struct {
NewSel0
}
func (e *NewSel30) Action_start(a, b *action.SelectSkillAction) bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
//fmt.Println(e.Ctx().SkillEntity)
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.Category() == info.Category.STATUS {
return true
}
e.Ctx().SkillEntity.CritRate += e.Args()[0]
return true
}
func init() {
input.InitEffect(input.EffectType.NewSel, 8, &NewSel30{})
input.InitEffect(input.EffectType.NewSel, 30, &NewSel30{})
}

View File

@@ -2,6 +2,7 @@ package fight
import (
"blazing/logic/service/common"
_ "blazing/logic/service/fight/boss"
_ "blazing/logic/service/fight/effect"
)

View File

@@ -46,7 +46,7 @@ func registerPhysicalAttackAddStatusEffects() {
// -----------------------------------------------------------
// 核心逻辑:受物理攻击时触发(覆盖父类方法)
// -----------------------------------------------------------
func (e *EffectPhysicalAttackAddStatus) Damage_DIV_ex(t *info.DamageZone) bool {
func (e *EffectPhysicalAttackAddStatus) Skill_Use_ex() bool {
// 1. 命中判定失败,不触发
if !e.Hit() {
return true

View File

@@ -24,8 +24,8 @@ func (e *Effect38) OnSkill() bool {
ee.EffectNode.Duration(-1) //给对方挂3回合子buff
//ee.ID(e.ID() + int(input.EffectType.Sub)) //子效果ID
tt := e.EffectIDCombiner
tt.EffectType(input.EffectType.Sub)
tt := e.ID()
tt.SetEffectType(input.EffectType.Sub)
ee.ID(tt)
ee.SetArgs(e.Ctx().Our, e.SideEffectArgs...)

View File

@@ -101,7 +101,7 @@ func (e *Effect62) OnSkill() bool {
ee.duy = e.EffectNode.SideEffectArgs[0]
ee.EffectNode.Duration(math.MaxInt) //给对方挂3回合子buff
tt := e.ID()
tt.EffectType(input.EffectType.Sub)
tt.SetEffectType(input.EffectType.Sub)
ee.ID(tt)
//e.e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0])

View File

@@ -31,8 +31,8 @@ func (e *Effect69) OnSkill() bool {
t := &Effect69_sub{
EffectNode: node.EffectNode{},
}
tt := e.EffectIDCombiner
tt.EffectType(input.EffectType.Sub)
tt := e.ID()
tt.SetEffectType(input.EffectType.Sub)
t.ID(tt)
t.SetArgs(e.Input, e.SideEffectArgs...)

View File

@@ -53,8 +53,8 @@ func (e *Effect71) Switch(in *input.Input, at info.AttackValue, oldpet *info.Bat
}
t := &Effect71_sub{}
t.Duration(1)
tt := e.EffectIDCombiner
tt.EffectType(input.EffectType.Sub)
tt := e.ID()
tt.SetEffectType(input.EffectType.Sub)
t.ID(tt)
e.Ctx().Our.AddEffect(e.Ctx().Our, t)

View File

@@ -61,7 +61,7 @@ func (e *EffectConditionalAddDamage) OnSkill() bool {
}
// 2. 获取当前效果ID对应的条件函数
cond, ok := conditionMap[int(e.EffectIDCombiner.Suffix())]
cond, ok := conditionMap[int(e.ID().Suffix())]
if !ok {
return true // 无对应条件函数,不触发
}

View File

@@ -309,7 +309,9 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
attacker.CurrentPet.Info.Hp = 1
}
defender.CanChange = true //被打死就可以切精灵了
defender.CanChange = true //被打死就可以切精灵了
// AI自动技能
if f.IsWin(attacker, defender.CurrentPet.Info.CatchTime) { //然后检查是否战斗结束
var WinnerId uint32
if i == 0 {
@@ -320,8 +322,14 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
f.FightOverInfo.WinnerId = WinnerId
f.closefight = true
break
} else {
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
defender.GetAction(f.Our)
//panic("AI自动技能")
}
}
break
}
}

View File

@@ -76,7 +76,7 @@ type FightPetInfo struct {
// 精灵是否能捕捉1为能捕捉0为不能捕捉
Catchable uint32 `fieldDesc:"精灵是否能捕捉. 1为能捕捉 0为不能捕捉" `
//能力提升属性
Prop PropDict
Prop [6]int8
}
type AttackValueS struct {
FAttack AttackValue

View File

@@ -36,7 +36,7 @@ func InitEffect(etype EnumEffectType, id int, t Effect) {
}
// 这里的catchtime为0,取出来之后如果是魂印,要重新赋值
func Geteffect[T int | byte](etype EnumEffectType, id T) Effect {
func Geteffect[T int | byte | uint16](etype EnumEffectType, id T) Effect {
pr := EffectIDCombiner{}
pr.Combine(etype, 0, gconv.Uint16(id))
@@ -113,7 +113,7 @@ func (our *Input) StatEffect_Exist_all() bool {
t := v.ID()
if t.EffectType() == EffectType.Status && v.Alive() {
if t.GetEffectType() == EffectType.Status && v.Alive() {
return true
}
@@ -125,7 +125,7 @@ func (our *Input) StatEffect_Exist_all() bool {
// 判断是否是状态技能
func (our *Input) IS_Stat(v Effect) bool {
t := v.ID()
if t.EffectType() == EffectType.Status && v.Alive() {
if t.GetEffectType() == EffectType.Status {
return true
}
@@ -159,14 +159,17 @@ func equalInts(a, b []int) bool {
// 返回被替换eddect
func (our *Input) AddEffect(in *Input, e Effect) Effect {
canuseskill := our.Exec(func(t Effect) bool { //这个是能否使用技能
//结算状态
return t.EFFect_Befer(in, e) //返回本身结算,如果false,说明不能使用技能了
})
if !canuseskill {
if in != our {
canuseskill := our.Exec(func(t Effect) bool { //这个是能否使用技能
//结算状态
return t.EFFect_Befer(in, e) //返回本身结算,如果false,说明不能使用技能了
return nil
})
if !canuseskill {
return nil
}
}
e.Alive(true) //添加后默认激活
@@ -261,3 +264,10 @@ func (our *Input) CancelTurn(in *Input) {
// }
// }
// 初始化魂印
func (our *Input) InitEFFect(info *info.FightStartOutboundInfo) {
//our.AttackValue = info.NewAttackValue(our.Player.GetInfo().UserID)
}

View File

@@ -197,6 +197,7 @@ func (our *Input) GetAction(opp *Input) {
for _, v := range our.AllPet {
if v.Info.Hp > 0 {
our.FightC.ChangePet(our.Player, v.Info.CatchTime)
our.GetAction(our.Opp)
return
}

View File

@@ -57,33 +57,33 @@ func (e *EffectIDCombiner) EffectID() int64 {
// EffectType 读取/替换效果类型(读写一体)
// 参数t可选传入则替换当前效果类型不传则仅读取
// 返回当前的效果类型EnumEffectType
func (e *EffectIDCombiner) EffectType(t ...EnumEffectType) EnumEffectType {
if len(t) > 0 {
// 替换逻辑先清空高16位再设置新值
e.Base = (e.Base & ^prefixMask) | (int64(t[0]) << prefixOffset)
}
// 读取并返回当前效果类型
func (e *EffectIDCombiner) SetEffectType(t ...EnumEffectType) {
e.Base = (e.Base & ^prefixMask) | (int64(t[0]) << prefixOffset)
}
func (e EffectIDCombiner) GetEffectType() EnumEffectType {
return EnumEffectType((e.Base >> prefixOffset) & 0xFFFF)
}
// CatchTime 读取/替换CatchTime读写一体完全保留你的写法
// 参数t可选传入则替换当前CatchTime不传则仅读取
// 返回当前的CatchTime值
func (e *EffectIDCombiner) CatchTime(t ...uint32) uint32 {
if len(t) > 0 {
e.Base = (e.Base & ^catchMask) | (int64(t[0]) << catchOffset)
}
func (e *EffectIDCombiner) SetCatchTime(t ...uint32) {
}
func (e EffectIDCombiner) GetCatchTime() uint32 {
return uint32((e.Base >> catchOffset) & catchMask)
}
// Suffix 读取/替换扩展标识读写一体和CatchTime写法一致
// 参数t可选传入则替换当前扩展标识不传则仅读取
// 返回:当前的扩展标识值
func (e *EffectIDCombiner) Suffix(t ...uint16) uint16 {
if len(t) > 0 {
// 替换逻辑先清空低16位再设置新值
e.Base = (e.Base & ^suffixMask) | int64(t[0])
}
func (e EffectIDCombiner) Suffix() uint16 {
// if len(t) > 0 {
// // 替换逻辑先清空低16位再设置新值
// e.Base = (e.Base & ^suffixMask) | int64(t[0])
// }
// 读取并返回当前扩展标识
return uint16(e.Base & suffixMask)
}
@@ -98,23 +98,23 @@ func Test() {
fmt.Println("=== 初始值 ===")
fmt.Printf("完整ID%d\n", combiner.EffectID())
fmt.Printf("效果类型:%d\n", combiner.EffectType()) // 仅读取
fmt.Printf("CatchTime%d\n", combiner.CatchTime()) // 仅读取
fmt.Printf("扩展标识:%d\n", combiner.Suffix()) // 仅读取
fmt.Printf("效果类型:%d\n", combiner.GetEffectType()) // 仅读取
fmt.Printf("CatchTime%d\n", combiner.GetCatchTime()) // 仅读取
fmt.Printf("扩展标识:%d\n", combiner.Suffix()) // 仅读取
// 2. 替换字段(传参即替换)
combiner.EffectType(EffectType.NewSel) // 替换效果类型为Buff
combiner.CatchTime(987654) // 替换CatchTime
combiner.Suffix(666) // 替换扩展标识
combiner.SetEffectType(EffectType.NewSel) // 替换效果类型为Buff
combiner.SetCatchTime(987654) // 替换CatchTime
// 替换扩展标识
fmt.Println("\n=== 替换后 ===")
fmt.Printf("完整ID%d\n", combiner.EffectID())
fmt.Printf("效果类型:%d\n", combiner.EffectType())
fmt.Printf("CatchTime%d\n", combiner.CatchTime())
fmt.Printf("效果类型:%d\n", combiner.GetEffectType())
fmt.Printf("CatchTime%d\n", combiner.GetCatchTime())
fmt.Printf("扩展标识:%d\n", combiner.Suffix())
// 3. 链式替换+读取(一行完成替换并获取新值)
newCatchTime := combiner.CatchTime(111222) // 替换并返回新值
fmt.Printf("\n替换CatchTime并读取%d\n", newCatchTime)
combiner.SetCatchTime(111222) // 替换并返回新值
fmt.Printf("\n替换CatchTime并读取%d\n", combiner.GetCatchTime())
}

View File

@@ -73,8 +73,22 @@ func (our *Input) SortPet() {
})
for _, v := range our.AllPet {
if v.Info.Hp == 0 {
v.NotAlive = true
} else {
for _, e1 := range v.Info.EffectInfo {
t := Geteffect(EffectType.NewSel, e1.EID)
if t != nil {
ef := t.ID()
ef.SetCatchTime(v.Info.CatchTime)
t.ID(ef)
t.Duration(-1)
t.SetArgs(our, e1.Args...) //设置入参,施加方永远是我方
our.AddEffect(our, t)
}
}
}
}

View File

@@ -24,7 +24,7 @@ type EffectNode struct {
hit bool
trunl sync.Once
ctx input.Ctx
input.EffectIDCombiner
//增加owner target如果owner target都为自身就回合效果结束后再使用回合效果
}

View File

@@ -10,6 +10,7 @@ type AI_player struct {
baseplayer
petinfo []model.PetInfo //精灵信息
CanCapture int
Prop [6]int8
}
func (p *AI_player) Getfightinfo() info.Fightinfo {

View File

@@ -117,6 +117,8 @@ func (p *Player) QuitFight() {
p.FightC = nil
atomic.StoreUint32(&p.Fightinfo.Mode, 0)
}
func (p *Player) GetSpace() *space.Space {
return space.GetSpace(p.Info.MapID)

View File

@@ -14,6 +14,7 @@ var MilestoneMode = enum.New[struct {
ITEM EnumMilestone //物品类 物品ID 使用精灵
Fight EnumMilestone //挑战类 对战模式->对战类型->1是赢,0是总局数
Moster EnumMilestone //野怪统计 地图ID->怪物ID
Task EnumMilestone
}]()
// 里程碑数据结构与DoneEvent对应记录单条里程碑的详细信息

View File

@@ -1323,6 +1323,7 @@ eg:
<Boss Id="0" TaskID="304" AppearTime="0 23" BossVisible="0" Name="SPT阿克希亚"
BonusProbability="20" BonusTotalProbability="1000" BonusID="5016" ItemBonusOutID="1" SptLevel="1">
<BossMon MonID="50" Hp="1000" Lv="65" NewSeIdxs="1 2 11 57"/>
<!-- <BossMon MonID="51" Hp="1000" Lv="65" NewSeIdxs="1 2 11 57"/> -->
</Boss>
<Boss Id="1" Symbol="14" AppearTime="0 23" BossVisible="0" PkFlag="1" Name="雷伊技能特训之阿克希亚">
<BossMon MonID="50" Hp="1000" Lv="65" NewSeIdxs="1 11 57"/>