diff --git a/gdconf/game_data_config.go b/gdconf/game_data_config.go index 25787a42..14eb1f7b 100644 --- a/gdconf/game_data_config.go +++ b/gdconf/game_data_config.go @@ -24,31 +24,32 @@ 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 // 场景标签 - SceneDetailMap map[int32]*SceneDetail // 场景详情LUA配置数据 - 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 // 玩家等级 - WeaponLevelDataMap map[int32]*WeaponLevelData // 武器等级 - WeaponPromoteDataMap map[int32]map[int32]*WeaponPromoteData // 角色突破 - RewardDataMap map[int32]*RewardData // 奖励 - AvatarCostumeDataMap map[int32]*AvatarCostumeData // 角色时装 - AvatarFlycloakDataMap map[int32]*AvatarFlycloakData // 角色风之翼 - ReliquaryMainDataMap map[int32]map[int32]*ReliquaryMainData // 圣遗物主属性 + 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 // 场景标签 + SceneDetailMap map[int32]*SceneDetail // 场景详情LUA配置数据 + 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 // 玩家等级 + WeaponLevelDataMap map[int32]*WeaponLevelData // 武器等级 + WeaponPromoteDataMap map[int32]map[int32]*WeaponPromoteData // 角色突破 + RewardDataMap map[int32]*RewardData // 奖励 + AvatarCostumeDataMap map[int32]*AvatarCostumeData // 角色时装 + AvatarFlycloakDataMap map[int32]*AvatarFlycloakData // 角色风之翼 + ReliquaryMainDataMap map[int32]map[int32]*ReliquaryMainData // 圣遗物主属性 + ReliquaryAffixDataMap map[int32]map[int32]*ReliquaryAffixData // 圣遗物追加属性 } func InitGameDataConfig() { @@ -72,7 +73,7 @@ func ReplaceGameDataConfig() { } func (g *GameDataConfig) loadAll() { - pathPrefix := config.CONF.Hk4e.GameDataConfigPath + pathPrefix := config.GetConfig().Hk4e.GameDataConfigPath dirInfo, err := os.Stat(pathPrefix) if err != nil || !dirInfo.IsDir() { @@ -133,6 +134,7 @@ func (g *GameDataConfig) load() { g.loadAvatarCostumeData() // 角色时装 g.loadAvatarFlycloakData() // 角色风之翼 g.loadReliquaryMainData() // 圣遗物主属性 + g.loadReliquaryAffixData() // 圣遗物追加属性 } func (g *GameDataConfig) readCsvFileData(fileName string) []byte { diff --git a/gdconf/item_data.go b/gdconf/item_data.go index 6cd8d26c..fd8c1ae9 100644 --- a/gdconf/item_data.go +++ b/gdconf/item_data.go @@ -38,6 +38,7 @@ type ItemData struct { ReliquaryType int32 `csv:"ReliquaryType,omitempty"` // 圣遗物类别 MainPropDepotId int32 `csv:"MainPropDepotId,omitempty"` // 主属性库ID AppendPropDepotId int32 `csv:"AppendPropDepotId,omitempty"` // 追加属性库ID + AppendPropCount int32 `csv:"AppendPropCount,omitempty"` // 追加属性初始条数 } func (g *GameDataConfig) loadItemData() { diff --git a/gdconf/reliquary_affix_data.go b/gdconf/reliquary_affix_data.go new file mode 100644 index 00000000..dbbc09f0 --- /dev/null +++ b/gdconf/reliquary_affix_data.go @@ -0,0 +1,69 @@ +package gdconf + +import ( + "fmt" + + "hk4e/pkg/logger" + + "github.com/jszwec/csvutil" + "github.com/mroth/weightedrand" +) + +// ReliquaryAffixData 圣遗物追加属性配置表 +type ReliquaryAffixData struct { + AppendPropId int32 `csv:"AppendPropId"` // 追加属性ID + AppendPropDepotId int32 `csv:"AppendPropDepotId,omitempty"` // 追加属性库ID + PropType int32 `csv:"PropType,omitempty"` // 属性类别 + RandomWeight int32 `csv:"RandomWeight,omitempty"` // 随机权重 +} + +func (g *GameDataConfig) loadReliquaryAffixData() { + g.ReliquaryAffixDataMap = make(map[int32]map[int32]*ReliquaryAffixData) + data := g.readCsvFileData("ReliquaryAffixData.csv") + var reliquaryAffixDataList []*ReliquaryAffixData + err := csvutil.Unmarshal(data, &reliquaryAffixDataList) + if err != nil { + info := fmt.Sprintf("parse file error: %v", err) + panic(info) + } + for _, reliquaryAffixData := range reliquaryAffixDataList { + // 通过主属性库ID找到 + _, ok := g.ReliquaryAffixDataMap[reliquaryAffixData.AppendPropDepotId] + if !ok { + g.ReliquaryAffixDataMap[reliquaryAffixData.AppendPropDepotId] = make(map[int32]*ReliquaryAffixData) + } + // list -> map + g.ReliquaryAffixDataMap[reliquaryAffixData.AppendPropDepotId][reliquaryAffixData.AppendPropId] = reliquaryAffixData + } + logger.Info("ReliquaryAffixData count: %v", len(g.ReliquaryAffixDataMap)) +} + +func GetReliquaryAffixDataByDepotIdAndPropId(appendPropDepotId int32, appendPropId int32) *ReliquaryAffixData { + value, exist := CONF.ReliquaryAffixDataMap[appendPropDepotId] + if !exist { + return nil + } + return value[appendPropId] +} + +func GetReliquaryAffixDataRandomByDepotId(appendPropDepotId int32) *ReliquaryAffixData { + appendPropMap, exist := CONF.ReliquaryAffixDataMap[appendPropDepotId] + if !exist { + return nil + } + choices := make([]weightedrand.Choice, 0, len(appendPropMap)) + for _, data := range appendPropMap { + choices = append(choices, weightedrand.NewChoice(data, uint(data.RandomWeight))) + } + chooser, err := weightedrand.NewChooser(choices...) + if err != nil { + logger.Error("reliquary append random error: %v", err) + return nil + } + result := chooser.Pick() + return result.(*ReliquaryAffixData) +} + +func GetReliquaryAffixDataMap() map[int32]map[int32]*ReliquaryAffixData { + return CONF.ReliquaryAffixDataMap +} diff --git a/gdconf/reliquary_main_data.go b/gdconf/reliquary_main_data.go index 3a3b0539..4d68ccfe 100644 --- a/gdconf/reliquary_main_data.go +++ b/gdconf/reliquary_main_data.go @@ -14,7 +14,7 @@ type ReliquaryMainData struct { MainPropId int32 `csv:"MainPropId"` // 主属性ID MainPropDepotId int32 `csv:"MainPropDepotId,omitempty"` // 主属性库ID PropType int32 `csv:"PropType,omitempty"` // 属性类别 - Weight int32 `csv:"Weight,omitempty"` // 随机权重 + RandomWeight int32 `csv:"RandomWeight,omitempty"` // 随机权重 } func (g *GameDataConfig) loadReliquaryMainData() { @@ -53,11 +53,11 @@ func GetReliquaryMainDataRandomByDepotId(mainPropDepotId int32) *ReliquaryMainDa } choices := make([]weightedrand.Choice, 0, len(mainPropMap)) for _, data := range mainPropMap { - choices = append(choices, weightedrand.NewChoice(data, uint(data.Weight))) + choices = append(choices, weightedrand.NewChoice(data, uint(data.RandomWeight))) } chooser, err := weightedrand.NewChooser(choices...) if err != nil { - logger.Error("reliquary main error: %v", err) + logger.Error("reliquary main random error: %v", err) return nil } result := chooser.Pick() diff --git a/gdconf/table_struct_mapping.json b/gdconf/table_struct_mapping.json index d874e25f..e5a4fddb 100644 --- a/gdconf/table_struct_mapping.json +++ b/gdconf/table_struct_mapping.json @@ -601,6 +601,11 @@ "field_name": "AppendPropDepotId", "field_type": "int32", "origin_name": "追加属性库ID" + }, + { + "field_name": "AppendPropCount", + "field_type": "int32", + "origin_name": "追加属性初始条数" } ] }, @@ -983,7 +988,32 @@ "origin_name": "属性类别" }, { - "field_name": "Weight", + "field_name": "RandomWeight", + "field_type": "int32", + "origin_name": "随机权重" + } + ] + }, + { + "table_name": "ReliquaryAffixData", + "field_list": [ + { + "field_name": "AppendPropId", + "field_type": "int32", + "origin_name": "追加属性ID" + }, + { + "field_name": "AppendPropDepotId", + "field_type": "int32", + "origin_name": "追加属性库ID" + }, + { + "field_name": "PropType", + "field_type": "int32", + "origin_name": "属性类别" + }, + { + "field_name": "RandomWeight", "field_type": "int32", "origin_name": "随机权重" } diff --git a/gs/game/player_reliquary.go b/gs/game/player_reliquary.go index 8afde9c1..bd74435a 100644 --- a/gs/game/player_reliquary.go +++ b/gs/game/player_reliquary.go @@ -18,8 +18,8 @@ func (g *GameManager) GetAllReliquaryDataConfig() map[int32]*gdconf.ItemData { if (itemId >= 20002 && itemId <= 20004) || itemId == 23334 || (itemId >= 23300 && itemId <= 23340) { - continue // 跳过无效圣遗物 + continue } allReliquaryDataConfig[itemId] = itemData } @@ -43,17 +43,80 @@ func (g *GameManager) AddUserReliquary(userId uint32, itemId uint32) uint64 { return 0 } reliquaryId := uint64(g.snowflake.GenId()) - // 根据圣遗物类型给予主属性Id - player.AddReliquary(itemId, reliquaryId, uint32(reliquaryMainConfig.MainPropId)) + // 圣遗物主属性 + mainPropId := uint32(reliquaryMainConfig.MainPropId) + // 玩家添加圣遗物 + player.AddReliquary(itemId, reliquaryId, mainPropId) reliquary := player.GetReliquary(reliquaryId) if reliquary == nil { logger.Error("reliquary is nil, itemId: %v, reliquaryId: %v", itemId, reliquaryId) return 0 } + // 设置圣遗物初始词条 + g.AppendReliquaryProp(reliquary, reliquaryConfig.AppendPropCount) g.SendMsg(cmd.StoreItemChangeNotify, userId, player.ClientSeq, g.PacketStoreItemChangeNotifyByReliquary(reliquary)) return reliquaryId } +// AppendReliquaryProp 圣遗物追加属性 +func (g *GameManager) AppendReliquaryProp(reliquary *model.Reliquary, count int32) { + // 获取圣遗物配置表 + reliquaryConfig := gdconf.GetItemDataById(int32(reliquary.ItemId)) + if reliquaryConfig == nil { + logger.Error("reliquary config error, itemId: %v", reliquary.ItemId) + return + } + // 主属性配置表 + reliquaryMainConfig := gdconf.GetReliquaryMainDataByDepotIdAndPropId(reliquaryConfig.MainPropDepotId, int32(reliquary.MainPropId)) + if reliquaryMainConfig == nil { + logger.Error("reliquary main config error, mainPropDepotId: %v, propId: %v", reliquaryConfig.MainPropDepotId, reliquary.MainPropId) + return + } + // 圣遗物追加属性的次数 + for i := 0; i < int(count); i++ { + // 将要添加的属性 + appendAffixConfig := gdconf.GetReliquaryAffixDataRandomByDepotId(reliquaryConfig.AppendPropDepotId) + if appendAffixConfig == nil { + logger.Error("append affix config error, appendPropDepotId: %v", reliquaryConfig.AppendPropDepotId) + return + } + + isNotBoth := false + // 如果圣遗物词条为0就直接加不用校验是否相同 + for len(reliquary.AppendPropIdList) > 0 { + if isNotBoth { + break + } + // 追加的属性类型不能相同 + for i, propId := range reliquary.AppendPropIdList { + targetAffixConfig := gdconf.GetReliquaryAffixDataByDepotIdAndPropId(reliquaryConfig.AppendPropDepotId, int32(propId)) + if targetAffixConfig == nil { + logger.Error("target affix config error, propId: %v", propId) + return + } + // 如果类型相同则重新随机获取一个属性 + // 追加的属性还不能和主属性相同 + if appendAffixConfig.PropType == targetAffixConfig.PropType || appendAffixConfig.PropType == reliquaryMainConfig.PropType { + reliquaryAffixConfig := gdconf.GetReliquaryAffixDataRandomByDepotId(reliquaryConfig.AppendPropDepotId) + if reliquaryAffixConfig == nil { + logger.Error("reliquary affix config error, appendPropDepotId: %v", reliquaryConfig.AppendPropDepotId) + return + } + // 将属性赋值并重新查找 + appendAffixConfig = reliquaryAffixConfig + break + } + // 如果循环到最后一个还不匹配那就是没有相同的了 + if i == len(reliquary.AppendPropIdList)-1 { + isNotBoth = true + } + } + } + // 圣遗物添加词条 + reliquary.AppendPropIdList = append(reliquary.AppendPropIdList, uint32(appendAffixConfig.AppendPropId)) + } +} + func (g *GameManager) CostUserReliquary(userId uint32, reliquaryIdList []uint64) { player := USER_MANAGER.GetOnlineUser(userId) if player == nil { diff --git a/gs/model/reliquary.go b/gs/model/reliquary.go index 84a3ffe6..24753f6b 100644 --- a/gs/model/reliquary.go +++ b/gs/model/reliquary.go @@ -76,7 +76,6 @@ func (p *Player) AddReliquary(itemId uint32, reliquaryId uint64, mainPropId uint AvatarId: 0, Guid: 0, } - _ = itemDataConfig p.InitReliquary(reliquary) p.ReliquaryMap[reliquaryId] = reliquary }