Files
bl/logic/service/fight/fightc.go
昔念 699231ee38 ```
feat(vscode): 添加调试参数配置

为launch.json添加-debug=1参数,便于调试模式启动

docs(README): 补充zellij终端复用工具使用说明

添加x-cmd安装和zellij会话管理相关命令示例

refactor(config): 注释掉GamePort配置项

暂时注释GamePort配置项以解决配置冲突问题

refactor(xmlres): 移除未使用的gf框架依赖并注释文件监控逻辑

移除未使用的gctx、gfile、gfsnotify、glog导入包
注释init函数中的文件监控逻辑,避免不必要的文件监听
```
2026-01-02 04:11:37 +08:00

374 lines
11 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 fight
import (
"blazing/common/utils"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/modules/blazing/model"
"fmt"
"reflect"
"github.com/alpacahq/alpacadecimal"
"github.com/barkimedes/go-deepcopy"
"github.com/gogf/gf/v2/util/grand"
)
// processSkillAttack 处理技能攻击逻辑
func (f *FightC) processSkillAttack(attacker, defender *input.Input, skill *info.SkillEntity) {
skill.AttackTimeC(attacker.GetProp(5, true)) //计算命中
defender.Exec(func(effect input.Effect) bool { //计算闪避,然后修改对方命中),同时相当于计算属性无效这种
effect.Ctx().SkillEntity = skill
effect.Skill_Hit_ex()
return true
})
var originalProps [2][6]int8
var originalPetInfo [2]model.PetInfo
originalProps[0], originalProps[1] = attacker.Prop, defender.Prop //先复制能力提升
originalPetInfo[0], originalPetInfo[1] = attacker.CurrentPet.Info, defender.CurrentPet.Info
attacker.Exec(func(effect input.Effect) bool {
//计算变威力
effect.Ctx().SkillEntity = skill
effect.Skill_Hit() //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
return true
})
//技能命中+效果失效 这里就是修改效果命中为false
//技能miss+效果生效 这里属于强制改命中效果,但是正常来说,技能miss掉后效果也应该失效
//技能失效+效果失效
attacker.AttackTime = skill.AttackTime
attacker.SkillID = uint32(skill.ID) //获取技能ID
if skill.AttackTime != 0 { //如果命中
attacker.CalculateCrit(defender, skill) //暴击计算
attacker.IsCritical = skill.Crit
attacker.SumDamage = attacker.CalculatePower(defender, skill)
}
attacker.Prop, defender.Prop = originalProps[0], originalProps[1]
attacker.CurrentPet.Info, defender.CurrentPet.Info = originalPetInfo[0], originalPetInfo[1]
if attacker.IsCritical == 1 { //命中了才有暴击
//暴击破防
if skill.Category() == info.Category.PHYSICAL && defender.Prop[1] > 0 {
defender.Prop[1] = 0
} else if skill.Category() == info.Category.SPECIAL && defender.Prop[3] > 0 {
defender.Prop[3] = 0
}
//暴击翻倍
attacker.SumDamage = attacker.SumDamage.Mul(alpacadecimal.NewFromInt(2))
}
if !skill.Side {
//这时候将被覆盖的效果全部装回来enterturn
for _, effect := range attacker.Effect_Lost {
if effect.Duration() > 0 || effect.Duration() == -1 {
effect.Alive(true)
}
}
} else {
for _, effect := range attacker.EffectCache {
effect.Hit(true) //我方效果命中
}
}
// 扣减防御方血量
attacker.Exec(func(effect input.Effect) bool {
effect.Ctx().SkillEntity = skill
effect.OnSkill() //调用伤害计算
return true
})
defender.Damage(attacker, &info.DamageZone{
Damage: attacker.SumDamage,
})
}
// IsNil 检查值是否为nil
func IsNil(x interface{}) bool {
if x == nil {
return true
}
rv := reflect.ValueOf(x)
return rv.Kind() == reflect.Ptr && rv.IsNil()
}
// copySkill 复制技能实体
func (f *FightC) copySkill(action *action.SelectSkillAction) *info.SkillEntity {
if action == nil {
return nil
}
if action.SkillEntity == nil {
return nil
}
originalSkill, _ := deepcopy.Anything(action.SkillEntity) //备份技能
originalSkill.(*info.SkillEntity).Rand = f.rand //拷贝后随机数丢失
return originalSkill.(*info.SkillEntity)
}
// enterturn 处理战斗回合逻辑
// 回合有先手方和后手方,同时有攻击方和被攻击方
func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction) {
//双方首发精灵登场时,依挑战方机制:房主方先判定,挑战方后判定
//双方非首发精灵登场时,根据切换先后判定(看手速)
// 神罗、圣华登场时魂免“登场时xx”等效果
//阿枫的效果也在这里判断
if f.closefight {
return
}
f.Broadcast(func(ff *input.Input) {
ff.Exec(func(effect input.Effect) bool { //回合开始前
effect.Turn_Start(firstAttack, secondAttack)
return true
})
})
if firstAttack != nil { //如果首技能是空的,说明都空过了
if firstAttack.GetPlayerID() == f.ownerID {
//是否miss都应该施加解析effect
f.Our.Parseskill(firstAttack) //解析到临时数据
f.Opp.Parseskill(secondAttack) //解析到临时数据
} else {
f.Opp.Parseskill(firstAttack)
f.Our.Parseskill(secondAttack)
}
}
f.Broadcast(func(fighter *input.Input) {
fighter.Exec(func(effect input.Effect) bool { //回合开始前
effect.Compare_Pre(firstAttack, secondAttack) //先结算技能的优先级
return true
})
fighter.ResetAttackValue()
})
f.First, f.Second = f.Our, f.Opp
if firstAttack != nil {
if firstAttack.GetPlayerID() != f.ownerID {
f.First, f.Second = f.Opp, f.Our // 攻击方为对方时,主攻击方是对方
}
}
if firstAttack != nil && secondAttack != nil {
switch {
case firstAttack.SkillEntity.Priority < secondAttack.SkillEntity.Priority:
firstAttack, secondAttack = secondAttack, firstAttack //互换先手权
f.First, f.Second = f.Second, f.First
case firstAttack.SkillEntity.Priority == secondAttack.SkillEntity.Priority:
if f.Second.GetProp(4, false) > f.First.GetProp(4, false) {
firstAttack, secondAttack = secondAttack, firstAttack //互换先手权
f.First, f.Second = f.Second, f.First
}
if f.Second.GetProp(4, false) == f.First.GetProp(4, false) {
if grand.Meet(1, 2) { //随机出手
firstAttack, secondAttack = secondAttack, firstAttack //互换先手权
f.First, f.Second = f.Second, f.First
}
}
}
}
if firstAttack == nil && secondAttack == nil {
firstAttack, secondAttack = secondAttack, firstAttack //互换先手权
f.First, f.Second = f.Second, f.First
}
var attacker, defender *input.Input
//开始回合操作
for i := 0; i < 2; i++ {
var originalSkill *info.SkillEntity //原始技能
var currentSkill *info.SkillEntity //当前技能
if i == 0 {
attacker, defender = f.First, f.Second
originalSkill = f.copySkill(firstAttack)
//先手阶段,先修复后手效果
f.Second.RecoverEffect()
} else {
attacker, defender = f.Second, f.First
originalSkill = f.copySkill(secondAttack)
f.Second.ReactvieEffect()
}
currentSkill = originalSkill
defender.Exec(func(effect input.Effect) bool { //这个是能否使用技能
effect.Ctx().SkillEntity = currentSkill
return effect.Action_start_ex(firstAttack, secondAttack)
})
canUseSkill := attacker.Exec(func(effect input.Effect) bool { //这个是能否使用技能
effect.Ctx().SkillEntity = currentSkill
return effect.Action_start(firstAttack, secondAttack)
})
canUse := canUseSkill && action.CanUse(currentSkill) && attacker.CurrentPet.Info.Hp > 0
if i == 0 { //先手方被控,这时候应该算做未出手状态
if canUse {
f.TrueFirst = attacker
} else {
f.TrueFirst = defender
}
}
if !canUse {
attacker.RecoverEffect()
currentSkill = nil
} else {
f.processSkillAttack(attacker, defender, currentSkill)
currentSkill = originalSkill //还原技能
_, skill, ok := utils.FindWithIndex(attacker.CurrentPet.Info.SkillList, func(item model.SkillInfo) bool {
return item.ID == currentSkill.Info.ID
})
if ok {
skill.PP--
}
}
if defender.CurrentPet.Info.Hp > 0 {
//技能使用后
defender.Exec(func(effect input.Effect) bool {
effect.Ctx().SkillEntity = currentSkill
effect.Skill_Use_ex()
return true
})
}
//技能使用后
attacker.Exec(func(effect input.Effect) bool { //技能使用后的我方效果
effect.Ctx().SkillEntity = currentSkill
effect.Skill_Useed()
return true
})
defender.Exec(func(effect input.Effect) bool {
effect.Ctx().SkillEntity = currentSkill
effect.Action_end_ex()
return true
})
if !attacker.CurrentPet.NotAlive {
//技能使用后
attacker.Exec(func(effect input.Effect) bool { //技能使用后的我方效果
effect.Ctx().SkillEntity = currentSkill
effect.Action_end()
return true
})
}
fmt.Println(i,
"技能名称:", attacker.CurrentPet.Info.Name,
"玩家技能伤害:", attacker.SumDamage,
"自身剩余血量:", attacker.CurrentPet.Info.Hp,
"对手剩余血量:", defender.CurrentPet.Info.Hp,
)
if attacker.CurrentPet.Info.Hp <= 0 {
attacker.CurrentPet.NotAlive = true
f.Broadcast(func(ff *input.Input) {
ff.Exec(func(t input.Effect) bool {
t.SwitchOut(attacker)
return true
})
})
if defender.CurrentPet.Info.Hp == 0 { //先手方死亡,触发反同归于尽
defender.CurrentPet.Info.Hp = 1
}
if f.IsWin(defender) { //然后检查是否战斗结束
f.FightOverInfo.WinnerId = defender.UserID
f.closefight = true
// break
}
//attacker.CanAction = true
break
}
if defender.CurrentPet.Info.Hp == 0 {
if attacker.CurrentPet.Info.Hp == 0 { //先手方死亡,触发反同归于尽
attacker.CurrentPet.Info.Hp = 1
}
//defender.CanAction = true //被打死就可以切精灵了
// AI自动技能
defender.CurrentPet.NotAlive = true
f.Broadcast(func(ff *input.Input) {
ff.Exec(func(t input.Effect) bool {
t.SwitchOut(defender)
return true
})
})
if f.IsWin(attacker) { //然后检查是否战斗结束
var WinnerId uint32
if i == 0 {
WinnerId = f.First.Player.GetInfo().UserID
} else {
WinnerId = f.Second.Player.GetInfo().UserID
}
f.FightOverInfo.WinnerId = WinnerId
f.closefight = true
}
//break
}
}
f.Broadcast(func(ff *input.Input) {
ff.GenSataus()
ff.Exec(func(t input.Effect) bool { //这个是能否使用技能
//结算状态
t.Turn_End() //返回本身结算,如果false,说明不能使用技能了
return true
})
ff.GenInfo()
})
if f.TrueFirst != f.First {
f.First, f.Second = f.Second, f.First
}
attackValueResult := info.AttackValueS{
FAttack: *f.First.AttackValue,
SAttack: *f.Second.AttackValue,
}
//因为切完才能广播,所以必须和回合结束分开结算
f.Broadcast(func(fighter *input.Input) {
for _, switchAction := range f.Switch {
if fighter.Player.GetInfo().UserID != switchAction.Reason.UserId {
println("切精灵", switchAction.Reason.UserId, switchAction.Reason.ID)
fighter.Player.SendPackCmd(2407, &switchAction.Reason)
}
}
})
f.Switch = make(map[uint32]*action.ActiveSwitchAction)
if f.closefight && f.Info.Mode == info.BattleMode.PET_MELEE {
return
}
f.Broadcast(func(fighter *input.Input) {
fighter.Player.SendPackCmd(2505, &attackValueResult)
fighter.CanChange = 0
})
println("回合结束")
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
if f.Opp.CurrentPet.Info.Hp <= 0 {
println("回合结束开始执行NPC动作")
f.Opp.GetAction()
//panic("AI自动技能")
}
}
}