fix(fight): 修复战斗中属性变化与暴击判定逻辑
- 调整能力提升计算时机,确保命中后再恢复原始属性 - 暴击判断前置,仅在命中时计算暴击翻倍及破防逻辑 - 优化回合结束效果清除逻辑,增加状态存活判断 refactor(controller): 重构擂台相关接口返回结构体类型 - 将 ARENA_SET_OWENR、ARENA_FIGHT_OWENR 等函数的返回值统一改为 NullOutboundInfo,并移除冗余字段返回 - 广播逻辑调整,统一使用 Broadcast
This commit is contained in:
@@ -301,10 +301,10 @@ var ErrorCodes = enum.New[struct {
|
|||||||
ErrPermanentBanCheatTool ErrorCode `enum:"100401"`
|
ErrPermanentBanCheatTool ErrorCode `enum:"100401"`
|
||||||
// 由于使用外挂,你的号码被24小时封停
|
// 由于使用外挂,你的号码被24小时封停
|
||||||
Err24hBanCheatTool ErrorCode `enum:"100402"`
|
Err24hBanCheatTool ErrorCode `enum:"100402"`
|
||||||
// 由于使用外挂,你的号码被7天封停
|
// // 由于使用外挂,你的号码被7天封停
|
||||||
Err7dBanCheatTool ErrorCode `enum:"100403"`
|
// Err7dBanCheatTool ErrorCode `enum:"100403"`
|
||||||
// 由于使用外挂,你的号码被14天封停
|
// // 由于使用外挂,你的号码被14天封停
|
||||||
Err14dBanCheatTool ErrorCode `enum:"100404"`
|
// Err14dBanCheatTool ErrorCode `enum:"100404"`
|
||||||
// 由于强制改名,你的号码被踢下线
|
// 由于强制改名,你的号码被踢下线
|
||||||
ErrKickedForNameChange ErrorCode `enum:"100501"`
|
ErrKickedForNameChange ErrorCode `enum:"100501"`
|
||||||
// 分配器中经验值不够
|
// 分配器中经验值不够
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
// 前端到后端无数据内容 空包
|
// 前端到后端无数据内容 空包
|
||||||
// 后端到前端无数据内容 空包
|
// 后端到前端无数据内容 空包
|
||||||
// 都需要通过2419包广播更新擂台状态
|
// 都需要通过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) {
|
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().Owner.Nick = c.GetInfo().Nick
|
||||||
c.GetSpace().ARENA_Player = c //添加用户
|
c.GetSpace().ARENA_Player = c //添加用户
|
||||||
|
|
||||||
c.GetSpace().Broadcast(c, 2419, &c.GetSpace().Owner)
|
c.GetSpace().Broadcast(c, 2419, c.GetSpace().Owner)
|
||||||
return &c.GetSpace().Owner, 0
|
c.SendPackCmd(2419, c.GetSpace().Owner)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errorcode.ErrorCodes.ErrChampionExists
|
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包通知后端开始战斗
|
// 还是后端主动发送2503的包给双方前端后 等待前端加载完毕 主动发送2404包通知后端开始战斗
|
||||||
// 并不会通知对方是否接受挑战。只要有人挑战就直接进入对战
|
// 并不会通知对方是否接受挑战。只要有人挑战就直接进入对战
|
||||||
func (h Controller) ARENA_FIGHT_OWENR(data *fight.ARENA_FIGHT_OWENR, c *player.Player) (result *space.ARENA, err errorcode.ErrorCode) {
|
func (h Controller) ARENA_FIGHT_OWENR(data *fight.ARENA_FIGHT_OWENR, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||||
s := c.GetSpace()
|
|
||||||
|
|
||||||
//原子操作,修改擂台状态
|
//原子操作,修改擂台状态
|
||||||
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.Mode = info.BattleMode.SINGLE_MODE
|
||||||
c.Fightinfo.Status = info.BattleStatus.FIGHT_WITH_PLAYER
|
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 { //发起战斗成功
|
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 {
|
} else {
|
||||||
//发起失败,改回1
|
//发起失败,改回1
|
||||||
atomic.StoreUint32(&s.Owner.Flag, 1)
|
atomic.StoreUint32(&c.GetSpace().Owner.Flag, 1)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Broadcast(c, 2419, &s.Owner)
|
return
|
||||||
return &s.Owner, 0
|
|
||||||
}
|
}
|
||||||
return nil, errorcode.ErrorCodes.ErrChampionExists
|
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) {
|
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;
|
// 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包广播更新擂台状态
|
// 都需要通过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)
|
if atomic.CompareAndSwapUint32(&c.GetSpace().Owner.UserID, c.GetInfo().UserID, 0) {
|
||||||
return &s.Owner, 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
|
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;
|
// 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()
|
s := c.GetSpace()
|
||||||
if atomic.LoadUint32(&s.Owner.UserID) != c.GetInfo().UserID && c.GetInfo().UserID != atomic.LoadUint32(&s.Owner.ChallengerID) { //说明已经有人了
|
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) {
|
if c.GetInfo().UserID == atomic.LoadUint32(&s.Owner.UserID) {
|
||||||
|
c.Info.MaxArenaWins += 1
|
||||||
s.Owner.HostWins += 1 //连胜+1
|
s.Owner.HostWins += 1 //连胜+1
|
||||||
|
|
||||||
} else {
|
} 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)
|
atomic.StoreUint32(&s.Owner.Flag, 1)
|
||||||
|
|
||||||
s.Broadcast(c, 2419, &s.Owner)
|
s.Broadcast(c, 2419, &s.Owner)
|
||||||
return &s.Owner, 0
|
c.SendPackCmd(2419, &c.GetSpace().Owner)
|
||||||
|
|
||||||
|
return nil, -1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,15 @@ import (
|
|||||||
func (h Controller) PET_MELEE(data *fight.StartPetWarInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
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.Mode = info.BattleMode.PET_MELEE
|
||||||
|
c.Fightinfo.Status = info.BattleStatus.FIGHT_WITH_PLAYER
|
||||||
c.Fightinfo.PlayerID = 0
|
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) {
|
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) {
|
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.Status = info.BattleStatus.FIGHT_WITH_PLAYER
|
||||||
|
c.Fightinfo.PlayerID = 0
|
||||||
switch data.Type {
|
switch data.Type {
|
||||||
case 5:
|
case 5:
|
||||||
c.Fightinfo.Mode = info.BattleMode.SINGLE_MODE
|
c.Fightinfo.Mode = info.BattleMode.SINGLE_MODE
|
||||||
case 6:
|
case 6:
|
||||||
c.Fightinfo.Mode = info.BattleMode.MULTI_MODE
|
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) {
|
fight.NewFight(p, c, func(foi *info.FightOverInfo) {
|
||||||
|
if foi.Reason == 0 && foi.WinnerId == c.GetInfo().UserID { //我放获胜
|
||||||
|
|
||||||
|
c.Info.MonKingWin += 1
|
||||||
|
|
||||||
|
}
|
||||||
}) ///开始对战,房主方以及被邀请方
|
}) ///开始对战,房主方以及被邀请方
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -17,8 +17,10 @@ func (h Controller) OnPlayerHandleFightInvite(data *fight.HandleFightInviteInbou
|
|||||||
return nil, errorcode.ErrorCodes.ErrInBattle
|
return nil, errorcode.ErrorCodes.ErrInBattle
|
||||||
|
|
||||||
}
|
}
|
||||||
c.Fightinfo.PlayerID = data.UserID
|
c.Fightinfo.PlayerID = c.Info.UserID
|
||||||
c.Fightinfo.Mode = data.Mode
|
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 = c.AgreeBattle(data.UserID, data.Flag, func(p common.PlayerI) bool {
|
||||||
|
|
||||||
_, err = fight.NewFight(p, c, func(foi *info.FightOverInfo) {
|
_, 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) { //邀请前提是自己没邀请别人
|
// if !atomic.CompareAndSwapUint32(&c.Fightinfo.PlayerID, 0, data.UserID) { //邀请前提是自己没邀请别人
|
||||||
return nil, errorcode.ErrorCodes.ErrCannotPerformAction
|
// return nil, errorcode.ErrorCodes.ErrCannotPerformAction
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
c.Fightinfo.PlayerID = data.UserID
|
||||||
c.Fightinfo.Mode = data.Mode
|
c.Fightinfo.Mode = data.Mode
|
||||||
|
c.Fightinfo.Status = 1
|
||||||
|
c.Fightinfo.Type = 0
|
||||||
c.InvitePlayerToBattle()
|
c.InvitePlayerToBattle()
|
||||||
|
|
||||||
return nil, 0
|
return nil, 0
|
||||||
@@ -50,7 +54,7 @@ func (h Controller) OnPlayerCanceledOtherInviteFight(data *fight.InviteFightCanc
|
|||||||
|
|
||||||
if atomic.LoadUint32(&c.Fightinfo.Status) != 0 { //如果没有战斗状态,则不做任何处理
|
if atomic.LoadUint32(&c.Fightinfo.Status) != 0 { //如果没有战斗状态,则不做任何处理
|
||||||
atomic.StoreUint32(&c.Fightinfo.Status, 0) //设置状态为0
|
atomic.StoreUint32(&c.Fightinfo.Status, 0) //设置状态为0
|
||||||
|
return nil, 0
|
||||||
}
|
}
|
||||||
//否则报错
|
//否则报错
|
||||||
return nil, errorcode.ErrorCodes.ErrCannotCancelBattle
|
return nil, errorcode.ErrorCodes.ErrCannotCancelBattle
|
||||||
|
|||||||
@@ -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.Info.UserID = data.Head.UserID
|
||||||
t.Logintime = uint32(time.Now().Unix()) //保存时间戳
|
t.Logintime = uint32(time.Now().Unix()) //保存时间戳
|
||||||
t.Changemap = true
|
|
||||||
cool.Loger.Info(context.Background(), "用户上次重置日期", t.Info.LastResetTime.String())
|
cool.Loger.Info(context.Background(), "用户上次重置日期", t.Info.LastResetTime.String())
|
||||||
if !IsToday(t.Info.LastResetTime) { //判断是否是今天
|
if !IsToday(t.Info.LastResetTime) { //判断是否是今天
|
||||||
t.Info.LastResetTime = gtime.Now().Time
|
t.Info.LastResetTime = gtime.Now().Time
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/common/socket/errorcode"
|
"blazing/common/socket/errorcode"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"blazing/logic/service/maphot"
|
"blazing/logic/service/maphot"
|
||||||
"blazing/logic/service/maps"
|
"blazing/logic/service/maps"
|
||||||
@@ -34,24 +35,25 @@ func (h Controller) MapHot(data *maphot.InInfo, c *player.Player) (result *mapho
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (h *Controller) MapLeave(data *maps.LeaveMapInboundInfo, c *player.Player) (result *info.LeaveMapOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
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) //玩家离开地图
|
defer c.GetSpace().LeaveMap(c) //玩家离开地图
|
||||||
|
|
||||||
// 如果有正在运行的刷怪协程,发送停止信号
|
// 如果有正在运行的刷怪协程,发送停止信号
|
||||||
|
|
||||||
//c.Info.MapID = 0 // 重置当前地图
|
//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应该是空的
|
func (h *Controller) MapList(data *maps.ListMapPlayerInboundInfo, c *player.Player) (result *info.ListMapPlayerOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
||||||
|
|
||||||
result = &info.ListMapPlayerOutboundInfo{
|
result = &info.ListMapPlayerOutboundInfo{
|
||||||
Player: c.GetSpace().GetInfo(),
|
Player: c.GetSpace().GetInfo(),
|
||||||
}
|
}
|
||||||
|
atomic.StoreUint32(&c.Canmon, 2)
|
||||||
|
|
||||||
c.Canmon = true //可以刷怪
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ func (h *Controller) NonoFollowOrHome(data *nono.NonoFollowOrHomeInInfo, c *play
|
|||||||
c.Info.NONO.Flag = data.Flag
|
c.Info.NONO.Flag = data.Flag
|
||||||
result = &nono.NonoFollowOutInfo{
|
result = &nono.NonoFollowOutInfo{
|
||||||
|
|
||||||
UserID: data.Head.UserID,
|
UserID: data.Head.UserID,
|
||||||
SuperStage: data.Flag,
|
SuperStage: data.Flag,
|
||||||
Flag: data.Flag,
|
Flag: data.Flag,
|
||||||
Nick: "",
|
Nick: "",
|
||||||
Color: 0,
|
Color: 0,
|
||||||
Power: 0,
|
Power: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -44,14 +44,17 @@ func (h *Controller) SwitchFlying(data *nono.SwitchFlyingInboundInfo, c *player.
|
|||||||
|
|
||||||
result = &nono.SwitchFlyingOutboundInfo{
|
result = &nono.SwitchFlyingOutboundInfo{
|
||||||
UserId: data.Head.UserID,
|
UserId: data.Head.UserID,
|
||||||
Type: data.Type,
|
Type: data.Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.GetSpace().Broadcast(c, data.Head.CMD, result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Controller) PlayerPetCure(data *nono.PetCureInboundInfo, c *player.Player) (result *nono.PetCureOutboundEmpty, err errorcode.ErrorCode) { //这个时候player应该是空的
|
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++ {
|
for i := 0; i < len(c.Info.PetList); i++ {
|
||||||
c.Info.PetList[i].Cure()
|
c.Info.PetList[i].Cure()
|
||||||
|
|
||||||
|
|||||||
@@ -63,9 +63,13 @@ func (h *Controller) PetRelease(
|
|||||||
err errorcode.ErrorCode) { //这个时候player应该是空的
|
err errorcode.ErrorCode) { //这个时候player应该是空的
|
||||||
//放入背包=数据库置1+添加到背包+pet release发包 仓库=数据库置0+移除背包 设置首发等于取到首发精灵后重新排序
|
//放入背包=数据库置1+添加到背包+pet release发包 仓库=数据库置0+移除背包 设置首发等于取到首发精灵后重新排序
|
||||||
//这里只修改,因为添加和移除背包在宠物获取时已经做了
|
//这里只修改,因为添加和移除背包在宠物获取时已经做了
|
||||||
|
|
||||||
result = &pet.PetReleaseOutboundInfo{}
|
result = &pet.PetReleaseOutboundInfo{}
|
||||||
result.Flag = uint32(data.Flag)
|
result.Flag = uint32(data.Flag)
|
||||||
|
//擂台住不能换精灵
|
||||||
|
if c.GetSpace().Owner.UserID == c.Info.UserID {
|
||||||
|
return result, errorcode.ErrorCodes.ErrChampionCannotSwitch
|
||||||
|
}
|
||||||
switch data.Flag {
|
switch data.Flag {
|
||||||
case 0:
|
case 0:
|
||||||
var temp []model.PetInfo
|
var temp []model.PetInfo
|
||||||
@@ -131,7 +135,9 @@ func (h *Controller) PlayerShowPet(
|
|||||||
}
|
}
|
||||||
func (h *Controller) PetOneCure(
|
func (h *Controller) PetOneCure(
|
||||||
data *pet.PetOneCureInboundInfo, c *player.Player) (result *pet.PetOneCureOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
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 {
|
_, onpet, ok := utils.FindWithIndex(c.Info.PetList, func(item model.PetInfo) bool {
|
||||||
return item.CatchTime == data.CatchTime
|
return item.CatchTime == data.CatchTime
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -98,6 +98,24 @@ func (h Controller) ChangeNONOColor(data *user.ChangeNONOColorInboundInfo, c *pl
|
|||||||
Sataus: c.Info.UserID,
|
Sataus: c.Info.UserID,
|
||||||
Color: c.Info.Color,
|
Color: c.Info.Color,
|
||||||
}
|
}
|
||||||
|
c.GetSpace().Broadcast(c, data.Head.CMD, result)
|
||||||
return result, 0
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ require (
|
|||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // 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/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
github.com/redis/go-redis/v9 v9.5.1 // indirect
|
github.com/redis/go-redis/v9 v9.5.1 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
|||||||
@@ -15,6 +15,6 @@ type PlayerI interface {
|
|||||||
InvitePlayer(PlayerI)
|
InvitePlayer(PlayerI)
|
||||||
SetFightC(FightI)
|
SetFightC(FightI)
|
||||||
QuitFight()
|
QuitFight()
|
||||||
|
CanFight() bool
|
||||||
SendPackCmd(uint32, any)
|
SendPackCmd(uint32, any)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,8 +221,6 @@ func (f *FightC) startBattle(startInfo info.FightStartOutboundInfo) {
|
|||||||
ff.Player.SendPackCmd(2504, &startInfo)
|
ff.Player.SendPackCmd(2504, &startInfo)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 标记战斗已启动(原注释逻辑)
|
|
||||||
// f.running = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var Fightpool *ants.Pool
|
var Fightpool *ants.Pool
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
// 基类特性
|
// 基类特性
|
||||||
type NewSel0 struct {
|
type NewSel0 struct {
|
||||||
node.EffectNode
|
node.EffectNode
|
||||||
Catchtime int //保存精灵的唯一指令,保证在上场时候正确注入
|
Catchtime int //保存精灵的唯一指令,保证在上场时候正确注入
|
||||||
Hide bool //是否隐藏 ,所属精灵下场后特性就应该消失
|
//Hide bool //是否隐藏 ,所属精灵下场后特性就应该消失
|
||||||
//??如果2只精灵一个特性,怎么办,每次切精灵注入特性
|
//??如果2只精灵一个特性,怎么办,每次切精灵注入特性
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
39
logic/service/fight/effect/effect_130.go
Normal file
39
logic/service/fight/effect/effect_130.go
Normal file
@@ -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{})
|
||||||
|
|
||||||
|
}
|
||||||
29
logic/service/fight/effect/effect_180.go
Normal file
29
logic/service/fight/effect/effect_180.go
Normal file
@@ -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
|
||||||
|
}
|
||||||
36
logic/service/fight/effect/effect_195.go
Normal file
36
logic/service/fight/effect/effect_195.go
Normal file
@@ -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
|
||||||
|
}
|
||||||
@@ -43,7 +43,7 @@ func (e *Effect45) SetArgs(t *input.Input, a ...int) {
|
|||||||
|
|
||||||
func (e *Effect45) Alive(t ...bool) bool {
|
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
|
e.Ctx().Our.CurrentPet.Info.Prop[1] = e.oldtype
|
||||||
}
|
}
|
||||||
|
|||||||
51
logic/service/fight/effect/effect_478.go
Normal file
51
logic/service/fight/effect/effect_478.go
Normal file
@@ -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])
|
||||||
|
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ func (e *Effect51) SetArgs(t *input.Input, a ...int) {
|
|||||||
|
|
||||||
func (e *Effect51) Alive(t ...bool) bool {
|
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
|
e.Ctx().Our.CurrentPet.Info.Prop[0] = e.oldtype
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func (e *Effect55) SetArgs(t *input.Input, a ...int) {
|
|||||||
|
|
||||||
func (e *Effect55) Alive(t ...bool) bool {
|
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
|
e.Ctx().Our.CurrentPet.PetInfo.Type, e.Ctx().Opp.CurrentPet.PetInfo.Type = e.Ctx().Opp.CurrentPet.PetInfo.Type, e.Ctx().Our.CurrentPet.PetInfo.Type
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func (e *Effect56) SetArgs(t *input.Input, a ...int) {
|
|||||||
|
|
||||||
func (e *Effect56) Alive(t ...bool) bool {
|
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
|
e.Ctx().Our.CurrentPet.PetInfo.Type = e.oldtype
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func init() {
|
|||||||
func registerConditionalAddDamageEffects() {
|
func registerConditionalAddDamageEffects() {
|
||||||
// 效果ID与条件函数的映射
|
// 效果ID与条件函数的映射
|
||||||
effectMap := map[int]conditionFunc{
|
effectMap := map[int]conditionFunc{
|
||||||
130: conditionIsTypeX, // 对方是X属性时
|
// 130: conditionIsTypeX, // 对方是X属性时
|
||||||
133: conditionIsBurned, // 对方烧伤时
|
133: conditionIsBurned, // 对方烧伤时
|
||||||
141: conditionIsFrozen, // 对方冻伤时
|
141: conditionIsFrozen, // 对方冻伤时
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package effect
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
element "blazing/common/data/Element"
|
element "blazing/common/data/Element"
|
||||||
|
"blazing/common/utils"
|
||||||
"blazing/logic/service/fight/action"
|
"blazing/logic/service/fight/action"
|
||||||
"blazing/logic/service/fight/info"
|
"blazing/logic/service/fight/info"
|
||||||
"blazing/logic/service/fight/input"
|
"blazing/logic/service/fight/input"
|
||||||
@@ -81,6 +82,16 @@ func (e *ContinuousDamage) calculateDamage() decimal.Decimal {
|
|||||||
Div(decimal.NewFromInt(8))
|
Div(decimal.NewFromInt(8))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Burned struct {
|
||||||
|
ContinuousDamage //继承扣血类
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Burned) Skill_Hit() bool {
|
||||||
|
|
||||||
|
e.Ctx().SkillEntity.Power /= 2
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// 寄生种子状态:扣血同时给对方回血
|
// 寄生种子状态:扣血同时给对方回血
|
||||||
type ParasiticSeed struct {
|
type ParasiticSeed struct {
|
||||||
BaseStatus
|
BaseStatus
|
||||||
@@ -107,13 +118,105 @@ func (e *ParasiticSeed) Skill_Hit_Pre_ex(attacker, defender *action.SelectSkillA
|
|||||||
return true
|
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() {
|
func init() {
|
||||||
// 注册持续伤害类状态
|
// 注册持续伤害类状态
|
||||||
input.InitEffect(input.EffectType.Status, int(info.PetStatus.DrainedHP), &ParasiticSeed{}) // 寄生种子
|
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.Poisoned), &ContinuousDamage{}) // 中毒
|
||||||
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Frozen), &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{
|
nonActingStatuses := []info.EnumPetStatus{
|
||||||
info.PetStatus.Paralysis, // 麻痹
|
info.PetStatus.Paralysis, // 麻痹
|
||||||
|
|||||||
@@ -32,13 +32,14 @@ func registerStatusEffects() {
|
|||||||
10: info.PetStatus.Paralysis,
|
10: info.PetStatus.Paralysis,
|
||||||
11: info.PetStatus.Poisoned,
|
11: info.PetStatus.Poisoned,
|
||||||
12: info.PetStatus.Burned,
|
12: info.PetStatus.Burned,
|
||||||
//13: info.PetStatus.DrainedHP,
|
|
||||||
14: info.PetStatus.Frozen,
|
14: info.PetStatus.Frozen,
|
||||||
15: info.PetStatus.Fear,
|
15: info.PetStatus.Fear,
|
||||||
16: info.PetStatus.Sleep,
|
16: info.PetStatus.Sleep,
|
||||||
22: info.PetStatus.Tired,
|
22: info.PetStatus.Tired,
|
||||||
94: info.PetStatus.Petrified,
|
94: info.PetStatus.Petrified,
|
||||||
99: info.PetStatus.Confused,
|
99: info.PetStatus.Confused,
|
||||||
|
103: info.PetStatus.Weakened,
|
||||||
114: info.PetStatus.Flammable,
|
114: info.PetStatus.Flammable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,13 +28,8 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *info.Ski
|
|||||||
})
|
})
|
||||||
|
|
||||||
attacker.AttackValue.AttackTime = a.AttackTime //是否命中赋值
|
attacker.AttackValue.AttackTime = a.AttackTime //是否命中赋值
|
||||||
// attacker.Exec(func(t input.Effect) bool { //计算命中 miss改命中
|
var oldprop [2][6]int8
|
||||||
// //计算视为效果
|
oldprop[0], oldprop[1] = attacker.Prop, defender.Prop //先复制能力提升
|
||||||
// t.Ctx().SkillEntity = a
|
|
||||||
// t.Calculate_Pre() //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// })
|
|
||||||
attacker.Exec(func(t input.Effect) bool {
|
attacker.Exec(func(t input.Effect) bool {
|
||||||
//计算变威力
|
//计算变威力
|
||||||
t.Ctx().SkillEntity = a
|
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)
|
attacker.DamageZone.Damage = attacker.CalculatePower(defender, a)
|
||||||
//睡眠受击消除
|
//睡眠受击消除
|
||||||
|
|
||||||
if attacker.IsCritical == 1 {
|
}
|
||||||
//暴击破防
|
attacker.Prop, defender.Prop = oldprop[0], oldprop[1] //先复制能力提升
|
||||||
if a.Category() == info.Category.PHYSICAL && defender.Prop[1] > 0 {
|
|
||||||
|
|
||||||
defender.Prop[1] = 0
|
if attacker.IsCritical == 1 { //命中了才有暴击
|
||||||
} else if a.Category() == info.Category.SPECIAL && defender.Prop[3] > 0 {
|
//暴击破防
|
||||||
defender.Prop[3] = 0
|
if a.Category() == info.Category.PHYSICAL && defender.Prop[1] > 0 {
|
||||||
}
|
|
||||||
|
|
||||||
//暴击翻倍
|
|
||||||
attacker.DamageZone.Damage = attacker.DamageZone.Damage.Mul(decimal.NewFromInt(2))
|
|
||||||
|
|
||||||
|
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...) //命中再添加效果
|
// attacker.AddEffects(attacker.EffectCache...) //命中再添加效果
|
||||||
for _, e := range 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)
|
ff.Player.SendPackCmd(2505, &ret)
|
||||||
|
|
||||||
})
|
})
|
||||||
f.Switch = []*action.ActiveSwitchAction{}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
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 := input.NewInput(f, c)
|
||||||
in.AllPet = make([]*info.BattlePetEntity, 0)
|
in.AllPet = make([]*info.BattlePetEntity, 0)
|
||||||
in.InitAttackValue()
|
in.InitAttackValue()
|
||||||
@@ -127,6 +131,7 @@ func (f *FightC) initplayer(c common.PlayerI) *input.Input {
|
|||||||
for _, v := range RandomElfIDs(3) {
|
for _, v := range RandomElfIDs(3) {
|
||||||
p := model.GenPetInfo(v, 24, -1, -1, -1, 100)
|
p := model.GenPetInfo(v, 24, -1, -1, -1, 100)
|
||||||
p.CatchTime = uint32(v)
|
p.CatchTime = uint32(v)
|
||||||
|
p.Update()
|
||||||
in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(*p, f.rand))
|
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]
|
in.CurrentPet = in.AllPet[0]
|
||||||
return in
|
return in, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandomElfIDs 从1-2000中随机抽取n个不重复的精灵ID
|
// 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
|
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.OurInfo, f.ReadyInfo.OurPetList = initfightready(f.Our)
|
||||||
f.ReadyInfo.OpponentInfo, f.ReadyInfo.OpponentPetList = initfightready(f.Opp)
|
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)
|
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 { //如果有任一没有加载完成
|
if !f.Our.Finished || !f.Opp.Finished { //如果有任一没有加载完成
|
||||||
f.closefight = true //阻止继续添加action
|
f.closefight = true //阻止继续添加action
|
||||||
f.Reason = info.BattleOverReason.PlayerOVerTime
|
f.Reason = info.BattleOverReason.PlayerOVerTime
|
||||||
|
|||||||
@@ -29,16 +29,17 @@ func InitEffect(etype EnumEffectType, id int, t Effect) {
|
|||||||
|
|
||||||
NodeM[id+int(etype)] = t
|
NodeM[id+int(etype)] = t
|
||||||
}
|
}
|
||||||
func Geteffect(etype EnumEffectType, id int) Effect {
|
func Geteffect[T int | byte](etype EnumEffectType, id T) Effect {
|
||||||
|
|
||||||
//todo 获取前GetEffect
|
//todo 获取前GetEffect
|
||||||
ret, ok := NodeM[id+int(etype)]
|
ret, ok := NodeM[int(id)+int(etype)]
|
||||||
if ok {
|
if ok {
|
||||||
//todo 获取前GetEffect
|
//todo 获取前GetEffect
|
||||||
|
|
||||||
eff := deep.MustCopy(ret)
|
eff := deep.MustCopy(ret)
|
||||||
if eff.ID() >= int(EffectType.Status) && eff.ID() < int(EffectType.Sub) {
|
if eff.ID() >= int(EffectType.Status) && eff.ID() < int(EffectType.Sub) {
|
||||||
eff.CanStack(true) //状态类不能被覆盖,只能无限叠加
|
eff.CanStack(true) //状态类不能被覆盖,只能无限叠加
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return eff
|
return eff
|
||||||
@@ -150,6 +151,7 @@ func (our *Input) AddEffect(in *Input, e Effect) Effect {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Alive(true) //添加后默认激活
|
e.Alive(true) //添加后默认激活
|
||||||
//todo 免疫
|
//todo 免疫
|
||||||
//TODO 先激活
|
//TODO 先激活
|
||||||
@@ -212,9 +214,9 @@ func (our *Input) Exec(fn func(Effect) bool) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 消除回合类效果 efftype 输入是消对方的还是自己的,false是自己,true是对方
|
// 消除回合类效果 efftype 输入是消对方的还是自己的,false是自己,true是对方
|
||||||
func (our *Input) CancelTurn() {
|
func (our *Input) CancelTurn(in *Input) {
|
||||||
for _, value := range our.Effects {
|
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:]...)
|
//slice = append(slice[:i], slice[i+1:]...)
|
||||||
value.Alive(false)
|
value.Alive(false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ func (f *FightC) battleLoop() {
|
|||||||
//待退出玩家战斗状态
|
//待退出玩家战斗状态
|
||||||
})
|
})
|
||||||
|
|
||||||
close(f.actionChan)
|
//close(f.actionChan)
|
||||||
//fmt.Println("战斗循环结束")
|
fmt.Println("战斗循环结束")
|
||||||
close(f.over)
|
close(f.over)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,3 +40,7 @@ func (f *AI_player) InvitePlayer(ff common.PlayerI) {
|
|||||||
func (p *AI_player) QuitFight() {
|
func (p *AI_player) QuitFight() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *AI_player) CanFight() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 {
|
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 //先将自身的准备信息置空
|
// p.Fightinfo = nil //先将自身的准备信息置空
|
||||||
// //value.PVPinfo = nil
|
// //value.PVPinfo = nil
|
||||||
|
ttt := fn(v)
|
||||||
|
if ttt {
|
||||||
|
|
||||||
|
}
|
||||||
// lw = value
|
// lw = value
|
||||||
return fn(v) //如果发起成功就停止,否则继续遍历队列
|
return ttt //如果发起成功就停止,否则继续遍历队列
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) SendLoadPercent(b info.LoadPercentOutboundInfo) {
|
func (p *Player) SendLoadPercent(b info.LoadPercentOutboundInfo) {
|
||||||
@@ -68,9 +76,7 @@ func (p *Player) SendLoadPercent(b info.LoadPercentOutboundInfo) {
|
|||||||
// common.PlayerI:对应的邀请者玩家(成功时有效)
|
// common.PlayerI:对应的邀请者玩家(成功时有效)
|
||||||
func (p *Player) AgreeBattle(userid, flag uint32, fn func(p common.PlayerI) bool) errorcode.ErrorCode {
|
func (p *Player) AgreeBattle(userid, flag uint32, fn func(p common.PlayerI) bool) errorcode.ErrorCode {
|
||||||
// 处理完毕后清空收到的邀请列表(原defer逻辑保留)
|
// 处理完毕后清空收到的邀请列表(原defer逻辑保留)
|
||||||
defer func() {
|
|
||||||
p.HavePVPinfo = make([]common.PlayerI, 0)
|
|
||||||
}()
|
|
||||||
resp := &info.S2C_NOTE_HANDLE_FIGHT_INVITE{
|
resp := &info.S2C_NOTE_HANDLE_FIGHT_INVITE{
|
||||||
UserID: p.Info.UserID,
|
UserID: p.Info.UserID,
|
||||||
Nick: p.Info.Nick,
|
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 {
|
if o != nil && o.Getfightinfo() == p.Fightinfo {
|
||||||
resp.Result = flag
|
resp.Result = flag
|
||||||
// 检查邀请者的邀请是否有效(对方已取消邀请)
|
// 检查邀请者的邀请是否有效(对方已取消邀请)
|
||||||
if atomic.LoadUint32(&o.GetInfo().UserID) == 0 {
|
if o.Getfightinfo().PlayerID == 0 {
|
||||||
resp.Result = 4 // 邀请已取消
|
resp.Result = 4 // 邀请已取消
|
||||||
|
|
||||||
}
|
}
|
||||||
//把不在线和不满足出战要求放到战斗检测里
|
//把不在线和不满足出战要求放到战斗检测里
|
||||||
//flasg本身就是00
|
//flasg本身就是00
|
||||||
if fn(o) { //发起成功
|
if fn(o) { //发起成功
|
||||||
|
p.HavePVPinfo = make([]common.PlayerI, 0)
|
||||||
|
|
||||||
return -1 //返回
|
return -1 //返回
|
||||||
} else { //发起失败
|
} else { //发起失败
|
||||||
resp.Result = 3
|
resp.Result = 3
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func NewPlayer(opts ...PlayerOption) *Player {
|
|||||||
p.monsters = generateThreeUniqueNumbers()
|
p.monsters = generateThreeUniqueNumbers()
|
||||||
p.Done = NewDone(p) //发布订阅事件
|
p.Done = NewDone(p) //发布订阅事件
|
||||||
p.StopChan = cool.Cron.ScheduleFunc(10*time.Second, func() {
|
p.StopChan = cool.Cron.ScheduleFunc(10*time.Second, func() {
|
||||||
if p.Canmon && p.FightC == nil { //已经进入地图或者没在战斗中,就可以刷新怪
|
if p.Canmon != 0 { //已经进入地图或者没在战斗中,就可以刷新怪
|
||||||
p.SpawnMonsters()
|
p.SpawnMonsters()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -63,8 +63,9 @@ type Player struct {
|
|||||||
// PVP被邀请信息
|
// PVP被邀请信息
|
||||||
HavePVPinfo []common.PlayerI
|
HavePVPinfo []common.PlayerI
|
||||||
monsters [3]int
|
monsters [3]int
|
||||||
Canmon bool //可以刷怪
|
//0 无,1可以刷怪,2是切换过地图
|
||||||
Changemap bool //是否切换过地图
|
Canmon uint32 //可以刷怪
|
||||||
|
// Changemap bool //是否切换过地图
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlayerOption 定义配置 Player 的函数类型
|
// PlayerOption 定义配置 Player 的函数类型
|
||||||
@@ -98,6 +99,8 @@ func (p *Player) Getfightinfo() info.Fightinfo {
|
|||||||
func (p *Player) QuitFight() {
|
func (p *Player) QuitFight() {
|
||||||
//将战斗标记设置为0 这里的标记是
|
//将战斗标记设置为0 这里的标记是
|
||||||
atomic.StoreUint32(&p.Fightinfo.Status, 0)
|
atomic.StoreUint32(&p.Fightinfo.Status, 0)
|
||||||
|
atomic.StoreUint32(&p.Fightinfo.PlayerID, 0)
|
||||||
|
p.FightC = nil
|
||||||
|
|
||||||
}
|
}
|
||||||
func (p *Player) GetSpace() *space.Space {
|
func (p *Player) GetSpace() *space.Space {
|
||||||
@@ -105,30 +108,30 @@ func (p *Player) GetSpace() *space.Space {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 0无战斗,1PVP,2,BOOS,3PVE
|
// 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
|
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
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,17 +193,15 @@ func (p *Player) genMonster(mapid uint32) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Changemap {
|
if atomic.CompareAndSwapUint32(&p.Canmon, 2, 1) {
|
||||||
p.Changemap = false
|
|
||||||
p.OgreInfo = OgreInfo{} //切地图清空
|
p.OgreInfo = OgreInfo{} //切地图清空
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
|
|
||||||
p.OgreInfo.Data[p.monsters[i]] = t1.Data[p.monsters[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]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,3 +7,13 @@ type ARENA struct {
|
|||||||
HostWins uint32 // 应该是擂台人的连胜数
|
HostWins uint32 // 应该是擂台人的连胜数
|
||||||
ChallengerID uint32 // 挑战者的userid
|
ChallengerID uint32 // 挑战者的userid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *ARENA) Reset() {
|
||||||
|
|
||||||
|
t.Flag = 0
|
||||||
|
t.UserID = 0
|
||||||
|
t.Nick = ""
|
||||||
|
t.HostWins = 0
|
||||||
|
t.ChallengerID = 0
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,31 +15,27 @@ var mappool, _ = ants.NewPool(-1)
|
|||||||
|
|
||||||
// 向其他人广播,不含自己
|
// 向其他人广播,不含自己
|
||||||
func (s *Space) Broadcast(c common.PlayerI, cmd uint32, data any) {
|
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 {
|
if k != c.GetInfo().UserID {
|
||||||
v.SendPackCmd(cmd, data)
|
v.SendPackCmd(cmd, data)
|
||||||
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
//})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Space) LeaveMap(c common.PlayerI) {
|
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) {
|
if atomic.CompareAndSwapUint32(&s.Owner.UserID, c.GetInfo().UserID, 0) {
|
||||||
s.ARENA_Player = nil
|
s.ARENA_Player = nil
|
||||||
|
|
||||||
|
s.Owner.Reset()
|
||||||
|
|
||||||
s.Broadcast(c, 2419, &s.Owner)
|
s.Broadcast(c, 2419, &s.Owner)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,3 +48,32 @@ type ChangeNONOColorOutboundInfo struct {
|
|||||||
Color uint32 `codec:"color"` // 前端发来的更改的颜色rgb值 (对应Java的@UInt long)
|
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"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -108,22 +108,49 @@ func (pet *PetInfo) Cure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 传入bool则不升级
|
// 传入bool则不升级
|
||||||
|
// Update 改造为循环进化:直到宠物无法再进化为止,再更新经验
|
||||||
|
// t ...bool:原参数逻辑,len(t)==0时触发进化检查,否则仅更新经验
|
||||||
func (petinfo *PetInfo) Update(t ...bool) {
|
func (petinfo *PetInfo) Update(t ...bool) {
|
||||||
|
// 仅在无额外参数时触发循环进化逻辑
|
||||||
basic := xmlres.PetMAP[int(petinfo.ID)]
|
|
||||||
|
|
||||||
if len(t) == 0 {
|
if len(t) == 0 {
|
||||||
// 检查是否可以进化
|
// 最大进化次数限制(防止配置表闭环导致死循环)
|
||||||
if basic.EvolvesTo != 0 && // 有明确的进化
|
maxEvolveTimes := 10
|
||||||
int(petinfo.Level) >= basic.EvolvingLv && // 有明确的进化等级
|
evolveCount := 0
|
||||||
basic.IsLarge == 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)
|
petinfo.ID = uint32(basic.EvolvesTo)
|
||||||
basic = xmlres.PetMAP[int(petinfo.ID)] //重新计算
|
evolveCount++ // 进化次数+1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 进化完成后,统一更新经验(原逻辑保留)
|
||||||
petinfo.LvExp = petinfo.NextLvExp
|
petinfo.LvExp = petinfo.NextLvExp
|
||||||
|
// 获取最终形态的宠物配置,计算下一等级经验
|
||||||
|
basic := xmlres.PetMAP[int(petinfo.ID)]
|
||||||
petinfo.NextLvExp = calculateExperience(petinfo.Level, basic.GetBasic())
|
petinfo.NextLvExp = calculateExperience(petinfo.Level, basic.GetBasic())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ type PlayerInfo struct {
|
|||||||
PetMaxLevel uint32 `struc:"uint32" json:"pet_max_level"` // 精灵最高等级
|
PetMaxLevel uint32 `struc:"uint32" json:"pet_max_level"` // 精灵最高等级
|
||||||
AllPetNumber uint32 `struc:"uint32" json:"all_pet_number"` // 精灵数量
|
AllPetNumber uint32 `struc:"uint32" json:"all_pet_number"` // 精灵数量
|
||||||
MonKingWin uint32 `struc:"uint32" json:"mon_king_win"` // 精灵王胜场
|
MonKingWin uint32 `struc:"uint32" json:"mon_king_win"` // 精灵王胜场
|
||||||
|
MessWin uint32 `struc:"skip" json:"mess_win"` // 大乱斗胜场
|
||||||
CurrentStage uint32 `struc:"uint32" json:"current_stage"` // 勇者之塔层数
|
CurrentStage uint32 `struc:"uint32" json:"current_stage"` // 勇者之塔层数
|
||||||
MaxStage uint32 `struc:"uint32" json:"max_stage"` // 试炼之塔最高层
|
MaxStage uint32 `struc:"uint32" json:"max_stage"` // 试炼之塔最高层
|
||||||
CurrentFreshStage uint32 `struc:"uint32" json:"current_fresh_stage"` // 当前试炼层数
|
CurrentFreshStage uint32 `struc:"uint32" json:"current_fresh_stage"` // 当前试炼层数
|
||||||
|
|||||||
Reference in New Issue
Block a user