```text
refactor(fight): 重构战斗准备逻辑并优化战斗启动流程 将 ReadyFight 方法拆分为多个职责清晰的子方法: - buildFightStartInfo: 构建战斗初始信息 - checkBothPlayersReady: 检查PVP双方是否就绪 - handleNPCFightSpecial: 处理NPC战斗特殊逻辑(如可捕捉标记) - startBattle: 统一启动战斗流程 同时修复部分逻辑顺序问题,增强代码可读性和扩展性。 feat(fight): 新增精灵王挑战协议支持 增加 StartPetWarInboundInfo 结构体用于接收精灵王挑战请求, 为后续实现相关功能提供基础。 fix(effect): 修正多个技能效果数值引用错误 - effect_37: 技能威力计算使用正确参数索引 - effect_50: 固定减伤比例调整为除以2 - effect_65: 正确比较技能分类类型 - effect_68: 致死保护改为锁定剩余1点生命值 - effect_77: 回复目标由敌方改为己方 - effect_93: 固定伤害值直接取参数 refactor(effect): 移除冗余效果类文件 删除 effect_133.go 和 effect_90.go 文件,其功能已被统一条件伤害和倍率系统取代; 移除 effect_74.go、effect_75.go 中重复的状态随机施加逻辑。 refactor(effect): 更新能力操作枚举命名一致性 重命名 AbilityOpType 枚举项名称,去除前缀,提升语义清晰度: - AbilityOpStealStrengthen → StealStrengthen - AbilityOpReverse → Reverse - AbilityOpBounceWeaken → BounceWeaken chore(fight): 完善 BattlePetEntity 属性初始化逻辑 在创建 BattlePetEntity 时即设置 PType,避免后续多次查询 PetMAP; 移除 Type() 方法中的冗余配置查找逻辑。 fix(skill): 确保必中技能不参与命中率计算 在 AttackTimeC 方法中添加 return 防止必中技能继续执行命中率公式计算。 refactor(fight): 调整战斗回合结束逻辑 进入新回合时允许玩家更换精灵,并提前跳出循环防止多余处理。 style(effect): 更正拼写及变量命名风格 修改 BaseSataus.Switch 方法签名中的参数命名; 更正 Effect58 中 can 字段首字母大写;
This commit is contained in:
@@ -1,205 +0,0 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"blazing/common/data/xmlres"
|
||||
"blazing/common/socket/errorcode"
|
||||
|
||||
"blazing/logic/service/fight"
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/player"
|
||||
"blazing/modules/blazing/model"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
// 挑战地图boss
|
||||
func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if !c.CanFight() {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotEligible
|
||||
}
|
||||
|
||||
var petid int
|
||||
var mo *model.PetInfo
|
||||
moinfo := &model.PlayerInfo{}
|
||||
|
||||
if c.Info.MapID == 515 && data.BossId == 0 { //说明是新手,随机生成
|
||||
switch c.Info.PetList[0].ID {
|
||||
|
||||
case 1:
|
||||
petid = 4
|
||||
|
||||
case 7:
|
||||
petid = 1
|
||||
|
||||
case 4:
|
||||
petid = 7
|
||||
}
|
||||
|
||||
mo = c.GenPetInfo(
|
||||
int(petid), 24, //24个体
|
||||
-1,
|
||||
0, //野怪没特性
|
||||
0,
|
||||
50)
|
||||
moinfo.Nick = xmlres.PetMAP[int(mo.ID)].DefName
|
||||
moinfo.PetList = append(moinfo.PetList, *mo)
|
||||
} else {
|
||||
|
||||
mdata, ok := xmlres.MonsterMap[int(c.Info.MapID)]
|
||||
if !ok {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
}
|
||||
if len(mdata.Bosses) == 0 {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
}
|
||||
for _, bc := range mdata.Bosses {
|
||||
if bc.Id == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
|
||||
}
|
||||
if uint32(*bc.Id) == data.BossId {
|
||||
for _, bm := range bc.BossMon {
|
||||
mo = c.GenPetInfo(
|
||||
gconv.Int(bm.MonID), 24, //24个体
|
||||
-1,
|
||||
0, //野怪没特性
|
||||
0,
|
||||
bm.Lv)
|
||||
|
||||
// mo.Level = uint32(bm.Lv)
|
||||
mo.CalculatePetPane()
|
||||
mo.Hp = uint32(bm.Hp)
|
||||
mo.MaxHp = uint32(bm.Hp)
|
||||
moinfo.PetList = append(moinfo.PetList, *mo)
|
||||
|
||||
}
|
||||
moinfo.Nick = xmlres.PetMAP[int(mo.ID)].DefName
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ai := player.NewAI_player(moinfo)
|
||||
fight.NewFight(info.BattleMode.MULTI_MODE, info.BattleStatus.FIGHT_WITH_BOSS, c, ai)
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 战斗野怪
|
||||
func (h Controller) OnPlayerFightNpcMonster(data *fight.FightNpcMonsterInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if !c.CanFight() {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotEligible
|
||||
}
|
||||
refpet := c.OgreInfo.Data[data.Number]
|
||||
if refpet.Id == 0 {
|
||||
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
}
|
||||
mo := c.GenPetInfo(
|
||||
int(refpet.Id), -1,
|
||||
-1,
|
||||
0, //野怪没特性
|
||||
int(refpet.Shiny),
|
||||
int(refpet.Lv))
|
||||
|
||||
moinfo := &model.PlayerInfo{}
|
||||
moinfo.Nick = xmlres.PetMAP[int(mo.ID)].DefName
|
||||
moinfo.PetList = append(moinfo.PetList, *mo)
|
||||
ai := player.NewAI_player(moinfo)
|
||||
|
||||
fight.NewFight(info.BattleMode.MULTI_MODE, info.BattleStatus.FIGHT_WITH_NPC, c, ai)
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 准备战斗
|
||||
func (h Controller) OnReadyToFight(data *fight.ReadyToFightInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
c.FightC.ReadyFight(c)
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 接收战斗或者取消战斗的包
|
||||
func (h Controller) OnPlayerHandleFightInvite(data *fight.HandleFightInviteInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
if ok, p1 := c.AgreeBattle(data.UserID, data.Flag, data.Mode); ok {
|
||||
fight.NewFight(data.Mode, info.BattleStatus.FIGHT_WITH_PLAYER, c, p1) ///开始对战,房主方以及被邀请方
|
||||
}
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 邀请其他人进行战斗
|
||||
func (h Controller) OnPlayerInviteOtherFight(data *fight.InviteToFightInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if !c.CanFight() {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotEligible
|
||||
}
|
||||
|
||||
c.InvitePlayerToBattle(&info.PVPinfo{PlayerID: data.UserID, Mode: data.Mode})
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
// 取消和他人战斗
|
||||
func (h Controller) OnPlayerCanceledOtherInviteFight(data *fight.InviteFightCancelInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
c.CancelBattle()
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
// 使用技能包
|
||||
func (h Controller) UseSkill(data *fight.UseSkillInInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if c.FightC != nil {
|
||||
c.FightC.UseSkill(c, int32(data.SkillId))
|
||||
}
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
// 战斗逃跑
|
||||
func (h Controller) Escape(data *fight.EscapeFightInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if c.FightC == nil {
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
if !c.FightC.CanEscape() {
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
c.FightC.Over(c, info.BattleOverReason.PlayerEscape)
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
// 切换精灵
|
||||
func (h Controller) ChangePet(data *fight.ChangePetInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if c.FightC != nil {
|
||||
c.FightC.ChangePet(c, data.CatchTime)
|
||||
}
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 切换精灵
|
||||
func (h Controller) Capture(data *fight.CatchMonsterInboundInfo, c *player.Player) (result *info.CatchMonsterOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
c.FightC.Capture(c, data.CapsuleId)
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 加载进度
|
||||
func (h Controller) LoadPercent(data *fight.LoadPercentInboundInfo, c *player.Player) (result *info.LoadPercentOutboundInfo, err errorcode.ErrorCode) {
|
||||
if c.FightC != nil {
|
||||
|
||||
c.FightC.LoadPercent(c, int32(data.Percent))
|
||||
}
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
func (h Controller) UsePetItemInboundInfo(data *fight.UsePetItemInboundInfo, c *player.Player) (result *info.UsePetIteminfo, err errorcode.ErrorCode) {
|
||||
if c.FightC != nil {
|
||||
|
||||
c.FightC.UseItem(c, data.CatchTime, data.ItemId)
|
||||
}
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
72
logic/controller/fight_base.go
Normal file
72
logic/controller/fight_base.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"blazing/common/socket/errorcode"
|
||||
|
||||
"blazing/logic/service/fight"
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/player"
|
||||
)
|
||||
|
||||
// 准备战斗
|
||||
func (h Controller) OnReadyToFight(data *fight.ReadyToFightInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
c.FightC.ReadyFight(c)
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 使用技能包
|
||||
func (h Controller) UseSkill(data *fight.UseSkillInInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if c.FightC != nil {
|
||||
c.FightC.UseSkill(c, int32(data.SkillId))
|
||||
}
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
// 战斗逃跑
|
||||
func (h Controller) Escape(data *fight.EscapeFightInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if c.FightC == nil {
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
if !c.FightC.CanEscape() {
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
c.FightC.Over(c, info.BattleOverReason.PlayerEscape)
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
// 切换精灵
|
||||
func (h Controller) ChangePet(data *fight.ChangePetInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if c.FightC != nil {
|
||||
c.FightC.ChangePet(c, data.CatchTime)
|
||||
}
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 切换精灵
|
||||
func (h Controller) Capture(data *fight.CatchMonsterInboundInfo, c *player.Player) (result *info.CatchMonsterOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
c.FightC.Capture(c, data.CapsuleId)
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 加载进度
|
||||
func (h Controller) LoadPercent(data *fight.LoadPercentInboundInfo, c *player.Player) (result *info.LoadPercentOutboundInfo, err errorcode.ErrorCode) {
|
||||
if c.FightC != nil {
|
||||
|
||||
c.FightC.LoadPercent(c, int32(data.Percent))
|
||||
}
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
func (h Controller) UsePetItemInboundInfo(data *fight.UsePetItemInboundInfo, c *player.Player) (result *info.UsePetIteminfo, err errorcode.ErrorCode) {
|
||||
if c.FightC != nil {
|
||||
|
||||
c.FightC.UseItem(c, data.CatchTime, data.ItemId)
|
||||
}
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
114
logic/controller/fight_boss.go
Normal file
114
logic/controller/fight_boss.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"blazing/common/data/xmlres"
|
||||
"blazing/common/socket/errorcode"
|
||||
"blazing/logic/service/fight"
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/player"
|
||||
"blazing/modules/blazing/model"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
// 挑战地图boss
|
||||
func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if !c.CanFight() {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotEligible
|
||||
}
|
||||
|
||||
var petid int
|
||||
var mo *model.PetInfo
|
||||
moinfo := &model.PlayerInfo{}
|
||||
|
||||
if c.Info.MapID == 515 && data.BossId == 0 { //说明是新手,随机生成
|
||||
switch c.Info.PetList[0].ID {
|
||||
|
||||
case 1:
|
||||
petid = 4
|
||||
|
||||
case 7:
|
||||
petid = 1
|
||||
|
||||
case 4:
|
||||
petid = 7
|
||||
}
|
||||
|
||||
mo = c.GenPetInfo(
|
||||
int(petid), 24, //24个体
|
||||
-1,
|
||||
0, //野怪没特性
|
||||
0,
|
||||
50)
|
||||
moinfo.Nick = xmlres.PetMAP[int(mo.ID)].DefName
|
||||
moinfo.PetList = append(moinfo.PetList, *mo)
|
||||
} else {
|
||||
|
||||
mdata, ok := xmlres.MonsterMap[int(c.Info.MapID)]
|
||||
if !ok {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
}
|
||||
if len(mdata.Bosses) == 0 {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
}
|
||||
for _, bc := range mdata.Bosses {
|
||||
if bc.Id == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
|
||||
}
|
||||
if uint32(*bc.Id) == data.BossId {
|
||||
for _, bm := range bc.BossMon {
|
||||
mo = c.GenPetInfo(
|
||||
gconv.Int(bm.MonID), 24, //24个体
|
||||
-1,
|
||||
0, //野怪没特性
|
||||
0,
|
||||
bm.Lv)
|
||||
|
||||
// mo.Level = uint32(bm.Lv)
|
||||
mo.CalculatePetPane()
|
||||
mo.Hp = uint32(bm.Hp)
|
||||
mo.MaxHp = uint32(bm.Hp)
|
||||
moinfo.PetList = append(moinfo.PetList, *mo)
|
||||
|
||||
}
|
||||
moinfo.Nick = xmlres.PetMAP[int(mo.ID)].DefName
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ai := player.NewAI_player(moinfo)
|
||||
fight.NewFight(info.BattleMode.MULTI_MODE, info.BattleStatus.FIGHT_WITH_BOSS, c, ai)
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 战斗野怪
|
||||
func (h Controller) OnPlayerFightNpcMonster(data *fight.FightNpcMonsterInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if !c.CanFight() {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotEligible
|
||||
}
|
||||
refpet := c.OgreInfo.Data[data.Number]
|
||||
if refpet.Id == 0 {
|
||||
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
}
|
||||
mo := c.GenPetInfo(
|
||||
int(refpet.Id), -1,
|
||||
-1,
|
||||
0, //野怪没特性
|
||||
int(refpet.Shiny),
|
||||
int(refpet.Lv))
|
||||
|
||||
moinfo := &model.PlayerInfo{}
|
||||
moinfo.Nick = xmlres.PetMAP[int(mo.ID)].DefName
|
||||
moinfo.PetList = append(moinfo.PetList, *mo)
|
||||
ai := player.NewAI_player(moinfo)
|
||||
|
||||
fight.NewFight(info.BattleMode.MULTI_MODE, info.BattleStatus.FIGHT_WITH_NPC, c, ai)
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
16
logic/controller/fight_pvp_king.go
Normal file
16
logic/controller/fight_pvp_king.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"blazing/common/socket/errorcode"
|
||||
"blazing/logic/service/fight"
|
||||
"blazing/logic/service/player"
|
||||
)
|
||||
|
||||
//精灵王之战
|
||||
|
||||
func (h Controller) PvpKingFight(data *fight.StartPetWarInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if !c.CanFight() {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotEligible
|
||||
}
|
||||
return
|
||||
}
|
||||
41
logic/controller/fight_pvp_withplayer.go
Normal file
41
logic/controller/fight_pvp_withplayer.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"blazing/common/socket/errorcode"
|
||||
"blazing/logic/service/fight"
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/player"
|
||||
)
|
||||
|
||||
// 接收战斗或者取消战斗的包
|
||||
func (h Controller) OnPlayerHandleFightInvite(data *fight.HandleFightInviteInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
if ok, p1 := c.AgreeBattle(data.UserID, data.Flag, data.Mode); ok {
|
||||
fight.NewFight(data.Mode, info.BattleStatus.FIGHT_WITH_PLAYER, p1, c) ///开始对战,房主方以及被邀请方
|
||||
}
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 邀请其他人进行战斗
|
||||
func (h Controller) OnPlayerInviteOtherFight(data *fight.InviteToFightInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if !c.CanFight() {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotEligible
|
||||
}
|
||||
|
||||
//进入邀请,以及确认对战模式
|
||||
|
||||
c.PVPinfo = &info.PVPinfo{PlayerID: data.UserID,
|
||||
Mode: data.Mode,
|
||||
Status: info.BattleStatus.FIGHT_WITH_PLAYER}
|
||||
|
||||
c.InvitePlayerToBattle()
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
// 取消和他人战斗
|
||||
func (h Controller) OnPlayerCanceledOtherInviteFight(data *fight.InviteFightCancelInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
c.CancelBattle()
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/logic/service/player"
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/jinzhu/copier"
|
||||
@@ -136,57 +137,92 @@ func (f *FightC) UseItem(c common.PlayerI, cacthid, itemid uint32) {
|
||||
f.actionChan <- &action.UseItemAction{BaseAction: action.NewBaseAction(c.GetInfo().UserID), ItemID: itemid, CacthTime: cacthid}
|
||||
}
|
||||
|
||||
// 战斗准备
|
||||
// ReadyFight 处理玩家战斗准备逻辑,当满足条件时启动战斗循环
|
||||
func (f *FightC) ReadyFight(c common.PlayerI) {
|
||||
// 1. 构建战斗开始信息(整理双方初始宠物信息)
|
||||
fightStartInfo := f.buildFightStartInfo()
|
||||
|
||||
rett := info.FightStartOutboundInfo{}
|
||||
// 2. 标记当前玩家已准备完成
|
||||
input := f.GetInputByPlayer(c, false)
|
||||
input.Finished = true
|
||||
|
||||
copier.Copy(&rett.Info1, &f.Info.OurPetList[0]) // 复制自己的信息
|
||||
copier.Copy(&rett.Info2, &f.Info.OpponentPetList[0])
|
||||
rett.Info1.UserID = f.Info.OurInfo.UserID //
|
||||
rett.Info2.UserID = f.Info.OpponentInfo.UserID
|
||||
|
||||
rrsult := func() { //传回函数
|
||||
// i := Fightpool.Free()
|
||||
// if i <= 0 {
|
||||
// Fightpool.Tune(Fightpool.Cap() + 1)
|
||||
|
||||
// cool.Loger.Error(context.Background(), "Fightpool is full")
|
||||
|
||||
// }
|
||||
rr := Fightpool.Submit(f.battleLoop)
|
||||
if rr != nil {
|
||||
panic(rr)
|
||||
}
|
||||
|
||||
f.Our.Player.SendReadyToFightInfo(rett)
|
||||
f.Opp.Player.SendReadyToFightInfo(rett)
|
||||
//f.runing = true
|
||||
//然后开始战斗循环
|
||||
|
||||
}
|
||||
f.GetInputByPlayer(c, false).Finished = true
|
||||
// 3. 根据战斗类型判断是否满足战斗启动条件,满足则启动
|
||||
switch f.Info.Status {
|
||||
case info.BattleStatus.FIGHT_WITH_PLAYER: //pvp
|
||||
|
||||
if f.GetInputByPlayer(c, true).Finished {
|
||||
rrsult()
|
||||
case info.BattleStatus.FIGHT_WITH_PLAYER: // PVP战斗:需双方都准备完成
|
||||
if f.checkBothPlayersReady(c) {
|
||||
f.startBattle(fightStartInfo)
|
||||
}
|
||||
case info.BattleStatus.FIGHT_WITH_BOSS: // 6v6
|
||||
rrsult()
|
||||
case info.BattleStatus.FIGHT_WITH_NPC: // 野怪战斗
|
||||
|
||||
if gconv.Int(xmlres.PetMAP[int(f.Info.OpponentPetList[0].ID)].CatchRate) > 0 {
|
||||
rett.Info2.Catchable = 1
|
||||
t, _ := f.Opp.Player.(*player.AI_player)
|
||||
t.CanCapture = true
|
||||
|
||||
}
|
||||
|
||||
rrsult()
|
||||
case info.BattleStatus.FIGHT_WITH_BOSS: // BOSS战:单方准备完成即可启动
|
||||
f.startBattle(fightStartInfo)
|
||||
case info.BattleStatus.FIGHT_WITH_NPC: // NPC/野怪战斗:处理捕捉相关逻辑后启动
|
||||
f.handleNPCFightSpecial(&fightStartInfo)
|
||||
f.startBattle(fightStartInfo)
|
||||
}
|
||||
}
|
||||
|
||||
// buildFightStartInfo 构建战斗开始时需要发送给双方的信息
|
||||
func (f *FightC) buildFightStartInfo() info.FightStartOutboundInfo {
|
||||
var startInfo info.FightStartOutboundInfo
|
||||
|
||||
// 复制双方初始宠物信息(取列表第一个宠物)
|
||||
if len(f.Info.OurPetList) > 0 {
|
||||
_ = copier.Copy(&startInfo.Info1, &f.Info.OurPetList[0])
|
||||
startInfo.Info1.UserID = f.Info.OurInfo.UserID
|
||||
}
|
||||
if len(f.Info.OpponentPetList) > 0 {
|
||||
_ = copier.Copy(&startInfo.Info2, &f.Info.OpponentPetList[0])
|
||||
startInfo.Info2.UserID = f.Info.OpponentInfo.UserID
|
||||
}
|
||||
|
||||
return startInfo
|
||||
}
|
||||
|
||||
// checkBothPlayersReady 检查PVP战斗中双方是否都已准备完成
|
||||
// 参数c为当前准备的玩家,返回true表示双方均准备完成
|
||||
func (f *FightC) checkBothPlayersReady(currentPlayer common.PlayerI) bool {
|
||||
// 这里的第二个参数true含义需结合业务确认(推测为"检查对手"),建议用常量替代
|
||||
opponentInput := f.GetInputByPlayer(currentPlayer, true)
|
||||
return opponentInput.Finished
|
||||
}
|
||||
|
||||
// handleNPCFightSpecial 处理NPC战斗的特殊逻辑(如可捕捉标记)
|
||||
func (f *FightC) handleNPCFightSpecial(startInfo *info.FightStartOutboundInfo) {
|
||||
// 检查野怪是否可捕捉(根据宠物ID获取捕捉率)
|
||||
if len(f.Info.OpponentPetList) == 0 {
|
||||
return
|
||||
}
|
||||
npcPetID := int(f.Info.OpponentPetList[0].ID)
|
||||
petCfg, ok := xmlres.PetMAP[npcPetID]
|
||||
if !ok {
|
||||
// log.Error(context.Background(), "NPC宠物配置不存在", "petID", npcPetID)
|
||||
return
|
||||
}
|
||||
|
||||
catchRate := gconv.Int(petCfg.CatchRate)
|
||||
if catchRate > 0 {
|
||||
startInfo.Info2.Catchable = 1 // 标记为可捕捉
|
||||
// 标记AI对手允许被捕捉(类型断言确保安全)
|
||||
if oppAI, ok := f.Opp.Player.(*player.AI_player); ok {
|
||||
oppAI.CanCapture = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// startBattle 启动战斗核心逻辑:提交战斗循环任务并通知双方
|
||||
func (f *FightC) startBattle(startInfo info.FightStartOutboundInfo) {
|
||||
// 提交战斗循环到战斗池(处理战斗池容量问题)
|
||||
if err := Fightpool.Submit(f.battleLoop); err != nil {
|
||||
log.Panic(context.Background(), "战斗循环提交失败", "error", err)
|
||||
}
|
||||
|
||||
// 通知双方玩家准备完成,即将开始战斗
|
||||
f.Our.Player.SendReadyToFightInfo(startInfo)
|
||||
f.Opp.Player.SendReadyToFightInfo(startInfo)
|
||||
|
||||
// 标记战斗已启动(原注释逻辑)
|
||||
// f.running = true
|
||||
}
|
||||
|
||||
var Fightpool *ants.Pool
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -30,6 +30,11 @@ type EscapeFightInboundInfo struct {
|
||||
Head player.TomeeHeader `cmd:"2410" struc:"[0]pad"`
|
||||
}
|
||||
|
||||
// 精灵王
|
||||
type StartPetWarInboundInfo struct {
|
||||
Head player.TomeeHeader `cmd:"2431" struc:"[0]pad"`
|
||||
}
|
||||
|
||||
// HandleFightInviteInboundInfo 处理战斗邀请的入站消息
|
||||
|
||||
type HandleFightInviteInboundInfo struct {
|
||||
@@ -45,7 +50,6 @@ type InviteToFightInboundInfo struct {
|
||||
UserID uint32 `codec:"true"`
|
||||
|
||||
// Mode 战斗类型 1 = 1v1 2 = 6v6
|
||||
|
||||
Mode info.EnumBattleMode `codec:"true"`
|
||||
}
|
||||
type InviteFightCancelInboundInfo struct {
|
||||
|
||||
@@ -17,7 +17,7 @@ func (e *Effect37) Skill_Hit() bool {
|
||||
|
||||
cmphp := e.GetInput().CurrentPet.GetMaxHP().Div(decimal.NewFromInt(int64(e.Args()[0])))
|
||||
if e.GetInput().CurrentPet.GetHP().Cmp(cmphp) == -1 {
|
||||
e.Ctx().SkillEntity.Power *= e.Args()[0]
|
||||
e.Ctx().SkillEntity.Power *= e.Args()[1]
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
// "可完全抵挡n次攻击伤害 百分百减伤 ,后面还有锁伤
|
||||
// 可以抵挡n点伤害
|
||||
// ---- Effect49 ----
|
||||
type Effect49 struct {
|
||||
node.EffectNode
|
||||
@@ -37,9 +37,7 @@ func (e *Effect49) Damage_SUB_ex(t *info.DamageZone) bool {
|
||||
}
|
||||
func (e *Effect49) SetArgs(t *input.Input, a ...int) {
|
||||
|
||||
//e.CanStack(-1)//后续的不会顶掉这个效果
|
||||
e.EffectNode.SetArgs(t, a...)
|
||||
//e.Duration(-1) //次数类,无限回合
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ func (e *Effect50) Damage_DIV_ex(t *info.DamageZone) bool {
|
||||
//fmt.Println("Effect50_o", t.Damage)
|
||||
if t.Type == info.DamageType.Red {
|
||||
|
||||
t.Damage = t.Damage.Div(decimal.NewFromInt(int64(e.Args()[1])))
|
||||
t.Damage = t.Damage.Div(decimal.NewFromInt(2))
|
||||
|
||||
}
|
||||
//fmt.Println("Effect50_n", t.Damage)
|
||||
|
||||
48
logic/service/fight/effect/effect_52.go
Normal file
48
logic/service/fight/effect/effect_52.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package effect
|
||||
|
||||
import (
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/logic/service/fight/node"
|
||||
)
|
||||
|
||||
/**
|
||||
* n回合若本方先手攻击: 使得技能miss (但MustHit有效)
|
||||
*/
|
||||
|
||||
func init() {
|
||||
t := &Effect52{
|
||||
EffectNode: node.EffectNode{},
|
||||
}
|
||||
// t.Duration(-1) //设置成无限回合,到回合数就停止
|
||||
input.InitEffect(input.EffectType.Skill, 52, t)
|
||||
|
||||
}
|
||||
|
||||
type Effect52 struct {
|
||||
node.EffectNode
|
||||
}
|
||||
|
||||
// 默认添加回合
|
||||
func (e *Effect52) SetArgs(t *input.Input, a ...int) {
|
||||
|
||||
e.EffectNode.SetArgs(t, a...)
|
||||
e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0])
|
||||
|
||||
}
|
||||
|
||||
func (e *Effect52) Skill_Hit_ex() bool {
|
||||
|
||||
//fmt.Println(e.Ctx().SkillEntity)
|
||||
if e.Ctx().SkillEntity == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if !e.Input.FightC.IsFirst(e.Ctx().Our.Player) {
|
||||
return true
|
||||
}
|
||||
if e.Ctx().SkillEntity.AttackTime == 1 {
|
||||
e.Ctx().SkillEntity.AttackTime = 0
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -28,7 +28,7 @@ func (e *Effect90) Damage_Mul(t *info.DamageZone) bool {
|
||||
|
||||
if t.Type == info.DamageType.Red {
|
||||
|
||||
e.Ctx().Our.DamageZone.Damage = e.Ctx().Our.DamageZone.Damage.Mul(decimal.NewFromInt(int64(e.SideEffectArgs[1])))
|
||||
t.Damage = t.Damage.Mul(decimal.NewFromInt(int64(e.SideEffectArgs[1])))
|
||||
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ func init() {
|
||||
|
||||
type Effect58 struct {
|
||||
node.EffectNode
|
||||
can bool
|
||||
Can bool
|
||||
}
|
||||
|
||||
func (e *Effect58) OnSkill() bool {
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
e.can = true
|
||||
e.Can = true
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -34,7 +34,7 @@ func (e *Effect58) Skill_Hit_Pre(a, b *action.SelectSkillAction) bool {
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
if !e.can {
|
||||
if !e.Can {
|
||||
return true
|
||||
}
|
||||
//fmt.Println(e.Ctx().SkillEntity)
|
||||
|
||||
@@ -26,7 +26,7 @@ func (e *Effect65) Skill_Hit() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
if e.Ctx().SkillEntity.Category() != info.EnumCategory(e.Args()[1]) {
|
||||
if info.EnumCategory(e.Ctx().SkillEntity.Move.Type) != info.EnumCategory(e.Args()[1]) {
|
||||
return true
|
||||
}
|
||||
//技能威力=【165-65*【当前体力百分比】】,任意体力百分比对应的威力浮动范围∈[-10,+10]
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/logic/service/fight/node"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
// 1回合内,受到致死攻击时则余下1点体力
|
||||
@@ -13,7 +15,7 @@ type Effect68 struct {
|
||||
StatusID int
|
||||
}
|
||||
|
||||
func (e *Effect68) Skill_Use_ex() bool {
|
||||
func (e *Effect68) Damage_Lock_ex(t *info.DamageZone) bool {
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
@@ -26,19 +28,13 @@ func (e *Effect68) Skill_Use_ex() bool {
|
||||
|
||||
//fmt.Println("Effect68_o", t.Damage)
|
||||
//伤害溢出
|
||||
if e.Ctx().Opp.DamageZone.Damage.Cmp(e.Ctx().Our.CurrentPet.GetHP()) == 1 {
|
||||
e.Ctx().Our.CurrentPet.Info.Hp = 1
|
||||
|
||||
if t.Type == info.DamageType.Red && t.Damage.Cmp(e.Ctx().Our.CurrentPet.GetHP()) == 1 {
|
||||
//e.Ctx().Our.CurrentPet.Info.Hp = 1
|
||||
t.Damage = e.Ctx().Our.CurrentPet.GetHP().Sub(decimal.NewFromInt(1))
|
||||
}
|
||||
//fmt.Println("Effect68_n", t.Damage)
|
||||
return true
|
||||
}
|
||||
func (e *Effect68) SetArgs(t *input.Input, a ...int) {
|
||||
|
||||
e.EffectNode.SetArgs(t, a...)
|
||||
e.EffectNode.Duration(e.EffectNode.SideEffectArgs[1])
|
||||
|
||||
}
|
||||
|
||||
// ---- 注册所有效果 ----
|
||||
func init() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package effect
|
||||
|
||||
import (
|
||||
"blazing/logic/service/fight/action"
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/logic/service/fight/node"
|
||||
@@ -18,7 +19,7 @@ type Effect71 struct {
|
||||
|
||||
func init() {
|
||||
|
||||
input.InitEffect(input.EffectType.Skill, 59, &Effect71{})
|
||||
input.InitEffect(input.EffectType.Skill, 71, &Effect71{})
|
||||
|
||||
}
|
||||
func (e *Effect71) SetArgs(t *input.Input, a ...int) {
|
||||
@@ -50,13 +51,29 @@ func (e *Effect71) Switch(in *input.Input, at info.AttackValue, oldpet *info.Bat
|
||||
if in != e.Ctx().Our {
|
||||
return true
|
||||
}
|
||||
t := &Effect71_sub{}
|
||||
t.Duration(2)
|
||||
t.ID(e.ID() + int(input.EffectType.Sub))
|
||||
e.Ctx().Our.AddEffect(e.Ctx().Our, t)
|
||||
|
||||
t := input.Geteffect(input.EffectType.Skill, 58)
|
||||
if t != nil {
|
||||
e.SetArgs(e.Ctx().Our, 2)
|
||||
e.Ctx().Our.AddEffect(e.Ctx().Our, e)
|
||||
|
||||
}
|
||||
e.Alive(false)
|
||||
return true
|
||||
}
|
||||
|
||||
type Effect71_sub struct {
|
||||
node.EffectNode
|
||||
}
|
||||
|
||||
func (e *Effect71_sub) Skill_Hit_Pre(a, b *action.SelectSkillAction) bool {
|
||||
|
||||
//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 = 16
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ func (e *Effect73) Skill_Use_ex() bool {
|
||||
|
||||
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
|
||||
Type: info.DamageType.Fixed,
|
||||
Damage: e.Ctx().Opp.DamageZone.Damage.Div(decimal.NewFromInt(2)),
|
||||
Damage: e.Ctx().Opp.DamageZone.Damage.Mul(decimal.NewFromInt(2)),
|
||||
})
|
||||
|
||||
return true
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
package effect
|
||||
|
||||
import (
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/logic/service/fight/node"
|
||||
)
|
||||
|
||||
/**
|
||||
* 10%中毒、10%烧伤、10%冻伤(剩下70%无效果)
|
||||
*/
|
||||
type Effect74 struct {
|
||||
node.EffectNode
|
||||
}
|
||||
|
||||
func init() {
|
||||
ret := &Effect74{}
|
||||
|
||||
input.InitEffect(input.EffectType.Skill, 74, ret)
|
||||
|
||||
}
|
||||
|
||||
// 命中之后
|
||||
func (e *Effect74) OnSkill() bool {
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
Status := info.PetStatus.NULL
|
||||
|
||||
// 生成0-99的随机数(共100种可能)
|
||||
switch t := e.Input.FightC.GetRand().Int31n(100); {
|
||||
case t < 10: // 0-9(10个数,占10%)
|
||||
Status = info.PetStatus.Poisoned
|
||||
case t < 20: // 10-19(10个数,占10%)
|
||||
// 触发睡眠效果
|
||||
Status = info.PetStatus.Burned
|
||||
case t < 30: // 20-29(10个数,占10%)
|
||||
// 触发害怕效果
|
||||
Status = info.PetStatus.Frozen
|
||||
default: // 30-99(70个数,占70%)
|
||||
// 无效果
|
||||
|
||||
}
|
||||
if Status == info.PetStatus.NULL {
|
||||
return true
|
||||
}
|
||||
// 获取状态效果
|
||||
eff := input.Geteffect(input.EffectType.Status, int(Status))
|
||||
if eff == nil {
|
||||
return true
|
||||
}
|
||||
duration := int(e.Input.FightC.GetRand().Int31n(2)) // 默认随机 2~3 回合
|
||||
duration++
|
||||
eff.Duration(duration)
|
||||
eff.SetArgs(e.Ctx().Our) //输入参数是对方
|
||||
e.Ctx().Opp.AddEffect(e.Ctx().Our, eff)
|
||||
return true
|
||||
}
|
||||
81
logic/service/fight/effect/effect_74_75.go
Normal file
81
logic/service/fight/effect/effect_74_75.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package effect
|
||||
|
||||
import (
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/logic/service/fight/node"
|
||||
)
|
||||
|
||||
// 定义状态区间配置:包含概率上限(0-100)和对应的状态
|
||||
type statusRange struct {
|
||||
upper int // 概率区间上限(例如10表示0-9区间)
|
||||
status info.EnumPetStatus // 该区间触发的状态
|
||||
}
|
||||
|
||||
// 通用随机状态效果结构体
|
||||
type EffectRandomStatus struct {
|
||||
node.EffectNode
|
||||
ranges []statusRange // 当前效果的状态概率配置
|
||||
}
|
||||
|
||||
// 工厂函数:创建通用随机状态效果实例(接收状态配置)
|
||||
func newEffectRandomStatus(ranges []statusRange) *EffectRandomStatus {
|
||||
return &EffectRandomStatus{
|
||||
ranges: ranges,
|
||||
}
|
||||
}
|
||||
|
||||
// 通用逻辑:命中后按概率随机触发状态
|
||||
func (e *EffectRandomStatus) OnSkill() bool {
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
|
||||
// 生成0-99的随机数(100种可能)
|
||||
randVal := int(e.Input.FightC.GetRand().Int31n(100))
|
||||
targetStatus := info.PetStatus.NULL
|
||||
|
||||
// 根据配置匹配对应的状态
|
||||
for _, r := range e.ranges {
|
||||
if randVal < r.upper {
|
||||
targetStatus = r.status
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 未匹配到任何状态(概率外情况)
|
||||
if targetStatus == info.PetStatus.NULL {
|
||||
return true
|
||||
}
|
||||
|
||||
// 获取状态效果并设置参数
|
||||
eff := input.Geteffect(input.EffectType.Status, int(targetStatus))
|
||||
if eff == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
// 持续时间:随机2-3回合(与原逻辑一致)
|
||||
duration := int(e.Input.FightC.GetRand().Int31n(2)) + 2
|
||||
eff.Duration(duration)
|
||||
eff.SetArgs(e.Ctx().Our)
|
||||
e.Ctx().Opp.AddEffect(e.Ctx().Our, eff)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 初始化:注册Effect74和Effect75(通过不同配置区分)
|
||||
func init() {
|
||||
// Effect74:10%中毒、10%烧伤、10%冻伤(70%无效果)
|
||||
input.InitEffect(input.EffectType.Skill, 74, newEffectRandomStatus([]statusRange{
|
||||
{upper: 10, status: info.PetStatus.Poisoned}, // 0-9:中毒
|
||||
{upper: 20, status: info.PetStatus.Burned}, // 10-19:烧伤
|
||||
{upper: 30, status: info.PetStatus.Frozen}, // 20-29:冻伤
|
||||
}))
|
||||
|
||||
// Effect75:10%麻痹、10%睡眠、10%害怕(70%无效果)
|
||||
input.InitEffect(input.EffectType.Skill, 75, newEffectRandomStatus([]statusRange{
|
||||
{upper: 10, status: info.PetStatus.Paralysis}, // 0-9:麻痹
|
||||
{upper: 20, status: info.PetStatus.Sleep}, // 10-19:睡眠
|
||||
{upper: 30, status: info.PetStatus.Fear}, // 20-29:害怕
|
||||
}))
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package effect
|
||||
|
||||
import (
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/logic/service/fight/node"
|
||||
)
|
||||
|
||||
/**
|
||||
* 10%麻痹、10%睡眠、10%害怕(剩下70%无效果)
|
||||
*/
|
||||
type Effect75 struct {
|
||||
node.EffectNode
|
||||
}
|
||||
|
||||
func init() {
|
||||
ret := &Effect75{}
|
||||
|
||||
input.InitEffect(input.EffectType.Skill, 75, ret)
|
||||
|
||||
}
|
||||
|
||||
// 命中之后
|
||||
func (e *Effect75) OnSkill() bool {
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
Status := info.PetStatus.NULL
|
||||
|
||||
// 生成0-99的随机数(共100种可能)
|
||||
switch t := e.Input.FightC.GetRand().Int31n(100); {
|
||||
case t < 10: // 0-9(10个数,占10%)
|
||||
Status = info.PetStatus.Paralysis
|
||||
case t < 20: // 10-19(10个数,占10%)
|
||||
// 触发睡眠效果
|
||||
Status = info.PetStatus.Sleep
|
||||
case t < 30: // 20-29(10个数,占10%)
|
||||
// 触发害怕效果
|
||||
Status = info.PetStatus.Fear
|
||||
default: // 30-99(70个数,占70%)
|
||||
// 无效果
|
||||
|
||||
}
|
||||
if Status == info.PetStatus.NULL {
|
||||
return true
|
||||
}
|
||||
// 获取状态效果
|
||||
eff := input.Geteffect(input.EffectType.Status, int(Status))
|
||||
if eff == nil {
|
||||
return true
|
||||
}
|
||||
duration := int(e.Input.FightC.GetRand().Int31n(2)) // 默认随机 2~3 回合
|
||||
duration++
|
||||
eff.Duration(duration)
|
||||
eff.SetArgs(e.Ctx().Our) //输入参数是对方
|
||||
e.Ctx().Opp.AddEffect(e.Ctx().Our, eff)
|
||||
return true
|
||||
}
|
||||
@@ -34,6 +34,6 @@ func (e *Effect77) OnSkill() bool {
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
e.Ctx().Opp.Heal(e.Ctx().Our, &action.SelectSkillAction{}, decimal.NewFromInt(int64(e.Args()[0])))
|
||||
e.Ctx().Our.Heal(e.Ctx().Our, &action.SelectSkillAction{}, decimal.NewFromInt(int64(e.Args()[1])))
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ func (e *Effect93) OnSkill() bool {
|
||||
}
|
||||
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
|
||||
Type: info.DamageType.Fixed,
|
||||
Damage: decimal.NewFromInt(int64(e.Ctx().Opp.CurrentPet.Info.Hp)).Div(decimal.NewFromInt(int64(e.SideEffectArgs[0]))),
|
||||
Damage: decimal.NewFromInt(int64(e.SideEffectArgs[0])),
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -11,19 +11,20 @@ import (
|
||||
// -----------------------------------------------------------
|
||||
// 通用效果:满足特定条件时,附加n点固定伤害
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// 条件回调函数:判断对方是否满足触发条件(返回true则触发伤害)
|
||||
type conditionFunc func(e *EffectConditionalAddDamage) bool
|
||||
|
||||
// 全局映射:关联效果ID与对应的条件函数
|
||||
var conditionMap = make(map[int]conditionFunc)
|
||||
|
||||
type EffectConditionalAddDamage struct {
|
||||
node.EffectNode
|
||||
condition conditionFunc // 差异化:判断触发条件的函数
|
||||
node.EffectNode // 仅继承基础效果节点,不嵌入条件函数
|
||||
}
|
||||
|
||||
// 工厂函数:创建"条件附加伤害"效果实例,传入条件判断函数
|
||||
func newEffectConditionalAddDamage(cond conditionFunc) *EffectConditionalAddDamage {
|
||||
return &EffectConditionalAddDamage{
|
||||
condition: cond,
|
||||
}
|
||||
// 工厂函数:创建"条件附加伤害"效果实例(无需传入函数)
|
||||
func newEffectConditionalAddDamage() *EffectConditionalAddDamage {
|
||||
return &EffectConditionalAddDamage{}
|
||||
}
|
||||
|
||||
// 初始化:批量注册所有"条件附加伤害"类效果
|
||||
@@ -33,19 +34,20 @@ func init() {
|
||||
|
||||
// 批量注册:绑定效果ID与对应的条件函数(可扩展)
|
||||
func registerConditionalAddDamageEffects() {
|
||||
// 效果ID与条件函数的映射:
|
||||
// 133: 对方烧伤时附加伤害;134:对方冻伤时附加伤害;135:对方是X属性时附加伤害;136:对方处于异常状态时附加伤害
|
||||
// 效果ID与条件函数的映射
|
||||
effectMap := map[int]conditionFunc{
|
||||
133: conditionIsBurned, // Effect133:对方烧伤时
|
||||
141: conditionIsFrozen, // 新增:对方冻伤时
|
||||
135: conditionIsAbnormal, // 新增:对方是X属性时(示例,需根据实际属性枚举调整)
|
||||
130: conditionIsTypeX, // 新增:对方处于任意异常状态时
|
||||
167: conditionprop, //167 若对手处于能力下降状态则附加n点伤害
|
||||
130: conditionIsTypeX, // 对方是X属性时
|
||||
133: conditionIsBurned, // 对方烧伤时
|
||||
141: conditionIsFrozen, // 对方冻伤时
|
||||
|
||||
162: conditionIsAbnormal, // 对方处于任意异常状态时
|
||||
167: conditionPropDown, // 对方处于能力下降状态时
|
||||
}
|
||||
|
||||
// 循环注册所有效果
|
||||
// 注册到全局映射,并初始化效果
|
||||
for effectID, cond := range effectMap {
|
||||
input.InitEffect(input.EffectType.Skill, effectID, newEffectConditionalAddDamage(cond))
|
||||
conditionMap[effectID] = cond
|
||||
input.InitEffect(input.EffectType.Skill, effectID, newEffectConditionalAddDamage())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,12 +60,18 @@ func (e *EffectConditionalAddDamage) OnSkill() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// 2. 检查是否满足触发条件(调用差异化的条件函数)
|
||||
if !e.condition(e) {
|
||||
// 2. 获取当前效果ID对应的条件函数
|
||||
cond, ok := conditionMap[e.ID()-int(input.EffectType.Skill)]
|
||||
if !ok {
|
||||
return true // 无对应条件函数,不触发
|
||||
}
|
||||
|
||||
// 3. 检查是否满足触发条件
|
||||
if !cond(e) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 3. 附加固定伤害(伤害值从SideEffectArgs[0]获取,与原Effect133一致)
|
||||
// 4. 附加固定伤害(从SideEffectArgs[0]获取伤害值)
|
||||
damageValue := decimal.NewFromInt(int64(e.SideEffectArgs[0]))
|
||||
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
|
||||
Type: info.DamageType.Fixed,
|
||||
@@ -77,37 +85,33 @@ func (e *EffectConditionalAddDamage) OnSkill() bool {
|
||||
// 差异化条件函数的实现(对应不同效果的判断逻辑)
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// conditionIsBurned:判断对方是否处于烧伤状态(对应原Effect133)
|
||||
// conditionIsBurned:判断对方是否处于烧伤状态
|
||||
func conditionIsBurned(e *EffectConditionalAddDamage) bool {
|
||||
return e.Ctx().Opp.StatEffect_Exist(info.PetStatus.Burned)
|
||||
}
|
||||
|
||||
// conditionIsFrozen:判断对方是否处于冻伤状态(新增效果)
|
||||
// conditionIsFrozen:判断对方是否处于冻伤状态
|
||||
func conditionIsFrozen(e *EffectConditionalAddDamage) bool {
|
||||
return e.Ctx().Opp.StatEffect_Exist(info.PetStatus.Frozen)
|
||||
}
|
||||
|
||||
// conditionIsTypeX:判断对方是否为X属性(示例,需根据实际属性枚举调整)
|
||||
// 假设属性枚举为info.PetType,X属性为info.PetType.X
|
||||
// conditionIsTypeX:判断对方是否为X属性(需根据实际属性枚举调整)
|
||||
func conditionIsTypeX(e *EffectConditionalAddDamage) bool {
|
||||
return e.Ctx().Opp.CurrentPet.Gender == e.Args()[0]
|
||||
// 示例:假设Args[0]为目标属性值,判断对方属性是否匹配
|
||||
return e.Ctx().Opp.CurrentPet.PType == e.Args()[0]
|
||||
}
|
||||
|
||||
// conditionIsAbnormal:判断对方是否处于任意异常状态(新增效果)
|
||||
// 假设异常状态包含烧伤、冻伤、麻痹等,通过检查是否存在任意异常状态实现
|
||||
// conditionIsAbnormal:判断对方是否处于任意异常状态
|
||||
func conditionIsAbnormal(e *EffectConditionalAddDamage) bool {
|
||||
return e.Ctx().Opp.StatEffect_Exist_all()
|
||||
|
||||
}
|
||||
func conditionprop(e *EffectConditionalAddDamage) bool {
|
||||
|
||||
// conditionPropDown:判断对方是否处于能力下降状态
|
||||
func conditionPropDown(e *EffectConditionalAddDamage) bool {
|
||||
for _, v := range e.Ctx().Opp.Prop {
|
||||
|
||||
if v < 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
@@ -57,11 +57,11 @@ func init() {
|
||||
level int8
|
||||
opType info.EnumAbilityOpType
|
||||
}{
|
||||
{3, false, -1, info.AbilityOpType.RESET}, // 解除自身能力下降状态
|
||||
{33, true, 1, info.AbilityOpType.RESET}, // 消除对手能力提升状态
|
||||
{63, false, 0, info.AbilityOpType.AbilityOpBounceWeaken}, // 将能力下降反馈给对手
|
||||
{85, false, -1, info.AbilityOpType.AbilityOpStealStrengthen}, // 将对手提升效果转移到自己
|
||||
{143, true, 1, info.AbilityOpType.AbilityOpReverse}, // 反转对手能力提升为下降
|
||||
{3, false, -1, info.AbilityOpType.RESET}, // 解除自身能力下降状态
|
||||
{33, true, 1, info.AbilityOpType.RESET}, // 消除对手能力提升状态
|
||||
{63, false, 0, info.AbilityOpType.BounceWeaken}, // 将能力下降反馈给对手
|
||||
{85, false, -1, info.AbilityOpType.StealStrengthen}, // 将对手提升效果转移到自己
|
||||
{143, true, 1, info.AbilityOpType.Reverse}, // 反转对手能力提升为下降
|
||||
}
|
||||
|
||||
for _, e := range effects {
|
||||
|
||||
@@ -16,10 +16,10 @@ type BaseSataus struct {
|
||||
}
|
||||
|
||||
// /重写切换事件
|
||||
func (e *BaseSataus) Switch(*input.Input, info.AttackValue, *info.BattlePetEntity) bool {
|
||||
func (e *BaseSataus) Switch(in *input.Input, _ info.AttackValue, _ *info.BattlePetEntity) bool {
|
||||
|
||||
//状态如果是我方切换,那么就消除掉状态效果
|
||||
if e.Input == e.Ctx().Our {
|
||||
if in == e.Ctx().Our {
|
||||
//下场,执行消回合效果
|
||||
// e.ctx.Our.CancelAll()
|
||||
///我放下场
|
||||
@@ -91,7 +91,7 @@ type DrainedHP struct {
|
||||
|
||||
func (e *DrainedHP) Skill_Hit_Pre(a, b *action.SelectSkillAction) bool {
|
||||
|
||||
if gconv.Int(e.Input.CurrentPet.Type) == 1 {
|
||||
if gconv.Int(e.Ctx().Our.CurrentPet.Type) == 1 {
|
||||
return true
|
||||
}
|
||||
e.DrainHP.Skill_Hit_Pre(a, b) //先调用父类扣血
|
||||
|
||||
@@ -45,9 +45,9 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *info.Ski
|
||||
//技能miss+效果生效 这里属于强制改命中效果,但是正常来说,技能miss掉后效果也应该失效
|
||||
//技能失效+效果失效
|
||||
// 记录技能信息
|
||||
attacker.SkillID = uint32(a.ID) //获取技能ID
|
||||
if attacker.AttackTime > 0 { //如果命中
|
||||
|
||||
if attacker.AttackTime > 0 { //如果命中
|
||||
attacker.SkillID = uint32(a.ID) //获取技能ID
|
||||
attacker.CalculateCrit(defender, a) //暴击计算
|
||||
attacker.IsCritical = a.Crit
|
||||
|
||||
@@ -323,6 +323,8 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
||||
f.closefight = true
|
||||
// break
|
||||
}
|
||||
attacker.CanChange = true
|
||||
break
|
||||
}
|
||||
|
||||
if defender.CurrentPet.Info.Hp == 0 {
|
||||
|
||||
@@ -49,6 +49,15 @@ func CreateBattlePetEntity(info *model.PetInfo, rand *rand.Rand) *BattlePetEntit
|
||||
|
||||
}
|
||||
|
||||
ret.PType = 8
|
||||
for _, v := range xmlres.PetMAP {
|
||||
if v.ID == int(ret.Info.ID) {
|
||||
ret.PType = v.Type
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
|
||||
}
|
||||
@@ -89,22 +98,6 @@ func (u *BattlePetEntity) GetMaxHP() decimal.Decimal {
|
||||
}
|
||||
func (u *BattlePetEntity) Type() *element.ElementCombination {
|
||||
// 1. 遍历宠物配置,查找对应元素类型ID
|
||||
found := false
|
||||
if u.PType == 0 {
|
||||
|
||||
for _, v := range xmlres.PetMAP {
|
||||
if v.ID == int(u.Info.ID) {
|
||||
u.PType = v.Type
|
||||
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// 2. 未找到配置时,默认使用"普通(8)"
|
||||
if !found {
|
||||
u.PType = 8
|
||||
}
|
||||
|
||||
// 3. 从预加载的组合池中获取实例(无需创建,直接读取)
|
||||
combo, err := element.Calculator.GetCombination(u.PType)
|
||||
|
||||
@@ -154,6 +154,7 @@ func (s *SkillEntity) AttackTimeC(level int) {
|
||||
|
||||
if s.MustHit != 0 {
|
||||
s.AttackTime = 2
|
||||
return
|
||||
}
|
||||
|
||||
a := int64(s.GetAccuracy(level))
|
||||
|
||||
@@ -96,8 +96,8 @@ var AbilityOpType = enum.New[struct {
|
||||
COPY EnumAbilityOpType `enum:"3"` // 复制强化/弱化
|
||||
RESET EnumAbilityOpType `enum:"4"` // 能力重置
|
||||
|
||||
AbilityOpStealStrengthen EnumAbilityOpType `enum:"6"` // 吸取强化
|
||||
AbilityOpReverse EnumAbilityOpType `enum:"7"` // 反转强化/弱化
|
||||
StealStrengthen EnumAbilityOpType `enum:"6"` // 吸取强化
|
||||
Reverse EnumAbilityOpType `enum:"7"` // 反转强化/弱化
|
||||
|
||||
AbilityOpBounceWeaken EnumAbilityOpType `enum:"10"` // 弹弱(反弹弱化效果)
|
||||
BounceWeaken EnumAbilityOpType `enum:"10"` // 弹弱(反弹弱化效果)
|
||||
}]()
|
||||
|
||||
@@ -46,6 +46,7 @@ type S2C_NOTE_HANDLE_FIGHT_INVITE struct {
|
||||
type PVPinfo struct {
|
||||
PlayerID uint32
|
||||
Mode EnumBattleMode
|
||||
Status EnumBattleMode
|
||||
}
|
||||
|
||||
// FightPetInfo 战斗精灵信息结构体,FightPetInfo类
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"blazing/common/utils"
|
||||
"blazing/logic/service/fight/action"
|
||||
"blazing/logic/service/fight/info"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
@@ -186,148 +185,6 @@ func (our *Input) Damage(in *Input, sub *info.DamageZone) {
|
||||
|
||||
}
|
||||
|
||||
// 攻击,防御,特供,特防,速度,命中
|
||||
// 施加方,类型,等级,操作类别,是否成功
|
||||
func (our *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpType) (ret bool) {
|
||||
//in.Our = our //设置属性的角色是我方
|
||||
canuseskill := our.Exec(func(t Effect) bool { //这个是能否使用技能
|
||||
//结算状态
|
||||
return t.Prop_Befer(in, prop, level, ptype) //返回本身结算,如果false,说明不能使用技能了
|
||||
|
||||
})
|
||||
if !canuseskill {
|
||||
|
||||
return false
|
||||
}
|
||||
var newValue int8
|
||||
abfunc := func(prop, level int8, ptype info.EnumAbilityOpType) (ret bool) {
|
||||
|
||||
switch ptype {
|
||||
case info.AbilityOpType.ADD:
|
||||
newValue = utils.Min(our.AttackValue.Prop[prop]+int8(level), 6)
|
||||
|
||||
if newValue > our.AttackValue.Prop[prop] {
|
||||
fmt.Println("属性值会增加")
|
||||
return true
|
||||
} else {
|
||||
fmt.Println("属性值不会增加")
|
||||
return false
|
||||
}
|
||||
|
||||
case info.AbilityOpType.SUB:
|
||||
newValue = utils.Max(our.AttackValue.Prop[prop]+int8(level), -6)
|
||||
if newValue < our.AttackValue.Prop[prop] {
|
||||
fmt.Println("属性值会减少")
|
||||
return true
|
||||
} else {
|
||||
fmt.Println("属性值不会增加")
|
||||
return false
|
||||
}
|
||||
|
||||
case info.AbilityOpType.RESET:
|
||||
if level > 0 && our.AttackValue.Prop[prop] > 0 { //消强
|
||||
newValue = 0
|
||||
return true
|
||||
|
||||
}
|
||||
if level < 0 && our.AttackValue.Prop[prop] < 0 { //解弱
|
||||
newValue = 0
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
switch ptype {
|
||||
|
||||
case info.AbilityOpType.AbilityOpStealStrengthen:
|
||||
|
||||
temp := our.Opp.AttackValue.Prop[prop]
|
||||
|
||||
if temp <= 0 { //对方没有强化
|
||||
return false
|
||||
}
|
||||
if abfunc(prop, temp, info.AbilityOpType.ADD) { //把对面的强化等级添加自身
|
||||
our.AttackValue.Prop[prop] = newValue //成功把 强化更新
|
||||
our.Opp.SetProp(our, prop, 1, info.AbilityOpType.RESET) //吸取后消除对面强化
|
||||
|
||||
}
|
||||
|
||||
case info.AbilityOpType.AbilityOpReverse:
|
||||
temp := our.AttackValue.Prop[prop]
|
||||
|
||||
switch {
|
||||
|
||||
case level > 0: //反转强化
|
||||
if temp <= 0 { //没有强化
|
||||
return false
|
||||
}
|
||||
if abfunc(prop, temp*2, info.AbilityOpType.SUB) {
|
||||
our.AttackValue.Prop[prop] = newValue
|
||||
if temp == -our.AttackValue.Prop[prop] { //成功到对应弱化
|
||||
|
||||
return true
|
||||
} else {
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
} else { //自身免弱或已到-6
|
||||
|
||||
return false
|
||||
}
|
||||
default: //反转弱化
|
||||
if temp >= 0 { //没有弱化
|
||||
return false
|
||||
}
|
||||
if abfunc(prop, -temp*2, info.AbilityOpType.ADD) {
|
||||
our.AttackValue.Prop[prop] = newValue
|
||||
if temp == -our.AttackValue.Prop[prop] { //成功到对应强化
|
||||
|
||||
return true
|
||||
} else {
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
} else { //自身免弱或已到-6
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
case info.AbilityOpType.AbilityOpBounceWeaken:
|
||||
temp := our.AttackValue.Prop[prop]
|
||||
if temp >= 0 { //没有弱化
|
||||
return false
|
||||
}
|
||||
|
||||
if our.Opp.SetProp(our, prop, temp, info.AbilityOpType.SUB) {
|
||||
|
||||
our.SetProp(our, prop, -1, info.AbilityOpType.RESET) //消除自身弱化
|
||||
return true
|
||||
}
|
||||
case info.AbilityOpType.COPY:
|
||||
temp := our.Opp.AttackValue.Prop[prop]
|
||||
if temp >= 0 {
|
||||
our.SetProp(our, prop, temp, info.AbilityOpType.ADD)
|
||||
} else {
|
||||
our.SetProp(our, prop, -temp, info.AbilityOpType.SUB)
|
||||
}
|
||||
|
||||
default: //增加减少重置
|
||||
|
||||
if abfunc(prop, level, ptype) {
|
||||
// 执行赋值
|
||||
our.AttackValue.Prop[prop] = newValue
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
func (our *Input) GetAction(opp *Input) {
|
||||
// 获取己方当前宠物和对方当前宠物
|
||||
selfPet := our.FightC.GetCurrPET(our.Player)
|
||||
|
||||
173
logic/service/fight/input/prop.go
Normal file
173
logic/service/fight/input/prop.go
Normal file
@@ -0,0 +1,173 @@
|
||||
package input
|
||||
|
||||
import (
|
||||
"blazing/common/utils"
|
||||
"blazing/logic/service/fight/info"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// SetProp 处理属性操作(提升/下降/消除/偷取等)
|
||||
// our:当前执行操作的主体(操作发起方)
|
||||
// target:输入源(操作的源头输入对象,可能是我方或对方)
|
||||
// prop:属性类型
|
||||
// level:操作幅度(强化/弱化的程度)
|
||||
// opType:操作类型(明确区分提升/下降/消除等)
|
||||
func (our *Input) SetProp(target *Input, prop int8, level int8, opType info.EnumAbilityOpType) bool {
|
||||
// 前置检查:输入源是否允许该操作(基于输入源的状态)
|
||||
if !our.checkPreCondition(target, prop, level, opType) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 根据操作类型处理(明确区分不同操作的逻辑)
|
||||
switch opType {
|
||||
case info.AbilityOpType.ADD: // 能力提升(强化):仅正向增加,不处理负数
|
||||
return our.handleStrengthen(target, prop, level)
|
||||
case info.AbilityOpType.SUB: // 能力下降(弱化):仅负向减少,不处理正数
|
||||
return our.handleWeaken(target, prop, level)
|
||||
case info.AbilityOpType.RESET: // 能力消除(重置):清除强化或弱化,恢复0
|
||||
return our.handleReset(target, prop, level)
|
||||
case info.AbilityOpType.StealStrengthen: // 偷取强化:从对方输入源偷取到自身
|
||||
return our.handleStealStrengthen(target, prop)
|
||||
case info.AbilityOpType.Reverse: // 反转:强化转弱化,弱化转强化
|
||||
return our.handleReverse(target, prop, level)
|
||||
case info.AbilityOpType.BounceWeaken: // 反弹弱化:将输入源的弱化反弹给对方
|
||||
return our.handleBounceWeaken(target, prop)
|
||||
case info.AbilityOpType.COPY: // 复制:复制对方属性到输入源
|
||||
return our.handleCopy(target, prop)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// checkPreCondition 检查输入源是否允许操作(基于输入源的状态)
|
||||
func (our *Input) checkPreCondition(inputSource *Input, prop, level int8, opType info.EnumAbilityOpType) bool {
|
||||
return our.Exec(func(e Effect) bool {
|
||||
// 检查输入源是否允许该操作(e.Prop_Befer的参数是输入源)
|
||||
return e.Prop_Befer(inputSource, prop, level, opType)
|
||||
})
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// 1. 能力提升(强化):仅处理正向增加,上限6
|
||||
// ------------------------------
|
||||
func (our *Input) handleStrengthen(inputSource *Input, prop, level int8) bool {
|
||||
if level <= 0 {
|
||||
fmt.Printf("强化失败:幅度必须为正数(level=%d)\n", level)
|
||||
return false
|
||||
}
|
||||
current := inputSource.AttackValue.Prop[prop]
|
||||
newVal := utils.Min(current+level, 6) // 强化上限6
|
||||
if newVal == current {
|
||||
fmt.Printf("属性[%d]强化无变化(当前%d,已达上限6)\n", prop, current)
|
||||
return false
|
||||
}
|
||||
inputSource.AttackValue.Prop[prop] = newVal
|
||||
fmt.Printf("属性[%d]强化:%d → %d(+%d)\n", prop, current, newVal, level)
|
||||
return true
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// 2. 能力下降(弱化):仅处理负向减少,下限-6
|
||||
// ------------------------------
|
||||
func (our *Input) handleWeaken(inputSource *Input, prop, level int8) bool {
|
||||
if level >= 0 {
|
||||
fmt.Printf("弱化失败:幅度必须为负数(level=%d)\n", level)
|
||||
return false
|
||||
}
|
||||
current := inputSource.AttackValue.Prop[prop]
|
||||
newVal := utils.Max(current+level, -6) // 弱化下限-6
|
||||
if newVal == current {
|
||||
fmt.Printf("属性[%d]弱化无变化(当前%d,已达下限-6)\n", prop, current)
|
||||
return false
|
||||
}
|
||||
inputSource.AttackValue.Prop[prop] = newVal
|
||||
fmt.Printf("属性[%d]弱化:%d → %d(%d)\n", prop, current, newVal, level)
|
||||
return true
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// 3. 能力消除(重置):仅清除对应状态(强化/弱化),不影响正常状态
|
||||
// ------------------------------
|
||||
func (our *Input) handleReset(inputSource *Input, prop, level int8) bool {
|
||||
current := inputSource.AttackValue.Prop[prop]
|
||||
// 规则:level>0清除强化(current>0),level<0清除弱化(current<0),不处理正常状态(current=0)
|
||||
if (level > 0 && current <= 0) || (level < 0 && current >= 0) {
|
||||
fmt.Printf("重置失败:属性[%d]当前状态(%d)与操作(level=%d)不匹配\n", prop, current, level)
|
||||
return false
|
||||
}
|
||||
inputSource.AttackValue.Prop[prop] = 0
|
||||
fmt.Printf("属性[%d]重置:%d → 0(level=%d)\n", prop, current, level)
|
||||
return true
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// 4. 偷取强化:从对方输入源偷取强化到自身输入源
|
||||
// ------------------------------
|
||||
func (our *Input) handleStealStrengthen(inputSource *Input, prop int8) bool {
|
||||
// 对方输入源的强化值(必须为正)
|
||||
oppProp := our.Opp.AttackValue.Prop[prop]
|
||||
if oppProp <= 0 {
|
||||
fmt.Printf("偷取失败:对方属性[%d]无强化(%d)\n", prop, oppProp)
|
||||
return false
|
||||
}
|
||||
// 自身输入源增加偷取的强化值
|
||||
if !our.handleStrengthen(inputSource, prop, oppProp) {
|
||||
return false
|
||||
}
|
||||
// 清除对方输入源的强化(用level>0重置)
|
||||
our.Opp.SetProp(our.Opp, prop, 1, info.AbilityOpType.RESET)
|
||||
return true
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// 5. 反转:输入源的强化转弱化,或弱化转强化
|
||||
// ------------------------------
|
||||
func (our *Input) handleReverse(inputSource *Input, prop, level int8) bool {
|
||||
current := inputSource.AttackValue.Prop[prop]
|
||||
switch {
|
||||
case level > 0 && current > 0: // 强化转弱化(幅度为当前强化值的2倍)
|
||||
// 例:当前+2 → 弱化-4(level>0指定强化转弱化)
|
||||
return our.handleWeaken(inputSource, prop, -current*2)
|
||||
case level < 0 && current < 0: // 弱化转强化(幅度为当前弱化值的2倍)
|
||||
// 例:当前-2 → 强化+4(level<0指定弱化转强化)
|
||||
return our.handleStrengthen(inputSource, prop, -current*2)
|
||||
default:
|
||||
fmt.Printf("反转失败:当前值(%d)与操作方向(level=%d)不匹配\n", current, level)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// 6. 反弹弱化:将输入源的弱化反弹给对方,同时清除输入源的弱化
|
||||
// ------------------------------
|
||||
func (our *Input) handleBounceWeaken(inputSource *Input, prop int8) bool {
|
||||
// 输入源的弱化值(必须为负)
|
||||
currentWeak := inputSource.AttackValue.Prop[prop]
|
||||
if currentWeak >= 0 {
|
||||
fmt.Printf("反弹失败:输入源属性[%d]无弱化(%d)\n", prop, currentWeak)
|
||||
return false
|
||||
}
|
||||
// 反弹给对方:对方输入源承受相同弱化(用弱化操作)
|
||||
if !our.Opp.SetProp(our.Opp, prop, currentWeak, info.AbilityOpType.SUB) {
|
||||
return false
|
||||
}
|
||||
// 清除输入源的弱化(用level<0重置)
|
||||
return our.handleReset(inputSource, prop, -1)
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// 7. 复制:将对方属性复制到输入源(强化/弱化均复制)
|
||||
// ------------------------------
|
||||
func (our *Input) handleCopy(inputSource *Input, prop int8) bool {
|
||||
oppProp := our.Opp.AttackValue.Prop[prop]
|
||||
if oppProp == 0 {
|
||||
fmt.Printf("复制无变化:对方属性[%d]为0\n", prop)
|
||||
return true // 无变化也算成功
|
||||
}
|
||||
// 根据对方属性类型选择强化/弱化操作
|
||||
if oppProp > 0 {
|
||||
return our.handleStrengthen(inputSource, prop, oppProp) // 复制强化
|
||||
} else {
|
||||
return our.handleWeaken(inputSource, prop, oppProp) // 复制弱化(oppProp是负数)
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,16 @@ package player
|
||||
import (
|
||||
"blazing/logic/service/common"
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/space"
|
||||
)
|
||||
|
||||
// 邀请玩家加入战斗 邀请者,被邀请者,邀请模式
|
||||
func (lw *Player) InvitePlayerToBattle(pinfo *info.PVPinfo) {
|
||||
lw.PVPinfo = pinfo
|
||||
Mainplayer.Range(func(key uint32, value *Player) bool {
|
||||
func (lw *Player) InvitePlayerToBattle() {
|
||||
pinfo := lw.PVPinfo
|
||||
space.GetSpace(lw.Info.MapID).User.IterCb(func(key uint32, v common.PlayerI) {
|
||||
|
||||
if key == uint32(pinfo.PlayerID) {
|
||||
value := v.(*Player)
|
||||
if key == uint32(pinfo.PlayerID) { //说明这里是针对玩家邀请的
|
||||
|
||||
value.HavePVPinfo = append([]*Player{lw}, value.HavePVPinfo...)
|
||||
t1 := NewTomeeHeader(2501, value.Info.UserID)
|
||||
@@ -20,10 +22,9 @@ func (lw *Player) InvitePlayerToBattle(pinfo *info.PVPinfo) {
|
||||
Mode: pinfo.Mode,
|
||||
}
|
||||
value.SendPack(t1.Pack(&t))
|
||||
return false
|
||||
return
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
}
|
||||
@@ -31,24 +32,6 @@ func (lw *Player) InvitePlayerToBattle(pinfo *info.PVPinfo) {
|
||||
// 取消对战邀请
|
||||
func (lw *Player) CancelBattle() {
|
||||
|
||||
if lw.PVPinfo == nil {
|
||||
return
|
||||
}
|
||||
Mainplayer.Range(func(key uint32, value *Player) bool {
|
||||
|
||||
if key == uint32(lw.PVPinfo.PlayerID) {
|
||||
for idx, v := range value.HavePVPinfo {
|
||||
if v != nil && v.GetInfo().UserID == lw.PVPinfo.PlayerID {
|
||||
value.HavePVPinfo = append(value.HavePVPinfo[:idx], value.HavePVPinfo[idx+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
lw.PVPinfo = nil
|
||||
}
|
||||
|
||||
@@ -59,51 +42,80 @@ func (p *Player) SendLoadPercent(b info.LoadPercentOutboundInfo) {
|
||||
}
|
||||
|
||||
// 同意对战
|
||||
// AgreeBattle 处理战斗邀请响应(同意/拒绝)
|
||||
// 参数:
|
||||
//
|
||||
// userid:邀请者ID
|
||||
// flag:0-拒绝,1-同意
|
||||
// mode:战斗模式
|
||||
//
|
||||
// 返回:
|
||||
//
|
||||
// bool:是否成功(仅同意且符合条件时为true)
|
||||
// common.PlayerI:对应的邀请者玩家(成功时有效)
|
||||
func (lw *Player) AgreeBattle(userid, flag uint32, mode info.EnumBattleMode) (bool, common.PlayerI) {
|
||||
// 处理完毕后清空收到的邀请列表(原defer逻辑保留)
|
||||
defer func() {
|
||||
lw.HavePVPinfo = make([]*Player, 0)
|
||||
}()
|
||||
|
||||
defer func(p *Player) {
|
||||
p.HavePVPinfo = make([]*Player, 0)
|
||||
|
||||
}(lw) //删除对方的邀请信息
|
||||
|
||||
for _, v := range lw.HavePVPinfo {
|
||||
if v == nil || v.Info.UserID != userid || v.PVPinfo == nil {
|
||||
continue
|
||||
|
||||
}
|
||||
t1 := NewTomeeHeader(2502, v.Info.UserID)
|
||||
ret := &info.S2C_NOTE_HANDLE_FIGHT_INVITE{
|
||||
UserID: lw.Info.UserID,
|
||||
Nick: lw.Info.Nick,
|
||||
}
|
||||
|
||||
if flag == 0 { //拒绝对战
|
||||
|
||||
v.SendPack(t1.Pack(ret))
|
||||
return false, nil
|
||||
}
|
||||
if !lw.IsLogin { //玩家未登录
|
||||
ret.Result = 4
|
||||
v.SendPack(t1.Pack(ret))
|
||||
return false, nil
|
||||
}
|
||||
if v.Info.UserID == userid && v.PVPinfo.Mode == mode { //成功找到,同意对战
|
||||
if lw.CanFight() &&v.CanFight(){
|
||||
ret.Result = 1
|
||||
|
||||
v.SendPack(t1.Pack(ret))
|
||||
return true, v
|
||||
|
||||
} else {
|
||||
ret.Result = 3
|
||||
v.SendPack(t1.Pack(ret))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// 遍历收到的邀请,寻找目标邀请者
|
||||
var inviter *Player
|
||||
for _, p := range lw.HavePVPinfo {
|
||||
if p == nil || p.Info.UserID != userid {
|
||||
continue // 跳过空指针或非目标邀请者
|
||||
}
|
||||
inviter = p
|
||||
break // 找到目标后退出循环
|
||||
}
|
||||
|
||||
// 未找到对应的邀请者(如邀请已过期、不存在)
|
||||
if inviter == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
} //如果对方掉线
|
||||
return false, nil
|
||||
// 构建响应消息(统一创建,避免重复代码)
|
||||
respHeader := NewTomeeHeader(2502, inviter.Info.UserID)
|
||||
resp := &info.S2C_NOTE_HANDLE_FIGHT_INVITE{
|
||||
UserID: lw.Info.UserID,
|
||||
Nick: lw.Info.Nick,
|
||||
}
|
||||
|
||||
// 检查邀请者的邀请是否有效(对方已取消邀请)
|
||||
if inviter.PVPinfo == nil {
|
||||
resp.Result = 4 // 邀请已取消
|
||||
inviter.SendPack(respHeader.Pack(resp))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// 检查战斗模式是否匹配
|
||||
if inviter.PVPinfo.Mode != mode {
|
||||
return false, nil // 模式不匹配,不响应(或根据业务加错误码)
|
||||
}
|
||||
|
||||
// 处理拒绝逻辑
|
||||
if flag == 0 {
|
||||
resp.Result = 0 // 拒绝邀请
|
||||
inviter.SendPack(respHeader.Pack(resp))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// 处理同意逻辑:检查自身状态
|
||||
if !lw.IsLogin {
|
||||
resp.Result = 4 // 玩家未登录(复用原错误码)
|
||||
inviter.SendPack(respHeader.Pack(resp))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// 检查双方是否可战斗
|
||||
if !lw.CanFight() || !inviter.CanFight() {
|
||||
resp.Result = 3 // 不可战斗(如正在战斗中)
|
||||
inviter.SendPack(respHeader.Pack(resp))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// 所有条件满足,同意战斗
|
||||
resp.Result = 1 // 成功同意
|
||||
inviter.SendPack(respHeader.Pack(resp))
|
||||
return true, inviter
|
||||
}
|
||||
|
||||
@@ -27,19 +27,6 @@ func NewSpace() *Space {
|
||||
}
|
||||
}
|
||||
|
||||
// // Range 遍历所有玩家并执行回调函数
|
||||
// // 读操作使用RLock,遍历过程中不会阻塞其他读操作
|
||||
// func (m *Space) Range(f func(playerID uint32, player common.PlayerI) bool) {
|
||||
// m.mu.RLock()
|
||||
// defer m.mu.RUnlock()
|
||||
// for id, player := range m.User {
|
||||
// // 若回调返回false,则停止遍历
|
||||
// if !f(id, player) {
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// 获取星球
|
||||
func GetSpace(id uint32) *Space {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user