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

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 {
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() {

View File

@@ -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,

View File

@@ -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

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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()

View File

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