mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-03-01 00:35:36 +08:00
同一类型载具唯一 载具耐力初步
This commit is contained in:
+11
-10
@@ -9,18 +9,19 @@ type StaminaCost struct {
|
|||||||
CLIMB_JUMP int32 // 攀爬跳跃
|
CLIMB_JUMP int32 // 攀爬跳跃
|
||||||
DASH int32 // 快速跑步
|
DASH int32 // 快速跑步
|
||||||
FLY int32 // 滑翔
|
FLY int32 // 滑翔
|
||||||
SKIFF_DASH int32 // 浪船加速
|
|
||||||
SPRINT int32 // 冲刺
|
SPRINT int32 // 冲刺
|
||||||
SWIM_DASH_START int32 // 快速游泳开始
|
SWIM_DASH_START int32 // 快速游泳开始
|
||||||
SWIM_DASH int32 // 快速游泳
|
SWIM_DASH int32 // 快速游泳
|
||||||
SWIMMING int32 // 缓慢游泳
|
SWIMMING int32 // 缓慢游泳
|
||||||
// 恢复耐力
|
// 恢复耐力
|
||||||
POWERED_FLY int32 // 滑翔加速(风圈等)
|
POWERED_FLY int32 // 滑翔加速(风圈等)
|
||||||
POWERED_SKIFF int32 // 浪船加速(风圈等)
|
RUN int32 // 正常跑步
|
||||||
RUN int32 // 正常跑步
|
STANDBY int32 // 站立
|
||||||
SKIFF int32 // 游艇行驶
|
WALK int32 // 走路
|
||||||
STANDBY int32 // 站立
|
// 载具浪船
|
||||||
WALK int32 // 走路
|
SKIFF_DASH int32 // 浪船加速
|
||||||
|
SKIFF_NORMAL int32 // 浪船正常移动 (回复耐力)
|
||||||
|
POWERED_SKIFF int32 // 浪船加速(风圈等) (回复耐力)
|
||||||
// 武器消耗默认值
|
// 武器消耗默认值
|
||||||
FIGHT_SWORD_ONE_HAND int32 // 单手剑
|
FIGHT_SWORD_ONE_HAND int32 // 单手剑
|
||||||
FIGHT_POLE int32 // 长枪
|
FIGHT_POLE int32 // 长枪
|
||||||
@@ -38,17 +39,17 @@ func InitStaminaCostConst() {
|
|||||||
StaminaCostConst.CLIMB_JUMP = -2500
|
StaminaCostConst.CLIMB_JUMP = -2500
|
||||||
StaminaCostConst.DASH = -360
|
StaminaCostConst.DASH = -360
|
||||||
StaminaCostConst.FLY = -60
|
StaminaCostConst.FLY = -60
|
||||||
StaminaCostConst.SKIFF_DASH = -204
|
|
||||||
StaminaCostConst.SPRINT = -1800
|
StaminaCostConst.SPRINT = -1800
|
||||||
StaminaCostConst.SWIM_DASH_START = -2000
|
StaminaCostConst.SWIM_DASH_START = -2000
|
||||||
StaminaCostConst.SWIM_DASH = -204
|
StaminaCostConst.SWIM_DASH = -204
|
||||||
StaminaCostConst.SWIMMING = -400
|
StaminaCostConst.SWIMMING = -400
|
||||||
StaminaCostConst.POWERED_FLY = 500
|
StaminaCostConst.POWERED_FLY = 500
|
||||||
StaminaCostConst.POWERED_SKIFF = 500
|
|
||||||
StaminaCostConst.RUN = 500
|
StaminaCostConst.RUN = 500
|
||||||
StaminaCostConst.SKIFF = 500
|
|
||||||
StaminaCostConst.STANDBY = 500
|
StaminaCostConst.STANDBY = 500
|
||||||
StaminaCostConst.WALK = 500
|
StaminaCostConst.WALK = 500
|
||||||
|
StaminaCostConst.SKIFF_DASH = -204
|
||||||
|
StaminaCostConst.SKIFF_NORMAL = 500
|
||||||
|
StaminaCostConst.POWERED_SKIFF = 500
|
||||||
StaminaCostConst.FIGHT_SWORD_ONE_HAND = -2000
|
StaminaCostConst.FIGHT_SWORD_ONE_HAND = -2000
|
||||||
StaminaCostConst.FIGHT_POLE = -2500
|
StaminaCostConst.FIGHT_POLE = -2500
|
||||||
StaminaCostConst.FIGHT_CATALYST = -5000
|
StaminaCostConst.FIGHT_CATALYST = -5000
|
||||||
|
|||||||
+63
-58
@@ -55,8 +55,14 @@ func (g *GameManager) HandleAbilityStamina(player *model.Player, entry *proto.Ab
|
|||||||
if avatarAbility == nil {
|
if avatarAbility == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 重击对应的耐力消耗
|
// 距离技能开始过去的时间
|
||||||
g.ChargedAttackStamina(player, worldAvatar, avatarAbility)
|
pastTime := time.Now().UnixMilli() - player.StaminaInfo.LastSkillTime
|
||||||
|
// 法器角色轻击也会算触发重击消耗
|
||||||
|
// 所以通过策略判断 必须距离技能开始过去100ms才算重击
|
||||||
|
if player.StaminaInfo.LastSkillId == uint32(avatarAbility.AvatarSkillId) && pastTime > 100 {
|
||||||
|
// 重击对应的耐力消耗
|
||||||
|
g.ChargedAttackStamina(player, worldAvatar, avatarAbility)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -117,7 +123,7 @@ func (g *GameManager) ImmediateStamina(player *model.Player, motionState proto.M
|
|||||||
//logger.LOG.Debug("stamina handle, uid: %v, motionState: %v", player.PlayerID, motionState)
|
//logger.LOG.Debug("stamina handle, uid: %v, motionState: %v", player.PlayerID, motionState)
|
||||||
|
|
||||||
// 设置用于持续消耗或恢复耐力的值
|
// 设置用于持续消耗或恢复耐力的值
|
||||||
g.SetStaminaCost(player, motionState)
|
staminaInfo.SetStaminaCost(motionState)
|
||||||
|
|
||||||
// 未改变状态不执行后面 有些仅在动作开始消耗耐力
|
// 未改变状态不执行后面 有些仅在动作开始消耗耐力
|
||||||
if motionState == staminaInfo.State {
|
if motionState == staminaInfo.State {
|
||||||
@@ -126,6 +132,7 @@ func (g *GameManager) ImmediateStamina(player *model.Player, motionState proto.M
|
|||||||
|
|
||||||
// 记录玩家的动作状态
|
// 记录玩家的动作状态
|
||||||
staminaInfo.State = motionState
|
staminaInfo.State = motionState
|
||||||
|
logger.LOG.Error("state: %v", motionState.String())
|
||||||
|
|
||||||
// 根据玩家的状态立刻消耗耐力
|
// 根据玩家的状态立刻消耗耐力
|
||||||
switch motionState {
|
switch motionState {
|
||||||
@@ -237,7 +244,6 @@ func (g *GameManager) SkillStartStamina(player *model.Player, casterId uint32, s
|
|||||||
|
|
||||||
// 获取该技能开始时所需消耗的耐力
|
// 获取该技能开始时所需消耗的耐力
|
||||||
costStamina := constant.StaminaCostConst.SKILL_START[skillId]
|
costStamina := constant.StaminaCostConst.SKILL_START[skillId]
|
||||||
logger.LOG.Debug("skill start stamina, skillId: %v, cost: %v", skillId, costStamina)
|
|
||||||
|
|
||||||
// 距离上次处理技能开始耐力消耗过去的时间
|
// 距离上次处理技能开始耐力消耗过去的时间
|
||||||
pastTime := time.Now().UnixMilli() - staminaInfo.LastSkillTime
|
pastTime := time.Now().UnixMilli() - staminaInfo.LastSkillTime
|
||||||
@@ -248,8 +254,12 @@ func (g *GameManager) SkillStartStamina(player *model.Player, casterId uint32, s
|
|||||||
// 根据配置消耗耐力
|
// 根据配置消耗耐力
|
||||||
g.UpdateStamina(player, costStamina)
|
g.UpdateStamina(player, costStamina)
|
||||||
|
|
||||||
|
logger.LOG.Debug("skill start stamina, skillId: %v, cost: %v", skillId, costStamina)
|
||||||
|
|
||||||
// 记录最后释放的技能
|
// 记录最后释放的技能
|
||||||
player.StaminaInfo.SetLastSkill(casterId, skillId)
|
staminaInfo.LastCasterId = casterId
|
||||||
|
staminaInfo.LastSkillId = skillId
|
||||||
|
staminaInfo.LastSkillTime = time.Now().UnixMilli()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SustainStaminaHandler 处理持续耐力消耗
|
// SustainStaminaHandler 处理持续耐力消耗
|
||||||
@@ -274,50 +284,6 @@ func (g *GameManager) SustainStaminaHandler(player *model.Player) {
|
|||||||
g.UpdateStamina(player, staminaInfo.CostStamina)
|
g.UpdateStamina(player, staminaInfo.CostStamina)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStaminaCost 设置动作需要消耗的耐力
|
|
||||||
func (g *GameManager) SetStaminaCost(player *model.Player, state proto.MotionState) {
|
|
||||||
staminaInfo := player.StaminaInfo
|
|
||||||
|
|
||||||
// 根据状态决定要修改的耐力
|
|
||||||
// TODO 角色天赋 食物 会影响耐力消耗
|
|
||||||
switch state {
|
|
||||||
// 消耗耐力
|
|
||||||
case proto.MotionState_MOTION_STATE_DASH:
|
|
||||||
// 快速跑步
|
|
||||||
staminaInfo.CostStamina = constant.StaminaCostConst.DASH
|
|
||||||
case proto.MotionState_MOTION_STATE_FLY, proto.MotionState_MOTION_STATE_FLY_FAST, proto.MotionState_MOTION_STATE_FLY_SLOW:
|
|
||||||
// 滑翔
|
|
||||||
staminaInfo.CostStamina = constant.StaminaCostConst.FLY
|
|
||||||
case proto.MotionState_MOTION_STATE_SWIM_DASH:
|
|
||||||
// 快速游泳
|
|
||||||
staminaInfo.CostStamina = constant.StaminaCostConst.SWIM_DASH
|
|
||||||
case proto.MotionState_MOTION_STATE_SKIFF_DASH:
|
|
||||||
// 浪船加速
|
|
||||||
// TODO 玩家使用载具时需要用载具的协议发送prop
|
|
||||||
staminaInfo.CostStamina = constant.StaminaCostConst.SKIFF_DASH
|
|
||||||
// 恢复耐力
|
|
||||||
case proto.MotionState_MOTION_STATE_DANGER_RUN, proto.MotionState_MOTION_STATE_RUN:
|
|
||||||
// 正常跑步
|
|
||||||
staminaInfo.CostStamina = constant.StaminaCostConst.RUN
|
|
||||||
case 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:
|
|
||||||
// 站立
|
|
||||||
staminaInfo.CostStamina = constant.StaminaCostConst.STANDBY
|
|
||||||
case proto.MotionState_MOTION_STATE_DANGER_WALK, proto.MotionState_MOTION_STATE_WALK:
|
|
||||||
// 走路
|
|
||||||
staminaInfo.CostStamina = constant.StaminaCostConst.WALK
|
|
||||||
case proto.MotionState_MOTION_STATE_POWERED_FLY:
|
|
||||||
// 滑翔加速 (风圈等)
|
|
||||||
staminaInfo.CostStamina = constant.StaminaCostConst.POWERED_FLY
|
|
||||||
case proto.MotionState_MOTION_STATE_SKIFF_POWERED_DASH:
|
|
||||||
// 浪船加速 (风圈等)
|
|
||||||
staminaInfo.CostStamina = constant.StaminaCostConst.POWERED_SKIFF
|
|
||||||
// 缓慢动作将在客户端发送消息后消耗
|
|
||||||
case proto.MotionState_MOTION_STATE_CLIMB, proto.MotionState_MOTION_STATE_SWIM_MOVE:
|
|
||||||
// 缓慢攀爬 或 缓慢游泳
|
|
||||||
staminaInfo.CostStamina = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateStamina 更新耐力 当前耐力值 + 消耗的耐力值
|
// UpdateStamina 更新耐力 当前耐力值 + 消耗的耐力值
|
||||||
func (g *GameManager) UpdateStamina(player *model.Player, staminaCost int32) {
|
func (g *GameManager) UpdateStamina(player *model.Player, staminaCost int32) {
|
||||||
// 耐力增加0是没有意义的
|
// 耐力增加0是没有意义的
|
||||||
@@ -330,10 +296,29 @@ func (g *GameManager) UpdateStamina(player *model.Player, staminaCost int32) {
|
|||||||
player.StaminaInfo.RestoreDelay = 0
|
player.StaminaInfo.RestoreDelay = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// 玩家最大耐力值
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
maxStamina := int32(player.PropertiesMap[constant.PlayerPropertyConst.PROP_MAX_STAMINA])
|
scene := world.GetSceneById(player.SceneId)
|
||||||
// 玩家现行耐力值
|
|
||||||
curStamina := int32(player.PropertiesMap[constant.PlayerPropertyConst.PROP_CUR_PERSIST_STAMINA])
|
// 最大耐力值 现行耐力值
|
||||||
|
var maxStamina, curStamina int32
|
||||||
|
// 玩家是否处于载具中
|
||||||
|
var isInVehicle bool
|
||||||
|
|
||||||
|
// 获取载具实体
|
||||||
|
entity := g.GetSceneVehicleEntity(scene, player.VehicleInfo.InVehicleEntityId)
|
||||||
|
// 判断玩家处于载具中
|
||||||
|
if entity != nil && g.IsPlayerInVehicle(player, entity.gadgetEntity.gadgetVehicleEntity) {
|
||||||
|
// 载具耐力
|
||||||
|
// 因为载具的耐力需要换算
|
||||||
|
// 这里先*100后面要用的时候再换算 为了确保精度
|
||||||
|
maxStamina = int32(entity.gadgetEntity.gadgetVehicleEntity.maxStamina * 100)
|
||||||
|
curStamina = int32(entity.gadgetEntity.gadgetVehicleEntity.curStamina * 100)
|
||||||
|
isInVehicle = true
|
||||||
|
} else {
|
||||||
|
// 角色耐力
|
||||||
|
maxStamina = int32(player.PropertiesMap[constant.PlayerPropertyConst.PROP_MAX_STAMINA])
|
||||||
|
curStamina = int32(player.PropertiesMap[constant.PlayerPropertyConst.PROP_CUR_PERSIST_STAMINA])
|
||||||
|
}
|
||||||
|
|
||||||
// 即将更改为的耐力值
|
// 即将更改为的耐力值
|
||||||
stamina := curStamina + staminaCost
|
stamina := curStamina + staminaCost
|
||||||
@@ -350,15 +335,35 @@ func (g *GameManager) UpdateStamina(player *model.Player, staminaCost int32) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
g.SetStamina(player, uint32(stamina))
|
if isInVehicle {
|
||||||
|
// 修改载具现行耐力
|
||||||
|
g.SetVehicleStamina(player, entity.gadgetEntity.gadgetVehicleEntity, float32(stamina)/100)
|
||||||
|
} else {
|
||||||
|
// 修改玩家现行耐力
|
||||||
|
g.SetPlayerStamina(player, uint32(stamina))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStamina 设置玩家的耐力
|
// SetVehicleStamina 设置载具的耐力
|
||||||
func (g *GameManager) SetStamina(player *model.Player, stamina uint32) {
|
func (g *GameManager) SetVehicleStamina(player *model.Player, gadgetVehicleEntity *GadgetVehicleEntity, stamina float32) {
|
||||||
|
// 设置载具的耐力
|
||||||
|
gadgetVehicleEntity.curStamina = stamina
|
||||||
|
logger.LOG.Debug("vehicle stamina set, stamina: %v", stamina)
|
||||||
|
|
||||||
|
// PacketVehicleStaminaNotify
|
||||||
|
vehicleStaminaNotify := new(proto.VehicleStaminaNotify)
|
||||||
|
vehicleStaminaNotify.EntityId = player.VehicleInfo.InVehicleEntityId
|
||||||
|
vehicleStaminaNotify.CurStamina = stamina
|
||||||
|
g.SendMsg(cmd.VehicleStaminaNotify, player.PlayerID, player.ClientSeq, vehicleStaminaNotify)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPlayerStamina 设置玩家的耐力
|
||||||
|
func (g *GameManager) SetPlayerStamina(player *model.Player, stamina uint32) {
|
||||||
|
// 设置玩家的耐力
|
||||||
prop := constant.PlayerPropertyConst.PROP_CUR_PERSIST_STAMINA
|
prop := constant.PlayerPropertyConst.PROP_CUR_PERSIST_STAMINA
|
||||||
// 设置玩家的耐力prop
|
|
||||||
player.PropertiesMap[prop] = stamina
|
player.PropertiesMap[prop] = stamina
|
||||||
//logger.LOG.Debug("player curr stamina: %v", stamina)
|
logger.LOG.Debug("player stamina set, stamina: %v", stamina)
|
||||||
|
|
||||||
// PacketPlayerPropNotify
|
// PacketPlayerPropNotify
|
||||||
playerPropNotify := new(proto.PlayerPropNotify)
|
playerPropNotify := new(proto.PlayerPropNotify)
|
||||||
|
|||||||
+95
-57
@@ -6,6 +6,7 @@ import (
|
|||||||
"hk4e/pkg/logger"
|
"hk4e/pkg/logger"
|
||||||
"hk4e/protocol/cmd"
|
"hk4e/protocol/cmd"
|
||||||
"hk4e/protocol/proto"
|
"hk4e/protocol/proto"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateVehicleReq 创建载具
|
// CreateVehicleReq 创建载具
|
||||||
@@ -15,37 +16,20 @@ func (g *GameManager) CreateVehicleReq(player *model.Player, payloadMsg pb.Messa
|
|||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
scene := world.GetSceneById(player.SceneId)
|
scene := world.GetSceneById(player.SceneId)
|
||||||
|
|
||||||
// TODO req.ScenePointId 验证浪船锚点是否已解锁
|
// 创建载具冷却时间
|
||||||
|
createVehicleCd := int64(5000) // TODO 冷却时间读取配置表
|
||||||
|
if time.Now().UnixMilli()-player.VehicleInfo.LastCreateTime < createVehicleCd {
|
||||||
|
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{}, proto.Retcode_RET_CREATE_VEHICLE_IN_CD)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO req.ScenePointId 验证浪船锚点是否已解锁 Retcode_RET_VEHICLE_POINT_NOT_UNLOCK
|
||||||
|
|
||||||
|
// TODO 验证将要创建的载具位置是否有效 Retcode_RET_CREATE_VEHICLE_POS_INVALID
|
||||||
|
|
||||||
// 清除已创建的载具
|
// 清除已创建的载具
|
||||||
for _, id := range scene.GetEntityIdList() {
|
if player.VehicleInfo.LastCreateEntityId != 0 {
|
||||||
entity := scene.GetEntity(id)
|
g.DestroyVehicleEntity(player, scene, req.VehicleId, player.VehicleInfo.LastCreateEntityId)
|
||||||
// 判断实体类型是否为载具
|
|
||||||
if entity.entityType != uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET) || entity.gadgetEntity.gadgetType != GADGET_TYPE_VEHICLE {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 确保载具Id为将要创建的 (每种载具允许存在1个)
|
|
||||||
if entity.gadgetEntity.gadgetVehicleEntity.vehicleId != req.VehicleId {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 该载具是否为此玩家的
|
|
||||||
if entity.gadgetEntity.gadgetVehicleEntity.owner != player {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 现行角色Guid
|
|
||||||
avatar, ok := player.AvatarMap[player.TeamConfig.GetActiveAvatarId()]
|
|
||||||
if !ok {
|
|
||||||
logger.LOG.Error("avatar is nil, avatarId: %v", player.TeamConfig.GetActiveAvatarId())
|
|
||||||
g.CommonRetError(cmd.CreateVehicleRsp, player, &proto.CreateVehicleRsp{})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 确保玩家正在载具中
|
|
||||||
if g.IsPlayerInVehicle(player, entity.gadgetEntity.gadgetVehicleEntity) {
|
|
||||||
// 离开载具
|
|
||||||
g.ExitVehicle(player, entity, avatar.Guid)
|
|
||||||
}
|
|
||||||
// TODO 删除实体 需要杀死实体 暂时实体模块还没写这个
|
|
||||||
// scene.DestroyEntity(entity.id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建载具实体
|
// 创建载具实体
|
||||||
@@ -54,11 +38,16 @@ func (g *GameManager) CreateVehicleReq(player *model.Player, payloadMsg pb.Messa
|
|||||||
entityId := scene.CreateEntityGadgetVehicle(player.PlayerID, pos, rot, req.VehicleId)
|
entityId := scene.CreateEntityGadgetVehicle(player.PlayerID, pos, rot, req.VehicleId)
|
||||||
if entityId == 0 {
|
if entityId == 0 {
|
||||||
logger.LOG.Error("vehicle entityId is 0, uid: %v", player.PlayerID)
|
logger.LOG.Error("vehicle entityId is 0, uid: %v", player.PlayerID)
|
||||||
g.CommonRetError(cmd.CreateVehicleRsp, player, &proto.CreateVehicleRsp{})
|
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
GAME_MANAGER.AddSceneEntityNotify(player, proto.VisionType_VISION_TYPE_BORN, []uint32{entityId}, true, false)
|
GAME_MANAGER.AddSceneEntityNotify(player, proto.VisionType_VISION_TYPE_BORN, []uint32{entityId}, true, false)
|
||||||
|
|
||||||
|
// 记录创建的载具信息
|
||||||
|
player.VehicleInfo.LastCreateEntityId = entityId
|
||||||
|
player.VehicleInfo.LastCreateTime = time.Now().UnixMilli()
|
||||||
|
|
||||||
|
// PacketCreateVehicleRsp
|
||||||
createVehicleRsp := &proto.CreateVehicleRsp{
|
createVehicleRsp := &proto.CreateVehicleRsp{
|
||||||
VehicleId: req.VehicleId,
|
VehicleId: req.VehicleId,
|
||||||
EntityId: entityId,
|
EntityId: entityId,
|
||||||
@@ -66,8 +55,24 @@ func (g *GameManager) CreateVehicleReq(player *model.Player, payloadMsg pb.Messa
|
|||||||
g.SendMsg(cmd.CreateVehicleRsp, player.PlayerID, player.ClientSeq, createVehicleRsp)
|
g.SendMsg(cmd.CreateVehicleRsp, player.PlayerID, player.ClientSeq, createVehicleRsp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSceneVehicleEntity 获取场景内的载具实体
|
||||||
|
func (g *GameManager) GetSceneVehicleEntity(scene *Scene, entityId uint32) *Entity {
|
||||||
|
entity := scene.GetEntity(entityId)
|
||||||
|
if entity == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// 确保实体类型是否为载具
|
||||||
|
if entity.entityType == uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET) && entity.gadgetEntity.gadgetType == GADGET_TYPE_VEHICLE {
|
||||||
|
return entity
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsPlayerInVehicle 判断玩家是否在载具中
|
// IsPlayerInVehicle 判断玩家是否在载具中
|
||||||
func (g *GameManager) IsPlayerInVehicle(player *model.Player, gadgetVehicleEntity *GadgetVehicleEntity) bool {
|
func (g *GameManager) IsPlayerInVehicle(player *model.Player, gadgetVehicleEntity *GadgetVehicleEntity) bool {
|
||||||
|
if gadgetVehicleEntity == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
for _, p := range gadgetVehicleEntity.memberMap {
|
for _, p := range gadgetVehicleEntity.memberMap {
|
||||||
if p == player {
|
if p == player {
|
||||||
return true
|
return true
|
||||||
@@ -76,28 +81,61 @@ func (g *GameManager) IsPlayerInVehicle(player *model.Player, gadgetVehicleEntit
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnterVehicle 进入载具
|
// DestroyVehicleEntity 删除载具实体
|
||||||
func (g *GameManager) EnterVehicle(player *model.Player, entity *Entity, avatarGuid uint64) {
|
func (g *GameManager) DestroyVehicleEntity(player *model.Player, scene *Scene, vehicleId uint32, entityId uint32) {
|
||||||
// 玩家是否已进入载具
|
entity := g.GetSceneVehicleEntity(scene, entityId)
|
||||||
if g.IsPlayerInVehicle(player, entity.gadgetEntity.gadgetVehicleEntity) {
|
if entity == nil {
|
||||||
logger.LOG.Error("vehicle has equal player, uid: %v", player.PlayerID)
|
|
||||||
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 找出载具空闲的位置
|
// 确保载具Id为将要创建的 (每种载具允许存在1个)
|
||||||
pos := uint32(0)
|
if entity.gadgetEntity.gadgetVehicleEntity.vehicleId != vehicleId {
|
||||||
for entity.gadgetEntity.gadgetVehicleEntity.memberMap[pos] != nil {
|
return
|
||||||
pos++
|
|
||||||
}
|
}
|
||||||
// 载具成员记录玩家
|
// 该载具是否为此玩家的
|
||||||
entity.gadgetEntity.gadgetVehicleEntity.memberMap[pos] = player
|
if entity.gadgetEntity.gadgetVehicleEntity.owner != player {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 确保玩家正在载具中
|
||||||
|
if g.IsPlayerInVehicle(player, entity.gadgetEntity.gadgetVehicleEntity) {
|
||||||
|
// 离开载具
|
||||||
|
g.ExitVehicle(player, entity, player.AvatarMap[player.TeamConfig.GetActiveAvatarId()].Guid)
|
||||||
|
}
|
||||||
|
// 删除已创建的载具
|
||||||
|
scene.DestroyEntity(entity.id)
|
||||||
|
g.RemoveSceneEntityNotifyBroadcast(scene, proto.VisionType_VISION_TYPE_MISS, []uint32{entity.id})
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnterVehicle 进入载具
|
||||||
|
func (g *GameManager) EnterVehicle(player *model.Player, entity *Entity, avatarGuid uint64) {
|
||||||
|
maxSlot := 1 // TODO 读取配置表
|
||||||
|
// 判断载具是否已满
|
||||||
|
if len(entity.gadgetEntity.gadgetVehicleEntity.memberMap) >= maxSlot {
|
||||||
|
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{}, proto.Retcode_RET_VEHICLE_SLOT_OCCUPIED)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找出载具空闲的位置
|
||||||
|
var freePos uint32
|
||||||
|
for i := uint32(0); i < uint32(maxSlot); i++ {
|
||||||
|
p := entity.gadgetEntity.gadgetVehicleEntity.memberMap[i]
|
||||||
|
// 玩家如果已进入载具重复记录不进行报错
|
||||||
|
if p == player || p == nil {
|
||||||
|
// 载具成员记录玩家
|
||||||
|
entity.gadgetEntity.gadgetVehicleEntity.memberMap[i] = player
|
||||||
|
freePos = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录玩家所在的载具信息
|
||||||
|
player.VehicleInfo.InVehicleEntityId = entity.id
|
||||||
|
|
||||||
|
// PacketVehicleInteractRsp
|
||||||
vehicleInteractRsp := &proto.VehicleInteractRsp{
|
vehicleInteractRsp := &proto.VehicleInteractRsp{
|
||||||
InteractType: proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_IN,
|
InteractType: proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_IN,
|
||||||
Member: &proto.VehicleMember{
|
Member: &proto.VehicleMember{
|
||||||
Uid: player.PlayerID,
|
Uid: player.PlayerID,
|
||||||
AvatarGuid: avatarGuid,
|
AvatarGuid: avatarGuid,
|
||||||
Pos: pos, // 应该是多人坐船时的位置?
|
Pos: freePos, // 应该是多人坐船时的位置?
|
||||||
},
|
},
|
||||||
EntityId: entity.id,
|
EntityId: entity.id,
|
||||||
}
|
}
|
||||||
@@ -109,7 +147,7 @@ func (g *GameManager) ExitVehicle(player *model.Player, entity *Entity, avatarGu
|
|||||||
// 玩家是否进入载具
|
// 玩家是否进入载具
|
||||||
if !g.IsPlayerInVehicle(player, entity.gadgetEntity.gadgetVehicleEntity) {
|
if !g.IsPlayerInVehicle(player, entity.gadgetEntity.gadgetVehicleEntity) {
|
||||||
logger.LOG.Error("vehicle not has player, uid: %v", player.PlayerID)
|
logger.LOG.Error("vehicle not has player, uid: %v", player.PlayerID)
|
||||||
g.SendMsg(cmd.VehicleInteractRsp, player.PlayerID, player.ClientSeq, &proto.VehicleInteractRsp{Retcode: int32(proto.Retcode_RET_NOT_IN_VEHICLE)})
|
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{}, proto.Retcode_RET_NOT_IN_VEHICLE)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 载具成员删除玩家
|
// 载具成员删除玩家
|
||||||
@@ -120,7 +158,10 @@ func (g *GameManager) ExitVehicle(player *model.Player, entity *Entity, avatarGu
|
|||||||
delete(entity.gadgetEntity.gadgetVehicleEntity.memberMap, pos)
|
delete(entity.gadgetEntity.gadgetVehicleEntity.memberMap, pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 清除记录的所在载具信息
|
||||||
|
player.VehicleInfo.InVehicleEntityId = 0
|
||||||
|
|
||||||
|
// PacketVehicleInteractRsp
|
||||||
vehicleInteractRsp := &proto.VehicleInteractRsp{
|
vehicleInteractRsp := &proto.VehicleInteractRsp{
|
||||||
InteractType: proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_OUT,
|
InteractType: proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_OUT,
|
||||||
Member: &proto.VehicleMember{
|
Member: &proto.VehicleMember{
|
||||||
@@ -137,34 +178,31 @@ func (g *GameManager) ExitVehicle(player *model.Player, entity *Entity, avatarGu
|
|||||||
func (g *GameManager) VehicleInteractReq(player *model.Player, payloadMsg pb.Message) {
|
func (g *GameManager) VehicleInteractReq(player *model.Player, payloadMsg pb.Message) {
|
||||||
req := payloadMsg.(*proto.VehicleInteractReq)
|
req := payloadMsg.(*proto.VehicleInteractReq)
|
||||||
|
|
||||||
// 获取载具实体
|
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
entity := world.GetSceneById(player.SceneId).GetEntity(req.EntityId)
|
scene := world.GetSceneById(player.SceneId)
|
||||||
|
|
||||||
|
// 获取载具实体
|
||||||
|
entity := g.GetSceneVehicleEntity(scene, req.EntityId)
|
||||||
if entity == nil {
|
if entity == nil {
|
||||||
logger.LOG.Error("vehicle entity is nil, entityId: %v", req.EntityId)
|
logger.LOG.Error("vehicle entity is nil, entityId: %v", req.EntityId)
|
||||||
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{})
|
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{}, proto.Retcode_RET_ENTITY_NOT_EXIST)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 判断实体类型是否为载具
|
// 判断实体类型是否为载具
|
||||||
if entity.entityType != uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET) || entity.gadgetEntity.gadgetType != GADGET_TYPE_VEHICLE {
|
if entity.entityType != uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET) || entity.gadgetEntity.gadgetType != GADGET_TYPE_VEHICLE {
|
||||||
logger.LOG.Error("vehicle entity error, entityType: %v", entity.entityType)
|
logger.LOG.Error("vehicle entity error, entityType: %v", entity.entityType)
|
||||||
g.SendMsg(cmd.VehicleInteractRsp, player.PlayerID, player.ClientSeq, &proto.VehicleInteractRsp{Retcode: int32(proto.Retcode_RET_GADGET_NOT_VEHICLE)})
|
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{}, proto.Retcode_RET_GADGET_NOT_VEHICLE)
|
||||||
return
|
|
||||||
}
|
|
||||||
// 现行角色Guid
|
|
||||||
avatar, ok := player.AvatarMap[player.TeamConfig.GetActiveAvatarId()]
|
|
||||||
if !ok {
|
|
||||||
logger.LOG.Error("avatar is nil, avatarId: %v", player.TeamConfig.GetActiveAvatarId())
|
|
||||||
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
avatarGuid := player.AvatarMap[player.TeamConfig.GetActiveAvatarId()].Guid
|
||||||
|
|
||||||
switch req.InteractType {
|
switch req.InteractType {
|
||||||
case proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_IN:
|
case proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_IN:
|
||||||
// 进入载具
|
// 进入载具
|
||||||
g.EnterVehicle(player, entity, avatar.Guid)
|
g.EnterVehicle(player, entity, avatarGuid)
|
||||||
case proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_OUT:
|
case proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_OUT:
|
||||||
// 离开载具
|
// 离开载具
|
||||||
g.ExitVehicle(player, entity, avatar.Guid)
|
g.ExitVehicle(player, entity, avatarGuid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -540,6 +540,7 @@ type GadgetGatherEntity struct {
|
|||||||
type GadgetVehicleEntity struct {
|
type GadgetVehicleEntity struct {
|
||||||
vehicleId uint32
|
vehicleId uint32
|
||||||
owner *model.Player
|
owner *model.Player
|
||||||
|
maxStamina float32
|
||||||
curStamina float32
|
curStamina float32
|
||||||
memberMap map[uint32]*model.Player // uint32 = pos
|
memberMap map[uint32]*model.Player // uint32 = pos
|
||||||
}
|
}
|
||||||
@@ -752,7 +753,8 @@ func (s *Scene) CreateEntityGadgetVehicle(uid uint32, pos, rot *model.Vector, ve
|
|||||||
gadgetVehicleEntity: &GadgetVehicleEntity{
|
gadgetVehicleEntity: &GadgetVehicleEntity{
|
||||||
vehicleId: vehicleId,
|
vehicleId: vehicleId,
|
||||||
owner: player,
|
owner: player,
|
||||||
curStamina: 240, // TODO 应该也能在配置表找到
|
maxStamina: 240, // TODO 应该也能在配置表找到
|
||||||
|
curStamina: 240, // TODO 与maxStamina一致
|
||||||
memberMap: make(map[uint32]*model.Player),
|
memberMap: make(map[uint32]*model.Player),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ type Player struct {
|
|||||||
SceneLoadState int `bson:"-" msgpack:"-"` // 场景加载状态
|
SceneLoadState int `bson:"-" msgpack:"-"` // 场景加载状态
|
||||||
CoopApplyMap map[uint32]int64 `bson:"-" msgpack:"-"` // 敲门申请的玩家uid及时间
|
CoopApplyMap map[uint32]int64 `bson:"-" msgpack:"-"` // 敲门申请的玩家uid及时间
|
||||||
StaminaInfo *StaminaInfo `bson:"-" msgpack:"-"` // 耐力临时数据
|
StaminaInfo *StaminaInfo `bson:"-" msgpack:"-"` // 耐力临时数据
|
||||||
|
VehicleInfo *VehicleInfo `bson:"-" msgpack:"-"` // 载具临时数据
|
||||||
ClientSeq uint32 `bson:"-" msgpack:"-"` // 客户端发包请求的序号
|
ClientSeq uint32 `bson:"-" msgpack:"-"` // 客户端发包请求的序号
|
||||||
CombatInvokeHandler *InvokeHandler[proto.CombatInvokeEntry] `bson:"-" msgpack:"-"` // combat转发器
|
CombatInvokeHandler *InvokeHandler[proto.CombatInvokeEntry] `bson:"-" msgpack:"-"` // combat转发器
|
||||||
AbilityInvokeHandler *InvokeHandler[proto.AbilityInvokeEntry] `bson:"-" msgpack:"-"` // ability转发器
|
AbilityInvokeHandler *InvokeHandler[proto.AbilityInvokeEntry] `bson:"-" msgpack:"-"` // ability转发器
|
||||||
@@ -79,6 +80,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.VehicleInfo = new(VehicleInfo)
|
||||||
p.InitAllAvatar()
|
p.InitAllAvatar()
|
||||||
p.InitAllWeapon()
|
p.InitAllWeapon()
|
||||||
p.InitAllItem()
|
p.InitAllItem()
|
||||||
|
|||||||
+43
-6
@@ -1,8 +1,8 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"hk4e/gs/constant"
|
||||||
"hk4e/protocol/proto"
|
"hk4e/protocol/proto"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StaminaInfo struct {
|
type StaminaInfo struct {
|
||||||
@@ -14,9 +14,46 @@ type StaminaInfo struct {
|
|||||||
LastSkillTime int64 // 最后释放技能的时间
|
LastSkillTime int64 // 最后释放技能的时间
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLastSkill 记录技能以便后续使用
|
// SetStaminaCost 设置动作需要消耗的耐力
|
||||||
func (s *StaminaInfo) SetLastSkill(casterId uint32, skillId uint32) {
|
func (s *StaminaInfo) SetStaminaCost(state proto.MotionState) {
|
||||||
s.LastCasterId = casterId
|
// 根据状态决定要修改的耐力
|
||||||
s.LastSkillId = skillId
|
// TODO 角色天赋 食物 会影响耐力消耗
|
||||||
s.LastSkillTime = time.Now().UnixMilli()
|
switch state {
|
||||||
|
// 消耗耐力
|
||||||
|
case proto.MotionState_MOTION_STATE_DASH:
|
||||||
|
// 快速跑步
|
||||||
|
s.CostStamina = constant.StaminaCostConst.DASH
|
||||||
|
case proto.MotionState_MOTION_STATE_FLY, proto.MotionState_MOTION_STATE_FLY_FAST, proto.MotionState_MOTION_STATE_FLY_SLOW:
|
||||||
|
// 滑翔
|
||||||
|
s.CostStamina = constant.StaminaCostConst.FLY
|
||||||
|
case proto.MotionState_MOTION_STATE_SWIM_DASH:
|
||||||
|
// 快速游泳
|
||||||
|
s.CostStamina = constant.StaminaCostConst.SWIM_DASH
|
||||||
|
case proto.MotionState_MOTION_STATE_SKIFF_DASH:
|
||||||
|
// 浪船加速
|
||||||
|
s.CostStamina = constant.StaminaCostConst.SKIFF_DASH
|
||||||
|
// 恢复耐力
|
||||||
|
case proto.MotionState_MOTION_STATE_DANGER_RUN, proto.MotionState_MOTION_STATE_RUN:
|
||||||
|
// 正常跑步
|
||||||
|
s.CostStamina = constant.StaminaCostConst.RUN
|
||||||
|
case 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:
|
||||||
|
// 站立
|
||||||
|
s.CostStamina = constant.StaminaCostConst.STANDBY
|
||||||
|
case proto.MotionState_MOTION_STATE_DANGER_WALK, proto.MotionState_MOTION_STATE_WALK:
|
||||||
|
// 走路
|
||||||
|
s.CostStamina = constant.StaminaCostConst.WALK
|
||||||
|
case proto.MotionState_MOTION_STATE_SKIFF_BOARDING, proto.MotionState_MOTION_STATE_SKIFF_NORMAL:
|
||||||
|
// 浪船正常移动或停下
|
||||||
|
s.CostStamina = constant.StaminaCostConst.SKIFF_NORMAL
|
||||||
|
case proto.MotionState_MOTION_STATE_POWERED_FLY:
|
||||||
|
// 滑翔加速 (风圈等)
|
||||||
|
s.CostStamina = constant.StaminaCostConst.POWERED_FLY
|
||||||
|
case proto.MotionState_MOTION_STATE_SKIFF_POWERED_DASH:
|
||||||
|
// 浪船加速 (风圈等)
|
||||||
|
s.CostStamina = constant.StaminaCostConst.POWERED_SKIFF
|
||||||
|
// 缓慢动作将在客户端发送消息后消耗
|
||||||
|
case proto.MotionState_MOTION_STATE_CLIMB, proto.MotionState_MOTION_STATE_SWIM_MOVE:
|
||||||
|
// 缓慢攀爬 或 缓慢游泳
|
||||||
|
s.CostStamina = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type VehicleInfo struct {
|
||||||
|
InVehicleEntityId uint32 // 玩家所在载具的实体Id
|
||||||
|
LastCreateTime int64 // 最后一次创建载具的时间
|
||||||
|
LastCreateEntityId uint32 // 最后一次创建载具的实体Id
|
||||||
|
}
|
||||||
@@ -231,10 +231,11 @@ func (c *CmdProtoMap) registerAllMessage() {
|
|||||||
c.registerMessage(McoinExchangeHcoinRsp, &proto.McoinExchangeHcoinRsp{}) // 结晶换原石响应
|
c.registerMessage(McoinExchangeHcoinRsp, &proto.McoinExchangeHcoinRsp{}) // 结晶换原石响应
|
||||||
|
|
||||||
// 载具
|
// 载具
|
||||||
c.registerMessage(CreateVehicleReq, &proto.CreateVehicleReq{}) // 创建载具请求
|
c.registerMessage(CreateVehicleReq, &proto.CreateVehicleReq{}) // 创建载具请求
|
||||||
c.registerMessage(CreateVehicleRsp, &proto.CreateVehicleRsp{}) // 创建载具响应
|
c.registerMessage(CreateVehicleRsp, &proto.CreateVehicleRsp{}) // 创建载具响应
|
||||||
c.registerMessage(VehicleInteractReq, &proto.VehicleInteractReq{}) // 载具交互请求
|
c.registerMessage(VehicleInteractReq, &proto.VehicleInteractReq{}) // 载具交互请求
|
||||||
c.registerMessage(VehicleInteractRsp, &proto.VehicleInteractRsp{}) // 载具交互响应
|
c.registerMessage(VehicleInteractRsp, &proto.VehicleInteractRsp{}) // 载具交互响应
|
||||||
|
c.registerMessage(VehicleStaminaNotify, &proto.VehicleStaminaNotify{}) // 载具耐力消耗通知
|
||||||
|
|
||||||
// 乱七八糟
|
// 乱七八糟
|
||||||
c.registerMessage(MarkMapReq, &proto.MarkMapReq{}) // 标记地图请求
|
c.registerMessage(MarkMapReq, &proto.MarkMapReq{}) // 标记地图请求
|
||||||
|
|||||||
Reference in New Issue
Block a user