diff --git a/common/socket/errorcode/error.go b/common/socket/errorcode/error.go index 7cce80868..ac0f491d1 100644 --- a/common/socket/errorcode/error.go +++ b/common/socket/errorcode/error.go @@ -301,10 +301,10 @@ var ErrorCodes = enum.New[struct { ErrPermanentBanCheatTool ErrorCode `enum:"100401"` // 由于使用外挂,你的号码被24小时封停 Err24hBanCheatTool ErrorCode `enum:"100402"` - // 由于使用外挂,你的号码被7天封停 - Err7dBanCheatTool ErrorCode `enum:"100403"` - // 由于使用外挂,你的号码被14天封停 - Err14dBanCheatTool ErrorCode `enum:"100404"` + // // 由于使用外挂,你的号码被7天封停 + // Err7dBanCheatTool ErrorCode `enum:"100403"` + // // 由于使用外挂,你的号码被14天封停 + // Err14dBanCheatTool ErrorCode `enum:"100404"` // 由于强制改名,你的号码被踢下线 ErrKickedForNameChange ErrorCode `enum:"100501"` // 分配器中经验值不够 diff --git a/logic/controller/fight_leitai.go b/logic/controller/fight_leitai.go index d5a2c0103..0b0302858 100644 --- a/logic/controller/fight_leitai.go +++ b/logic/controller/fight_leitai.go @@ -15,7 +15,7 @@ import ( // 前端到后端无数据内容 空包 // 后端到前端无数据内容 空包 // 都需要通过2419包广播更新擂台状态 -func (h Controller) ARENA_SET_OWENR(data *fight.ARENA_SET_OWENR, c *player.Player) (result *space.ARENA, err errorcode.ErrorCode) { +func (h Controller) ARENA_SET_OWENR(data *fight.ARENA_SET_OWENR, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { if atomic.CompareAndSwapUint32(&c.GetSpace().Owner.Flag, 0, 1) { @@ -23,8 +23,9 @@ func (h Controller) ARENA_SET_OWENR(data *fight.ARENA_SET_OWENR, c *player.Playe c.GetSpace().Owner.Nick = c.GetInfo().Nick c.GetSpace().ARENA_Player = c //添加用户 - c.GetSpace().Broadcast(c, 2419, &c.GetSpace().Owner) - return &c.GetSpace().Owner, 0 + c.GetSpace().Broadcast(c, 2419, c.GetSpace().Owner) + c.SendPackCmd(2419, c.GetSpace().Owner) + return } return nil, errorcode.ErrorCodes.ErrChampionExists @@ -36,29 +37,29 @@ func (h Controller) ARENA_SET_OWENR(data *fight.ARENA_SET_OWENR, c *player.Playe // 后端到前端无数据内容 空包 // 还是后端主动发送2503的包给双方前端后 等待前端加载完毕 主动发送2404包通知后端开始战斗 // 并不会通知对方是否接受挑战。只要有人挑战就直接进入对战 -func (h Controller) ARENA_FIGHT_OWENR(data *fight.ARENA_FIGHT_OWENR, c *player.Player) (result *space.ARENA, err errorcode.ErrorCode) { - s := c.GetSpace() +func (h Controller) ARENA_FIGHT_OWENR(data *fight.ARENA_FIGHT_OWENR, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { //原子操作,修改擂台状态 - if atomic.CompareAndSwapUint32(&s.Owner.Flag, 1, 2) { + if atomic.CompareAndSwapUint32(&c.GetSpace().Owner.Flag, 1, 2) { //成功发起擂台挑战后才修改我放状态 c.Fightinfo.Mode = info.BattleMode.SINGLE_MODE c.Fightinfo.Status = info.BattleStatus.FIGHT_WITH_PLAYER - _, err = fight.NewFight(c, s.ARENA_Player, func(foi *info.FightOverInfo) { //我方邀请擂主挑战,我方先手 + _, err = fight.NewFight(c, c.GetSpace().ARENA_Player, func(foi *info.FightOverInfo) { //我方邀请擂主挑战,我方先手 }) ///开始对战,房主方以及被邀请方 if err <= 0 { //发起战斗成功 - atomic.StoreUint32(&s.Owner.ChallengerID, c.GetInfo().UserID) //传回的指针赋值给ID - + atomic.StoreUint32(&c.GetSpace().Owner.ChallengerID, c.GetInfo().UserID) //传回的指针赋值给ID + c.GetSpace().Broadcast(c, 2419, &c.GetSpace().Owner) + c.SendPackCmd(2419, &c.GetSpace().Owner) } else { //发起失败,改回1 - atomic.StoreUint32(&s.Owner.Flag, 1) + atomic.StoreUint32(&c.GetSpace().Owner.Flag, 1) + } - s.Broadcast(c, 2419, &s.Owner) - return &s.Owner, 0 + return } return nil, errorcode.ErrorCodes.ErrChampionExists @@ -69,7 +70,8 @@ func (h Controller) ARENA_FIGHT_OWENR(data *fight.ARENA_FIGHT_OWENR, c *player.P // 后端到前端 func (h Controller) ARENA_GET_INFO(data *fight.ARENA_GET_INFO, c *player.Player) (result *space.ARENA, err errorcode.ErrorCode) { - return &space.GetSpace(c.Info.MapID).Owner, 0 + result = &c.GetSpace().Owner + return } // public static const ARENA_UPFIGHT:uint = 2420; @@ -77,14 +79,16 @@ func (h Controller) ARENA_GET_INFO(data *fight.ARENA_GET_INFO, c *player.Player) // 前端到后端无数据内容 // 后端到前端无数据内容 // 都需要通过2419包广播更新擂台状态 -func (h Controller) ARENA_UPFIGHT(data *fight.ARENA_UPFIGHT, c *player.Player) (result *space.ARENA, err errorcode.ErrorCode) { +func (h Controller) ARENA_UPFIGHT(data *fight.ARENA_UPFIGHT, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { //原子操作,修改擂台状态 - s := c.GetSpace() - if atomic.CompareAndSwapUint32(&s.Owner.UserID, c.GetInfo().UserID, 0) { - s.ARENA_Player = nil - s.Broadcast(c, 2419, &s.Owner) - return &s.Owner, 0 + if atomic.CompareAndSwapUint32(&c.GetSpace().Owner.UserID, c.GetInfo().UserID, 0) { + c.GetSpace().ARENA_Player = nil + c.GetSpace().Owner.Reset() + + c.GetSpace().Broadcast(c, 2419, &c.GetSpace().Owner) + c.SendPackCmd(2419, &c.GetSpace().Owner) + return nil, -1 } return nil, errorcode.ErrorCodes.ErrChampionCannotCancel @@ -96,14 +100,14 @@ func (h Controller) ARENA_UPFIGHT(data *fight.ARENA_UPFIGHT, c *player.Player) ( // 后端到前端无数据内容 // public static const ARENA_OWENR_OUT:uint = 2423; // 此包不清楚具体怎么触发 但已知此包为后端主动发送。不清楚什么情况下回用到 -func (h Controller) ARENA_OWENR_ACCE(data *fight.ARENA_OWENR_ACCE, c *player.Player) (result *space.ARENA, err errorcode.ErrorCode) { +func (h Controller) ARENA_OWENR_ACCE(data *fight.ARENA_OWENR_ACCE, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { s := c.GetSpace() if atomic.LoadUint32(&s.Owner.UserID) != c.GetInfo().UserID && c.GetInfo().UserID != atomic.LoadUint32(&s.Owner.ChallengerID) { //说明已经有人了 - return nil, errorcode.ErrorCodes.Err24hBanCheatTool + return nil, -1 } if c.GetInfo().UserID == atomic.LoadUint32(&s.Owner.UserID) { - + c.Info.MaxArenaWins += 1 s.Owner.HostWins += 1 //连胜+1 } else { @@ -116,5 +120,7 @@ func (h Controller) ARENA_OWENR_ACCE(data *fight.ARENA_OWENR_ACCE, c *player.Pla atomic.StoreUint32(&s.Owner.Flag, 1) s.Broadcast(c, 2419, &s.Owner) - return &s.Owner, 0 + c.SendPackCmd(2419, &c.GetSpace().Owner) + + return nil, -1 } diff --git a/logic/controller/fight_pvp_king.go b/logic/controller/fight_pvp_king.go index 531501c6d..dc290fa8f 100644 --- a/logic/controller/fight_pvp_king.go +++ b/logic/controller/fight_pvp_king.go @@ -14,9 +14,15 @@ import ( func (h Controller) PET_MELEE(data *fight.StartPetWarInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { c.Fightinfo.Mode = info.BattleMode.PET_MELEE + c.Fightinfo.Status = info.BattleStatus.FIGHT_WITH_PLAYER c.Fightinfo.PlayerID = 0 - c.JoinFight(func(p common.PlayerI) bool { + err = c.JoinFight(func(p common.PlayerI) bool { fight.NewFight(p, c, func(foi *info.FightOverInfo) { + if foi.Reason == 0 && foi.WinnerId == c.GetInfo().UserID { //我放获胜 + + c.Info.MessWin += 1 + + } }) ///开始对战,房主方以及被邀请方 @@ -28,16 +34,20 @@ func (h Controller) PET_MELEE(data *fight.StartPetWarInboundInfo, c *player.Play func (h Controller) PET_King(data *fight.PetKingJoinInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { c.Fightinfo.Status = info.BattleStatus.FIGHT_WITH_PLAYER - + c.Fightinfo.PlayerID = 0 switch data.Type { case 5: c.Fightinfo.Mode = info.BattleMode.SINGLE_MODE case 6: c.Fightinfo.Mode = info.BattleMode.MULTI_MODE } - c.JoinFight(func(p common.PlayerI) bool { + err = c.JoinFight(func(p common.PlayerI) bool { fight.NewFight(p, c, func(foi *info.FightOverInfo) { + if foi.Reason == 0 && foi.WinnerId == c.GetInfo().UserID { //我放获胜 + c.Info.MonKingWin += 1 + + } }) ///开始对战,房主方以及被邀请方 return true diff --git a/logic/controller/fight_pvp_withplayer.go b/logic/controller/fight_pvp_withplayer.go index 1805d9083..f36b9a8e0 100644 --- a/logic/controller/fight_pvp_withplayer.go +++ b/logic/controller/fight_pvp_withplayer.go @@ -17,8 +17,10 @@ func (h Controller) OnPlayerHandleFightInvite(data *fight.HandleFightInviteInbou return nil, errorcode.ErrorCodes.ErrInBattle } - c.Fightinfo.PlayerID = data.UserID + c.Fightinfo.PlayerID = c.Info.UserID c.Fightinfo.Mode = data.Mode + c.Fightinfo.Status = 1 + c.Fightinfo.Type = 0 err = c.AgreeBattle(data.UserID, data.Flag, func(p common.PlayerI) bool { _, err = fight.NewFight(p, c, func(foi *info.FightOverInfo) { @@ -34,12 +36,14 @@ func (h Controller) OnPlayerInviteOtherFight(data *fight.InviteToFightInboundInf //进入邀请,以及确认对战模式 - if !atomic.CompareAndSwapUint32(&c.Fightinfo.PlayerID, 0, data.UserID) { //邀请前提是自己没邀请别人 - return nil, errorcode.ErrorCodes.ErrCannotPerformAction + // if !atomic.CompareAndSwapUint32(&c.Fightinfo.PlayerID, 0, data.UserID) { //邀请前提是自己没邀请别人 + // return nil, errorcode.ErrorCodes.ErrCannotPerformAction - } + // } + c.Fightinfo.PlayerID = data.UserID c.Fightinfo.Mode = data.Mode - + c.Fightinfo.Status = 1 + c.Fightinfo.Type = 0 c.InvitePlayerToBattle() return nil, 0 @@ -50,7 +54,7 @@ func (h Controller) OnPlayerCanceledOtherInviteFight(data *fight.InviteFightCanc if atomic.LoadUint32(&c.Fightinfo.Status) != 0 { //如果没有战斗状态,则不做任何处理 atomic.StoreUint32(&c.Fightinfo.Status, 0) //设置状态为0 - + return nil, 0 } //否则报错 return nil, errorcode.ErrorCodes.ErrCannotCancelBattle diff --git a/logic/controller/login.go b/logic/controller/login.go index d0f67afaa..653c99c27 100644 --- a/logic/controller/login.go +++ b/logic/controller/login.go @@ -64,7 +64,7 @@ func (h *Controller) Login(data *user.MAIN_LOGIN_IN, c gnet.Conn) (result *user. } t.Info.UserID = data.Head.UserID t.Logintime = uint32(time.Now().Unix()) //保存时间戳 - t.Changemap = true + cool.Loger.Info(context.Background(), "用户上次重置日期", t.Info.LastResetTime.String()) if !IsToday(t.Info.LastResetTime) { //判断是否是今天 t.Info.LastResetTime = gtime.Now().Time diff --git a/logic/controller/map.go b/logic/controller/map.go index 9ef7646a7..7b1b80845 100644 --- a/logic/controller/map.go +++ b/logic/controller/map.go @@ -2,6 +2,7 @@ package controller import ( "blazing/common/socket/errorcode" + "sync/atomic" "blazing/logic/service/maphot" "blazing/logic/service/maps" @@ -34,24 +35,25 @@ func (h Controller) MapHot(data *maphot.InInfo, c *player.Player) (result *mapho return } func (h *Controller) MapLeave(data *maps.LeaveMapInboundInfo, c *player.Player) (result *info.LeaveMapOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的 - //result = &maps.LeaveMapOutboundInfo{UserID: c.GetUserID()} - c.Canmon = false - c.Changemap = true //可以刷怪 - //data.Broadcast(c.Info.MapID, info.LeaveMapOutboundInfo{UserID: c.Info.UserID}) //同步广播 + atomic.StoreUint32(&c.Canmon, 0) + //data.Broadcast(c.Info.MapID, info.LeaveMapOutboundInfo{UserID: c.Info.UserID}) //同步广播 + result = &info.LeaveMapOutboundInfo{ + UserID: c.Info.UserID, + } defer c.GetSpace().LeaveMap(c) //玩家离开地图 // 如果有正在运行的刷怪协程,发送停止信号 //c.Info.MapID = 0 // 重置当前地图 - return &info.LeaveMapOutboundInfo{UserID: c.Info.UserID}, 0 + return } func (h *Controller) MapList(data *maps.ListMapPlayerInboundInfo, c *player.Player) (result *info.ListMapPlayerOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的 result = &info.ListMapPlayerOutboundInfo{ Player: c.GetSpace().GetInfo(), } + atomic.StoreUint32(&c.Canmon, 2) - c.Canmon = true //可以刷怪 return } diff --git a/logic/controller/nono.go b/logic/controller/nono.go index ad8c2fc89..865388483 100644 --- a/logic/controller/nono.go +++ b/logic/controller/nono.go @@ -13,12 +13,12 @@ func (h *Controller) NonoFollowOrHome(data *nono.NonoFollowOrHomeInInfo, c *play c.Info.NONO.Flag = data.Flag result = &nono.NonoFollowOutInfo{ - UserID: data.Head.UserID, + UserID: data.Head.UserID, SuperStage: data.Flag, - Flag: data.Flag, - Nick: "", - Color: 0, - Power: 0, + Flag: data.Flag, + Nick: "", + Color: 0, + Power: 0, } return @@ -44,14 +44,17 @@ func (h *Controller) SwitchFlying(data *nono.SwitchFlyingInboundInfo, c *player. result = &nono.SwitchFlyingOutboundInfo{ UserId: data.Head.UserID, - Type: data.Type, + Type: data.Type, } + c.GetSpace().Broadcast(c, data.Head.CMD, result) return } func (h *Controller) PlayerPetCure(data *nono.PetCureInboundInfo, c *player.Player) (result *nono.PetCureOutboundEmpty, err errorcode.ErrorCode) { //这个时候player应该是空的 - + if c.GetSpace().Owner.UserID == c.Info.UserID { + return result, errorcode.ErrorCodes.ErrChampionCannotHeal + } for i := 0; i < len(c.Info.PetList); i++ { c.Info.PetList[i].Cure() diff --git a/logic/controller/pet.go b/logic/controller/pet.go index 3a889aaa4..225c574f1 100644 --- a/logic/controller/pet.go +++ b/logic/controller/pet.go @@ -63,9 +63,13 @@ func (h *Controller) PetRelease( err errorcode.ErrorCode) { //这个时候player应该是空的 //放入背包=数据库置1+添加到背包+pet release发包 仓库=数据库置0+移除背包 设置首发等于取到首发精灵后重新排序 //这里只修改,因为添加和移除背包在宠物获取时已经做了 + result = &pet.PetReleaseOutboundInfo{} result.Flag = uint32(data.Flag) - + //擂台住不能换精灵 + if c.GetSpace().Owner.UserID == c.Info.UserID { + return result, errorcode.ErrorCodes.ErrChampionCannotSwitch + } switch data.Flag { case 0: var temp []model.PetInfo @@ -131,7 +135,9 @@ func (h *Controller) PlayerShowPet( } func (h *Controller) PetOneCure( data *pet.PetOneCureInboundInfo, c *player.Player) (result *pet.PetOneCureOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的 - + if c.GetSpace().Owner.UserID == c.Info.UserID { + return result, errorcode.ErrorCodes.ErrChampionCannotHeal + } _, onpet, ok := utils.FindWithIndex(c.Info.PetList, func(item model.PetInfo) bool { return item.CatchTime == data.CatchTime }) diff --git a/logic/controller/user.go b/logic/controller/user.go index 849424105..8c6e238f7 100644 --- a/logic/controller/user.go +++ b/logic/controller/user.go @@ -98,6 +98,24 @@ func (h Controller) ChangeNONOColor(data *user.ChangeNONOColorInboundInfo, c *pl Sataus: c.Info.UserID, Color: c.Info.Color, } - - return result, 0 + c.GetSpace().Broadcast(c, data.Head.CMD, result) + return +} +func (h Controller) DANCE_ACTION(data *user.C2SDanceAction, c *player.Player) (result *user.S2CDanceAction, err errorcode.ErrorCode) { + + result = &user.S2CDanceAction{ + Type: data.Type, + UserID: c.Info.UserID, + } + c.GetSpace().Broadcast(c, data.Head.CMD, result) + return +} +func (h Controller) PEOPLE_TRANSFROM(data *user.C2SPEOPLE_TRANSFROM, c *player.Player) (result *user.S2CPEOPLE_TRANSFROM, err errorcode.ErrorCode) { + + result = &user.S2CPEOPLE_TRANSFROM{ + SuitID: data.SuitID, + UserID: c.Info.UserID, + } + c.GetSpace().Broadcast(c, data.Head.CMD, result) + return } diff --git a/logic/go.mod b/logic/go.mod index 04950ed87..3c1461d6b 100644 --- a/logic/go.mod +++ b/logic/go.mod @@ -39,7 +39,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/mhmtszr/concurrent-swiss-map v1.0.9 // indirect + github.com/mhmtszr/concurrent-swiss-map v1.0.9 github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/redis/go-redis/v9 v9.5.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect diff --git a/logic/service/common/playeri.go b/logic/service/common/playeri.go index c0aba00b2..823bc63cc 100644 --- a/logic/service/common/playeri.go +++ b/logic/service/common/playeri.go @@ -15,6 +15,6 @@ type PlayerI interface { InvitePlayer(PlayerI) SetFightC(FightI) QuitFight() - + CanFight() bool SendPackCmd(uint32, any) } diff --git a/logic/service/fight/action.go b/logic/service/fight/action.go index e0a2a7fd0..af560e485 100644 --- a/logic/service/fight/action.go +++ b/logic/service/fight/action.go @@ -221,8 +221,6 @@ func (f *FightC) startBattle(startInfo info.FightStartOutboundInfo) { ff.Player.SendPackCmd(2504, &startInfo) }) - // 标记战斗已启动(原注释逻辑) - // f.running = true } var Fightpool *ants.Pool diff --git a/logic/service/fight/boss/NewSeIdx_1.go b/logic/service/fight/boss/NewSeIdx_1.go index 32662c2d6..e4d0904e6 100644 --- a/logic/service/fight/boss/NewSeIdx_1.go +++ b/logic/service/fight/boss/NewSeIdx_1.go @@ -9,8 +9,8 @@ import ( // 基类特性 type NewSel0 struct { node.EffectNode - Catchtime int //保存精灵的唯一指令,保证在上场时候正确注入 - Hide bool //是否隐藏 ,所属精灵下场后特性就应该消失 + Catchtime int //保存精灵的唯一指令,保证在上场时候正确注入 + //Hide bool //是否隐藏 ,所属精灵下场后特性就应该消失 //??如果2只精灵一个特性,怎么办,每次切精灵注入特性 } diff --git a/logic/service/fight/effect/effect_130.go b/logic/service/fight/effect/effect_130.go new file mode 100644 index 000000000..425e903f3 --- /dev/null +++ b/logic/service/fight/effect/effect_130.go @@ -0,0 +1,39 @@ +package effect + +import ( + "blazing/logic/service/fight/info" + "blazing/logic/service/fight/input" + "blazing/logic/service/fight/node" + + "github.com/shopspring/decimal" +) + +type Effect130 struct { + node.EffectNode // 仅继承基础效果节点,不嵌入条件函数 +} + +// ----------------------------------------------------------- +// 核心共性逻辑:命中且满足条件时,附加固定伤害 +// ----------------------------------------------------------- +func (e *Effect130) OnSkill() bool { + // 1. 命中判定失败,不触发 + if !e.Hit() { + return true + } + + if e.Ctx().Opp.CurrentPet.PetInfo.Gender == e.Args()[0] { + return true + } + // 4. 附加固定伤害(从SideEffectArgs[0]获取伤害值) + damageValue := decimal.NewFromInt(int64(e.SideEffectArgs[1])) + e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{ + Type: info.DamageType.Fixed, + Damage: damageValue, + }) + + return true +} +func init() { + input.InitEffect(input.EffectType.Skill, 130, &Effect130{}) + +} diff --git a/logic/service/fight/effect/effect_180.go b/logic/service/fight/effect/effect_180.go new file mode 100644 index 000000000..5d2c815b7 --- /dev/null +++ b/logic/service/fight/effect/effect_180.go @@ -0,0 +1,29 @@ +package effect + +import ( + "blazing/logic/service/fight/input" + "blazing/logic/service/fight/node" +) + +/** + * 消除对手回合类效果 + */ +type Effect180 struct { + node.EffectNode +} + +func init() { + ret := &Effect180{} + + input.InitEffect(input.EffectType.Skill, 180, ret) + +} + +// 命中之后 +func (e *Effect180) OnSkill() bool { + if !e.Hit() { + return true + } + e.Ctx().Opp.CancelTurn(e.Ctx().Our) + return true +} diff --git a/logic/service/fight/effect/effect_195.go b/logic/service/fight/effect/effect_195.go new file mode 100644 index 000000000..8c73e7c7c --- /dev/null +++ b/logic/service/fight/effect/effect_195.go @@ -0,0 +1,36 @@ +package effect + +import ( + "blazing/common/utils" + "blazing/logic/service/fight/input" + "blazing/logic/service/fight/node" +) + +/** + * 无视对手双防能力提升状态 + */ +type Effect195 struct { + node.EffectNode +} + +func init() { + ret := &Effect195{} + + input.InitEffect(input.EffectType.Skill, 195, ret) + +} + +// 命中之后 +func (e *Effect195) OnSkill() bool { + if !e.Hit() { + return true + } + e.Ctx().Opp.CancelTurn(e.Ctx().Our) + return true +} +func (e *Effect195) Skill_Hit() bool { + + e.Ctx().Opp.Prop[1] = utils.Min(e.Ctx().Opp.Prop[1], 0) + e.Ctx().Opp.Prop[3] = utils.Min(e.Ctx().Opp.Prop[3], 0) + return true +} diff --git a/logic/service/fight/effect/effect_45.go b/logic/service/fight/effect/effect_45.go index 813ea59a9..5b1863629 100644 --- a/logic/service/fight/effect/effect_45.go +++ b/logic/service/fight/effect/effect_45.go @@ -43,7 +43,7 @@ func (e *Effect45) SetArgs(t *input.Input, a ...int) { func (e *Effect45) Alive(t ...bool) bool { - if !e.GetBool(t...) { //说明到了回合结束取消节点,那么就将变化过的属性变化回来 + if !e.GetBool(t...) && e.Hit() { //说明到了回合结束取消节点,那么就将变化过的属性变化回来 //还原属性 e.Ctx().Our.CurrentPet.Info.Prop[1] = e.oldtype } diff --git a/logic/service/fight/effect/effect_478.go b/logic/service/fight/effect/effect_478.go new file mode 100644 index 000000000..8c3466e88 --- /dev/null +++ b/logic/service/fight/effect/effect_478.go @@ -0,0 +1,51 @@ +package effect + +import ( + "blazing/logic/service/fight/info" + "blazing/logic/service/fight/input" + "blazing/logic/service/fight/node" +) + +/** + * n回合内令对手使用的属性技能无效 + */ +type Effect478 struct { + node.EffectNode + can bool +} + +func init() { + ret := &Effect478{} + + input.InitEffect(input.EffectType.Skill, 478, ret) + +} + +// 命中之后 +func (e *Effect478) OnSkill() bool { + if !e.Hit() { + return true + } + e.can = true + return true +} + +func (e *Effect478) Skill_Hit_ex() bool { + if !e.Hit() { + return true + } + if !e.can { + return true + } + if e.Ctx().SkillEntity.Category() != info.Category.STATUS { + return true + } + e.Ctx().Opp.EffectCache = make([]input.Effect, 0) + return true +} +func (e *Effect478) SetArgs(t *input.Input, a ...int) { + + e.EffectNode.SetArgs(t, a...) + e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0]) + +} diff --git a/logic/service/fight/effect/effect_51.go b/logic/service/fight/effect/effect_51.go index 9e3ca6f35..0d9417474 100644 --- a/logic/service/fight/effect/effect_51.go +++ b/logic/service/fight/effect/effect_51.go @@ -34,7 +34,7 @@ func (e *Effect51) SetArgs(t *input.Input, a ...int) { func (e *Effect51) Alive(t ...bool) bool { - if !e.GetBool(t...) { //说明到了回合结束取消节点,那么就将变化过的属性变化回来 + if !e.GetBool(t...) && e.Hit() { //说明到了回合结束取消节点,那么就将变化过的属性变化回来 //还原属性 e.Ctx().Our.CurrentPet.Info.Prop[0] = e.oldtype } diff --git a/logic/service/fight/effect/effect_55.go b/logic/service/fight/effect/effect_55.go index 446201649..d72a9d7e3 100644 --- a/logic/service/fight/effect/effect_55.go +++ b/logic/service/fight/effect/effect_55.go @@ -32,7 +32,7 @@ func (e *Effect55) SetArgs(t *input.Input, a ...int) { func (e *Effect55) Alive(t ...bool) bool { - if !e.GetBool(t...) { //说明到了回合结束取消节点,那么就将变化过的属性变化回来 + if !e.GetBool(t...) && e.Hit() { //说明到了回合结束取消节点,那么就将变化过的属性变化回来 //还原属性 e.Ctx().Our.CurrentPet.PetInfo.Type, e.Ctx().Opp.CurrentPet.PetInfo.Type = e.Ctx().Opp.CurrentPet.PetInfo.Type, e.Ctx().Our.CurrentPet.PetInfo.Type } diff --git a/logic/service/fight/effect/effect_56.go b/logic/service/fight/effect/effect_56.go index 8320ed637..f311fb7a4 100644 --- a/logic/service/fight/effect/effect_56.go +++ b/logic/service/fight/effect/effect_56.go @@ -34,7 +34,7 @@ func (e *Effect56) SetArgs(t *input.Input, a ...int) { func (e *Effect56) Alive(t ...bool) bool { - if !e.GetBool(t...) { //说明到了回合结束取消节点,那么就将变化过的属性变化回来 + if !e.GetBool(t...) && e.Hit() { //说明到了回合结束取消节点,那么就将变化过的属性变化回来 //还原属性 e.Ctx().Our.CurrentPet.PetInfo.Type = e.oldtype } diff --git a/logic/service/fight/effect/effect_EffectConditionalAddDamage.go b/logic/service/fight/effect/effect_EffectConditionalAddDamage.go index d29b8933b..5fd0a2a80 100644 --- a/logic/service/fight/effect/effect_EffectConditionalAddDamage.go +++ b/logic/service/fight/effect/effect_EffectConditionalAddDamage.go @@ -36,7 +36,7 @@ func init() { func registerConditionalAddDamageEffects() { // 效果ID与条件函数的映射 effectMap := map[int]conditionFunc{ - 130: conditionIsTypeX, // 对方是X属性时 + // 130: conditionIsTypeX, // 对方是X属性时 133: conditionIsBurned, // 对方烧伤时 141: conditionIsFrozen, // 对方冻伤时 diff --git a/logic/service/fight/effect/effect_status.go b/logic/service/fight/effect/effect_status.go index b604ff8fa..b2be05704 100644 --- a/logic/service/fight/effect/effect_status.go +++ b/logic/service/fight/effect/effect_status.go @@ -2,6 +2,7 @@ package effect import ( element "blazing/common/data/Element" + "blazing/common/utils" "blazing/logic/service/fight/action" "blazing/logic/service/fight/info" "blazing/logic/service/fight/input" @@ -81,6 +82,16 @@ func (e *ContinuousDamage) calculateDamage() decimal.Decimal { Div(decimal.NewFromInt(8)) } +type Burned struct { + ContinuousDamage //继承扣血类 +} + +func (e *Burned) Skill_Hit() bool { + + e.Ctx().SkillEntity.Power /= 2 + return true +} + // 寄生种子状态:扣血同时给对方回血 type ParasiticSeed struct { BaseStatus @@ -107,13 +118,105 @@ func (e *ParasiticSeed) Skill_Hit_Pre_ex(attacker, defender *action.SelectSkillA return true } +type Flammable struct { + BaseStatus +} + +func (e *Flammable) Skill_Hit_Pre(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) bool { + if e.Ctx().SkillEntity == nil { + return true + } + e.Ctx().SkillEntity.Accuracy -= 30 + + return true + +} +func (e *Flammable) Skill_Use_ex() bool { + if e.Ctx().SkillEntity == nil { + return true + } + if e.Ctx().SkillEntity.Type().Secondary != nil { + return true + } + if e.Ctx().SkillEntity.Type().Primary != element.ElementTypeFire { + return true + } + // 获取状态效果 + eff := input.Geteffect(input.EffectType.Status, info.PetStatus.Burned) + if eff == nil { + return true + } + duration := int(e.Input.FightC.GetRand().Int31n(2)) // 默认随机 2~3 回合 + eff.Duration(duration) + eff.SetArgs(e.Ctx().Our) //输入参数是对方 + e.Ctx().Our.AddEffect(e.Ctx().Our, eff) + + return true + +} + +type Confused struct { + BaseStatus +} + +func (e *Confused) Skill_Hit_Pre(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) bool { + if e.Ctx().SkillEntity == nil { + return true + } + e.Ctx().SkillEntity.Accuracy -= 80 + ok, _, _ := e.Input.Player.Roll(5, 100) + if !ok { + return true + } + + e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{ + Type: info.DamageType.Fixed, + Damage: decimal.NewFromInt(50), + }) + return true + +} + +type Weakened struct { + BaseStatus +} + +func (e *Weakened) Damage_DIV_ex(t *info.DamageZone) bool { + // 1. 定义衰弱等级对应的倍率表(索引对应等级,0级无倍率) + // 索引0: 0%(未衰弱)、1:25%、2:50%、3:100%、4:250%、5:500% + weakenedMultiples := []decimal.Decimal{ + decimal.NewFromInt(0), // 0级 + decimal.NewFromFloat(0.25), // 1级(25%) + decimal.NewFromFloat(0.5), // 2级(50%) + decimal.NewFromFloat(1.0), // 3级(100%) + decimal.NewFromFloat(2.5), // 4级(250%) + decimal.NewFromFloat(5.0), // 5级(500%) + } + + // 2. 校验并限制衰弱等级(≤0 直接返回,≥5 按5级算) + level := e.Status + if level <= 0 { + return true + } + // 等级上限限制为5(避免越界) + level = utils.Min(level, 5) + + // 3. 获取对应等级的倍率,计算最终伤害 + multiple := weakenedMultiples[level] + // 伤害计算公式:原伤害 + 原伤害 × 倍率(等价于 原伤害 × (1+倍率)) + t.Damage = t.Damage.Add(t.Damage.Mul(multiple)) + + return true +} func init() { // 注册持续伤害类状态 input.InitEffect(input.EffectType.Status, int(info.PetStatus.DrainedHP), &ParasiticSeed{}) // 寄生种子 input.InitEffect(input.EffectType.Status, int(info.PetStatus.Poisoned), &ContinuousDamage{}) // 中毒 input.InitEffect(input.EffectType.Status, int(info.PetStatus.Frozen), &ContinuousDamage{}) // 冻伤 - input.InitEffect(input.EffectType.Status, int(info.PetStatus.Burned), &ContinuousDamage{}) // 烧伤 - + input.InitEffect(input.EffectType.Status, int(info.PetStatus.Burned), &Burned{}) // 烧伤 + input.InitEffect(input.EffectType.Status, int(info.PetStatus.Weakened), &Weakened{}) // 衰弱 + input.InitEffect(input.EffectType.Status, int(info.PetStatus.Confused), &Confused{}) // 混乱 + input.InitEffect(input.EffectType.Status, int(info.PetStatus.Flammable), &Flammable{}) // 易燃 // 批量注册不能行动的状态 nonActingStatuses := []info.EnumPetStatus{ info.PetStatus.Paralysis, // 麻痹 diff --git a/logic/service/fight/effect/sterStatusEffects.go b/logic/service/fight/effect/sterStatusEffects.go index 3a68d4e3b..b934fcf48 100644 --- a/logic/service/fight/effect/sterStatusEffects.go +++ b/logic/service/fight/effect/sterStatusEffects.go @@ -32,13 +32,14 @@ func registerStatusEffects() { 10: info.PetStatus.Paralysis, 11: info.PetStatus.Poisoned, 12: info.PetStatus.Burned, - //13: info.PetStatus.DrainedHP, + 14: info.PetStatus.Frozen, 15: info.PetStatus.Fear, 16: info.PetStatus.Sleep, 22: info.PetStatus.Tired, 94: info.PetStatus.Petrified, 99: info.PetStatus.Confused, + 103: info.PetStatus.Weakened, 114: info.PetStatus.Flammable, } diff --git a/logic/service/fight/fightc.go b/logic/service/fight/fightc.go index 1b6389446..e46426936 100644 --- a/logic/service/fight/fightc.go +++ b/logic/service/fight/fightc.go @@ -28,13 +28,8 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *info.Ski }) attacker.AttackValue.AttackTime = a.AttackTime //是否命中赋值 - // attacker.Exec(func(t input.Effect) bool { //计算命中 miss改命中 - // //计算视为效果 - // t.Ctx().SkillEntity = a - // t.Calculate_Pre() //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率 - - // return true - // }) + var oldprop [2][6]int8 + oldprop[0], oldprop[1] = attacker.Prop, defender.Prop //先复制能力提升 attacker.Exec(func(t input.Effect) bool { //计算变威力 t.Ctx().SkillEntity = a @@ -55,20 +50,21 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *info.Ski attacker.DamageZone.Damage = attacker.CalculatePower(defender, a) //睡眠受击消除 - if attacker.IsCritical == 1 { - //暴击破防 - if a.Category() == info.Category.PHYSICAL && defender.Prop[1] > 0 { + } + attacker.Prop, defender.Prop = oldprop[0], oldprop[1] //先复制能力提升 - defender.Prop[1] = 0 - } else if a.Category() == info.Category.SPECIAL && defender.Prop[3] > 0 { - defender.Prop[3] = 0 - } - - //暴击翻倍 - attacker.DamageZone.Damage = attacker.DamageZone.Damage.Mul(decimal.NewFromInt(2)) + if attacker.IsCritical == 1 { //命中了才有暴击 + //暴击破防 + if a.Category() == info.Category.PHYSICAL && defender.Prop[1] > 0 { + defender.Prop[1] = 0 + } else if a.Category() == info.Category.SPECIAL && defender.Prop[3] > 0 { + defender.Prop[3] = 0 } + //暴击翻倍 + attacker.DamageZone.Damage = attacker.DamageZone.Damage.Mul(decimal.NewFromInt(2)) + } // attacker.AddEffects(attacker.EffectCache...) //命中再添加效果 for _, e := range attacker.EffectCache { @@ -337,8 +333,9 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) { } } + f.Switch = []*action.ActiveSwitchAction{} ff.Player.SendPackCmd(2505, &ret) }) - f.Switch = []*action.ActiveSwitchAction{} + } diff --git a/logic/service/fight/input.go b/logic/service/fight/input.go index 846046ac3..eaa078582 100644 --- a/logic/service/fight/input.go +++ b/logic/service/fight/input.go @@ -103,12 +103,16 @@ func (f *FightC) LoadPercent(c common.PlayerI, percent int32) { } -func (f *FightC) initplayer(c common.PlayerI) *input.Input { +func (f *FightC) initplayer(c common.PlayerI) (*input.Input, errorcode.ErrorCode) { if len(c.GetInfo().PetList) == 0 { - return nil + return nil, 0 } + if !c.CanFight() { + return nil, errorcode.ErrorCodes.ErrNoEligiblePokemon + } + in := input.NewInput(f, c) in.AllPet = make([]*info.BattlePetEntity, 0) in.InitAttackValue() @@ -127,6 +131,7 @@ func (f *FightC) initplayer(c common.PlayerI) *input.Input { for _, v := range RandomElfIDs(3) { p := model.GenPetInfo(v, 24, -1, -1, -1, 100) p.CatchTime = uint32(v) + p.Update() in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(*p, f.rand)) } @@ -135,7 +140,7 @@ func (f *FightC) initplayer(c common.PlayerI) *input.Input { } in.CurrentPet = in.AllPet[0] - return in + return in, 0 } // RandomElfIDs 从1-2000中随机抽取n个不重复的精灵ID @@ -194,8 +199,18 @@ func NewFight(p1, p2 common.PlayerI, fn func(*info.FightOverInfo)) (*FightC, err //这里应该挪到玩家初始化执行 f.ReadyInfo.Status = f.Info.Status + var err errorcode.ErrorCode + f.Our, err = f.initplayer(p1) + if err > 0 { + return nil, err - f.Our, f.Opp = f.initplayer(p1), f.initplayer(p2) + } + + f.Opp, err = f.initplayer(p2) + if err > 0 { + return nil, err + + } f.ReadyInfo.OurInfo, f.ReadyInfo.OurPetList = initfightready(f.Our) f.ReadyInfo.OpponentInfo, f.ReadyInfo.OpponentPetList = initfightready(f.Opp) @@ -217,9 +232,17 @@ func NewFight(p1, p2 common.PlayerI, fn func(*info.FightOverInfo)) (*FightC, err ff.Player.SendPackCmd(2503, &f.ReadyInfo) }) - // 60秒后判断战斗是否开始 - cool.Cron.AfterFunc(60*time.Second, func() { + var t time.Duration + // 60秒后判断战斗是否开始 + switch f.Info.Status { + case info.BattleMode.PET_MELEE: + t = 120 * time.Second + + default: + t = 60 * time.Second + } + cool.Cron.AfterFunc(t, func() { if !f.Our.Finished || !f.Opp.Finished { //如果有任一没有加载完成 f.closefight = true //阻止继续添加action f.Reason = info.BattleOverReason.PlayerOVerTime diff --git a/logic/service/fight/input/effect.go b/logic/service/fight/input/effect.go index 2773673e1..1f6adb189 100644 --- a/logic/service/fight/input/effect.go +++ b/logic/service/fight/input/effect.go @@ -29,16 +29,17 @@ func InitEffect(etype EnumEffectType, id int, t Effect) { NodeM[id+int(etype)] = t } -func Geteffect(etype EnumEffectType, id int) Effect { +func Geteffect[T int | byte](etype EnumEffectType, id T) Effect { //todo 获取前GetEffect - ret, ok := NodeM[id+int(etype)] + ret, ok := NodeM[int(id)+int(etype)] if ok { //todo 获取前GetEffect eff := deep.MustCopy(ret) if eff.ID() >= int(EffectType.Status) && eff.ID() < int(EffectType.Sub) { eff.CanStack(true) //状态类不能被覆盖,只能无限叠加 + } return eff @@ -150,6 +151,7 @@ func (our *Input) AddEffect(in *Input, e Effect) Effect { return nil } + e.Alive(true) //添加后默认激活 //todo 免疫 //TODO 先激活 @@ -212,9 +214,9 @@ func (our *Input) Exec(fn func(Effect) bool) bool { } // 消除回合类效果 efftype 输入是消对方的还是自己的,false是自己,true是对方 -func (our *Input) CancelTurn() { +func (our *Input) CancelTurn(in *Input) { for _, value := range our.Effects { - if value.Duration() > 0 { //false是自身,true是对方,反转后为真就是自己的 + if value.Duration() > 0 && value.Alive() { //false是自身,true是对方,反转后为真就是自己的 //slice = append(slice[:i], slice[i+1:]...) value.Alive(false) } diff --git a/logic/service/fight/loop.go b/logic/service/fight/loop.go index ad2613ce3..99a9d69f2 100644 --- a/logic/service/fight/loop.go +++ b/logic/service/fight/loop.go @@ -71,8 +71,8 @@ func (f *FightC) battleLoop() { //待退出玩家战斗状态 }) - close(f.actionChan) - //fmt.Println("战斗循环结束") + //close(f.actionChan) + fmt.Println("战斗循环结束") close(f.over) } diff --git a/logic/service/player/ai.go b/logic/service/player/ai.go index 01637a376..48ba6f8b5 100644 --- a/logic/service/player/ai.go +++ b/logic/service/player/ai.go @@ -40,3 +40,7 @@ func (f *AI_player) InvitePlayer(ff common.PlayerI) { func (p *AI_player) QuitFight() { } + +func (p *AI_player) CanFight() bool { + return true +} diff --git a/logic/service/player/fight.go b/logic/service/player/fight.go index 95b419a30..ca6b740d9 100644 --- a/logic/service/player/fight.go +++ b/logic/service/player/fight.go @@ -28,7 +28,11 @@ func (p *Player) InvitePlayerToBattle() { }) } -func (p *Player) JoinFight(fn func(p common.PlayerI) bool) { +func (p *Player) JoinFight(fn func(p common.PlayerI) bool) errorcode.ErrorCode { + if !p.CanFight() { + return errorcode.ErrorCodes.ErrNoEligiblePokemon + + } p.GetSpace().User.Range(func(key uint32, v common.PlayerI) bool { @@ -39,14 +43,18 @@ func (p *Player) JoinFight(fn func(p common.PlayerI) bool) { // p.Fightinfo = nil //先将自身的准备信息置空 // //value.PVPinfo = nil + ttt := fn(v) + if ttt { + + } // lw = value - return fn(v) //如果发起成功就停止,否则继续遍历队列 + return ttt //如果发起成功就停止,否则继续遍历队列 } } return false }) - + return 0 } func (p *Player) SendLoadPercent(b info.LoadPercentOutboundInfo) { @@ -68,9 +76,7 @@ func (p *Player) SendLoadPercent(b info.LoadPercentOutboundInfo) { // common.PlayerI:对应的邀请者玩家(成功时有效) func (p *Player) AgreeBattle(userid, flag uint32, fn func(p common.PlayerI) bool) errorcode.ErrorCode { // 处理完毕后清空收到的邀请列表(原defer逻辑保留) - defer func() { - p.HavePVPinfo = make([]common.PlayerI, 0) - }() + resp := &info.S2C_NOTE_HANDLE_FIGHT_INVITE{ UserID: p.Info.UserID, Nick: p.Info.Nick, @@ -80,13 +86,15 @@ func (p *Player) AgreeBattle(userid, flag uint32, fn func(p common.PlayerI) bool if o != nil && o.Getfightinfo() == p.Fightinfo { resp.Result = flag // 检查邀请者的邀请是否有效(对方已取消邀请) - if atomic.LoadUint32(&o.GetInfo().UserID) == 0 { + if o.Getfightinfo().PlayerID == 0 { resp.Result = 4 // 邀请已取消 } //把不在线和不满足出战要求放到战斗检测里 //flasg本身就是00 if fn(o) { //发起成功 + p.HavePVPinfo = make([]common.PlayerI, 0) + return -1 //返回 } else { //发起失败 resp.Result = 3 diff --git a/logic/service/player/new.go b/logic/service/player/new.go index 1e01cabf6..1629fc033 100644 --- a/logic/service/player/new.go +++ b/logic/service/player/new.go @@ -17,7 +17,7 @@ func NewPlayer(opts ...PlayerOption) *Player { p.monsters = generateThreeUniqueNumbers() p.Done = NewDone(p) //发布订阅事件 p.StopChan = cool.Cron.ScheduleFunc(10*time.Second, func() { - if p.Canmon && p.FightC == nil { //已经进入地图或者没在战斗中,就可以刷新怪 + if p.Canmon != 0 { //已经进入地图或者没在战斗中,就可以刷新怪 p.SpawnMonsters() } }) diff --git a/logic/service/player/player.go b/logic/service/player/player.go index 60139ddc6..ade2aee61 100644 --- a/logic/service/player/player.go +++ b/logic/service/player/player.go @@ -63,8 +63,9 @@ type Player struct { // PVP被邀请信息 HavePVPinfo []common.PlayerI monsters [3]int - Canmon bool //可以刷怪 - Changemap bool //是否切换过地图 + //0 无,1可以刷怪,2是切换过地图 + Canmon uint32 //可以刷怪 + // Changemap bool //是否切换过地图 } // PlayerOption 定义配置 Player 的函数类型 @@ -98,6 +99,8 @@ func (p *Player) Getfightinfo() info.Fightinfo { func (p *Player) QuitFight() { //将战斗标记设置为0 这里的标记是 atomic.StoreUint32(&p.Fightinfo.Status, 0) + atomic.StoreUint32(&p.Fightinfo.PlayerID, 0) + p.FightC = nil } func (p *Player) GetSpace() *space.Space { @@ -105,30 +108,30 @@ func (p *Player) GetSpace() *space.Space { } // 0无战斗,1PVP,2,BOOS,3PVE -func (p *Player) CanFight(staus uint32) bool { +func (p *Player) CanFight() bool { - if atomic.CompareAndSwapUint32(&p.Fightinfo.Status, 0, staus) { //先判断是否竞态条件被挑战 + // if atomic.CompareAndSwapUint32(&p.Fightinfo.Status, 0, staus) { //先判断是否竞态条件被挑战 - //成功,继续判断 - - if p.FightC != nil { - return false - - } - // if p.GetSpace().ARENA.ChallengerID == p.Info.UserID || p.GetSpace().ARENA.Id == p.Info.UserID { - // return false - // } - for _, v := range p.Info.PetList { - if v.Hp > 0 { // 只要找到一个血量大于0的宠物,就可以战斗 - return true - } - } - // 遍历完所有宠物,都没有血量大于0的,才不能战斗 + //成功,继续判断 + if p.FightC != nil { return false + } + // if p.GetSpace().ARENA.ChallengerID == p.Info.UserID || p.GetSpace().ARENA.Id == p.Info.UserID { + // return false + // } + for _, v := range p.Info.PetList { + if v.Hp > 0 { // 只要找到一个血量大于0的宠物,就可以战斗 + return true + } + } + // 遍历完所有宠物,都没有血量大于0的,才不能战斗 return false + // } + + // return false } @@ -190,17 +193,15 @@ func (p *Player) genMonster(mapid uint32) { } - if p.Changemap { - p.Changemap = false + if atomic.CompareAndSwapUint32(&p.Canmon, 2, 1) { p.OgreInfo = OgreInfo{} //切地图清空 for i := 0; i < 3; i++ { p.OgreInfo.Data[p.monsters[i]] = t1.Data[p.monsters[i]] } - } else { - p.OgreInfo.Data[oldnum] = OgrePetInfo{} - p.OgreInfo.Data[newNum] = t1.Data[newNum] } + p.OgreInfo.Data[oldnum] = OgrePetInfo{} + p.OgreInfo.Data[newNum] = t1.Data[newNum] } diff --git a/logic/service/space/arena.go b/logic/service/space/arena.go index dc7e7e9c7..613864b58 100644 --- a/logic/service/space/arena.go +++ b/logic/service/space/arena.go @@ -7,3 +7,13 @@ type ARENA struct { HostWins uint32 // 应该是擂台人的连胜数 ChallengerID uint32 // 挑战者的userid } + +func (t *ARENA) Reset() { + + t.Flag = 0 + t.UserID = 0 + t.Nick = "" + t.HostWins = 0 + t.ChallengerID = 0 + +} diff --git a/logic/service/space/in_out.go b/logic/service/space/in_out.go index ca3b1025d..4a0f04968 100644 --- a/logic/service/space/in_out.go +++ b/logic/service/space/in_out.go @@ -15,31 +15,27 @@ var mappool, _ = ants.NewPool(-1) // 向其他人广播,不含自己 func (s *Space) Broadcast(c common.PlayerI, cmd uint32, data any) { - mappool.Submit(func() { + //mappool.Submit(func() { - s.User.Range(func(k uint32, v common.PlayerI) (stop bool) { + s.User.Range(func(k uint32, v common.PlayerI) (stop bool) { - if k != c.GetInfo().UserID { - v.SendPackCmd(cmd, data) + if k != c.GetInfo().UserID { + v.SendPackCmd(cmd, data) - } - return false - }) + } + return false }) + //}) } func (s *Space) LeaveMap(c common.PlayerI) { - if c == nil { - return - } - if c.GetInfo() == nil { - return - } if atomic.CompareAndSwapUint32(&s.Owner.UserID, c.GetInfo().UserID, 0) { s.ARENA_Player = nil + s.Owner.Reset() + s.Broadcast(c, 2419, &s.Owner) } diff --git a/logic/service/user/chat.go b/logic/service/user/chat.go index 536336303..c605da806 100644 --- a/logic/service/user/chat.go +++ b/logic/service/user/chat.go @@ -48,3 +48,32 @@ type ChangeNONOColorOutboundInfo struct { Color uint32 `codec:"color"` // 前端发来的更改的颜色rgb值 (对应Java的@UInt long) } + +// C2SDanceAction 前端发送给后端的舞蹈动作请求结构体 +// 对应 C# 的 C2S_DANCE_ACTION +type C2SDanceAction struct { + Head common.TomeeHeader `cmd:"2103" struc:"[0]pad"` + + // Reserve 固定参数(值为 10001) + Reserve uint32 `struc:"uint32,big"` + // Type 动作类型(3 = 蹲下) + Type uint32 `struc:"uint32,big"` +} +type S2CDanceAction struct { + // UserID 玩家ID + UserID uint32 `struc:"uint32,big"` + // Type 动作类型(透传前端的 type,3 = 蹲下) + Type uint32 `struc:"uint32,big"` +} +type C2SPEOPLE_TRANSFROM struct { + Head common.TomeeHeader `cmd:"2111" struc:"[0]pad"` + + // Reserve 固定参数(值为 10001) + SuitID uint32 `struc:"uint32,big"` +} +type S2CPEOPLE_TRANSFROM struct { + // UserID 玩家ID + UserID uint32 `struc:"uint32,big"` + // Type 动作类型(透传前端的 type,3 = 蹲下) + SuitID uint32 `struc:"uint32,big"` +} diff --git a/modules/blazing/model/pet.go b/modules/blazing/model/pet.go index d0920102e..fb56752ba 100644 --- a/modules/blazing/model/pet.go +++ b/modules/blazing/model/pet.go @@ -108,22 +108,49 @@ func (pet *PetInfo) Cure() { } // 传入bool则不升级 +// Update 改造为循环进化:直到宠物无法再进化为止,再更新经验 +// t ...bool:原参数逻辑,len(t)==0时触发进化检查,否则仅更新经验 func (petinfo *PetInfo) Update(t ...bool) { - - basic := xmlres.PetMAP[int(petinfo.ID)] - + // 仅在无额外参数时触发循环进化逻辑 if len(t) == 0 { - // 检查是否可以进化 - if basic.EvolvesTo != 0 && // 有明确的进化 - int(petinfo.Level) >= basic.EvolvingLv && // 有明确的进化等级 - basic.IsLarge == 0 { // 非最终形态 + // 最大进化次数限制(防止配置表闭环导致死循环) + maxEvolveTimes := 10 + evolveCount := 0 + // 循环进化:直到不满足进化条件 或 达到最大进化次数 + for { + // 防止死循环,超出次数直接退出 + if evolveCount >= maxEvolveTimes { + break + } + + // 获取当前宠物形态的配置 + basic, ok := xmlres.PetMAP[int(petinfo.ID)] + // 配置不存在,直接退出循环 + if !ok { + break + } + + // 检查是否满足进化条件 + canEvolve := basic.EvolvesTo != 0 && // 有明确的进化目标 + int(petinfo.Level) >= basic.EvolvingLv && // 等级达到进化要求 + basic.IsLarge == 0 // 非最终形态 + + // 不满足进化条件,退出循环 + if !canEvolve { + break + } + + // 执行进化:更新宠物ID为进化后形态 petinfo.ID = uint32(basic.EvolvesTo) - basic = xmlres.PetMAP[int(petinfo.ID)] //重新计算 + evolveCount++ // 进化次数+1 } } + // 进化完成后,统一更新经验(原逻辑保留) petinfo.LvExp = petinfo.NextLvExp + // 获取最终形态的宠物配置,计算下一等级经验 + basic := xmlres.PetMAP[int(petinfo.ID)] petinfo.NextLvExp = calculateExperience(petinfo.Level, basic.GetBasic()) } diff --git a/modules/blazing/model/player.go b/modules/blazing/model/player.go index 83f16a634..de44fa6b4 100644 --- a/modules/blazing/model/player.go +++ b/modules/blazing/model/player.go @@ -114,6 +114,7 @@ type PlayerInfo struct { PetMaxLevel uint32 `struc:"uint32" json:"pet_max_level"` // 精灵最高等级 AllPetNumber uint32 `struc:"uint32" json:"all_pet_number"` // 精灵数量 MonKingWin uint32 `struc:"uint32" json:"mon_king_win"` // 精灵王胜场 + MessWin uint32 `struc:"skip" json:"mess_win"` // 大乱斗胜场 CurrentStage uint32 `struc:"uint32" json:"current_stage"` // 勇者之塔层数 MaxStage uint32 `struc:"uint32" json:"max_stage"` // 试炼之塔最高层 CurrentFreshStage uint32 `struc:"uint32" json:"current_fresh_stage"` // 当前试炼层数