mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 14:22:26 +08:00
角色升级初步
This commit is contained in:
31
gdconf/avatar_level_data.go
Normal file
31
gdconf/avatar_level_data.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package gdconf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hk4e/pkg/logger"
|
||||
|
||||
"github.com/jszwec/csvutil"
|
||||
)
|
||||
|
||||
// 角色等级配置表
|
||||
|
||||
type AvatarLevelData struct {
|
||||
Level int32 `csv:"Level"` // 等级
|
||||
Exp int32 `csv:"Exp,omitempty"` // 升到下一级所需经验
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadAvatarLevelData() {
|
||||
g.AvatarLevelDataMap = make(map[int32]*AvatarLevelData)
|
||||
data := g.readCsvFileData("AvatarLevelData.csv")
|
||||
var avatarLevelDataList []*AvatarLevelData
|
||||
err := csvutil.Unmarshal(data, &avatarLevelDataList)
|
||||
if err != nil {
|
||||
info := fmt.Sprintf("parse file error: %v", err)
|
||||
panic(info)
|
||||
}
|
||||
for _, avatarLevelData := range avatarLevelDataList {
|
||||
// list -> map
|
||||
g.AvatarLevelDataMap[avatarLevelData.Level] = avatarLevelData
|
||||
}
|
||||
logger.Info("AvatarLevelData count: %v", len(g.AvatarLevelDataMap))
|
||||
}
|
||||
32
gdconf/avatar_promote_data.go
Normal file
32
gdconf/avatar_promote_data.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package gdconf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hk4e/pkg/logger"
|
||||
|
||||
"github.com/jszwec/csvutil"
|
||||
)
|
||||
|
||||
// 角色突破配置表
|
||||
|
||||
type AvatarPromoteData struct {
|
||||
PromoteId int32 `csv:"PromoteId"` // 角色突破ID
|
||||
PromoteLevel int32 `csv:"PromoteLevel,omitempty"` // 突破等级
|
||||
LevelLimit int32 `csv:"LevelLimit,omitempty"` // 解锁等级上限
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadAvatarPromoteData() {
|
||||
g.AvatarPromoteDataMap = make(map[int32]*AvatarPromoteData)
|
||||
data := g.readCsvFileData("AvatarPromoteData.csv")
|
||||
var avatarPromoteDataList []*AvatarPromoteData
|
||||
err := csvutil.Unmarshal(data, &avatarPromoteDataList)
|
||||
if err != nil {
|
||||
info := fmt.Sprintf("parse file error: %v", err)
|
||||
panic(info)
|
||||
}
|
||||
for _, avatarPromoteData := range avatarPromoteDataList {
|
||||
// list -> map
|
||||
g.AvatarPromoteDataMap[avatarPromoteData.PromoteLevel] = avatarPromoteData
|
||||
}
|
||||
logger.Info("AvatarPromoteData count: %v", len(g.AvatarPromoteDataMap))
|
||||
}
|
||||
@@ -38,6 +38,8 @@ type GameDataConfig struct {
|
||||
FetterDataMap map[int32]*FetterData // 角色资料解锁
|
||||
FetterDataAvatarIdMap map[int32][]int32 // 角色资料解锁角色id索引
|
||||
ItemDataMap map[int32]*ItemData // 统一道具
|
||||
AvatarLevelDataMap map[int32]*AvatarLevelData // 角色等级
|
||||
AvatarPromoteDataMap map[int32]*AvatarPromoteData // 角色突破
|
||||
}
|
||||
|
||||
func InitGameDataConfig() {
|
||||
@@ -97,6 +99,8 @@ func (g *GameDataConfig) load() {
|
||||
g.loadGatherData() // 采集物
|
||||
g.loadFetterData() // 角色资料解锁
|
||||
g.loadItemData() // 统一道具
|
||||
g.loadAvatarLevelData() // 角色等级
|
||||
g.loadAvatarPromoteData() // 角色突破
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) readCsvFileData(fileName string) []byte {
|
||||
|
||||
@@ -588,5 +588,40 @@
|
||||
"origin_name": "数值用类型"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"table_name": "AvatarLevelData",
|
||||
"field_list": [
|
||||
{
|
||||
"field_name": "Level",
|
||||
"field_type": "int32",
|
||||
"origin_name": "等级"
|
||||
},
|
||||
{
|
||||
"field_name": "Exp",
|
||||
"field_type": "int32",
|
||||
"origin_name": "升到下一级所需经验"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"table_name": "AvatarPromoteData",
|
||||
"field_list": [
|
||||
{
|
||||
"field_name": "PromoteId",
|
||||
"field_type": "int32",
|
||||
"origin_name": "角色突破ID"
|
||||
},
|
||||
{
|
||||
"field_name": "PromoteLevel",
|
||||
"field_type": "int32",
|
||||
"origin_name": "突破等级"
|
||||
},
|
||||
{
|
||||
"field_name": "LevelLimit",
|
||||
"field_type": "int32",
|
||||
"origin_name": "解锁等级上限"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -66,6 +66,107 @@ func (g *GameManager) AddUserAvatar(userId uint32, avatarId uint32) {
|
||||
g.SendMsg(cmd.AvatarAddNotify, userId, player.ClientSeq, avatarAddNotify)
|
||||
}
|
||||
|
||||
// AvatarUpgradeReq 角色升级请求
|
||||
func (g *GameManager) AvatarUpgradeReq(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.Debug("user upgrade, uid: %v", player.PlayerID)
|
||||
req := payloadMsg.(*proto.AvatarUpgradeReq)
|
||||
// 是否拥有角色
|
||||
avatar, ok := player.AvatarMap[player.GetAvatarIdByGuid(req.AvatarGuid)]
|
||||
if !ok {
|
||||
logger.Error("avatar error, avatarGuid: %v", req.AvatarGuid)
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{}, proto.Retcode_RET_CAN_NOT_FIND_AVATAR)
|
||||
return
|
||||
}
|
||||
// 经验书数量是否足够
|
||||
if player.GetItemCount(req.ItemId) < req.Count {
|
||||
logger.Error("item count not enough, itemCount: %v", req.Count)
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{}, proto.Retcode_RET_ITEM_COUNT_NOT_ENOUGH)
|
||||
return
|
||||
}
|
||||
// TODO 摩拉数量是否足够
|
||||
// 获取角色突破配置表
|
||||
avatarPromoteConfig, ok := gdconf.CONF.AvatarPromoteDataMap[int32(avatar.Promote)]
|
||||
if !ok {
|
||||
logger.Error("avatar promote config error, promoteLevel: %v", avatar.Promote)
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
|
||||
return
|
||||
}
|
||||
// 角色等级是否达到限制
|
||||
if avatar.Level >= uint8(avatarPromoteConfig.LevelLimit) {
|
||||
logger.Error("avatar promote config error, promoteLevel: %v", avatar.Promote)
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
|
||||
return
|
||||
}
|
||||
// 消耗升级材料并升级角色
|
||||
GAME_MANAGER.CostUserItem(player.PlayerID, []*UserItem{
|
||||
{
|
||||
ItemId: req.ItemId,
|
||||
ChangeCount: req.Count,
|
||||
},
|
||||
})
|
||||
// 角色升级前的信息
|
||||
oldLevel := avatar.Level
|
||||
oldFightPropMap := make(map[uint32]float32, len(avatar.FightPropMap))
|
||||
for propType, propValue := range avatar.FightPropMap {
|
||||
oldFightPropMap[propType] = propValue
|
||||
}
|
||||
// 角色增加经验
|
||||
avatar.Exp += req.Count * 20000 // TODO 根据物品id给予相应的经验
|
||||
// 角色升级
|
||||
for {
|
||||
// 获取角色等级配置表
|
||||
avatarLevelConfig, ok := gdconf.CONF.AvatarLevelDataMap[int32(avatar.Level)]
|
||||
if !ok {
|
||||
logger.Error("avatar level config error, level: %v", avatar.Level)
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
|
||||
return
|
||||
}
|
||||
// 角色当前等级未突破则跳出循环
|
||||
if avatar.Level >= uint8(avatarPromoteConfig.LevelLimit) {
|
||||
break
|
||||
}
|
||||
// 角色经验小于升级所需的经验则跳出循环
|
||||
if avatar.Exp < uint32(avatarLevelConfig.Exp) {
|
||||
break
|
||||
}
|
||||
// 角色等级提升
|
||||
avatar.Exp -= uint32(avatarLevelConfig.Exp)
|
||||
avatar.Level++
|
||||
}
|
||||
// 角色更新面板
|
||||
player.InitAvatarFightProp(avatar)
|
||||
// 角色属性表更新通知
|
||||
g.SendMsg(cmd.AvatarPropNotify, player.PlayerID, player.ClientSeq, g.PacketAvatarPropNotify(avatar))
|
||||
avatarUpgradeRsp := &proto.AvatarUpgradeRsp{
|
||||
CurLevel: uint32(avatar.Level),
|
||||
OldLevel: uint32(oldLevel),
|
||||
OldFightPropMap: oldFightPropMap,
|
||||
CurFightPropMap: avatar.FightPropMap,
|
||||
AvatarGuid: req.AvatarGuid,
|
||||
}
|
||||
g.SendMsg(cmd.AvatarUpgradeRsp, player.PlayerID, player.ClientSeq, avatarUpgradeRsp)
|
||||
}
|
||||
|
||||
// PacketAvatarPropNotify 角色属性表更新通知
|
||||
func (g *GameManager) PacketAvatarPropNotify(avatar *model.Avatar) *proto.AvatarPropNotify {
|
||||
avatarPropNotify := &proto.AvatarPropNotify{
|
||||
PropMap: make(map[uint32]int64, 5),
|
||||
AvatarGuid: avatar.Guid,
|
||||
}
|
||||
// 角色等级
|
||||
avatarPropNotify.PropMap[uint32(constant.PlayerPropertyConst.PROP_LEVEL)] = int64(avatar.Level)
|
||||
// 角色经验
|
||||
avatarPropNotify.PropMap[uint32(constant.PlayerPropertyConst.PROP_EXP)] = int64(avatar.Exp)
|
||||
// 角色突破等级
|
||||
avatarPropNotify.PropMap[uint32(constant.PlayerPropertyConst.PROP_BREAK_LEVEL)] = int64(avatar.Promote)
|
||||
// 角色饱食度
|
||||
avatarPropNotify.PropMap[uint32(constant.PlayerPropertyConst.PROP_SATIATION_VAL)] = int64(avatar.Satiation)
|
||||
// 角色饱食度溢出
|
||||
avatarPropNotify.PropMap[uint32(constant.PlayerPropertyConst.PROP_SATIATION_PENALTY_TIME)] = int64(avatar.SatiationPenalty)
|
||||
|
||||
return avatarPropNotify
|
||||
}
|
||||
|
||||
func (g *GameManager) WearEquipReq(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.Debug("user wear equip, uid: %v", player.PlayerID)
|
||||
req := payloadMsg.(*proto.WearEquipReq)
|
||||
@@ -73,13 +174,13 @@ func (g *GameManager) WearEquipReq(player *model.Player, payloadMsg pb.Message)
|
||||
equipGuid := req.EquipGuid
|
||||
avatar, ok := player.GameObjectGuidMap[avatarGuid].(*model.Avatar)
|
||||
if !ok {
|
||||
logger.Error("avatar error, avatar guid: %v", avatarGuid)
|
||||
g.CommonRetError(cmd.WearEquipRsp, player, &proto.WearEquipRsp{})
|
||||
logger.Error("avatar error, avatarGuid: %v", avatarGuid)
|
||||
g.CommonRetError(cmd.WearEquipRsp, player, &proto.WearEquipRsp{}, proto.Retcode_RET_CAN_NOT_FIND_AVATAR)
|
||||
return
|
||||
}
|
||||
weapon, ok := player.GameObjectGuidMap[equipGuid].(*model.Weapon)
|
||||
if !ok {
|
||||
logger.Error("equip error, equip guid: %v", equipGuid)
|
||||
logger.Error("equip error, equipGuid: %v", equipGuid)
|
||||
g.CommonRetError(cmd.WearEquipRsp, player, &proto.WearEquipRsp{})
|
||||
return
|
||||
}
|
||||
@@ -219,7 +320,7 @@ func (g *GameManager) AvatarWearFlycloakReq(player *model.Player, payloadMsg pb.
|
||||
func (g *GameManager) PacketAvatarEquipChangeNotify(avatar *model.Avatar, weapon *model.Weapon, entityId uint32) *proto.AvatarEquipChangeNotify {
|
||||
itemDataConfig, ok := gdconf.CONF.ItemDataMap[int32(weapon.ItemId)]
|
||||
if !ok {
|
||||
logger.Error("item data config error, item id: %v")
|
||||
logger.Error("item data config error, itemId: %v")
|
||||
return new(proto.AvatarEquipChangeNotify)
|
||||
}
|
||||
avatarEquipChangeNotify := &proto.AvatarEquipChangeNotify{
|
||||
|
||||
@@ -129,6 +129,7 @@ func (r *RouteManager) initRoute() {
|
||||
r.registerRouter(cmd.GCGInitFinishReq, GAME_MANAGER.GCGInitFinishReq)
|
||||
r.registerRouter(cmd.GCGOperationReq, GAME_MANAGER.GCGOperationReq)
|
||||
r.registerRouter(cmd.ObstacleModifyNotify, GAME_MANAGER.ObstacleModifyNotify)
|
||||
r.registerRouter(cmd.AvatarUpgradeReq, GAME_MANAGER.AvatarUpgradeReq)
|
||||
}
|
||||
|
||||
func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
|
||||
|
||||
@@ -41,12 +41,23 @@ func (p *Player) InitAllAvatar() {
|
||||
}
|
||||
|
||||
func (p *Player) InitAvatar(avatar *Avatar) {
|
||||
// 角色战斗属性
|
||||
p.InitAvatarFightProp(avatar)
|
||||
// guid
|
||||
avatar.Guid = p.GetNextGameObjectGuid()
|
||||
p.GameObjectGuidMap[avatar.Guid] = GameObject(avatar)
|
||||
avatar.EquipGuidList = make(map[uint64]uint64)
|
||||
p.AvatarMap[avatar.AvatarId] = avatar
|
||||
return
|
||||
}
|
||||
|
||||
// InitAvatarFightProp 初始化角色面板
|
||||
func (p *Player) InitAvatarFightProp(avatar *Avatar) {
|
||||
avatarDataConfig, ok := gdconf.CONF.AvatarDataMap[int32(avatar.AvatarId)]
|
||||
if !ok {
|
||||
logger.Error("avatarDataConfig error, avatarId: %v", avatar.AvatarId)
|
||||
return
|
||||
}
|
||||
// 角色战斗属性
|
||||
avatar.FightPropMap = make(map[uint32]float32)
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_NONE)] = 0.0
|
||||
// 白字攻防血
|
||||
@@ -65,12 +76,6 @@ func (p *Player) InitAvatar(avatar *Avatar) {
|
||||
// 元素充能
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CHARGE_EFFICIENCY)] = 1.0
|
||||
p.SetCurrEnergy(avatar, avatar.CurrEnergy, true)
|
||||
// guid
|
||||
avatar.Guid = p.GetNextGameObjectGuid()
|
||||
p.GameObjectGuidMap[avatar.Guid] = GameObject(avatar)
|
||||
avatar.EquipGuidList = make(map[uint64]uint64)
|
||||
p.AvatarMap[avatar.AvatarId] = avatar
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Player) GetAvatarIdByGuid(guid uint64) uint32 {
|
||||
|
||||
@@ -221,6 +221,9 @@ func (c *CmdProtoMap) registerAllMessage() {
|
||||
c.registerMessage(AvatarWearFlycloakRsp, &proto.AvatarWearFlycloakRsp{}) // 角色换风之翼响应
|
||||
c.registerMessage(AvatarFlycloakChangeNotify, &proto.AvatarFlycloakChangeNotify{}) // 角色换风之翼通知
|
||||
c.registerMessage(AvatarLifeStateChangeNotify, &proto.AvatarLifeStateChangeNotify{}) // 角色存活状态改变通知
|
||||
c.registerMessage(AvatarUpgradeReq, &proto.AvatarUpgradeReq{}) // 角色升级请求
|
||||
c.registerMessage(AvatarUpgradeRsp, &proto.AvatarUpgradeRsp{}) // 角色升级通知
|
||||
c.registerMessage(AvatarPropNotify, &proto.AvatarPropNotify{}) // 角色属性表更新通知
|
||||
|
||||
// 背包与道具
|
||||
c.registerMessage(PlayerStoreNotify, &proto.PlayerStoreNotify{}) // 玩家背包数据通知
|
||||
|
||||
Reference in New Issue
Block a user