mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 14:22:26 +08:00
角色突破功能
This commit is contained in:
@@ -3,12 +3,14 @@ package constant
|
||||
var ItemConstantConst *ItemConstant
|
||||
|
||||
type ItemConstant struct {
|
||||
HCOIN uint32 // 原石 201
|
||||
SCOIN uint32 // 摩拉 202
|
||||
MCOIN uint32 // 创世结晶 203
|
||||
RESIN uint32 // 树脂 106
|
||||
LEGENDARY_KEY uint32 // 传说任务钥匙 107
|
||||
HOME_COIN uint32 // 洞天宝钱 204
|
||||
HCOIN uint32 // 原石 201
|
||||
SCOIN uint32 // 摩拉 202
|
||||
MCOIN uint32 // 创世结晶 203
|
||||
RESIN uint32 // 树脂 106
|
||||
LEGENDARY_KEY uint32 // 传说任务钥匙 107
|
||||
HOME_COIN uint32 // 洞天宝钱 204
|
||||
PLAYER_EXP uint32 // 冒险阅历 102
|
||||
VIRTUAL_ITEM_PROP map[uint32]uint16 // 虚拟物品对应玩家的属性
|
||||
}
|
||||
|
||||
func InitItemConstantConst() {
|
||||
@@ -20,4 +22,14 @@ func InitItemConstantConst() {
|
||||
ItemConstantConst.RESIN = 106
|
||||
ItemConstantConst.LEGENDARY_KEY = 207
|
||||
ItemConstantConst.HOME_COIN = 204
|
||||
ItemConstantConst.PLAYER_EXP = 102
|
||||
ItemConstantConst.VIRTUAL_ITEM_PROP = map[uint32]uint16{
|
||||
ItemConstantConst.HCOIN: PlayerPropertyConst.PROP_PLAYER_HCOIN,
|
||||
ItemConstantConst.SCOIN: PlayerPropertyConst.PROP_PLAYER_SCOIN,
|
||||
ItemConstantConst.MCOIN: PlayerPropertyConst.PROP_PLAYER_MCOIN,
|
||||
ItemConstantConst.RESIN: PlayerPropertyConst.PROP_PLAYER_RESIN,
|
||||
ItemConstantConst.LEGENDARY_KEY: PlayerPropertyConst.PROP_PLAYER_LEGENDARY_KEY,
|
||||
ItemConstantConst.HOME_COIN: PlayerPropertyConst.PROP_PLAYER_HOME_COIN,
|
||||
ItemConstantConst.PLAYER_EXP: PlayerPropertyConst.PROP_PLAYER_EXP,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ type AvatarData struct {
|
||||
InitialWeapon int32 `csv:"InitialWeapon,omitempty"` // 初始武器
|
||||
WeaponType int32 `csv:"WeaponType,omitempty"` // 武器种类
|
||||
SkillDepotId int32 `csv:"SkillDepotId,omitempty"` // 技能库ID
|
||||
PromoteId int32 `csv:"PromoteId,omitempty"` // 角色突破ID
|
||||
|
||||
AbilityHashCodeList []int32
|
||||
}
|
||||
|
||||
@@ -10,13 +10,23 @@ import (
|
||||
// 角色突破配置表
|
||||
|
||||
type AvatarPromoteData struct {
|
||||
PromoteId int32 `csv:"PromoteId"` // 角色突破ID
|
||||
PromoteLevel int32 `csv:"PromoteLevel,omitempty"` // 突破等级
|
||||
LevelLimit int32 `csv:"LevelLimit,omitempty"` // 解锁等级上限
|
||||
PromoteId int32 `csv:"PromoteId"` // 角色突破ID
|
||||
PromoteLevel int32 `csv:"PromoteLevel,omitempty"` // 突破等级
|
||||
CostCoin int32 `csv:"CostCoin,omitempty"` // 消耗金币
|
||||
CostItemId1 int32 `csv:"CostItemId1,omitempty"` // [消耗物品]1ID
|
||||
CostItemCount1 int32 `csv:"CostItemCount1,omitempty"` // [消耗物品]1数量
|
||||
CostItemId2 int32 `csv:"CostItemId2,omitempty"` // [消耗物品]2ID
|
||||
CostItemCount2 int32 `csv:"CostItemCount2,omitempty"` // [消耗物品]2数量
|
||||
CostItemId3 int32 `csv:"CostItemId3,omitempty"` // [消耗物品]3ID
|
||||
CostItemCount3 int32 `csv:"CostItemCount3,omitempty"` // [消耗物品]3数量
|
||||
LevelLimit int32 `csv:"LevelLimit,omitempty"` // 解锁等级上限
|
||||
MinPlayerLevel int32 `csv:"MinPlayerLevel,omitempty"` // 冒险等级要求
|
||||
|
||||
CostItemMap map[uint32]uint32 // 消耗物品列表
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadAvatarPromoteData() {
|
||||
g.AvatarPromoteDataMap = make(map[int32]*AvatarPromoteData)
|
||||
g.AvatarPromoteDataMap = make(map[int32]map[int32]*AvatarPromoteData)
|
||||
data := g.readCsvFileData("AvatarPromoteData.csv")
|
||||
var avatarPromoteDataList []*AvatarPromoteData
|
||||
err := csvutil.Unmarshal(data, &avatarPromoteDataList)
|
||||
@@ -26,7 +36,22 @@ func (g *GameDataConfig) loadAvatarPromoteData() {
|
||||
}
|
||||
for _, avatarPromoteData := range avatarPromoteDataList {
|
||||
// list -> map
|
||||
g.AvatarPromoteDataMap[avatarPromoteData.PromoteLevel] = avatarPromoteData
|
||||
_, ok := g.AvatarPromoteDataMap[avatarPromoteData.PromoteId]
|
||||
if !ok {
|
||||
g.AvatarPromoteDataMap[avatarPromoteData.PromoteId] = make(map[int32]*AvatarPromoteData)
|
||||
}
|
||||
avatarPromoteData.CostItemMap = make(map[uint32]uint32, 3)
|
||||
avatarPromoteData.CostItemMap[uint32(avatarPromoteData.CostItemId1)] = uint32(avatarPromoteData.CostItemCount1)
|
||||
avatarPromoteData.CostItemMap[uint32(avatarPromoteData.CostItemId2)] = uint32(avatarPromoteData.CostItemCount2)
|
||||
avatarPromoteData.CostItemMap[uint32(avatarPromoteData.CostItemId3)] = uint32(avatarPromoteData.CostItemCount3)
|
||||
for itemId, count := range avatarPromoteData.CostItemMap {
|
||||
// 两个值都不能为0
|
||||
if itemId == 0 || count == 0 {
|
||||
delete(avatarPromoteData.CostItemMap, itemId)
|
||||
}
|
||||
}
|
||||
// 通过突破等级找到突破数据
|
||||
g.AvatarPromoteDataMap[avatarPromoteData.PromoteId][avatarPromoteData.PromoteLevel] = avatarPromoteData
|
||||
}
|
||||
logger.Info("AvatarPromoteData count: %v", len(g.AvatarPromoteDataMap))
|
||||
}
|
||||
|
||||
@@ -24,24 +24,25 @@ type GameDataConfig struct {
|
||||
jsonPrefix string
|
||||
luaPrefix string
|
||||
// 配置表数据
|
||||
AvatarDataMap map[int32]*AvatarData // 角色
|
||||
AvatarSkillDataMap map[int32]*AvatarSkillData // 角色技能
|
||||
AvatarSkillDepotDataMap map[int32]*AvatarSkillDepotData // 角色技能库
|
||||
DropGroupDataMap map[int32]*DropGroupData // 掉落组
|
||||
GCGCharDataMap map[int32]*GCGCharData // 角色卡牌
|
||||
GCGSkillDataMap map[int32]*GCGSkillData // 卡牌技能
|
||||
SceneDataMap map[int32]*SceneData // 场景
|
||||
ScenePointMap map[int32]*ScenePoint // 场景传送点
|
||||
SceneTagDataMap map[int32]*SceneTagData // 场景地图图标
|
||||
SceneMap map[int32]*Scene // 场景详情
|
||||
WorldAreaDataMap map[int32]*WorldAreaData // 世界区域
|
||||
GatherDataMap map[int32]*GatherData // 采集物
|
||||
GatherDataPointTypeMap map[int32]*GatherData // 采集物场景节点索引
|
||||
FetterDataMap map[int32]*FetterData // 角色资料解锁
|
||||
FetterDataAvatarIdMap map[int32][]int32 // 角色资料解锁角色id索引
|
||||
ItemDataMap map[int32]*ItemData // 统一道具
|
||||
AvatarLevelDataMap map[int32]*AvatarLevelData // 角色等级
|
||||
AvatarPromoteDataMap map[int32]*AvatarPromoteData // 角色突破
|
||||
AvatarDataMap map[int32]*AvatarData // 角色
|
||||
AvatarSkillDataMap map[int32]*AvatarSkillData // 角色技能
|
||||
AvatarSkillDepotDataMap map[int32]*AvatarSkillDepotData // 角色技能库
|
||||
DropGroupDataMap map[int32]*DropGroupData // 掉落组
|
||||
GCGCharDataMap map[int32]*GCGCharData // 角色卡牌
|
||||
GCGSkillDataMap map[int32]*GCGSkillData // 卡牌技能
|
||||
SceneDataMap map[int32]*SceneData // 场景
|
||||
ScenePointMap map[int32]*ScenePoint // 场景传送点
|
||||
SceneTagDataMap map[int32]*SceneTagData // 场景地图图标
|
||||
SceneMap map[int32]*Scene // 场景详情
|
||||
WorldAreaDataMap map[int32]*WorldAreaData // 世界区域
|
||||
GatherDataMap map[int32]*GatherData // 采集物
|
||||
GatherDataPointTypeMap map[int32]*GatherData // 采集物场景节点索引
|
||||
FetterDataMap map[int32]*FetterData // 角色资料解锁
|
||||
FetterDataAvatarIdMap map[int32][]int32 // 角色资料解锁角色id索引
|
||||
ItemDataMap map[int32]*ItemData // 统一道具
|
||||
AvatarLevelDataMap map[int32]*AvatarLevelData // 角色等级
|
||||
AvatarPromoteDataMap map[int32]map[int32]*AvatarPromoteData // 角色突破
|
||||
PlayerLevelDataMap map[int32]*PlayerLevelData // 玩家等级
|
||||
}
|
||||
|
||||
func InitGameDataConfig() {
|
||||
@@ -117,6 +118,7 @@ func (g *GameDataConfig) load() {
|
||||
g.loadItemData() // 统一道具
|
||||
g.loadAvatarLevelData() // 角色等级
|
||||
g.loadAvatarPromoteData() // 角色突破
|
||||
g.loadPlayerLevelData() // 玩家等级
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) readCsvFileData(fileName string) []byte {
|
||||
|
||||
31
gdconf/player_level_data.go
Normal file
31
gdconf/player_level_data.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package gdconf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hk4e/pkg/logger"
|
||||
|
||||
"github.com/jszwec/csvutil"
|
||||
)
|
||||
|
||||
// 玩家等级配置表
|
||||
|
||||
type PlayerLevelData struct {
|
||||
Level int32 `csv:"Level"` // 等级
|
||||
Exp int32 `csv:"Exp,omitempty"` // 升到下一级所需经验
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadPlayerLevelData() {
|
||||
g.PlayerLevelDataMap = make(map[int32]*PlayerLevelData)
|
||||
data := g.readCsvFileData("PlayerLevelData.csv")
|
||||
var playerLevelDataList []*PlayerLevelData
|
||||
err := csvutil.Unmarshal(data, &playerLevelDataList)
|
||||
if err != nil {
|
||||
info := fmt.Sprintf("parse file error: %v", err)
|
||||
panic(info)
|
||||
}
|
||||
for _, playerLevelData := range playerLevelDataList {
|
||||
// list -> map
|
||||
g.PlayerLevelDataMap[playerLevelData.Level] = playerLevelData
|
||||
}
|
||||
logger.Info("PlayerLevelData count: %v", len(g.PlayerLevelDataMap))
|
||||
}
|
||||
@@ -56,6 +56,11 @@
|
||||
"field_name": "SkillDepotId",
|
||||
"field_type": "int32",
|
||||
"origin_name": "技能库ID"
|
||||
},
|
||||
{
|
||||
"field_name": "PromoteId",
|
||||
"field_type": "int32",
|
||||
"origin_name": "角色突破ID"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -622,10 +627,75 @@
|
||||
"field_type": "int32",
|
||||
"origin_name": "突破等级"
|
||||
},
|
||||
{
|
||||
"field_name": "CostCoin",
|
||||
"field_type": "int32",
|
||||
"origin_name": "消耗金币"
|
||||
},
|
||||
{
|
||||
"field_name": "CostItemId1",
|
||||
"field_type": "int32",
|
||||
"origin_name": "[消耗物品]1ID"
|
||||
},
|
||||
{
|
||||
"field_name": "CostItemCount1",
|
||||
"field_type": "int32",
|
||||
"origin_name": "[消耗物品]1数量"
|
||||
},
|
||||
{
|
||||
"field_name": "CostItemId2",
|
||||
"field_type": "int32",
|
||||
"origin_name": "[消耗物品]2ID"
|
||||
},
|
||||
{
|
||||
"field_name": "CostItemCount2",
|
||||
"field_type": "int32",
|
||||
"origin_name": "[消耗物品]2数量"
|
||||
},
|
||||
{
|
||||
"field_name": "CostItemId3",
|
||||
"field_type": "int32",
|
||||
"origin_name": "[消耗物品]3ID"
|
||||
},
|
||||
{
|
||||
"field_name": "CostItemCount3",
|
||||
"field_type": "int32",
|
||||
"origin_name": "[消耗物品]3数量"
|
||||
},
|
||||
{
|
||||
"field_name": "CostItemId4",
|
||||
"field_type": "int32",
|
||||
"origin_name": "[消耗物品]4ID"
|
||||
},
|
||||
{
|
||||
"field_name": "CostItemCount4",
|
||||
"field_type": "int32",
|
||||
"origin_name": "[消耗物品]4数量"
|
||||
},
|
||||
{
|
||||
"field_name": "LevelLimit",
|
||||
"field_type": "int32",
|
||||
"origin_name": "解锁等级上限"
|
||||
},
|
||||
{
|
||||
"field_name": "MinPlayerLevel",
|
||||
"field_type": "int32",
|
||||
"origin_name": "冒险等级要求"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"table_name": "PlayerLevelData",
|
||||
"field_list": [
|
||||
{
|
||||
"field_name": "Level",
|
||||
"field_type": "int32",
|
||||
"origin_name": "等级"
|
||||
},
|
||||
{
|
||||
"field_name": "Exp",
|
||||
"field_type": "int32",
|
||||
"origin_name": "升到下一级所需经验"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -67,6 +67,82 @@ func (g *GameManager) AddUserAvatar(userId uint32, avatarId uint32) {
|
||||
g.SendMsg(cmd.AvatarAddNotify, userId, player.ClientSeq, avatarAddNotify)
|
||||
}
|
||||
|
||||
// AvatarPromoteReq 角色突破请求
|
||||
func (g *GameManager) AvatarPromoteReq(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.Debug("user promote, uid: %v", player.PlayerID)
|
||||
req := payloadMsg.(*proto.AvatarPromoteReq)
|
||||
// 是否拥有角色
|
||||
avatar, ok := player.AvatarMap[player.GetAvatarIdByGuid(req.Guid)]
|
||||
if !ok {
|
||||
logger.Error("avatar error, avatarGuid: %v", req.Guid)
|
||||
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarUpgradeRsp{}, proto.Retcode_RET_CAN_NOT_FIND_AVATAR)
|
||||
return
|
||||
}
|
||||
// 获取角色配置表
|
||||
avatarDataConfig, ok := gdconf.CONF.AvatarDataMap[int32(avatar.AvatarId)]
|
||||
if !ok {
|
||||
logger.Error("avatar config error, avatarId: %v", avatar.AvatarId)
|
||||
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarUpgradeRsp{})
|
||||
return
|
||||
}
|
||||
// 获取角色突破配置表
|
||||
avatarPromoteDataMap, ok := gdconf.CONF.AvatarPromoteDataMap[avatarDataConfig.PromoteId]
|
||||
if !ok {
|
||||
logger.Error("avatar promote config error, promoteId: %v", avatarDataConfig.PromoteId)
|
||||
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarUpgradeRsp{})
|
||||
return
|
||||
}
|
||||
// 获取角色突破下一级的配置表
|
||||
avatarPromoteConfig, ok := avatarPromoteDataMap[int32(avatar.Promote+1)]
|
||||
if !ok {
|
||||
logger.Error("avatar promote config error, promoteLevel: %v", avatar.Promote)
|
||||
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarUpgradeRsp{})
|
||||
return
|
||||
}
|
||||
// 将被消耗的物品列表
|
||||
costItemList := make([]*UserItem, 0, len(avatarPromoteConfig.CostItemMap)+1)
|
||||
// 突破材料是否足够并添加到消耗物品列表
|
||||
for itemId, count := range avatarPromoteConfig.CostItemMap {
|
||||
costItemList = append(costItemList, &UserItem{
|
||||
ItemId: itemId,
|
||||
ChangeCount: count,
|
||||
})
|
||||
}
|
||||
// 消耗列表添加摩拉的消耗
|
||||
costItemList = append(costItemList, &UserItem{
|
||||
ItemId: constant.ItemConstantConst.SCOIN,
|
||||
ChangeCount: uint32(avatarPromoteConfig.CostCoin),
|
||||
})
|
||||
// 突破材料以及摩拉是否足够
|
||||
for _, item := range costItemList {
|
||||
if player.GetItemCount(item.ItemId) < item.ChangeCount {
|
||||
logger.Error("item count not enough, itemId: %v", item.ItemId)
|
||||
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarPromoteRsp{}, proto.Retcode_RET_SCOIN_NOT_ENOUGH)
|
||||
return
|
||||
}
|
||||
}
|
||||
// 冒险等级是否符合要求
|
||||
if player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL] < uint32(avatarPromoteConfig.MinPlayerLevel) {
|
||||
logger.Error("player level not enough, level: %v", player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL])
|
||||
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarPromoteRsp{})
|
||||
return
|
||||
}
|
||||
// 消耗突破材料和摩拉
|
||||
GAME_MANAGER.CostUserItem(player.PlayerID, costItemList)
|
||||
|
||||
// 角色突破等级+1
|
||||
avatar.Promote++
|
||||
// 角色更新面板
|
||||
player.InitAvatarFightProp(avatar)
|
||||
// 角色属性表更新通知
|
||||
g.SendMsg(cmd.AvatarPropNotify, player.PlayerID, player.ClientSeq, g.PacketAvatarPropNotify(avatar))
|
||||
|
||||
avatarPromoteRsp := &proto.AvatarPromoteRsp{
|
||||
Guid: req.Guid,
|
||||
}
|
||||
g.SendMsg(cmd.AvatarPromoteRsp, player.PlayerID, player.ClientSeq, avatarPromoteRsp)
|
||||
}
|
||||
|
||||
// AvatarUpgradeReq 角色升级请求
|
||||
func (g *GameManager) AvatarUpgradeReq(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.Debug("user upgrade, uid: %v", player.PlayerID)
|
||||
@@ -106,8 +182,22 @@ func (g *GameManager) AvatarUpgradeReq(player *model.Player, payloadMsg pb.Messa
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{}, proto.Retcode_RET_SCOIN_NOT_ENOUGH)
|
||||
return
|
||||
}
|
||||
// 获取角色配置表
|
||||
avatarDataConfig, ok := gdconf.CONF.AvatarDataMap[int32(avatar.AvatarId)]
|
||||
if !ok {
|
||||
logger.Error("avatar config error, avatarId: %v", avatar.AvatarId)
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
|
||||
return
|
||||
}
|
||||
// 获取角色突破配置表
|
||||
avatarPromoteConfig, ok := gdconf.CONF.AvatarPromoteDataMap[int32(avatar.Promote)]
|
||||
avatarPromoteDataMap, ok := gdconf.CONF.AvatarPromoteDataMap[avatarDataConfig.PromoteId]
|
||||
if !ok {
|
||||
logger.Error("avatar promote config error, promoteId: %v", avatarDataConfig.PromoteId)
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
|
||||
return
|
||||
}
|
||||
// 获取角色突破等级对应的配置表
|
||||
avatarPromoteConfig, ok := avatarPromoteDataMap[int32(avatar.Promote)]
|
||||
if !ok {
|
||||
logger.Error("avatar promote config error, promoteLevel: %v", avatar.Promote)
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
|
||||
@@ -115,8 +205,8 @@ func (g *GameManager) AvatarUpgradeReq(player *model.Player, payloadMsg pb.Messa
|
||||
}
|
||||
// 角色等级是否达到限制
|
||||
if avatar.Level >= uint8(avatarPromoteConfig.LevelLimit) {
|
||||
logger.Error("avatar promote config error, promoteLevel: %v", avatar.Promote)
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{}, proto.Retcode_RET_AVATAR_LIMIT_LEVEL_ERROR)
|
||||
logger.Error("avatar level ge level limit, level: %v", avatar.Level)
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
|
||||
return
|
||||
}
|
||||
// 消耗升级材料以及摩拉
|
||||
@@ -136,8 +226,10 @@ func (g *GameManager) AvatarUpgradeReq(player *model.Player, payloadMsg pb.Messa
|
||||
for propType, propValue := range avatar.FightPropMap {
|
||||
oldFightPropMap[propType] = propValue
|
||||
}
|
||||
|
||||
// 角色添加经验
|
||||
g.UpgradeUserAvatar(player.PlayerID, avatar.AvatarId, expCount)
|
||||
|
||||
avatarUpgradeRsp := &proto.AvatarUpgradeRsp{
|
||||
CurLevel: uint32(avatar.Level),
|
||||
OldLevel: uint32(oldLevel),
|
||||
@@ -148,7 +240,7 @@ func (g *GameManager) AvatarUpgradeReq(player *model.Player, payloadMsg pb.Messa
|
||||
g.SendMsg(cmd.AvatarUpgradeRsp, player.PlayerID, player.ClientSeq, avatarUpgradeRsp)
|
||||
}
|
||||
|
||||
// UpgradeUserAvatar 用户角色升级
|
||||
// UpgradeUserAvatar 玩家角色升级
|
||||
func (g *GameManager) UpgradeUserAvatar(userId uint32, avatarId uint32, expCount uint32) {
|
||||
player := USER_MANAGER.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
@@ -160,11 +252,22 @@ func (g *GameManager) UpgradeUserAvatar(userId uint32, avatarId uint32, expCount
|
||||
logger.Error("avatar error, avatarId: %v", avatarId)
|
||||
return
|
||||
}
|
||||
// 获取角色配置表
|
||||
avatarDataConfig, ok := gdconf.CONF.AvatarDataMap[int32(avatar.AvatarId)]
|
||||
if !ok {
|
||||
logger.Error("avatar config error, avatarId: %v", avatar.AvatarId)
|
||||
return
|
||||
}
|
||||
// 获取角色突破配置表
|
||||
avatarPromoteConfig, ok := gdconf.CONF.AvatarPromoteDataMap[int32(avatar.Promote)]
|
||||
avatarPromoteDataMap, ok := gdconf.CONF.AvatarPromoteDataMap[avatarDataConfig.PromoteId]
|
||||
if !ok {
|
||||
logger.Error("avatar promote config error, promoteId: %v", avatarDataConfig.PromoteId)
|
||||
return
|
||||
}
|
||||
// 获取角色突破等级对应的配置表
|
||||
avatarPromoteConfig, ok := avatarPromoteDataMap[int32(avatar.Promote)]
|
||||
if !ok {
|
||||
logger.Error("avatar promote config error, promoteLevel: %v", avatar.Promote)
|
||||
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
|
||||
return
|
||||
}
|
||||
// 角色增加经验
|
||||
@@ -174,19 +277,17 @@ func (g *GameManager) UpgradeUserAvatar(userId uint32, avatarId uint32, expCount
|
||||
// 获取角色等级配置表
|
||||
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
|
||||
// 获取不到代表已经到达最大等级
|
||||
break
|
||||
}
|
||||
// 角色当前等级未突破则跳出循环
|
||||
if avatar.Level >= uint8(avatarPromoteConfig.LevelLimit) {
|
||||
// 角色未突破溢出的经验处理
|
||||
avatar.Exp = 0
|
||||
break
|
||||
}
|
||||
// 角色经验小于升级所需的经验则跳出循环
|
||||
if avatar.Exp > uint32(avatarLevelConfig.Exp) {
|
||||
// 角色当前等级未突破则跳出循环
|
||||
if avatar.Level >= uint8(avatarPromoteConfig.LevelLimit) {
|
||||
// 角色未突破溢出的经验处理
|
||||
avatar.Exp = uint32(avatarLevelConfig.Exp)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if avatar.Exp < uint32(avatarLevelConfig.Exp) {
|
||||
break
|
||||
}
|
||||
// 角色等级提升
|
||||
|
||||
57
gs/game/player_base.go
Normal file
57
gs/game/player_base.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"hk4e/common/constant"
|
||||
"hk4e/gdconf"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/protocol/cmd"
|
||||
"hk4e/protocol/proto"
|
||||
)
|
||||
|
||||
// AddUserPlayerExp 基于玩家冒险阅历
|
||||
func (g *GameManager) AddUserPlayerExp(userId uint32, expCount uint32) {
|
||||
player := USER_MANAGER.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userId)
|
||||
return
|
||||
}
|
||||
// 玩家增加冒险阅历
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_EXP] += expCount
|
||||
// 玩家升级
|
||||
for {
|
||||
playerLevel := player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]
|
||||
// 读取玩家等级配置表
|
||||
playerLevelConfig, ok := gdconf.CONF.PlayerLevelDataMap[int32(playerLevel)]
|
||||
if !ok {
|
||||
// 获取不到代表已经到达最大等级
|
||||
break
|
||||
}
|
||||
// 玩家冒险阅历不足则跳出循环
|
||||
if player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_EXP] < uint32(playerLevelConfig.Exp) {
|
||||
break
|
||||
}
|
||||
// 玩家增加冒险等阶
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]++
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_EXP] -= uint32(playerLevelConfig.Exp)
|
||||
|
||||
// 更新玩家属性
|
||||
playerPropNotify := &proto.PlayerPropNotify{
|
||||
PropMap: make(map[uint32]*proto.PropValue),
|
||||
}
|
||||
playerPropNotify.PropMap[uint32(constant.PlayerPropertyConst.PROP_PLAYER_LEVEL)] = &proto.PropValue{
|
||||
Type: uint32(constant.PlayerPropertyConst.PROP_PLAYER_LEVEL),
|
||||
Val: int64(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]),
|
||||
Value: &proto.PropValue_Ival{
|
||||
Ival: int64(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]),
|
||||
},
|
||||
}
|
||||
playerPropNotify.PropMap[uint32(constant.PlayerPropertyConst.PROP_PLAYER_EXP)] = &proto.PropValue{
|
||||
Type: uint32(constant.PlayerPropertyConst.PROP_PLAYER_EXP),
|
||||
Val: int64(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_EXP]),
|
||||
Value: &proto.PropValue_Ival{
|
||||
Ival: int64(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_EXP]),
|
||||
},
|
||||
}
|
||||
g.SendMsg(cmd.PlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
|
||||
}
|
||||
}
|
||||
@@ -48,14 +48,46 @@ func (g *GameManager) GetAllItemDataConfig() map[int32]*gdconf.ItemData {
|
||||
return allItemDataConfig
|
||||
}
|
||||
|
||||
// AddUserItem 玩家添加物品
|
||||
func (g *GameManager) AddUserItem(userId uint32, itemList []*UserItem, isHint bool, hintReason uint16) {
|
||||
player := USER_MANAGER.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userId)
|
||||
return
|
||||
}
|
||||
playerPropNotify := &proto.PlayerPropNotify{
|
||||
PropMap: make(map[uint32]*proto.PropValue),
|
||||
}
|
||||
for _, userItem := range itemList {
|
||||
player.AddItem(userItem.ItemId, userItem.ChangeCount)
|
||||
// 物品为虚拟物品则另外处理
|
||||
switch userItem.ItemId {
|
||||
case constant.ItemConstantConst.RESIN, constant.ItemConstantConst.LEGENDARY_KEY, constant.ItemConstantConst.HCOIN,
|
||||
constant.ItemConstantConst.SCOIN, constant.ItemConstantConst.MCOIN, constant.ItemConstantConst.HOME_COIN:
|
||||
// 树脂 传说任务钥匙 原石 摩拉 创世结晶 洞天宝钱
|
||||
prop, ok := constant.ItemConstantConst.VIRTUAL_ITEM_PROP[userItem.ItemId]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// 角色属性物品数量增加
|
||||
player.PropertiesMap[prop] += userItem.ChangeCount
|
||||
|
||||
playerPropNotify.PropMap[uint32(prop)] = &proto.PropValue{
|
||||
Type: uint32(prop),
|
||||
Val: int64(player.PropertiesMap[prop]),
|
||||
Value: &proto.PropValue_Ival{
|
||||
Ival: int64(player.PropertiesMap[prop]),
|
||||
},
|
||||
}
|
||||
case constant.ItemConstantConst.PLAYER_EXP:
|
||||
// 冒险阅历
|
||||
g.AddUserPlayerExp(userId, userItem.ChangeCount)
|
||||
default:
|
||||
// 普通物品直接进背包
|
||||
player.AddItem(userItem.ItemId, userItem.ChangeCount)
|
||||
}
|
||||
}
|
||||
if len(playerPropNotify.PropMap) > 0 {
|
||||
g.SendMsg(cmd.PlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
|
||||
}
|
||||
|
||||
storeItemChangeNotify := &proto.StoreItemChangeNotify{
|
||||
@@ -93,26 +125,6 @@ func (g *GameManager) AddUserItem(userId uint32, itemList []*UserItem, isHint bo
|
||||
}
|
||||
g.SendMsg(cmd.ItemAddHintNotify, userId, player.ClientSeq, itemAddHintNotify)
|
||||
}
|
||||
|
||||
playerPropNotify := &proto.PlayerPropNotify{
|
||||
PropMap: make(map[uint32]*proto.PropValue),
|
||||
}
|
||||
for _, userItem := range itemList {
|
||||
isVirtualItem, prop := player.GetVirtualItemProp(userItem.ItemId)
|
||||
if !isVirtualItem {
|
||||
continue
|
||||
}
|
||||
playerPropNotify.PropMap[uint32(prop)] = &proto.PropValue{
|
||||
Type: uint32(prop),
|
||||
Val: int64(player.PropertiesMap[prop]),
|
||||
Value: &proto.PropValue_Ival{
|
||||
Ival: int64(player.PropertiesMap[prop]),
|
||||
},
|
||||
}
|
||||
}
|
||||
if len(playerPropNotify.PropMap) > 0 {
|
||||
g.SendMsg(cmd.PlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) {
|
||||
@@ -121,8 +133,42 @@ func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) {
|
||||
logger.Error("player is nil, uid: %v", userId)
|
||||
return
|
||||
}
|
||||
playerPropNotify := &proto.PlayerPropNotify{
|
||||
PropMap: make(map[uint32]*proto.PropValue),
|
||||
}
|
||||
for _, userItem := range itemList {
|
||||
player.CostItem(userItem.ItemId, userItem.ChangeCount)
|
||||
// 物品为虚拟物品则另外处理
|
||||
switch userItem.ItemId {
|
||||
case constant.ItemConstantConst.RESIN, constant.ItemConstantConst.LEGENDARY_KEY, constant.ItemConstantConst.HCOIN,
|
||||
constant.ItemConstantConst.SCOIN, constant.ItemConstantConst.MCOIN, constant.ItemConstantConst.HOME_COIN:
|
||||
// 树脂 传说任务钥匙 原石 摩拉 创世结晶 洞天宝钱
|
||||
prop, ok := constant.ItemConstantConst.VIRTUAL_ITEM_PROP[userItem.ItemId]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// 角色属性物品数量增加
|
||||
if player.PropertiesMap[prop] < userItem.ChangeCount {
|
||||
player.PropertiesMap[prop] = 0
|
||||
} else {
|
||||
player.PropertiesMap[prop] -= userItem.ChangeCount
|
||||
}
|
||||
|
||||
playerPropNotify.PropMap[uint32(prop)] = &proto.PropValue{
|
||||
Type: uint32(prop),
|
||||
Val: int64(player.PropertiesMap[prop]),
|
||||
Value: &proto.PropValue_Ival{
|
||||
Ival: int64(player.PropertiesMap[prop]),
|
||||
},
|
||||
}
|
||||
case constant.ItemConstantConst.PLAYER_EXP:
|
||||
// 冒险阅历应该也没人会去扣吧?
|
||||
default:
|
||||
// 普通物品直接扣除
|
||||
player.CostItem(userItem.ItemId, userItem.ChangeCount)
|
||||
}
|
||||
}
|
||||
if len(playerPropNotify.PropMap) > 0 {
|
||||
g.SendMsg(cmd.PlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
|
||||
}
|
||||
|
||||
storeItemChangeNotify := &proto.StoreItemChangeNotify{
|
||||
@@ -163,24 +209,4 @@ func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) {
|
||||
if len(storeItemDelNotify.GuidList) > 0 {
|
||||
g.SendMsg(cmd.StoreItemDelNotify, userId, player.ClientSeq, storeItemDelNotify)
|
||||
}
|
||||
|
||||
playerPropNotify := &proto.PlayerPropNotify{
|
||||
PropMap: make(map[uint32]*proto.PropValue),
|
||||
}
|
||||
for _, userItem := range itemList {
|
||||
isVirtualItem, prop := player.GetVirtualItemProp(userItem.ItemId)
|
||||
if !isVirtualItem {
|
||||
continue
|
||||
}
|
||||
playerPropNotify.PropMap[uint32(prop)] = &proto.PropValue{
|
||||
Type: uint32(prop),
|
||||
Val: int64(player.PropertiesMap[prop]),
|
||||
Value: &proto.PropValue_Ival{
|
||||
Ival: int64(player.PropertiesMap[prop]),
|
||||
},
|
||||
}
|
||||
}
|
||||
if len(playerPropNotify.PropMap) > 0 {
|
||||
g.SendMsg(cmd.PlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ func (r *RouteManager) initRoute() {
|
||||
r.registerRouter(cmd.GCGOperationReq, GAME_MANAGER.GCGOperationReq)
|
||||
r.registerRouter(cmd.ObstacleModifyNotify, GAME_MANAGER.ObstacleModifyNotify)
|
||||
r.registerRouter(cmd.AvatarUpgradeReq, GAME_MANAGER.AvatarUpgradeReq)
|
||||
r.registerRouter(cmd.AvatarPromoteReq, GAME_MANAGER.AvatarPromoteReq)
|
||||
}
|
||||
|
||||
func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"hk4e/common/constant"
|
||||
)
|
||||
import "hk4e/common/constant"
|
||||
|
||||
type Item struct {
|
||||
ItemId uint32 `bson:"itemId"` // 道具id
|
||||
@@ -26,8 +24,8 @@ func (p *Player) GetItemGuid(itemId uint32) uint64 {
|
||||
}
|
||||
|
||||
func (p *Player) GetItemCount(itemId uint32) uint32 {
|
||||
isVirtualItem, prop := p.GetVirtualItemProp(itemId)
|
||||
if isVirtualItem {
|
||||
prop, ok := constant.ItemConstantConst.VIRTUAL_ITEM_PROP[itemId]
|
||||
if ok {
|
||||
value := p.PropertiesMap[prop]
|
||||
return value
|
||||
} else {
|
||||
@@ -39,73 +37,28 @@ func (p *Player) GetItemCount(itemId uint32) uint32 {
|
||||
}
|
||||
}
|
||||
|
||||
// 虚拟道具如下 实际值存在玩家的属性上
|
||||
// 原石 201
|
||||
// 摩拉 202
|
||||
// 创世结晶 203
|
||||
// 树脂 106
|
||||
// 传说任务钥匙 107
|
||||
// 洞天宝钱 204
|
||||
|
||||
func (p *Player) GetVirtualItemProp(itemId uint32) (isVirtualItem bool, prop uint16) {
|
||||
switch itemId {
|
||||
case 106:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_RESIN
|
||||
case 107:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_LEGENDARY_KEY
|
||||
case 201:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_HCOIN
|
||||
case 202:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_SCOIN
|
||||
case 203:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_MCOIN
|
||||
case 204:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_HOME_COIN
|
||||
default:
|
||||
return false, 0
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Player) AddItem(itemId uint32, count uint32) {
|
||||
isVirtualItem, prop := p.GetVirtualItemProp(itemId)
|
||||
if isVirtualItem {
|
||||
value := p.PropertiesMap[prop]
|
||||
value += count
|
||||
p.PropertiesMap[prop] = value
|
||||
} else {
|
||||
itemInfo := p.ItemMap[itemId]
|
||||
if itemInfo == nil {
|
||||
itemInfo = &Item{
|
||||
ItemId: itemId,
|
||||
Count: 0,
|
||||
Guid: p.GetNextGameObjectGuid(),
|
||||
}
|
||||
itemInfo := p.ItemMap[itemId]
|
||||
if itemInfo == nil {
|
||||
itemInfo = &Item{
|
||||
ItemId: itemId,
|
||||
Count: 0,
|
||||
Guid: p.GetNextGameObjectGuid(),
|
||||
}
|
||||
itemInfo.Count += count
|
||||
p.ItemMap[itemId] = itemInfo
|
||||
}
|
||||
itemInfo.Count += count
|
||||
p.ItemMap[itemId] = itemInfo
|
||||
}
|
||||
|
||||
func (p *Player) CostItem(itemId uint32, count uint32) {
|
||||
isVirtualItem, prop := p.GetVirtualItemProp(itemId)
|
||||
if isVirtualItem {
|
||||
value := p.PropertiesMap[prop]
|
||||
if value < count {
|
||||
value = 0
|
||||
} else {
|
||||
value -= count
|
||||
}
|
||||
p.PropertiesMap[prop] = value
|
||||
} else {
|
||||
itemInfo := p.ItemMap[itemId]
|
||||
if itemInfo == nil {
|
||||
return
|
||||
}
|
||||
if itemInfo.Count < count {
|
||||
itemInfo.Count = 0
|
||||
} else {
|
||||
itemInfo.Count -= count
|
||||
}
|
||||
p.ItemMap[itemId] = itemInfo
|
||||
itemInfo := p.ItemMap[itemId]
|
||||
if itemInfo == nil {
|
||||
return
|
||||
}
|
||||
if itemInfo.Count < count {
|
||||
itemInfo.Count = 0
|
||||
} else {
|
||||
itemInfo.Count -= count
|
||||
}
|
||||
p.ItemMap[itemId] = itemInfo
|
||||
}
|
||||
|
||||
@@ -224,6 +224,8 @@ func (c *CmdProtoMap) registerAllMessage() {
|
||||
c.registerMessage(AvatarUpgradeReq, &proto.AvatarUpgradeReq{}) // 角色升级请求
|
||||
c.registerMessage(AvatarUpgradeRsp, &proto.AvatarUpgradeRsp{}) // 角色升级通知
|
||||
c.registerMessage(AvatarPropNotify, &proto.AvatarPropNotify{}) // 角色属性表更新通知
|
||||
c.registerMessage(AvatarPromoteReq, &proto.AvatarPromoteReq{}) // 角色突破请求
|
||||
c.registerMessage(AvatarPromoteRsp, &proto.AvatarPromoteRsp{}) // 角色突破响应
|
||||
|
||||
// 背包与道具
|
||||
c.registerMessage(PlayerStoreNotify, &proto.PlayerStoreNotify{}) // 玩家背包数据通知
|
||||
|
||||
Reference in New Issue
Block a user