同一类型载具唯一 载具耐力初步

This commit is contained in:
UnKownOwO
2022-12-15 23:16:52 +08:00
parent 3a2b82585f
commit 072caf5302
8 changed files with 229 additions and 136 deletions

View File

@@ -9,18 +9,19 @@ type StaminaCost struct {
CLIMB_JUMP int32 // 攀爬跳跃
DASH int32 // 快速跑步
FLY int32 // 滑翔
SKIFF_DASH int32 // 浪船加速
SPRINT int32 // 冲刺
SWIM_DASH_START int32 // 快速游泳开始
SWIM_DASH int32 // 快速游泳
SWIMMING int32 // 缓慢游泳
// 恢复耐力
POWERED_FLY int32 // 滑翔加速(风圈等)
POWERED_SKIFF int32 // 浪船加速(风圈等)
RUN int32 // 正常跑步
SKIFF int32 // 游艇行驶
STANDBY int32 // 站立
WALK int32 // 走路
POWERED_FLY int32 // 滑翔加速(风圈等)
RUN int32 // 正常跑步
STANDBY int32 // 站立
WALK int32 // 走路
// 载具浪船
SKIFF_DASH int32 // 浪船加速
SKIFF_NORMAL int32 // 浪船正常移动 (回复耐力)
POWERED_SKIFF int32 // 浪船加速(风圈等) (回复耐力)
// 武器消耗默认值
FIGHT_SWORD_ONE_HAND int32 // 单手剑
FIGHT_POLE int32 // 长枪
@@ -38,17 +39,17 @@ func InitStaminaCostConst() {
StaminaCostConst.CLIMB_JUMP = -2500
StaminaCostConst.DASH = -360
StaminaCostConst.FLY = -60
StaminaCostConst.SKIFF_DASH = -204
StaminaCostConst.SPRINT = -1800
StaminaCostConst.SWIM_DASH_START = -2000
StaminaCostConst.SWIM_DASH = -204
StaminaCostConst.SWIMMING = -400
StaminaCostConst.POWERED_FLY = 500
StaminaCostConst.POWERED_SKIFF = 500
StaminaCostConst.RUN = 500
StaminaCostConst.SKIFF = 500
StaminaCostConst.STANDBY = 500
StaminaCostConst.WALK = 500
StaminaCostConst.SKIFF_DASH = -204
StaminaCostConst.SKIFF_NORMAL = 500
StaminaCostConst.POWERED_SKIFF = 500
StaminaCostConst.FIGHT_SWORD_ONE_HAND = -2000
StaminaCostConst.FIGHT_POLE = -2500
StaminaCostConst.FIGHT_CATALYST = -5000

View File

@@ -55,8 +55,14 @@ func (g *GameManager) HandleAbilityStamina(player *model.Player, entry *proto.Ab
if avatarAbility == nil {
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:
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)
// 设置用于持续消耗或恢复耐力的值
g.SetStaminaCost(player, motionState)
staminaInfo.SetStaminaCost(motionState)
// 未改变状态不执行后面 有些仅在动作开始消耗耐力
if motionState == staminaInfo.State {
@@ -126,6 +132,7 @@ func (g *GameManager) ImmediateStamina(player *model.Player, motionState proto.M
// 记录玩家的动作状态
staminaInfo.State = motionState
logger.LOG.Error("state: %v", motionState.String())
// 根据玩家的状态立刻消耗耐力
switch motionState {
@@ -237,7 +244,6 @@ func (g *GameManager) SkillStartStamina(player *model.Player, casterId uint32, s
// 获取该技能开始时所需消耗的耐力
costStamina := constant.StaminaCostConst.SKILL_START[skillId]
logger.LOG.Debug("skill start stamina, skillId: %v, cost: %v", skillId, costStamina)
// 距离上次处理技能开始耐力消耗过去的时间
pastTime := time.Now().UnixMilli() - staminaInfo.LastSkillTime
@@ -248,8 +254,12 @@ func (g *GameManager) SkillStartStamina(player *model.Player, casterId uint32, s
// 根据配置消耗耐力
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 处理持续耐力消耗
@@ -274,50 +284,6 @@ func (g *GameManager) SustainStaminaHandler(player *model.Player) {
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 更新耐力 当前耐力值 + 消耗的耐力值
func (g *GameManager) UpdateStamina(player *model.Player, staminaCost int32) {
// 耐力增加0是没有意义的
@@ -330,10 +296,29 @@ func (g *GameManager) UpdateStamina(player *model.Player, staminaCost int32) {
player.StaminaInfo.RestoreDelay = 0
}
// 玩家最大耐力值
maxStamina := int32(player.PropertiesMap[constant.PlayerPropertyConst.PROP_MAX_STAMINA])
// 玩家现行耐力值
curStamina := int32(player.PropertiesMap[constant.PlayerPropertyConst.PROP_CUR_PERSIST_STAMINA])
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
scene := world.GetSceneById(player.SceneId)
// 最大耐力值 现行耐力值
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
@@ -350,15 +335,35 @@ func (g *GameManager) UpdateStamina(player *model.Player, staminaCost int32) {
return
}
g.SetStamina(player, uint32(stamina))
if isInVehicle {
// 修改载具现行耐力
g.SetVehicleStamina(player, entity.gadgetEntity.gadgetVehicleEntity, float32(stamina)/100)
} else {
// 修改玩家现行耐力
g.SetPlayerStamina(player, uint32(stamina))
}
}
// SetStamina 设置玩家的耐力
func (g *GameManager) SetStamina(player *model.Player, stamina uint32) {
// SetVehicleStamina 设置载具的耐力
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
player.PropertiesMap[prop] = stamina
//logger.LOG.Debug("player curr stamina: %v", stamina)
logger.LOG.Debug("player stamina set, stamina: %v", stamina)
// PacketPlayerPropNotify
playerPropNotify := new(proto.PlayerPropNotify)

View File

@@ -6,6 +6,7 @@ import (
"hk4e/pkg/logger"
"hk4e/protocol/cmd"
"hk4e/protocol/proto"
"time"
)
// CreateVehicleReq 创建载具
@@ -15,37 +16,20 @@ func (g *GameManager) CreateVehicleReq(player *model.Player, payloadMsg pb.Messa
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
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() {
entity := scene.GetEntity(id)
// 判断实体类型是否为载具
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)
if player.VehicleInfo.LastCreateEntityId != 0 {
g.DestroyVehicleEntity(player, scene, req.VehicleId, player.VehicleInfo.LastCreateEntityId)
}
// 创建载具实体
@@ -54,11 +38,16 @@ func (g *GameManager) CreateVehicleReq(player *model.Player, payloadMsg pb.Messa
entityId := scene.CreateEntityGadgetVehicle(player.PlayerID, pos, rot, req.VehicleId)
if entityId == 0 {
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
}
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{
VehicleId: req.VehicleId,
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)
}
// 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 判断玩家是否在载具中
func (g *GameManager) IsPlayerInVehicle(player *model.Player, gadgetVehicleEntity *GadgetVehicleEntity) bool {
if gadgetVehicleEntity == nil {
return false
}
for _, p := range gadgetVehicleEntity.memberMap {
if p == player {
return true
@@ -76,28 +81,61 @@ func (g *GameManager) IsPlayerInVehicle(player *model.Player, gadgetVehicleEntit
return false
}
// EnterVehicle 进入载具
func (g *GameManager) EnterVehicle(player *model.Player, entity *Entity, avatarGuid uint64) {
// 玩家是否已进入载具
if g.IsPlayerInVehicle(player, entity.gadgetEntity.gadgetVehicleEntity) {
logger.LOG.Error("vehicle has equal player, uid: %v", player.PlayerID)
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{})
// DestroyVehicleEntity 删除载具实体
func (g *GameManager) DestroyVehicleEntity(player *model.Player, scene *Scene, vehicleId uint32, entityId uint32) {
entity := g.GetSceneVehicleEntity(scene, entityId)
if entity == nil {
return
}
// 找出载具空闲的位置
pos := uint32(0)
for entity.gadgetEntity.gadgetVehicleEntity.memberMap[pos] != nil {
pos++
// 确保载具Id为将要创建的 (每种载具允许存在1个)
if entity.gadgetEntity.gadgetVehicleEntity.vehicleId != vehicleId {
return
}
// 载具成员记录玩家
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{
InteractType: proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_IN,
Member: &proto.VehicleMember{
Uid: player.PlayerID,
AvatarGuid: avatarGuid,
Pos: pos, // 应该是多人坐船时的位置?
Pos: freePos, // 应该是多人坐船时的位置?
},
EntityId: entity.id,
}
@@ -109,7 +147,7 @@ func (g *GameManager) ExitVehicle(player *model.Player, entity *Entity, avatarGu
// 玩家是否进入载具
if !g.IsPlayerInVehicle(player, entity.gadgetEntity.gadgetVehicleEntity) {
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
}
// 载具成员删除玩家
@@ -120,7 +158,10 @@ func (g *GameManager) ExitVehicle(player *model.Player, entity *Entity, avatarGu
delete(entity.gadgetEntity.gadgetVehicleEntity.memberMap, pos)
}
}
// 清除记录的所在载具信息
player.VehicleInfo.InVehicleEntityId = 0
// PacketVehicleInteractRsp
vehicleInteractRsp := &proto.VehicleInteractRsp{
InteractType: proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_OUT,
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) {
req := payloadMsg.(*proto.VehicleInteractReq)
// 获取载具实体
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 {
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
}
// 判断实体类型是否为载具
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)
g.SendMsg(cmd.VehicleInteractRsp, player.PlayerID, player.ClientSeq, &proto.VehicleInteractRsp{Retcode: int32(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{})
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{}, proto.Retcode_RET_GADGET_NOT_VEHICLE)
return
}
avatarGuid := player.AvatarMap[player.TeamConfig.GetActiveAvatarId()].Guid
switch req.InteractType {
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:
// 离开载具
g.ExitVehicle(player, entity, avatar.Guid)
g.ExitVehicle(player, entity, avatarGuid)
}
}

View File

@@ -540,6 +540,7 @@ type GadgetGatherEntity struct {
type GadgetVehicleEntity struct {
vehicleId uint32
owner *model.Player
maxStamina float32
curStamina float32
memberMap map[uint32]*model.Player // uint32 = pos
}
@@ -752,7 +753,8 @@ func (s *Scene) CreateEntityGadgetVehicle(uid uint32, pos, rot *model.Vector, ve
gadgetVehicleEntity: &GadgetVehicleEntity{
vehicleId: vehicleId,
owner: player,
curStamina: 240, // TODO 应该也能在配置表找到
maxStamina: 240, // TODO 应该也能在配置表找到
curStamina: 240, // TODO 与maxStamina一致
memberMap: make(map[uint32]*model.Player),
},
},

View File

@@ -65,6 +65,7 @@ type Player struct {
SceneLoadState int `bson:"-" msgpack:"-"` // 场景加载状态
CoopApplyMap map[uint32]int64 `bson:"-" msgpack:"-"` // 敲门申请的玩家uid及时间
StaminaInfo *StaminaInfo `bson:"-" msgpack:"-"` // 耐力临时数据
VehicleInfo *VehicleInfo `bson:"-" msgpack:"-"` // 载具临时数据
ClientSeq uint32 `bson:"-" msgpack:"-"` // 客户端发包请求的序号
CombatInvokeHandler *InvokeHandler[proto.CombatInvokeEntry] `bson:"-" msgpack:"-"` // combat转发器
AbilityInvokeHandler *InvokeHandler[proto.AbilityInvokeEntry] `bson:"-" msgpack:"-"` // ability转发器
@@ -79,6 +80,7 @@ func (p *Player) InitAll() {
p.GameObjectGuidMap = make(map[uint64]GameObject)
p.CoopApplyMap = make(map[uint32]int64)
p.StaminaInfo = new(StaminaInfo)
p.VehicleInfo = new(VehicleInfo)
p.InitAllAvatar()
p.InitAllWeapon()
p.InitAllItem()

View File

@@ -1,8 +1,8 @@
package model
import (
"hk4e/gs/constant"
"hk4e/protocol/proto"
"time"
)
type StaminaInfo struct {
@@ -14,9 +14,46 @@ type StaminaInfo struct {
LastSkillTime int64 // 最后释放技能的时间
}
// SetLastSkill 记录技能以便后续使用
func (s *StaminaInfo) SetLastSkill(casterId uint32, skillId uint32) {
s.LastCasterId = casterId
s.LastSkillId = skillId
s.LastSkillTime = time.Now().UnixMilli()
// SetStaminaCost 设置动作需要消耗的耐力
func (s *StaminaInfo) SetStaminaCost(state proto.MotionState) {
// 根据状态决定要修改的耐力
// TODO 角色天赋 食物 会影响耐力消耗
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
}
}

7
gs/model/vehicle.go Normal file
View File

@@ -0,0 +1,7 @@
package model
type VehicleInfo struct {
InVehicleEntityId uint32 // 玩家所在载具的实体Id
LastCreateTime int64 // 最后一次创建载具的时间
LastCreateEntityId uint32 // 最后一次创建载具的实体Id
}

View File

@@ -231,10 +231,11 @@ func (c *CmdProtoMap) registerAllMessage() {
c.registerMessage(McoinExchangeHcoinRsp, &proto.McoinExchangeHcoinRsp{}) // 结晶换原石响应
// 载具
c.registerMessage(CreateVehicleReq, &proto.CreateVehicleReq{}) // 创建载具请求
c.registerMessage(CreateVehicleRsp, &proto.CreateVehicleRsp{}) // 创建载具响应
c.registerMessage(VehicleInteractReq, &proto.VehicleInteractReq{}) // 载具交互请求
c.registerMessage(VehicleInteractRsp, &proto.VehicleInteractRsp{}) // 载具交互响应
c.registerMessage(CreateVehicleReq, &proto.CreateVehicleReq{}) // 创建载具请求
c.registerMessage(CreateVehicleRsp, &proto.CreateVehicleRsp{}) // 创建载具响应
c.registerMessage(VehicleInteractReq, &proto.VehicleInteractReq{}) // 载具交互请求
c.registerMessage(VehicleInteractRsp, &proto.VehicleInteractRsp{}) // 载具交互响应
c.registerMessage(VehicleStaminaNotify, &proto.VehicleStaminaNotify{}) // 载具耐力消耗通知
// 乱七八糟
c.registerMessage(MarkMapReq, &proto.MarkMapReq{}) // 标记地图请求