From 056ae5f8d8050838ba3b2d23e6b5cb85228e129a Mon Sep 17 00:00:00 2001 From: UnKownOwO <80520429@qq.com> Date: Tue, 20 Dec 2022 18:13:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=BA=BA=E6=B0=B4=E4=BC=A0=E9=80=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20=E6=BA=BA=E6=B0=B4=E5=AE=89=E5=85=A8=E7=82=B9?= =?UTF-8?q?=E6=97=A0=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gs/constant/enter_reason.go | 62 +++++++++++++++++------------------ gs/game/command_gm.go | 3 +- gs/game/route_manager.go | 2 +- gs/game/user_fight_sync.go | 21 ++++-------- gs/game/user_map.go | 10 +++--- gs/game/user_stamina.go | 64 ++++++++++++++++++++++++++----------- gs/game/world_manager.go | 11 +++++-- gs/model/player.go | 1 + gs/model/stamina.go | 1 + 9 files changed, 101 insertions(+), 74 deletions(-) diff --git a/gs/constant/enter_reason.go b/gs/constant/enter_reason.go index 7f3e5224..774f512c 100644 --- a/gs/constant/enter_reason.go +++ b/gs/constant/enter_reason.go @@ -4,37 +4,37 @@ var EnterReasonConst *EnterReason type EnterReason struct { None uint16 - Login uint16 - DungeonReplay uint16 - DungeonReviveOnWaypoint uint16 - DungeonEnter uint16 - DungeonQuit uint16 - Gm uint16 - QuestRollback uint16 - Revival uint16 - PersonalScene uint16 - TransPoint uint16 - ClientTransmit uint16 - ForceDragBack uint16 - TeamKick uint16 - TeamJoin uint16 - TeamBack uint16 - Muip uint16 - DungeonInviteAccept uint16 - Lua uint16 - ActivityLoadTerrain uint16 - HostFromSingleToMp uint16 - MpPlay uint16 - AnchorPoint uint16 - LuaSkipUi uint16 - ReloadTerrain uint16 - DraftTransfer uint16 - EnterHome uint16 - ExitHome uint16 - ChangeHomeModule uint16 - Gallery uint16 - HomeSceneJump uint16 - HideAndSeek uint16 + Login uint16 // 登录 + DungeonReplay uint16 // 秘境重新挑战 + DungeonReviveOnWaypoint uint16 // 秘境重生 + DungeonEnter uint16 // 秘境进入 + DungeonQuit uint16 // 秘境离开 + Gm uint16 // 管理员 + QuestRollback uint16 // 任务回滚 + Revival uint16 // 重生 + PersonalScene uint16 // 个人场景 + TransPoint uint16 // 传送点 + ClientTransmit uint16 // 客户端传送 + ForceDragBack uint16 // 强制后退 + TeamKick uint16 // 队伍踢出 + TeamJoin uint16 // 队伍加入 + TeamBack uint16 // 队伍返回 + Muip uint16 // ?? + DungeonInviteAccept uint16 // 秘境邀请接受 + Lua uint16 // 脚本 + ActivityLoadTerrain uint16 // 活动加载地形 + HostFromSingleToMp uint16 // 房主从单人到多人 + MpPlay uint16 // 多人游戏 + AnchorPoint uint16 // 迷你锚点 + LuaSkipUi uint16 // 脚本跳过UI + ReloadTerrain uint16 // 重载地形 + DraftTransfer uint16 // 某个东西传送 ?? + EnterHome uint16 // 进入尘歌壶 + ExitHome uint16 // 离开尘歌壶 + ChangeHomeModule uint16 // 更改尘歌壶模块 + Gallery uint16 // ?? + HomeSceneJump uint16 // 尘歌壶场景跳转 + HideAndSeek uint16 // 隐藏和搜索 ?? } func InitEnterReasonConst() { diff --git a/gs/game/command_gm.go b/gs/game/command_gm.go index d8e68bc9..5407cdd9 100644 --- a/gs/game/command_gm.go +++ b/gs/game/command_gm.go @@ -1,6 +1,7 @@ package game import ( + "hk4e/gs/constant" "hk4e/gs/model" "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) return } - GAME_MANAGER.TeleportPlayer(player, sceneId, &model.Vector{ + GAME_MANAGER.TeleportPlayer(player, uint32(constant.EnterReasonConst.Gm), sceneId, &model.Vector{ X: posX, Y: posY, Z: posZ, diff --git a/gs/game/route_manager.go b/gs/game/route_manager.go index ba8ef0ac..68e8c00b 100644 --- a/gs/game/route_manager.go +++ b/gs/game/route_manager.go @@ -38,7 +38,7 @@ func (r *RouteManager) doRoute(cmdId uint16, userId uint32, clientSeq uint32, pa if player == nil { logger.Error("player is nil, uid: %v", userId) // 临时为了调试便捷搞的重连 生产环境请务必去除 不然新用户会一直重连不能进入 - // GAME_MANAGER.ReconnectPlayer(userId) + GAME_MANAGER.ReconnectPlayer(userId) return } player.ClientSeq = clientSeq diff --git a/gs/game/user_fight_sync.go b/gs/game/user_fight_sync.go index eb2fb0a7..4b8ef5e8 100644 --- a/gs/game/user_fight_sync.go +++ b/gs/game/user_fight_sync.go @@ -113,21 +113,12 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p if sceneEntity.avatarEntity != nil { // 玩家实体在移动 // 更新玩家的位置信息 - - switch motionInfo.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.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) - - } + 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) diff --git a/gs/game/user_map.go b/gs/game/user_map.go index d0b92737..189726d3 100644 --- a/gs/game/user_map.go +++ b/gs/game/user_map.go @@ -1,10 +1,10 @@ package game import ( + "hk4e/gs/constant" "strconv" gdc "hk4e/gs/config" - "hk4e/gs/constant" "hk4e/gs/model" "hk4e/pkg/logger" "hk4e/protocol/cmd" @@ -32,7 +32,7 @@ func (g *GameManager) SceneTransToPointReq(player *model.Player, payloadMsg pb.M Y: transPos.Y, Z: transPos.Z, } - g.TeleportPlayer(player, sceneId, pos) + g.TeleportPlayer(player, uint32(constant.EnterReasonConst.TransPoint), sceneId, pos) sceneTransToPointRsp := &proto.SceneTransToPointRsp{ Retcode: 0, @@ -60,13 +60,13 @@ func (g *GameManager) MarkMapReq(player *model.Player, payloadMsg pb.Message) { Y: float64(posYInt), 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 传送玩家至地图上的某个位置 -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 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) 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) } diff --git a/gs/game/user_stamina.go b/gs/game/user_stamina.go index 4e5ef3fe..7c9421b9 100644 --- a/gs/game/user_stamina.go +++ b/gs/game/user_stamina.go @@ -422,26 +422,54 @@ func (g *GameManager) DrownBackHandler(player *model.Player) { if player.StaminaInfo.DrownBackTime == 0 { return } - if time.Now().UnixMilli() >= player.StaminaInfo.DrownBackTime { - world := WORLD_MANAGER.GetWorldByID(player.WorldId) - scene := world.GetSceneById(player.SceneId) - activeAvatar := world.GetPlayerWorldAvatar(player, player.TeamConfig.GetActiveAvatarId()) - avatarEntity := scene.GetEntity(activeAvatar.avatarEntityId) - if avatarEntity == nil { - logger.Error("avatar entity is nil, entityId: %v", activeAvatar.avatarEntityId) - return + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + scene := world.GetSceneById(player.SceneId) + activeAvatar := world.GetPlayerWorldAvatar(player, world.GetPlayerActiveAvatarId(player)) + avatarEntity := scene.GetEntity(activeAvatar.avatarEntityId) + if avatarEntity == nil { + logger.Error("avatar entity is nil, entityId: %v", activeAvatar.avatarEntityId) + 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 目前存在的问题 - // 传送会显示玩家实体后再传送 返回安全位置写的不是很好可能存在问题 - // 官服 游戏离线也会回到安全位置 - - // 设置角色存活 - scene.SetEntityLifeState(avatarEntity, constant.LifeStateConst.LIFE_ALIVE, proto.PlayerDieType_PLAYER_DIE_TYPE_NONE) + } else if time.Now().UnixMilli() >= player.StaminaInfo.DrownBackTime { + // 临时 防止一直淹死 尚未完善 + g.SetPlayerStamina(player, 10000) // 传送玩家至安全位置 - g.TeleportPlayer(player, player.SceneId, player.Pos) + g.TeleportPlayer(player, uint32(constant.EnterReasonConst.Revival), player.SceneId, player.StaminaInfo.DrownBackPos) - // 重置溺水返回时间 - player.StaminaInfo.DrownBackTime = 0 + // 设置溺水返回时间为1 + // 1代表加载完场景后再复活玩家 + player.StaminaInfo.DrownBackTime = 1 // 重置动作状态否则可能会导致多次溺水 player.StaminaInfo.State = 0 } @@ -456,7 +484,7 @@ func (g *GameManager) HandleDrown(player *model.Player, stamina uint32) { world := WORLD_MANAGER.GetWorldByID(player.WorldId) scene := world.GetSceneById(player.SceneId) - activeAvatar := world.GetPlayerWorldAvatar(player, player.TeamConfig.GetActiveAvatarId()) + activeAvatar := world.GetPlayerWorldAvatar(player, world.GetPlayerActiveAvatarId(player)) avatarEntity := scene.GetEntity(activeAvatar.avatarEntityId) if avatarEntity == nil { logger.Error("avatar entity is nil, entityId: %v", activeAvatar.avatarEntityId) diff --git a/gs/game/world_manager.go b/gs/game/world_manager.go index 215d494f..ab05eb1f 100644 --- a/gs/game/world_manager.go +++ b/gs/game/world_manager.go @@ -634,11 +634,16 @@ func (s *Scene) SetEntityLifeState(entity *Entity, lifeState uint16, dieType pro 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 avatarLifeStateChangeNotify := &proto.AvatarLifeStateChangeNotify{ - LifeState: uint32(avatar.LifeState), + LifeState: uint32(lifeState), AttackTag: "", DieType: dieType, ServerBuffList: nil, @@ -665,7 +670,7 @@ func (s *Scene) SetEntityLifeState(entity *Entity, lifeState uint16, dieType pro AttackTag: "", MoveReliableSeq: entity.lastMoveReliableSeq, DieType: dieType, - LifeState: uint32(entity.lifeState), + LifeState: uint32(lifeState), SourceEntityId: 0, } for _, p := range s.playerMap { diff --git a/gs/model/player.go b/gs/model/player.go index 6300b4b1..6d1c9708 100644 --- a/gs/model/player.go +++ b/gs/model/player.go @@ -81,6 +81,7 @@ func (p *Player) InitAll() { p.GameObjectGuidMap = make(map[uint64]GameObject) p.CoopApplyMap = make(map[uint32]int64) p.StaminaInfo = new(StaminaInfo) + p.StaminaInfo.DrownBackPos = new(Vector) p.VehicleInfo = new(VehicleInfo) p.VehicleInfo.LastCreateEntityIdMap = make(map[uint32]uint32) p.InitAllAvatar() diff --git a/gs/model/stamina.go b/gs/model/stamina.go index 56c32abc..3d7a580e 100644 --- a/gs/model/stamina.go +++ b/gs/model/stamina.go @@ -15,6 +15,7 @@ type StaminaInfo struct { LastSkillTime int64 // 最后释放技能的时间 LastSkillStartTime int64 // 最后执行开始技能耐力消耗的时间 DrownBackTime int64 // 溺水返回安全点的时间 + DrownBackPos *Vector // 溺水返回的安全点坐标 } // SetStaminaCost 设置动作需要消耗的耐力