修复地牢内传送问题

This commit is contained in:
flswld
2023-04-05 02:27:13 +08:00
parent ec3000d9ae
commit 630c0444a0
10 changed files with 142 additions and 98 deletions

View File

@@ -25,11 +25,32 @@ func (g *GMCmd) GMTeleportPlayer(userId, sceneId, dungeonId uint32, posX, posY,
logger.Error("player is nil, uid: %v", userId)
return
}
GAME.TeleportPlayer(player, proto.EnterReason_ENTER_REASON_GM, sceneId, &model.Vector{
X: posX,
Y: posY,
Z: posZ,
}, new(model.Vector), dungeonId)
dungeonPointId := uint32(0)
end := false
for _, pointData := range gdconf.GetScenePointMapBySceneId(int32(sceneId)) {
if end {
break
}
for _, v := range pointData.DungeonIds {
if uint32(v) == dungeonId {
dungeonPointId = uint32(pointData.Id)
end = true
break
}
}
}
if dungeonPointId == 0 {
return
}
GAME.TeleportPlayer(
player,
proto.EnterReason_ENTER_REASON_GM,
sceneId,
&model.Vector{X: posX, Y: posY, Z: posZ},
new(model.Vector),
dungeonId,
dungeonPointId,
)
}
// GMAddUserItem 给予玩家物品

View File

@@ -193,10 +193,10 @@ func (w *WorldManager) GetMultiplayerWorldNum() uint32 {
// EnterSceneContext 场景切换上下文数据结构
type EnterSceneContext struct {
OldSceneId uint32
OldPos *model.Vector
OldDungeonId uint32
Uid uint32
OldSceneId uint32
OldPos *model.Vector
OldDungeonPointId uint32
Uid uint32
}
// World 世界数据结构

View File

@@ -134,7 +134,7 @@ func (g *Game) CombatInvocationsNotify(player *model.Player, payloadMsg pb.Messa
logger.Error("get gadget data config is nil, gadgetId: %v", gadgetEntity.GetGadgetId())
break
}
logger.Debug("[EvtBeingHit] GadgetData: %+v, uid: %v", gadgetDataConfig, player.PlayerID)
logger.Debug("[EvtBeingHit] GadgetData: %+v, EntityId: %v, uid: %v", gadgetDataConfig, target.GetId(), player.PlayerID)
// TODO 临时的解决方案
if strings.Contains(gadgetDataConfig.ServerLuaScript, "SetGadgetState") {
g.ChangeGadgetState(player, target.GetId(), constant.GADGET_STATE_GEAR_START)
@@ -325,12 +325,6 @@ func (g *Game) AbilityInvocationsNotify(player *model.Player, payloadMsg pb.Mess
if player.SceneLoadState != model.SceneEnterDone {
return
}
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
if world == nil {
logger.Error("get player world is nil, uid: %v", player.PlayerID)
return
}
scene := world.GetSceneById(player.SceneId)
for _, entry := range req.Invokes {
player.AbilityInvokeHandler.AddEntry(entry.ForwardType, entry)
switch entry.ArgumentType {
@@ -341,7 +335,7 @@ func (g *Game) AbilityInvocationsNotify(player *model.Player, payloadMsg pb.Mess
logger.Error("parse AbilityMetaModifierChange error: %v", err)
continue
}
logger.Debug("EntityId: %v, ModifierChange: %v", entry.EntityId, modifierChange)
// logger.Debug("EntityId: %v, ModifierChange: %v", entry.EntityId, modifierChange)
// 处理耐力消耗
g.HandleAbilityStamina(player, entry)
case proto.AbilityInvokeArgument_ABILITY_MIXIN_COST_STAMINA:
@@ -351,17 +345,7 @@ func (g *Game) AbilityInvocationsNotify(player *model.Player, payloadMsg pb.Mess
logger.Error("parse AbilityMixinCostStamina error: %v", err)
continue
}
logger.Debug("EntityId: %v, MixinCostStamina: %v", entry.EntityId, costStamina)
// 处理耐力消耗
g.HandleAbilityStamina(player, entry)
case proto.AbilityInvokeArgument_ABILITY_ACTION_DEDUCT_STAMINA:
deductStamina := new(proto.AbilityActionDeductStamina)
err := pb.Unmarshal(entry.AbilityData, deductStamina)
if err != nil {
logger.Error("parse AbilityActionDeductStamina error: %v", err)
continue
}
logger.Debug("EntityId: %v, ActionDeductStamina: %v", entry.EntityId, deductStamina)
// logger.Debug("EntityId: %v, MixinCostStamina: %v", entry.EntityId, costStamina)
// 处理耐力消耗
g.HandleAbilityStamina(player, entry)
case proto.AbilityInvokeArgument_ABILITY_META_MODIFIER_DURABILITY_CHANGE:
@@ -371,20 +355,7 @@ func (g *Game) AbilityInvocationsNotify(player *model.Player, payloadMsg pb.Mess
logger.Error("parse AbilityMetaModifierDurabilityChange error: %v", err)
continue
}
logger.Debug("EntityId: %v, DurabilityChange: %v", entry.EntityId, modifierDurabilityChange)
case proto.AbilityInvokeArgument_ABILITY_META_DURABILITY_IS_ZERO:
durabilityIsZero := new(proto.AbilityMetaDurabilityIsZero)
err := pb.Unmarshal(entry.AbilityData, durabilityIsZero)
if err != nil {
logger.Error("parse AbilityMetaDurabilityIsZero error: %v", err)
continue
}
logger.Debug("EntityId: %v, DurabilityIsZero: %v", entry.EntityId, durabilityIsZero)
g.KillEntity(player, scene, entry.EntityId, proto.PlayerDieType_PLAYER_DIE_GM)
case proto.AbilityInvokeArgument_ABILITY_MIXIN_ELITE_SHIELD:
case proto.AbilityInvokeArgument_ABILITY_MIXIN_ELEMENT_SHIELD:
case proto.AbilityInvokeArgument_ABILITY_MIXIN_GLOBAL_SHIELD:
case proto.AbilityInvokeArgument_ABILITY_MIXIN_SHIELD_BAR:
// logger.Debug("EntityId: %v, DurabilityChange: %v", entry.EntityId, modifierDurabilityChange)
}
}
}
@@ -569,12 +540,22 @@ func (g *Game) EvtDestroyGadgetNotify(player *model.Player, payloadMsg pb.Messag
func (g *Game) EvtAiSyncSkillCdNotify(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.EvtAiSyncSkillCdNotify)
_ = req
if player.SceneLoadState != model.SceneEnterDone {
return
}
// logger.Debug("EvtAiSyncSkillCdNotify: %v", req)
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
g.SendToWorldA(world, cmd.EvtAiSyncSkillCdNotify, player.ClientSeq, req)
}
func (g *Game) EvtAiSyncCombatThreatInfoNotify(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.EvtAiSyncCombatThreatInfoNotify)
_ = req
if player.SceneLoadState != model.SceneEnterDone {
return
}
// logger.Debug("EvtAiSyncCombatThreatInfoNotify: %v", req)
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
g.SendToWorldA(world, cmd.EvtAiSyncCombatThreatInfoNotify, player.ClientSeq, req)
}
func (g *Game) EntityConfigHashNotify(player *model.Player, payloadMsg pb.Message) {

View File

@@ -63,7 +63,15 @@ func (g *Game) GCGStartChallenge(player *model.Player) {
g.PacketGCGGameBriefDataNotify(player, proto.GCGGameBusinessType_GCG_GAME_GUIDE_GROUP, game))
// 玩家进入GCG界面
g.TeleportPlayer(player, proto.EnterReason_ENTER_REASON_DUNGEON_ENTER, 79999, new(model.Vector), new(model.Vector), 2162)
g.TeleportPlayer(
player,
proto.EnterReason_ENTER_REASON_DUNGEON_ENTER,
79999,
new(model.Vector),
new(model.Vector),
2162,
0,
)
}
// GCGAskDuelReq GCG决斗请求

View File

@@ -60,8 +60,6 @@ func (g *Game) SetPlayerBornDataReq(player *model.Player, payloadMsg pb.Message)
g.AcceptQuest(player, false)
g.SendMsg(cmd.SetPlayerBornDataRsp, player.PlayerID, player.ClientSeq, new(proto.SetPlayerBornDataRsp))
g.LoginNotify(player.PlayerID, player.ClientSeq, player)
// 创建世界
@@ -73,6 +71,8 @@ func (g *Game) SetPlayerBornDataReq(player *model.Player, payloadMsg pb.Message)
player.SceneLoadState = model.SceneNone
g.SendMsg(cmd.PlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, g.PacketPlayerEnterSceneNotifyLogin(player, proto.EnterType_ENTER_SELF))
g.SendMsg(cmd.SetPlayerBornDataRsp, player.PlayerID, player.ClientSeq, new(proto.SetPlayerBornDataRsp))
}
func (g *Game) OnLogin(userId uint32, clientSeq uint32, gateAppId string, player *model.Player, joinHostUserId uint32) {
@@ -116,10 +116,10 @@ func (g *Game) OnLogin(userId uint32, clientSeq uint32, gateAppId string, player
g.LoginNotify(userId, clientSeq, player)
if joinHostUserId != 0 {
hostPlayer := USER_MANAGER.GetOnlineUser(joinHostUserId)
if hostPlayer == nil {
logger.Error("player is nil, uid: %v", joinHostUserId)
} else {
if hostPlayer != nil {
g.JoinOtherWorld(player, hostPlayer)
} else {
logger.Error("player is nil, uid: %v", joinHostUserId)
}
} else {
// 创建世界

View File

@@ -70,6 +70,8 @@ func (g *Game) JoinPlayerSceneReq(player *model.Player, payloadMsg pb.Message) {
return
}
g.LoginNotify(player.PlayerID, player.ClientSeq, player)
g.JoinOtherWorld(player, hostPlayer)
}
@@ -94,7 +96,6 @@ func (g *Game) JoinOtherWorld(player *model.Player, hostPlayer *model.Player) {
proto.EnterReason_ENTER_REASON_TEAM_JOIN,
0,
new(model.Vector),
0,
)
g.SendMsg(cmd.PlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, playerEnterSceneNotify)
} else {
@@ -344,7 +345,6 @@ func (g *Game) HostEnterMpWorld(hostPlayer *model.Player) {
proto.EnterReason_ENTER_REASON_HOST_FROM_SINGLE_TO_MP,
hostPlayer.SceneId,
hostPlayer.Pos,
0,
)
g.SendMsg(cmd.PlayerEnterSceneNotify, hostPlayer.PlayerID, hostPlayer.ClientSeq, hostPlayerEnterSceneNotify)

View File

@@ -766,8 +766,9 @@ func (g *Game) PacketPlayerEnterSceneNotifyTp(
prevSceneId uint32,
prevPos *model.Vector,
dungeonId uint32,
dungeonPointId uint32,
) *proto.PlayerEnterSceneNotify {
return g.PacketPlayerEnterSceneNotifyCore(player, player, enterType, enterReason, prevSceneId, prevPos, dungeonId)
return g.PacketPlayerEnterSceneNotifyCore(player, player, enterType, enterReason, prevSceneId, prevPos, dungeonId, dungeonPointId)
}
func (g *Game) PacketPlayerEnterSceneNotifyMp(
@@ -777,9 +778,8 @@ func (g *Game) PacketPlayerEnterSceneNotifyMp(
enterReason proto.EnterReason,
prevSceneId uint32,
prevPos *model.Vector,
dungeonId uint32,
) *proto.PlayerEnterSceneNotify {
return g.PacketPlayerEnterSceneNotifyCore(player, targetPlayer, enterType, enterReason, prevSceneId, prevPos, dungeonId)
return g.PacketPlayerEnterSceneNotifyCore(player, targetPlayer, enterType, enterReason, prevSceneId, prevPos, 0, 0)
}
func (g *Game) PacketPlayerEnterSceneNotifyCore(
@@ -790,6 +790,7 @@ func (g *Game) PacketPlayerEnterSceneNotifyCore(
prevSceneId uint32,
prevPos *model.Vector,
dungeonId uint32,
dungeonPointId uint32,
) *proto.PlayerEnterSceneNotify {
world := WORLD_MANAGER.GetWorldByID(targetPlayer.WorldId)
scene := world.GetSceneById(targetPlayer.SceneId)
@@ -800,8 +801,8 @@ func (g *Game) PacketPlayerEnterSceneNotifyCore(
Y: prevPos.Y,
Z: prevPos.Z,
},
OldDungeonId: dungeonId,
Uid: player.PlayerID,
OldDungeonPointId: dungeonPointId,
Uid: player.PlayerID,
})
playerEnterSceneNotify := &proto.PlayerEnterSceneNotify{
PrevSceneId: prevSceneId,

View File

@@ -83,13 +83,14 @@ func (g *Game) HandleAbilityStamina(player *model.Player, entry *proto.AbilityIn
return
}
staminaInfo := player.StaminaInfo
now := time.Now().UnixMilli()
switch entry.ArgumentType {
case proto.AbilityInvokeArgument_ABILITY_META_MODIFIER_CHANGE:
// 普通角色重击耐力消耗
// 距离技能开始过去的时间
startPastTime := time.Now().UnixMilli() - staminaInfo.LastSkillTime
startPastTime := now - staminaInfo.LastSkillTime
// 距离上次技能消耗的时间
changePastTime := time.Now().UnixMilli() - staminaInfo.LastSkillChargeTime
changePastTime := now - staminaInfo.LastCostStaminaTime
// 法器角色轻击也会算触发重击消耗 胡桃等角色重击一次会多次消耗
// 所以通过策略判断 必须距离技能开始过去200ms才算重击 两次技能耐力消耗之间需间隔500ms
// 暂时就这样实现重击消耗 以后应该还会有更好的办法~
@@ -97,19 +98,22 @@ func (g *Game) HandleAbilityStamina(player *model.Player, entry *proto.AbilityIn
costStamina := -(staminaDataConfig.CostStamina * 100)
logger.Debug("stamina cost, skillId: %v, cost: %v", staminaDataConfig.AvatarSkillId, costStamina)
g.UpdatePlayerStamina(player, costStamina)
staminaInfo.LastSkillChargeTime = time.Now().UnixMilli()
staminaInfo.LastCostStaminaTime = now
}
case proto.AbilityInvokeArgument_ABILITY_MIXIN_COST_STAMINA:
// 大剑重击 或 持续技能 耐力消耗
// 根据配置以及距离上次的时间计算消耗的耐力
pastTime := time.Now().UnixMilli() - staminaInfo.LastSkillTime
pastTime := now - staminaInfo.LastCostStaminaTime
if pastTime > 500 {
staminaInfo.LastCostStaminaTime = now
pastTime = 0
}
costStamina := -(staminaDataConfig.CostStamina * 100)
costStamina = int32(float64(pastTime) / 1000 * float64(costStamina))
logger.Debug("stamina cost, skillId: %v, cost: %v", staminaDataConfig.AvatarSkillId, costStamina)
g.UpdatePlayerStamina(player, costStamina)
// 记录最后释放技能的时间
staminaInfo.LastSkillTime = time.Now().UnixMilli()
case proto.AbilityInvokeArgument_ABILITY_ACTION_DEDUCT_STAMINA:
staminaInfo.LastCostStaminaTime = now
}
}
@@ -340,7 +344,15 @@ func (g *Game) DrownBackHandler(player *model.Player) {
Z: player.SafePos.Z,
}
// 传送玩家至安全位置
g.TeleportPlayer(player, proto.EnterReason_ENTER_REASON_REVIVAL, player.SceneId, pos, new(model.Vector), 0)
g.TeleportPlayer(
player,
proto.EnterReason_ENTER_REASON_REVIVAL,
player.SceneId,
pos,
new(model.Vector),
0,
0,
)
}
// 防止重置后又被修改
if player.StaminaInfo.DrownBackDelay != 0 {

View File

@@ -18,6 +18,10 @@ import (
func (g *Game) SceneTransToPointReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.SceneTransToPointReq)
if player.SceneLoadState != model.SceneEnterDone {
g.SendError(cmd.SceneTransToPointRsp, player, &proto.SceneTransToPointRsp{}, proto.Retcode_RET_IN_TRANSFER)
return
}
dbWorld := player.GetDbWorld()
dbScene := dbWorld.GetSceneById(req.SceneId)
if dbScene == nil {
@@ -26,8 +30,8 @@ func (g *Game) SceneTransToPointReq(player *model.Player, payloadMsg pb.Message)
}
unlock := dbScene.CheckPointUnlock(req.PointId)
if !unlock {
g.SendError(cmd.SceneTransToPointRsp, player, &proto.SceneTransToPointRsp{}, proto.Retcode_RET_POINT_NOT_UNLOCKED)
return
// g.SendError(cmd.SceneTransToPointRsp, player, &proto.SceneTransToPointRsp{}, proto.Retcode_RET_POINT_NOT_UNLOCKED)
// return
}
pointDataConfig := gdconf.GetScenePointBySceneIdAndPointId(int32(req.SceneId), int32(req.PointId))
if pointDataConfig == nil {
@@ -36,15 +40,15 @@ func (g *Game) SceneTransToPointReq(player *model.Player, payloadMsg pb.Message)
}
// 传送玩家
g.TeleportPlayer(player, proto.EnterReason_ENTER_REASON_TRANS_POINT, req.SceneId, &model.Vector{
X: pointDataConfig.TranPos.X,
Y: pointDataConfig.TranPos.Y,
Z: pointDataConfig.TranPos.Z,
}, &model.Vector{
X: pointDataConfig.TranRot.X,
Y: pointDataConfig.TranRot.Y,
Z: pointDataConfig.TranRot.Z,
}, 0)
g.TeleportPlayer(
player,
proto.EnterReason_ENTER_REASON_TRANS_POINT,
req.SceneId,
&model.Vector{X: pointDataConfig.TranPos.X, Y: pointDataConfig.TranPos.Y, Z: pointDataConfig.TranPos.Z},
&model.Vector{X: pointDataConfig.TranRot.X, Y: pointDataConfig.TranRot.Y, Z: pointDataConfig.TranRot.Z},
0,
0,
)
sceneTransToPointRsp := &proto.SceneTransToPointRsp{
PointId: req.PointId,
@@ -124,11 +128,15 @@ func (g *Game) MarkMapReq(player *model.Player, payloadMsg pb.Message) {
posYInt = 300
}
// 传送玩家
g.TeleportPlayer(player, proto.EnterReason_ENTER_REASON_GM, req.Mark.SceneId, &model.Vector{
X: float64(req.Mark.Pos.X),
Y: float64(posYInt),
Z: float64(req.Mark.Pos.Z),
}, new(model.Vector), 0)
g.TeleportPlayer(
player,
proto.EnterReason_ENTER_REASON_GM,
req.Mark.SceneId,
&model.Vector{X: float64(req.Mark.Pos.X), Y: float64(posYInt), Z: float64(req.Mark.Pos.Z)},
new(model.Vector),
0,
0,
)
}
}
g.SendMsg(cmd.MarkMapRsp, player.PlayerID, player.ClientSeq, &proto.MarkMapRsp{})
@@ -247,15 +255,16 @@ func (g *Game) PlayerEnterDungeonReq(player *model.Player, payloadMsg pb.Message
logger.Error("get scene lua config is nil, sceneId: %v, uid: %v", dungeonDataConfig.SceneId, player.PlayerID)
return
}
g.TeleportPlayer(player, proto.EnterReason_ENTER_REASON_DUNGEON_ENTER, uint32(dungeonDataConfig.SceneId), &model.Vector{
X: float64(sceneLuaConfig.SceneConfig.BornPos.X),
Y: float64(sceneLuaConfig.SceneConfig.BornPos.Y),
Z: float64(sceneLuaConfig.SceneConfig.BornPos.Z),
}, &model.Vector{
X: float64(sceneLuaConfig.SceneConfig.BornRot.X),
Y: float64(sceneLuaConfig.SceneConfig.BornRot.Y),
Z: float64(sceneLuaConfig.SceneConfig.BornRot.Z),
}, req.DungeonId)
sceneConfig := sceneLuaConfig.SceneConfig
g.TeleportPlayer(
player,
proto.EnterReason_ENTER_REASON_DUNGEON_ENTER,
uint32(dungeonDataConfig.SceneId),
&model.Vector{X: float64(sceneConfig.BornPos.X), Y: float64(sceneConfig.BornPos.Y), Z: float64(sceneConfig.BornPos.Z)},
&model.Vector{X: float64(sceneConfig.BornRot.X), Y: float64(sceneConfig.BornRot.Y), Z: float64(sceneConfig.BornRot.Z)},
req.DungeonId,
req.PointId,
)
rsp := &proto.PlayerEnterDungeonRsp{
DungeonId: req.DungeonId,
@@ -274,11 +283,19 @@ func (g *Game) PlayerQuitDungeonReq(player *model.Player, payloadMsg pb.Message)
if ctx == nil {
return
}
g.TeleportPlayer(player, proto.EnterReason_ENTER_REASON_DUNGEON_QUIT, 3, &model.Vector{
X: ctx.OldPos.X,
Y: ctx.OldPos.Y,
Z: ctx.OldPos.Z,
}, new(model.Vector), 0)
pointDataConfig := gdconf.GetScenePointBySceneIdAndPointId(3, int32(ctx.OldDungeonPointId))
if pointDataConfig == nil {
return
}
g.TeleportPlayer(
player,
proto.EnterReason_ENTER_REASON_DUNGEON_QUIT,
3,
&model.Vector{X: pointDataConfig.TranPos.X, Y: pointDataConfig.TranPos.Y, Z: pointDataConfig.TranPos.Z},
&model.Vector{X: pointDataConfig.TranRot.X, Y: pointDataConfig.TranRot.Y, Z: pointDataConfig.TranRot.Z},
0,
0,
)
rsp := &proto.PlayerQuitDungeonRsp{
PointId: req.PointId,
@@ -309,7 +326,7 @@ func (g *Game) GadgetInteractReq(player *model.Player, payloadMsg pb.Message) {
logger.Error("get gadget data config is nil, gadgetId: %v, uid: %v", gadgetEntity.GetGadgetId(), player.PlayerID)
return
}
logger.Debug("[GadgetInteractReq] GadgetData: %+v, uid: %v", gadgetDataConfig, player.PlayerID)
logger.Debug("[GadgetInteractReq] GadgetData: %+v, EntityId: %v, uid: %v", gadgetDataConfig, entity.GetId(), player.PlayerID)
interactType := proto.InteractType_INTERACT_NONE
switch gadgetDataConfig.Type {
case constant.GADGET_TYPE_GADGET:
@@ -476,7 +493,11 @@ func (g *Game) doRandDropOnce(dropDataConfig *gdconf.DropData) map[int32]int32 {
}
// TeleportPlayer 传送玩家至地图上的某个位置
func (g *Game) TeleportPlayer(player *model.Player, enterReason proto.EnterReason, sceneId uint32, pos, rot *model.Vector, dungeonId uint32) {
func (g *Game) TeleportPlayer(
player *model.Player, enterReason proto.EnterReason,
sceneId uint32, pos, rot *model.Vector,
dungeonId, dungeonPointId uint32,
) {
// 传送玩家
newSceneId := sceneId
oldSceneId := player.SceneId
@@ -531,6 +552,6 @@ func (g *Game) TeleportPlayer(player *model.Player, enterReason proto.EnterReaso
logger.Debug("player goto scene, scene: %v, pos: %v", player.SceneId, player.Pos)
enterType = proto.EnterType_ENTER_GOTO
}
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyTp(player, enterType, enterReason, oldSceneId, oldPos, dungeonId)
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyTp(player, enterType, enterReason, oldSceneId, oldPos, dungeonId, dungeonPointId)
g.SendMsg(cmd.PlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, playerEnterSceneNotify)
}

View File

@@ -11,7 +11,7 @@ type StaminaInfo struct {
PlayerRestoreDelay uint8 // 玩家耐力回复延时
VehicleRestoreDelay uint8 // 载具耐力回复延时
LastSkillTime int64 // 最后释放技能的时间
LastSkillChargeTime int64 // 最后执行技能耐力消耗的时间
LastCostStaminaTime int64 // 最后执行技能耐力消耗的时间
DrownBackDelay uint8 // 溺水返回安全点延时
}