溺水传送优化 溺水安全点无果

This commit is contained in:
UnKownOwO
2022-12-20 18:13:12 +08:00
parent 391738e29a
commit 056ae5f8d8
9 changed files with 101 additions and 74 deletions

View File

@@ -4,37 +4,37 @@ var EnterReasonConst *EnterReason
type EnterReason struct { type EnterReason struct {
None uint16 None uint16
Login uint16 Login uint16 // 登录
DungeonReplay uint16 DungeonReplay uint16 // 秘境重新挑战
DungeonReviveOnWaypoint uint16 DungeonReviveOnWaypoint uint16 // 秘境重生
DungeonEnter uint16 DungeonEnter uint16 // 秘境进入
DungeonQuit uint16 DungeonQuit uint16 // 秘境离开
Gm uint16 Gm uint16 // 管理员
QuestRollback uint16 QuestRollback uint16 // 任务回滚
Revival uint16 Revival uint16 // 重生
PersonalScene uint16 PersonalScene uint16 // 个人场景
TransPoint uint16 TransPoint uint16 // 传送点
ClientTransmit uint16 ClientTransmit uint16 // 客户端传送
ForceDragBack uint16 ForceDragBack uint16 // 强制后退
TeamKick uint16 TeamKick uint16 // 队伍踢出
TeamJoin uint16 TeamJoin uint16 // 队伍加入
TeamBack uint16 TeamBack uint16 // 队伍返回
Muip uint16 Muip uint16 // ??
DungeonInviteAccept uint16 DungeonInviteAccept uint16 // 秘境邀请接受
Lua uint16 Lua uint16 // 脚本
ActivityLoadTerrain uint16 ActivityLoadTerrain uint16 // 活动加载地形
HostFromSingleToMp uint16 HostFromSingleToMp uint16 // 房主从单人到多人
MpPlay uint16 MpPlay uint16 // 多人游戏
AnchorPoint uint16 AnchorPoint uint16 // 迷你锚点
LuaSkipUi uint16 LuaSkipUi uint16 // 脚本跳过UI
ReloadTerrain uint16 ReloadTerrain uint16 // 重载地形
DraftTransfer uint16 DraftTransfer uint16 // 某个东西传送 ??
EnterHome uint16 EnterHome uint16 // 进入尘歌壶
ExitHome uint16 ExitHome uint16 // 离开尘歌壶
ChangeHomeModule uint16 ChangeHomeModule uint16 // 更改尘歌壶模块
Gallery uint16 Gallery uint16 // ??
HomeSceneJump uint16 HomeSceneJump uint16 // 尘歌壶场景跳转
HideAndSeek uint16 HideAndSeek uint16 // 隐藏和搜索 ??
} }
func InitEnterReasonConst() { func InitEnterReasonConst() {

View File

@@ -1,6 +1,7 @@
package game package game
import ( import (
"hk4e/gs/constant"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
) )
@@ -12,7 +13,7 @@ func (c *CommandManager) GMTeleportPlayer(userId, sceneId uint32, posX, posY, po
logger.Error("player is nil, uid: %v", userId) logger.Error("player is nil, uid: %v", userId)
return return
} }
GAME_MANAGER.TeleportPlayer(player, sceneId, &model.Vector{ GAME_MANAGER.TeleportPlayer(player, uint32(constant.EnterReasonConst.Gm), sceneId, &model.Vector{
X: posX, X: posX,
Y: posY, Y: posY,
Z: posZ, Z: posZ,

View File

@@ -38,7 +38,7 @@ func (r *RouteManager) doRoute(cmdId uint16, userId uint32, clientSeq uint32, pa
if player == nil { if player == nil {
logger.Error("player is nil, uid: %v", userId) logger.Error("player is nil, uid: %v", userId)
// 临时为了调试便捷搞的重连 生产环境请务必去除 不然新用户会一直重连不能进入 // 临时为了调试便捷搞的重连 生产环境请务必去除 不然新用户会一直重连不能进入
// GAME_MANAGER.ReconnectPlayer(userId) GAME_MANAGER.ReconnectPlayer(userId)
return return
} }
player.ClientSeq = clientSeq player.ClientSeq = clientSeq

View File

@@ -113,21 +113,12 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
if sceneEntity.avatarEntity != nil { if sceneEntity.avatarEntity != nil {
// 玩家实体在移动 // 玩家实体在移动
// 更新玩家的位置信息 // 更新玩家的位置信息
player.Pos.X = float64(motionInfo.Pos.X)
switch motionInfo.State { player.Pos.Y = float64(motionInfo.Pos.Y)
case proto.MotionState_MOTION_STATE_DANGER_RUN, proto.MotionState_MOTION_STATE_RUN, player.Pos.Z = float64(motionInfo.Pos.Z)
proto.MotionState_MOTION_STATE_DANGER_STANDBY_MOVE, proto.MotionState_MOTION_STATE_DANGER_STANDBY, proto.MotionState_MOTION_STATE_LADDER_TO_STANDBY, proto.MotionState_MOTION_STATE_STANDBY_MOVE, proto.MotionState_MOTION_STATE_STANDBY, player.Rot.X = float64(motionInfo.Rot.X)
proto.MotionState_MOTION_STATE_DANGER_WALK, proto.MotionState_MOTION_STATE_WALK, player.Rot.Y = float64(motionInfo.Rot.Y)
proto.MotionState_MOTION_STATE_DASH: player.Rot.Z = float64(motionInfo.Rot.Z)
// 为了实现游泳返回安全位置 但是我觉得这么做肯定会出问题
player.Pos.X = float64(motionInfo.Pos.X)
player.Pos.Y = float64(motionInfo.Pos.Y)
player.Pos.Z = float64(motionInfo.Pos.Z)
player.Rot.X = float64(motionInfo.Rot.X)
player.Rot.Y = float64(motionInfo.Rot.Y)
player.Rot.Z = float64(motionInfo.Rot.Z)
}
// 处理耐力消耗 // 处理耐力消耗
g.ImmediateStamina(player, motionInfo.State) g.ImmediateStamina(player, motionInfo.State)

View File

@@ -1,10 +1,10 @@
package game package game
import ( import (
"hk4e/gs/constant"
"strconv" "strconv"
gdc "hk4e/gs/config" gdc "hk4e/gs/config"
"hk4e/gs/constant"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
@@ -32,7 +32,7 @@ func (g *GameManager) SceneTransToPointReq(player *model.Player, payloadMsg pb.M
Y: transPos.Y, Y: transPos.Y,
Z: transPos.Z, Z: transPos.Z,
} }
g.TeleportPlayer(player, sceneId, pos) g.TeleportPlayer(player, uint32(constant.EnterReasonConst.TransPoint), sceneId, pos)
sceneTransToPointRsp := &proto.SceneTransToPointRsp{ sceneTransToPointRsp := &proto.SceneTransToPointRsp{
Retcode: 0, Retcode: 0,
@@ -60,13 +60,13 @@ func (g *GameManager) MarkMapReq(player *model.Player, payloadMsg pb.Message) {
Y: float64(posYInt), Y: float64(posYInt),
Z: float64(req.Mark.Pos.Z), Z: float64(req.Mark.Pos.Z),
} }
g.TeleportPlayer(player, req.Mark.SceneId, pos) g.TeleportPlayer(player, uint32(constant.EnterReasonConst.Gm), req.Mark.SceneId, pos)
} }
} }
} }
// TeleportPlayer 传送玩家至地图上的某个位置 // TeleportPlayer 传送玩家至地图上的某个位置
func (g *GameManager) TeleportPlayer(player *model.Player, sceneId uint32, pos *model.Vector) { func (g *GameManager) TeleportPlayer(player *model.Player, enterReason uint32, sceneId uint32, pos *model.Vector) {
// 传送玩家 // 传送玩家
newSceneId := sceneId newSceneId := sceneId
oldSceneId := player.SceneId oldSceneId := player.SceneId
@@ -105,7 +105,7 @@ func (g *GameManager) TeleportPlayer(player *model.Player, sceneId uint32, pos *
logger.Debug("player goto scene, scene: %v, pos: %v", player.SceneId, player.Pos) logger.Debug("player goto scene, scene: %v, pos: %v", player.SceneId, player.Pos)
enterType = proto.EnterType_ENTER_TYPE_GOTO enterType = proto.EnterType_ENTER_TYPE_GOTO
} }
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyTp(player, enterType, uint32(constant.EnterReasonConst.TransPoint), oldSceneId, oldPos) playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyTp(player, enterType, enterReason, oldSceneId, oldPos)
g.SendMsg(cmd.PlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, playerEnterSceneNotify) g.SendMsg(cmd.PlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, playerEnterSceneNotify)
} }

View File

@@ -422,26 +422,54 @@ func (g *GameManager) DrownBackHandler(player *model.Player) {
if player.StaminaInfo.DrownBackTime == 0 { if player.StaminaInfo.DrownBackTime == 0 {
return return
} }
if time.Now().UnixMilli() >= player.StaminaInfo.DrownBackTime { world := WORLD_MANAGER.GetWorldByID(player.WorldId)
world := WORLD_MANAGER.GetWorldByID(player.WorldId) scene := world.GetSceneById(player.SceneId)
scene := world.GetSceneById(player.SceneId) activeAvatar := world.GetPlayerWorldAvatar(player, world.GetPlayerActiveAvatarId(player))
activeAvatar := world.GetPlayerWorldAvatar(player, player.TeamConfig.GetActiveAvatarId()) avatarEntity := scene.GetEntity(activeAvatar.avatarEntityId)
avatarEntity := scene.GetEntity(activeAvatar.avatarEntityId) if avatarEntity == nil {
if avatarEntity == nil { logger.Error("avatar entity is nil, entityId: %v", activeAvatar.avatarEntityId)
logger.Error("avatar entity is nil, entityId: %v", activeAvatar.avatarEntityId) return
return }
// 记录溺水安全点
// 溺水安全点可能需要读取附近锚点坐标
// 多次溺水后提示溺水的死亡信息
// 官服 游戏离线也会回到安全位置
// 很显然目前这个很不完善
switch player.StaminaInfo.State {
case proto.MotionState_MOTION_STATE_DANGER_RUN, proto.MotionState_MOTION_STATE_RUN,
proto.MotionState_MOTION_STATE_DANGER_STANDBY_MOVE, proto.MotionState_MOTION_STATE_DANGER_STANDBY, proto.MotionState_MOTION_STATE_LADDER_TO_STANDBY, proto.MotionState_MOTION_STATE_STANDBY_MOVE, proto.MotionState_MOTION_STATE_STANDBY,
proto.MotionState_MOTION_STATE_DANGER_WALK, proto.MotionState_MOTION_STATE_WALK,
proto.MotionState_MOTION_STATE_DASH:
player.StaminaInfo.DrownBackPos.X = player.Pos.X
player.StaminaInfo.DrownBackPos.Y = player.Pos.Y
player.StaminaInfo.DrownBackPos.Z = player.Pos.Z
}
// 临时
if player.StaminaInfo.DrownBackPos.X == 0 && player.StaminaInfo.DrownBackPos.Y == 0 && player.StaminaInfo.DrownBackPos.Z == 0 {
player.StaminaInfo.DrownBackPos.X = player.Pos.X
player.StaminaInfo.DrownBackPos.Y = player.Pos.Y
player.StaminaInfo.DrownBackPos.Z = player.Pos.Z
}
if player.StaminaInfo.DrownBackTime == 1 {
// 确保玩家已经完成加载场景
if player.SceneLoadState == model.SceneEnterDone {
// 设置角色存活
scene.SetEntityLifeState(avatarEntity, constant.LifeStateConst.LIFE_REVIVE, proto.PlayerDieType_PLAYER_DIE_TYPE_NONE)
// 重置溺水返回时间
player.StaminaInfo.DrownBackTime = 0
} }
// TODO 目前存在的问题 } else if time.Now().UnixMilli() >= player.StaminaInfo.DrownBackTime {
// 传送会显示玩家实体后再传送 返回安全位置写的不是很好可能存在问题 // 临时 防止一直淹死 尚未完善
// 官服 游戏离线也会回到安全位置 g.SetPlayerStamina(player, 10000)
// 设置角色存活
scene.SetEntityLifeState(avatarEntity, constant.LifeStateConst.LIFE_ALIVE, proto.PlayerDieType_PLAYER_DIE_TYPE_NONE)
// 传送玩家至安全位置 // 传送玩家至安全位置
g.TeleportPlayer(player, player.SceneId, player.Pos) g.TeleportPlayer(player, uint32(constant.EnterReasonConst.Revival), player.SceneId, player.StaminaInfo.DrownBackPos)
// 置溺水返回时间 // 置溺水返回时间为1
player.StaminaInfo.DrownBackTime = 0 // 1代表加载完场景后再复活玩家
player.StaminaInfo.DrownBackTime = 1
// 重置动作状态否则可能会导致多次溺水 // 重置动作状态否则可能会导致多次溺水
player.StaminaInfo.State = 0 player.StaminaInfo.State = 0
} }
@@ -456,7 +484,7 @@ func (g *GameManager) HandleDrown(player *model.Player, stamina uint32) {
world := WORLD_MANAGER.GetWorldByID(player.WorldId) world := WORLD_MANAGER.GetWorldByID(player.WorldId)
scene := world.GetSceneById(player.SceneId) scene := world.GetSceneById(player.SceneId)
activeAvatar := world.GetPlayerWorldAvatar(player, player.TeamConfig.GetActiveAvatarId()) activeAvatar := world.GetPlayerWorldAvatar(player, world.GetPlayerActiveAvatarId(player))
avatarEntity := scene.GetEntity(activeAvatar.avatarEntityId) avatarEntity := scene.GetEntity(activeAvatar.avatarEntityId)
if avatarEntity == nil { if avatarEntity == nil {
logger.Error("avatar entity is nil, entityId: %v", activeAvatar.avatarEntityId) logger.Error("avatar entity is nil, entityId: %v", activeAvatar.avatarEntityId)

View File

@@ -634,11 +634,16 @@ func (s *Scene) SetEntityLifeState(entity *Entity, lifeState uint16, dieType pro
return return
} }
// 设置角色存活状态 // 设置角色存活状态
avatar.LifeState = lifeState if lifeState == constant.LifeStateConst.LIFE_REVIVE {
avatar.LifeState = constant.LifeStateConst.LIFE_ALIVE
// 设置血量
entity.fightProp[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)] = 110
GAME_MANAGER.EntityFightPropUpdateNotifyBroadcast(s, entity, uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP))
}
// PacketAvatarLifeStateChangeNotify // PacketAvatarLifeStateChangeNotify
avatarLifeStateChangeNotify := &proto.AvatarLifeStateChangeNotify{ avatarLifeStateChangeNotify := &proto.AvatarLifeStateChangeNotify{
LifeState: uint32(avatar.LifeState), LifeState: uint32(lifeState),
AttackTag: "", AttackTag: "",
DieType: dieType, DieType: dieType,
ServerBuffList: nil, ServerBuffList: nil,
@@ -665,7 +670,7 @@ func (s *Scene) SetEntityLifeState(entity *Entity, lifeState uint16, dieType pro
AttackTag: "", AttackTag: "",
MoveReliableSeq: entity.lastMoveReliableSeq, MoveReliableSeq: entity.lastMoveReliableSeq,
DieType: dieType, DieType: dieType,
LifeState: uint32(entity.lifeState), LifeState: uint32(lifeState),
SourceEntityId: 0, SourceEntityId: 0,
} }
for _, p := range s.playerMap { for _, p := range s.playerMap {

View File

@@ -81,6 +81,7 @@ func (p *Player) InitAll() {
p.GameObjectGuidMap = make(map[uint64]GameObject) p.GameObjectGuidMap = make(map[uint64]GameObject)
p.CoopApplyMap = make(map[uint32]int64) p.CoopApplyMap = make(map[uint32]int64)
p.StaminaInfo = new(StaminaInfo) p.StaminaInfo = new(StaminaInfo)
p.StaminaInfo.DrownBackPos = new(Vector)
p.VehicleInfo = new(VehicleInfo) p.VehicleInfo = new(VehicleInfo)
p.VehicleInfo.LastCreateEntityIdMap = make(map[uint32]uint32) p.VehicleInfo.LastCreateEntityIdMap = make(map[uint32]uint32)
p.InitAllAvatar() p.InitAllAvatar()

View File

@@ -15,6 +15,7 @@ type StaminaInfo struct {
LastSkillTime int64 // 最后释放技能的时间 LastSkillTime int64 // 最后释放技能的时间
LastSkillStartTime int64 // 最后执行开始技能耐力消耗的时间 LastSkillStartTime int64 // 最后执行开始技能耐力消耗的时间
DrownBackTime int64 // 溺水返回安全点的时间 DrownBackTime int64 // 溺水返回安全点的时间
DrownBackPos *Vector // 溺水返回的安全点坐标
} }
// SetStaminaCost 设置动作需要消耗的耐力 // SetStaminaCost 设置动作需要消耗的耐力