mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 13:02:26 +08:00
场景group分suite加载、读取掉落表
This commit is contained in:
24
common/constant/gadget_state.go
Normal file
24
common/constant/gadget_state.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package constant
|
||||
|
||||
const (
|
||||
GADGET_STATE_DEFAULT = 0
|
||||
GADGET_STATE_GATHER_DROP = 1
|
||||
GADGET_STATE_CHEST_LOCKED = 101
|
||||
GADGET_STATE_CHEST_OPENED = 102
|
||||
GADGET_STATE_CHEST_TRAP = 103
|
||||
GADGET_STATE_CHEST_BRAMBLE = 104
|
||||
GADGET_STATE_CHEST_FROZEN = 105
|
||||
GADGET_STATE_CHEST_ROCK = 106
|
||||
GADGET_STATE_GEAR_START = 201
|
||||
GADGET_STATE_GEAR_STOP = 202
|
||||
GADGET_STATE_GEAR_ACTION1 = 203
|
||||
GADGET_STATE_GEAR_ACTION2 = 204
|
||||
GADGET_STATE_CRYSTAL_RESONATE1 = 301
|
||||
GADGET_STATE_CRYSTAL_RESONATE2 = 302
|
||||
GADGET_STATE_CRYSTAL_EXPLODE = 303
|
||||
GADGET_STATE_CRYSTAL_DRAIN = 304
|
||||
GADGET_STATE_STATUE_ACTIVE = 401
|
||||
GADGET_STATE_ACTION01 = 901
|
||||
GADGET_STATE_ACTION02 = 902
|
||||
GADGET_STATE_ACTION03 = 903
|
||||
)
|
||||
@@ -2,6 +2,7 @@ package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
@@ -47,7 +48,17 @@ func NewController(dao *dao.Dao, discovery *rpc.DiscoveryClient) (r *Controller)
|
||||
|
||||
func (c *Controller) authorize() gin.HandlerFunc {
|
||||
return func(context *gin.Context) {
|
||||
if context.Query("key") == "flswld" {
|
||||
addr := context.ClientIP()
|
||||
if addr == "" {
|
||||
addr = context.Request.RemoteAddr
|
||||
}
|
||||
ip := net.ParseIP(addr)
|
||||
ipv4 := ip.To4()
|
||||
if ip.IsLoopback() ||
|
||||
ipv4[0] == 10 ||
|
||||
ipv4[0] == 169 && ipv4[1] == 254 ||
|
||||
ipv4[0] == 172 && ipv4[1] >= 16 && ipv4[1] <= 31 ||
|
||||
ipv4[0] == 192 && ipv4[1] == 168 {
|
||||
context.Next()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@ func (k *KcpConnectManager) getPlayerToken(req *proto.GetPlayerTokenReq, session
|
||||
}
|
||||
}
|
||||
tokenVerifyRsp, err := httpclient.PostJson[controller.TokenVerifyRsp](
|
||||
config.GetConfig().Hk4e.LoginSdkUrl+"/gate/token/verify?key=flswld",
|
||||
config.GetConfig().Hk4e.LoginSdkUrl+"/gate/token/verify",
|
||||
&controller.TokenVerifyReq{
|
||||
AccountId: req.AccountUid,
|
||||
AccountToken: req.AccountToken,
|
||||
|
||||
@@ -13,13 +13,12 @@ type AvatarCostumeData struct {
|
||||
func (g *GameDataConfig) loadAvatarCostumeData() {
|
||||
g.AvatarCostumeDataMap = make(map[int32]*AvatarCostumeData)
|
||||
avatarCostumeDataList := make([]*AvatarCostumeData, 0)
|
||||
readTable[AvatarCostumeData](g.tablePrefix+"AvatarCostumeData.txt", &avatarCostumeDataList)
|
||||
readTable[AvatarCostumeData](g.txtPrefix+"AvatarCostumeData.txt", &avatarCostumeDataList)
|
||||
for _, avatarCostumeData := range avatarCostumeDataList {
|
||||
// 屏蔽默认时装
|
||||
if avatarCostumeData.ItemID == 0 {
|
||||
continue
|
||||
}
|
||||
// list -> map
|
||||
g.AvatarCostumeDataMap[avatarCostumeData.CostumeID] = avatarCostumeData
|
||||
}
|
||||
logger.Info("AvatarCostumeData count: %v", len(g.AvatarCostumeDataMap))
|
||||
|
||||
@@ -43,7 +43,7 @@ type ConfigAvatarAbility struct {
|
||||
func (g *GameDataConfig) loadAvatarData() {
|
||||
g.AvatarDataMap = make(map[int32]*AvatarData)
|
||||
avatarDataList := make([]*AvatarData, 0)
|
||||
readTable[AvatarData](g.tablePrefix+"AvatarData.txt", &avatarDataList)
|
||||
readTable[AvatarData](g.txtPrefix+"AvatarData.txt", &avatarDataList)
|
||||
for _, avatarData := range avatarDataList {
|
||||
// 读取战斗config解析技能并转化为哈希码
|
||||
fileData, err := os.ReadFile(g.jsonPrefix + "avatar/" + avatarData.ConfigJson + ".json")
|
||||
@@ -72,7 +72,6 @@ func (g *GameDataConfig) loadAvatarData() {
|
||||
avatarData.PromoteRewardMap[uint32(promoteLevel)] = uint32(rewardId)
|
||||
}
|
||||
}
|
||||
// list -> map
|
||||
g.AvatarDataMap[avatarData.AvatarId] = avatarData
|
||||
}
|
||||
logger.Info("AvatarData count: %v", len(g.AvatarDataMap))
|
||||
|
||||
@@ -13,9 +13,8 @@ type AvatarFlycloakData struct {
|
||||
func (g *GameDataConfig) loadAvatarFlycloakData() {
|
||||
g.AvatarFlycloakDataMap = make(map[int32]*AvatarFlycloakData)
|
||||
avatarFlycloakDataList := make([]*AvatarFlycloakData, 0)
|
||||
readTable[AvatarFlycloakData](g.tablePrefix+"AvatarFlycloakData.txt", &avatarFlycloakDataList)
|
||||
readTable[AvatarFlycloakData](g.txtPrefix+"AvatarFlycloakData.txt", &avatarFlycloakDataList)
|
||||
for _, avatarFlycloakData := range avatarFlycloakDataList {
|
||||
// list -> map
|
||||
g.AvatarFlycloakDataMap[avatarFlycloakData.FlycloakID] = avatarFlycloakData
|
||||
}
|
||||
logger.Info("AvatarFlycloakData count: %v", len(g.AvatarFlycloakDataMap))
|
||||
|
||||
@@ -13,9 +13,8 @@ type AvatarLevelData struct {
|
||||
func (g *GameDataConfig) loadAvatarLevelData() {
|
||||
g.AvatarLevelDataMap = make(map[int32]*AvatarLevelData)
|
||||
avatarLevelDataList := make([]*AvatarLevelData, 0)
|
||||
readTable[AvatarLevelData](g.tablePrefix+"AvatarLevelData.txt", &avatarLevelDataList)
|
||||
readTable[AvatarLevelData](g.txtPrefix+"AvatarLevelData.txt", &avatarLevelDataList)
|
||||
for _, avatarLevelData := range avatarLevelDataList {
|
||||
// list -> map
|
||||
g.AvatarLevelDataMap[avatarLevelData.Level] = avatarLevelData
|
||||
}
|
||||
logger.Info("AvatarLevelData count: %v", len(g.AvatarLevelDataMap))
|
||||
|
||||
@@ -26,9 +26,8 @@ type AvatarPromoteData struct {
|
||||
func (g *GameDataConfig) loadAvatarPromoteData() {
|
||||
g.AvatarPromoteDataMap = make(map[int32]map[int32]*AvatarPromoteData)
|
||||
avatarPromoteDataList := make([]*AvatarPromoteData, 0)
|
||||
readTable[AvatarPromoteData](g.tablePrefix+"AvatarPromoteData.txt", &avatarPromoteDataList)
|
||||
readTable[AvatarPromoteData](g.txtPrefix+"AvatarPromoteData.txt", &avatarPromoteDataList)
|
||||
for _, avatarPromoteData := range avatarPromoteDataList {
|
||||
// list -> map
|
||||
_, ok := g.AvatarPromoteDataMap[avatarPromoteData.PromoteId]
|
||||
if !ok {
|
||||
g.AvatarPromoteDataMap[avatarPromoteData.PromoteId] = make(map[int32]*AvatarPromoteData)
|
||||
|
||||
@@ -17,9 +17,8 @@ type AvatarSkillData struct {
|
||||
func (g *GameDataConfig) loadAvatarSkillData() {
|
||||
g.AvatarSkillDataMap = make(map[int32]*AvatarSkillData)
|
||||
avatarSkillDataList := make([]*AvatarSkillData, 0)
|
||||
readTable[AvatarSkillData](g.tablePrefix+"AvatarSkillData.txt", &avatarSkillDataList)
|
||||
readTable[AvatarSkillData](g.txtPrefix+"AvatarSkillData.txt", &avatarSkillDataList)
|
||||
for _, avatarSkillData := range avatarSkillDataList {
|
||||
// list -> map
|
||||
g.AvatarSkillDataMap[avatarSkillData.AvatarSkillId] = avatarSkillData
|
||||
}
|
||||
logger.Info("AvatarSkillData count: %v", len(g.AvatarSkillDataMap))
|
||||
|
||||
@@ -43,7 +43,7 @@ type InherentProudSkillOpens struct {
|
||||
func (g *GameDataConfig) loadAvatarSkillDepotData() {
|
||||
g.AvatarSkillDepotDataMap = make(map[int32]*AvatarSkillDepotData)
|
||||
avatarSkillDepotDataList := make([]*AvatarSkillDepotData, 0)
|
||||
readTable[AvatarSkillDepotData](g.tablePrefix+"AvatarSkillDepotData.txt", &avatarSkillDepotDataList)
|
||||
readTable[AvatarSkillDepotData](g.txtPrefix+"AvatarSkillDepotData.txt", &avatarSkillDepotDataList)
|
||||
playerElementsFilePath := g.jsonPrefix + "ability_group/AbilityGroup_Other_PlayerElementAbility.json"
|
||||
playerElementsFile, err := os.ReadFile(playerElementsFilePath)
|
||||
if err != nil {
|
||||
@@ -113,7 +113,6 @@ func (g *GameDataConfig) loadAvatarSkillDepotData() {
|
||||
}
|
||||
}
|
||||
}
|
||||
// list -> map
|
||||
g.AvatarSkillDepotDataMap[avatarSkillDepotData.AvatarSkillDepotId] = avatarSkillDepotData
|
||||
}
|
||||
logger.Info("AvatarSkillDepotData count: %v", len(g.AvatarSkillDepotDataMap))
|
||||
|
||||
39
gdconf/chest_drop_data.go
Normal file
39
gdconf/chest_drop_data.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package gdconf
|
||||
|
||||
import (
|
||||
"hk4e/pkg/logger"
|
||||
)
|
||||
|
||||
// ChestDropData 宝箱掉落配置表
|
||||
type ChestDropData struct {
|
||||
Level int32 `csv:"最小等级"`
|
||||
DropTag string `csv:"总索引"`
|
||||
DropId int32 `csv:"掉落ID,omitempty"`
|
||||
DropCount int32 `csv:"掉落次数,omitempty"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadChestDropData() {
|
||||
g.ChestDropDataMap = make(map[string]map[int32]*ChestDropData)
|
||||
chestDropDataList := make([]*ChestDropData, 0)
|
||||
readTable[ChestDropData](g.txtPrefix+"ChestDropData.txt", &chestDropDataList)
|
||||
for _, chestDropData := range chestDropDataList {
|
||||
_, exist := g.ChestDropDataMap[chestDropData.DropTag]
|
||||
if !exist {
|
||||
g.ChestDropDataMap[chestDropData.DropTag] = make(map[int32]*ChestDropData)
|
||||
}
|
||||
g.ChestDropDataMap[chestDropData.DropTag][chestDropData.Level] = chestDropData
|
||||
}
|
||||
logger.Info("ChestDropData count: %v", len(g.ChestDropDataMap))
|
||||
}
|
||||
|
||||
func GetChestDropDataByDropTagAndLevel(dropTag string, level int32) *ChestDropData {
|
||||
value, exist := CONF.ChestDropDataMap[dropTag]
|
||||
if !exist {
|
||||
return nil
|
||||
}
|
||||
return value[level]
|
||||
}
|
||||
|
||||
func GetChestDropDataMap() map[string]map[int32]*ChestDropData {
|
||||
return CONF.ChestDropDataMap
|
||||
}
|
||||
248
gdconf/drop_data.go
Normal file
248
gdconf/drop_data.go
Normal file
@@ -0,0 +1,248 @@
|
||||
package gdconf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"hk4e/pkg/logger"
|
||||
)
|
||||
|
||||
type SubDrop struct {
|
||||
Id int32 // 子掉落ID
|
||||
CountRange []int32 // 子掉落数量区间
|
||||
Weight int32 // 子掉落权重
|
||||
}
|
||||
|
||||
const (
|
||||
RandomTypeChoose = 0
|
||||
RandomTypeIndep = 1
|
||||
RandomTypeIndepWeight = 10000
|
||||
)
|
||||
|
||||
// DropData 掉落配置表
|
||||
type DropData struct {
|
||||
DropId int32 `csv:"掉落ID"`
|
||||
RandomType int32 `csv:"随机方式,omitempty"` // 0:轮盘选择法掉落单个权重项 1:每个权重项独立随机(分母为10000)
|
||||
DropLayer int32 `csv:"掉落层级,omitempty"`
|
||||
SubDrop1Id int32 `csv:"子掉落1ID,omitempty"`
|
||||
SubDrop1CountRange FloatArray `csv:"子掉落1数量区间,omitempty"`
|
||||
SubDrop1Weight int32 `csv:"子掉落1权重,omitempty"`
|
||||
SubDrop2Id int32 `csv:"子掉落2ID,omitempty"`
|
||||
SubDrop2CountRange FloatArray `csv:"子掉落2数量区间,omitempty"`
|
||||
SubDrop2Weight int32 `csv:"子掉落2权重,omitempty"`
|
||||
SubDrop3Id int32 `csv:"子掉落3ID,omitempty"`
|
||||
SubDrop3CountRange FloatArray `csv:"子掉落3数量区间,omitempty"`
|
||||
SubDrop3Weight int32 `csv:"子掉落3权重,omitempty"`
|
||||
SubDrop4Id int32 `csv:"子掉落4ID,omitempty"`
|
||||
SubDrop4CountRange FloatArray `csv:"子掉落4数量区间,omitempty"`
|
||||
SubDrop4Weight int32 `csv:"子掉落4权重,omitempty"`
|
||||
SubDrop5Id int32 `csv:"子掉落5ID,omitempty"`
|
||||
SubDrop5CountRange FloatArray `csv:"子掉落5数量区间,omitempty"`
|
||||
SubDrop5Weight int32 `csv:"子掉落5权重,omitempty"`
|
||||
SubDrop6Id int32 `csv:"子掉落6ID,omitempty"`
|
||||
SubDrop6CountRange FloatArray `csv:"子掉落6数量区间,omitempty"`
|
||||
SubDrop6Weight int32 `csv:"子掉落6权重,omitempty"`
|
||||
SubDrop7Id int32 `csv:"子掉落7ID,omitempty"`
|
||||
SubDrop7CountRange FloatArray `csv:"子掉落7数量区间,omitempty"`
|
||||
SubDrop7Weight int32 `csv:"子掉落7权重,omitempty"`
|
||||
SubDrop8Id int32 `csv:"子掉落8ID,omitempty"`
|
||||
SubDrop8CountRange FloatArray `csv:"子掉落8数量区间,omitempty"`
|
||||
SubDrop8Weight int32 `csv:"子掉落8权重,omitempty"`
|
||||
SubDrop9Id int32 `csv:"子掉落9ID,omitempty"`
|
||||
SubDrop9CountRange FloatArray `csv:"子掉落9数量区间,omitempty"`
|
||||
SubDrop9Weight int32 `csv:"子掉落9权重,omitempty"`
|
||||
SubDrop10Id int32 `csv:"子掉落10ID,omitempty"`
|
||||
SubDrop10CountRange FloatArray `csv:"子掉落10数量区间,omitempty"`
|
||||
SubDrop10Weight int32 `csv:"子掉落10权重,omitempty"`
|
||||
SubDrop11Id int32 `csv:"子掉落11ID,omitempty"`
|
||||
SubDrop11CountRange FloatArray `csv:"子掉落11数量区间,omitempty"`
|
||||
SubDrop11Weight int32 `csv:"子掉落11权重,omitempty"`
|
||||
SubDrop12Id int32 `csv:"子掉落12ID,omitempty"`
|
||||
SubDrop12CountRange FloatArray `csv:"子掉落12数量区间,omitempty"`
|
||||
SubDrop12Weight int32 `csv:"子掉落12权重,omitempty"`
|
||||
|
||||
SubDropList []*SubDrop // 子掉落列表
|
||||
SubDropTotalWeight int32 // 总权重
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadDropData() {
|
||||
g.DropDataMap = make(map[int32]*DropData)
|
||||
fileNameList := []string{"DropLeafData.txt", "DropTreeData.txt"}
|
||||
for _, fileName := range fileNameList {
|
||||
dropDataList := make([]*DropData, 0)
|
||||
readTable[DropData](g.txtPrefix+fileName, &dropDataList)
|
||||
for _, dropData := range dropDataList {
|
||||
// 子掉落列合并
|
||||
dropData.SubDropList = make([]*SubDrop, 0)
|
||||
if dropData.SubDrop1Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop1CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop1Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop1Weight,
|
||||
})
|
||||
}
|
||||
if dropData.SubDrop2Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop2CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop2Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop2Weight,
|
||||
})
|
||||
}
|
||||
if dropData.SubDrop3Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop3CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop3Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop3Weight,
|
||||
})
|
||||
}
|
||||
if dropData.SubDrop4Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop4CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop4Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop4Weight,
|
||||
})
|
||||
}
|
||||
if dropData.SubDrop5Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop5CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop5Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop5Weight,
|
||||
})
|
||||
}
|
||||
if dropData.SubDrop6Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop6CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop6Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop6Weight,
|
||||
})
|
||||
}
|
||||
if dropData.SubDrop7Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop7CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop7Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop7Weight,
|
||||
})
|
||||
}
|
||||
if dropData.SubDrop8Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop8CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop8Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop8Weight,
|
||||
})
|
||||
}
|
||||
if dropData.SubDrop9Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop9CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop9Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop9Weight,
|
||||
})
|
||||
}
|
||||
if dropData.SubDrop10Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop10CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop10Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop10Weight,
|
||||
})
|
||||
}
|
||||
if dropData.SubDrop11Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop11CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop11Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop11Weight,
|
||||
})
|
||||
}
|
||||
if dropData.SubDrop12Id != 0 {
|
||||
countRange := make([]int32, 0)
|
||||
for _, v := range dropData.SubDrop12CountRange {
|
||||
countRange = append(countRange, int32(v))
|
||||
}
|
||||
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
|
||||
Id: dropData.SubDrop12Id,
|
||||
CountRange: countRange,
|
||||
Weight: dropData.SubDrop12Weight,
|
||||
})
|
||||
}
|
||||
if dropData.RandomType == RandomTypeChoose {
|
||||
// 计算轮盘总权重
|
||||
for _, subDrop := range dropData.SubDropList {
|
||||
dropData.SubDropTotalWeight += subDrop.Weight
|
||||
}
|
||||
}
|
||||
g.DropDataMap[dropData.DropId] = dropData
|
||||
}
|
||||
}
|
||||
// 检查
|
||||
for _, dropData := range g.DropDataMap {
|
||||
if dropData.RandomType == RandomTypeIndep {
|
||||
for _, subDrop := range dropData.SubDropList {
|
||||
if subDrop.Weight > RandomTypeIndepWeight {
|
||||
info := fmt.Sprintf("invalid weight for indep rand type, weight: %v, dropId: %v", subDrop.Weight, dropData.DropId)
|
||||
panic(info)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, subDrop := range dropData.SubDropList {
|
||||
// 掉落id优先在掉落表里找 找不到就去道具表里找
|
||||
_, exist := g.DropDataMap[subDrop.Id]
|
||||
if !exist {
|
||||
_, exist := g.ItemDataMap[subDrop.Id]
|
||||
if !exist {
|
||||
info := fmt.Sprintf("drop item id not exist, itemId: %v, dropId: %v", subDrop.Id, dropData.DropId)
|
||||
panic(info)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.Info("DropData count: %v", len(g.DropDataMap))
|
||||
}
|
||||
|
||||
func GetDropDataById(dropId int32) *DropData {
|
||||
return CONF.DropDataMap[dropId]
|
||||
}
|
||||
|
||||
func GetDropDataMap() map[int32]*DropData {
|
||||
return CONF.DropDataMap
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package gdconf
|
||||
|
||||
import (
|
||||
"hk4e/pkg/logger"
|
||||
)
|
||||
|
||||
// 当初写卡池算法的时候临时建立的表 以后再做迁移吧
|
||||
|
||||
type Drop struct {
|
||||
DropId int32 `csv:"DropId"`
|
||||
Weight int32 `csv:"Weight"`
|
||||
Result int32 `csv:"Result"`
|
||||
IsEnd bool `csv:"IsEnd"`
|
||||
}
|
||||
|
||||
type DropGroupData struct {
|
||||
DropId int32
|
||||
WeightAll int32
|
||||
DropConfig []*Drop
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadDropGroupData() {
|
||||
g.DropGroupDataMap = make(map[int32]*DropGroupData)
|
||||
fileNameList := []string{"DropGachaAvatarUp.csv", "DropGachaWeaponUp.csv", "DropGachaNormal.csv"}
|
||||
for _, fileName := range fileNameList {
|
||||
dropList := make([]*Drop, 0)
|
||||
readExtCsv[Drop](g.extPrefix+fileName, &dropList)
|
||||
for _, drop := range dropList {
|
||||
dropGroupData, exist := g.DropGroupDataMap[drop.DropId]
|
||||
if !exist {
|
||||
dropGroupData = new(DropGroupData)
|
||||
dropGroupData.DropId = drop.DropId
|
||||
dropGroupData.WeightAll = 0
|
||||
dropGroupData.DropConfig = make([]*Drop, 0)
|
||||
g.DropGroupDataMap[drop.DropId] = dropGroupData
|
||||
}
|
||||
dropGroupData.WeightAll += drop.Weight
|
||||
dropGroupData.DropConfig = append(dropGroupData.DropConfig, drop)
|
||||
}
|
||||
}
|
||||
logger.Info("DropGroupData count: %v", len(g.DropGroupDataMap))
|
||||
}
|
||||
@@ -16,9 +16,8 @@ func (g *GameDataConfig) loadFetterData() {
|
||||
fileNameList := []string{"FettersData.txt", "FetterDataStory.txt", "FetterDataIformation.txt", "PhotographExpressionName.txt", "PhotographPoseName.txt"}
|
||||
for _, fileName := range fileNameList {
|
||||
fetterDataList := make([]*FetterData, 0)
|
||||
readTable[FetterData](g.tablePrefix+fileName, &fetterDataList)
|
||||
readTable[FetterData](g.txtPrefix+fileName, &fetterDataList)
|
||||
for _, fetterData := range fetterDataList {
|
||||
// list -> map
|
||||
g.FetterDataMap[fetterData.FetterId] = fetterData
|
||||
fetterIdList := g.FetterDataAvatarIdMap[fetterData.AvatarId]
|
||||
if fetterIdList == nil {
|
||||
|
||||
42
gdconf/gacha_drop_group_data.go
Normal file
42
gdconf/gacha_drop_group_data.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package gdconf
|
||||
|
||||
import (
|
||||
"hk4e/pkg/logger"
|
||||
)
|
||||
|
||||
// 当初写卡池算法的时候临时建立的表 以后再做迁移吧
|
||||
|
||||
type GachaDrop struct {
|
||||
DropId int32 `csv:"DropId"`
|
||||
Weight int32 `csv:"Weight"`
|
||||
Result int32 `csv:"Result"`
|
||||
IsEnd bool `csv:"IsEnd"`
|
||||
}
|
||||
|
||||
type GachaDropGroupData struct {
|
||||
DropId int32
|
||||
WeightAll int32
|
||||
DropConfig []*GachaDrop
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadGachaDropGroupData() {
|
||||
g.GachaDropGroupDataMap = make(map[int32]*GachaDropGroupData)
|
||||
fileNameList := []string{"GachaDropAvatarUp.csv", "GachaDropWeaponUp.csv", "GachaDropNormal.csv"}
|
||||
for _, fileName := range fileNameList {
|
||||
gachaDropList := make([]*GachaDrop, 0)
|
||||
readExtCsv[GachaDrop](g.extPrefix+fileName, &gachaDropList)
|
||||
for _, gachaDrop := range gachaDropList {
|
||||
gachaDropGroupData, exist := g.GachaDropGroupDataMap[gachaDrop.DropId]
|
||||
if !exist {
|
||||
gachaDropGroupData = new(GachaDropGroupData)
|
||||
gachaDropGroupData.DropId = gachaDrop.DropId
|
||||
gachaDropGroupData.WeightAll = 0
|
||||
gachaDropGroupData.DropConfig = make([]*GachaDrop, 0)
|
||||
g.GachaDropGroupDataMap[gachaDrop.DropId] = gachaDropGroupData
|
||||
}
|
||||
gachaDropGroupData.WeightAll += gachaDrop.Weight
|
||||
gachaDropGroupData.DropConfig = append(gachaDropGroupData.DropConfig, gachaDrop)
|
||||
}
|
||||
}
|
||||
logger.Info("GachaDropGroupData count: %v", len(g.GachaDropGroupDataMap))
|
||||
}
|
||||
@@ -27,26 +27,24 @@ var CONF_RELOAD *GameDataConfig = nil
|
||||
|
||||
type GameDataConfig struct {
|
||||
// 配置表路径前缀
|
||||
tablePrefix string
|
||||
jsonPrefix string
|
||||
luaPrefix string
|
||||
extPrefix string
|
||||
txtPrefix string
|
||||
jsonPrefix string
|
||||
luaPrefix string
|
||||
extPrefix 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 // 场景标签
|
||||
SceneLuaConfigMap map[int32]*SceneLuaConfig // 场景LUA配置
|
||||
GroupMap map[int32]*Group // 场景LUA区块group索引
|
||||
LuaStateLruMap map[int32]*LuaStateLru // 场景LUA虚拟机LRU内存淘汰
|
||||
WorldAreaDataMap map[int32]*WorldAreaData // 世界区域
|
||||
TriggerDataMap map[int32]*TriggerData // 场景LUA触发器
|
||||
ScenePointMap map[int32]*ScenePoint // 场景传送点
|
||||
SceneTagDataMap map[int32]*SceneTagData // 场景标签
|
||||
GatherDataMap map[int32]*GatherData // 采集物
|
||||
GatherDataPointTypeMap map[int32]*GatherData // 采集物场景节点索引
|
||||
WorldAreaDataMap map[int32]*WorldAreaData // 世界区域
|
||||
AvatarDataMap map[int32]*AvatarData // 角色
|
||||
AvatarSkillDataMap map[int32]*AvatarSkillData // 角色技能
|
||||
AvatarSkillDepotDataMap map[int32]*AvatarSkillDepotData // 角色技能库
|
||||
FetterDataMap map[int32]*FetterData // 角色资料解锁
|
||||
FetterDataAvatarIdMap map[int32][]int32 // 角色资料解锁角色id索引
|
||||
ItemDataMap map[int32]*ItemData // 统一道具
|
||||
@@ -61,7 +59,12 @@ type GameDataConfig struct {
|
||||
ReliquaryMainDataMap map[int32]map[int32]*ReliquaryMainData // 圣遗物主属性
|
||||
ReliquaryAffixDataMap map[int32]map[int32]*ReliquaryAffixData // 圣遗物追加属性
|
||||
QuestDataMap map[int32]*QuestData // 任务
|
||||
TriggerDataMap map[int32]*TriggerData // 场景LUA触发器
|
||||
DropDataMap map[int32]*DropData // 掉落
|
||||
MonsterDropDataMap map[string]map[int32]*MonsterDropData // 怪物掉落
|
||||
ChestDropDataMap map[string]map[int32]*ChestDropData // 宝箱掉落
|
||||
GCGCharDataMap map[int32]*GCGCharData // 七圣召唤角色卡牌
|
||||
GCGSkillDataMap map[int32]*GCGSkillData // 七圣召唤卡牌技能
|
||||
GachaDropGroupDataMap map[int32]*GachaDropGroupData // 卡池掉落组 临时的
|
||||
}
|
||||
|
||||
func InitGameDataConfig() {
|
||||
@@ -95,13 +98,13 @@ func (g *GameDataConfig) loadAll() {
|
||||
panic(info)
|
||||
}
|
||||
|
||||
g.tablePrefix = pathPrefix + "/txt"
|
||||
dirInfo, err = os.Stat(g.tablePrefix)
|
||||
g.txtPrefix = pathPrefix + "/txt"
|
||||
dirInfo, err = os.Stat(g.txtPrefix)
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
info := fmt.Sprintf("open game data config txt dir error: %v", err)
|
||||
panic(info)
|
||||
}
|
||||
g.tablePrefix += "/"
|
||||
g.txtPrefix += "/"
|
||||
|
||||
g.jsonPrefix = pathPrefix + "/json"
|
||||
dirInfo, err = os.Stat(g.jsonPrefix)
|
||||
@@ -131,34 +134,35 @@ func (g *GameDataConfig) loadAll() {
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) load() {
|
||||
g.loadSceneData() // 场景
|
||||
g.loadSceneLuaConfig() // 场景LUA配置
|
||||
g.loadTriggerData() // 场景LUA触发器
|
||||
g.loadScenePoint() // 场景传送点
|
||||
g.loadSceneTagData() // 场景标签
|
||||
g.loadGatherData() // 采集物
|
||||
g.loadWorldAreaData() // 世界区域
|
||||
g.loadAvatarData() // 角色
|
||||
g.loadAvatarSkillData() // 角色技能
|
||||
g.loadAvatarSkillDepotData() // 角色技能库
|
||||
g.loadDropGroupData() // 掉落组 卡池 临时的
|
||||
g.loadGCGCharData() // 角色卡牌
|
||||
g.loadGCGSkillData() // 卡牌技能
|
||||
g.loadSceneData() // 场景
|
||||
g.loadScenePoint() // 场景传送点
|
||||
g.loadSceneTagData() // 场景地图图标
|
||||
if config.GetConfig().Hk4e.LoadSceneLuaConfig {
|
||||
g.loadSceneLuaConfig() // 场景LUA配置
|
||||
}
|
||||
g.loadWorldAreaData() // 世界区域
|
||||
g.loadGatherData() // 采集物
|
||||
g.loadFetterData() // 角色资料解锁
|
||||
g.loadItemData() // 统一道具
|
||||
g.loadAvatarLevelData() // 角色等级
|
||||
g.loadAvatarPromoteData() // 角色突破
|
||||
g.loadPlayerLevelData() // 玩家等级
|
||||
g.loadWeaponLevelData() // 武器等级
|
||||
g.loadWeaponPromoteData() // 武器突破
|
||||
g.loadRewardData() // 奖励
|
||||
g.loadAvatarCostumeData() // 角色时装
|
||||
g.loadAvatarFlycloakData() // 角色风之翼
|
||||
g.loadReliquaryMainData() // 圣遗物主属性
|
||||
g.loadReliquaryAffixData() // 圣遗物追加属性
|
||||
g.loadQuestData() // 任务
|
||||
g.loadTriggerData() // 场景LUA触发器
|
||||
g.loadFetterData() // 角色资料解锁
|
||||
g.loadItemData() // 统一道具
|
||||
g.loadAvatarLevelData() // 角色等级
|
||||
g.loadAvatarPromoteData() // 角色突破
|
||||
g.loadPlayerLevelData() // 玩家等级
|
||||
g.loadWeaponLevelData() // 武器等级
|
||||
g.loadWeaponPromoteData() // 武器突破
|
||||
g.loadRewardData() // 奖励
|
||||
g.loadAvatarCostumeData() // 角色时装
|
||||
g.loadAvatarFlycloakData() // 角色风之翼
|
||||
g.loadReliquaryMainData() // 圣遗物主属性
|
||||
g.loadReliquaryAffixData() // 圣遗物追加属性
|
||||
g.loadQuestData() // 任务
|
||||
g.loadDropData() // 掉落
|
||||
g.loadMonsterDropData() // 怪物掉落
|
||||
g.loadChestDropData() // 宝箱掉落
|
||||
g.loadGCGCharData() // 七圣召唤角色卡牌
|
||||
g.loadGCGSkillData() // 七圣召唤卡牌技能
|
||||
g.loadGachaDropGroupData() // 卡池掉落组 临时的
|
||||
}
|
||||
|
||||
// CSV相关
|
||||
@@ -191,6 +195,22 @@ func (a *IntArray) UnmarshalCSV(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type FloatArray []float32
|
||||
|
||||
func (a *FloatArray) UnmarshalCSV(data []byte) error {
|
||||
str := string(data)
|
||||
str = strings.ReplaceAll(str, " ", "")
|
||||
floatStrList := splitStringArray(str)
|
||||
for _, floatStr := range floatStrList {
|
||||
v, err := strconv.ParseFloat(floatStr, 32)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*a = append(*a, float32(v))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readExtCsv[T any](tablePath string, table *[]*T) {
|
||||
fileData, err := os.ReadFile(tablePath)
|
||||
if err != nil {
|
||||
@@ -260,6 +280,9 @@ func initLuaState(luaState *lua.LState) {
|
||||
luaState.SetField(eventType, "EVENT_NONE", lua.LNumber(constant.LUA_EVENT_NONE))
|
||||
luaState.SetField(eventType, "EVENT_ENTER_REGION", lua.LNumber(constant.LUA_EVENT_ENTER_REGION))
|
||||
luaState.SetField(eventType, "EVENT_LEAVE_REGION", lua.LNumber(constant.LUA_EVENT_LEAVE_REGION))
|
||||
luaState.SetField(eventType, "EVENT_ANY_MONSTER_DIE", lua.LNumber(constant.LUA_EVENT_ANY_MONSTER_DIE))
|
||||
luaState.SetField(eventType, "EVENT_ANY_MONSTER_LIVE", lua.LNumber(constant.LUA_EVENT_ANY_MONSTER_LIVE))
|
||||
luaState.SetField(eventType, "EVENT_QUEST_START", lua.LNumber(constant.LUA_EVENT_QUEST_START))
|
||||
|
||||
entityType := luaState.NewTable()
|
||||
luaState.SetGlobal("EntityType", entityType)
|
||||
@@ -287,11 +310,17 @@ func initLuaState(luaState *lua.LState) {
|
||||
|
||||
gadgetState := luaState.NewTable()
|
||||
luaState.SetGlobal("GadgetState", gadgetState)
|
||||
luaState.SetField(gadgetState, "NONE", lua.LNumber(0))
|
||||
luaState.SetField(gadgetState, "Default", lua.LNumber(constant.GADGET_STATE_DEFAULT))
|
||||
luaState.SetField(gadgetState, "ChestLocked", lua.LNumber(constant.GADGET_STATE_CHEST_LOCKED))
|
||||
luaState.SetField(gadgetState, "GearStart", lua.LNumber(constant.GADGET_STATE_GEAR_START))
|
||||
luaState.SetField(gadgetState, "GearStop", lua.LNumber(constant.GADGET_STATE_GEAR_STOP))
|
||||
|
||||
visionLevelType := luaState.NewTable()
|
||||
luaState.SetGlobal("VisionLevelType", visionLevelType)
|
||||
luaState.SetField(visionLevelType, "NONE", lua.LNumber(0))
|
||||
luaState.SetField(visionLevelType, "VISION_LEVEL_NEARBY", lua.LNumber(1))
|
||||
luaState.SetField(visionLevelType, "VISION_LEVEL_NORMAL", lua.LNumber(2))
|
||||
luaState.SetField(visionLevelType, "VISION_LEVEL_REMOTE", lua.LNumber(3))
|
||||
luaState.SetField(visionLevelType, "VISION_LEVEL_LITTLE_REMOTE", lua.LNumber(4))
|
||||
}
|
||||
|
||||
func newLuaState(luaStr string) *lua.LState {
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
AvatarId,GachaItemId,Name
|
||||
int32,int32,string
|
||||
角色id,卡池道具id,角色名称
|
||||
10000002,1002,神里绫华
|
||||
10000003,1003,琴
|
||||
10000006,1006,丽莎
|
||||
10000014,1014,芭芭拉
|
||||
10000015,1015,凯亚
|
||||
10000016,1016,迪卢克
|
||||
10000020,1020,雷泽
|
||||
10000021,1021,安柏
|
||||
10000022,1022,温迪
|
||||
10000023,1023,香菱
|
||||
10000024,1024,北斗
|
||||
10000025,1025,行秋
|
||||
10000026,1026,魈
|
||||
10000027,1027,凝光
|
||||
10000029,1029,可莉
|
||||
10000030,1030,钟离
|
||||
10000031,1031,菲谢尔
|
||||
10000032,1032,班尼特
|
||||
10000033,1033,达达利亚
|
||||
10000034,1034,诺艾尔
|
||||
10000035,1035,七七
|
||||
10000036,1036,重云
|
||||
10000037,1037,甘雨
|
||||
10000038,1038,阿贝多
|
||||
10000039,1039,迪奥娜
|
||||
10000041,1041,莫娜
|
||||
10000042,1042,刻晴
|
||||
10000043,1043,砂糖
|
||||
10000044,1044,辛焱
|
||||
10000045,1045,罗莎莉亚
|
||||
10000046,1046,胡桃
|
||||
10000047,1047,枫原万叶
|
||||
10000048,1048,烟绯
|
||||
10000049,1049,宵宫
|
||||
10000050,1050,托马
|
||||
10000051,1051,优菈
|
||||
10000052,1052,雷电将军
|
||||
10000053,1053,早柚
|
||||
10000054,1054,珊瑚宫心海
|
||||
10000055,1055,五郎
|
||||
10000056,1056,九条裟罗
|
||||
10000057,1057,荒泷一斗
|
||||
10000058,1058,八重神子
|
||||
10000062,1062,埃洛伊
|
||||
10000063,1063,申鹤
|
||||
10000064,1064,云堇
|
||||
10000065,1065,久歧忍
|
||||
10000066,1066,神里绫人
|
||||
10000067,1067,柯莱
|
||||
10000068,1068,多莉
|
||||
10000069,1069,提纳里
|
||||
|
@@ -25,7 +25,7 @@ func TestInitGameDataConfig(t *testing.T) {
|
||||
logger.Info("start load conf")
|
||||
InitGameDataConfig()
|
||||
logger.Info("load conf finish")
|
||||
time.Sleep(time.Second)
|
||||
time.Sleep(time.Minute)
|
||||
}
|
||||
|
||||
func CheckJsonLoop(path string, errorJsonFileList *[]string, totalJsonFileCount *int) {
|
||||
|
||||
@@ -8,17 +8,16 @@ import (
|
||||
type GatherData struct {
|
||||
PointType int32 `csv:"挂节点类型"`
|
||||
GatherId int32 `csv:"ID"`
|
||||
GadgetId int32 `csv:"采集物ID"`
|
||||
ItemId int32 `csv:"获得物品ID"`
|
||||
GadgetId int32 `csv:"采集物ID,omitempty"`
|
||||
ItemId int32 `csv:"获得物品ID,omitempty"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadGatherData() {
|
||||
g.GatherDataMap = make(map[int32]*GatherData)
|
||||
gatherDataList := make([]*GatherData, 0)
|
||||
readTable[GatherData](g.tablePrefix+"GatherData.txt", &gatherDataList)
|
||||
readTable[GatherData](g.txtPrefix+"GatherData.txt", &gatherDataList)
|
||||
g.GatherDataPointTypeMap = make(map[int32]*GatherData)
|
||||
for _, gatherData := range gatherDataList {
|
||||
// list -> map
|
||||
g.GatherDataMap[gatherData.GatherId] = gatherData
|
||||
g.GatherDataPointTypeMap[gatherData.PointType] = gatherData
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ type GCGCharData struct {
|
||||
func (g *GameDataConfig) loadGCGCharData() {
|
||||
g.GCGCharDataMap = make(map[int32]*GCGCharData)
|
||||
gcgCharDataList := make([]*GCGCharData, 0)
|
||||
readTable[GCGCharData](g.tablePrefix+"GCGCharData.txt", &gcgCharDataList)
|
||||
readTable[GCGCharData](g.txtPrefix+"GCGCharData.txt", &gcgCharDataList)
|
||||
for _, gcgCharData := range gcgCharDataList {
|
||||
// 将TagId整合进TagList
|
||||
gcgCharData.TagList = make([]uint32, 0, 5)
|
||||
@@ -35,7 +35,6 @@ func (g *GameDataConfig) loadGCGCharData() {
|
||||
}
|
||||
gcgCharData.TagList = append(gcgCharData.TagList, uint32(tagId))
|
||||
}
|
||||
// list -> map
|
||||
g.GCGCharDataMap[gcgCharData.CharId] = gcgCharData
|
||||
}
|
||||
logger.Info("GCGCharData count: %v", len(g.GCGCharDataMap))
|
||||
|
||||
@@ -35,7 +35,7 @@ type ConfigSkillEffectValue struct {
|
||||
func (g *GameDataConfig) loadGCGSkillData() {
|
||||
g.GCGSkillDataMap = make(map[int32]*GCGSkillData)
|
||||
gcgSkillDataList := make([]*GCGSkillData, 0)
|
||||
readTable[GCGSkillData](g.tablePrefix+"GCGSkillData.txt", &gcgSkillDataList)
|
||||
readTable[GCGSkillData](g.txtPrefix+"GCGSkillData.txt", &gcgSkillDataList)
|
||||
for _, gcgSkillData := range gcgSkillDataList {
|
||||
// 技能消耗整合进CostMap
|
||||
gcgSkillData.CostMap = map[uint32]uint32{
|
||||
@@ -97,7 +97,6 @@ func (g *GameDataConfig) loadGCGSkillData() {
|
||||
}
|
||||
}
|
||||
}
|
||||
// list -> map
|
||||
g.GCGSkillDataMap[gcgSkillData.SkillId] = gcgSkillData
|
||||
}
|
||||
logger.Info("GCGSkillData count: %v", len(g.GCGSkillDataMap))
|
||||
|
||||
@@ -38,9 +38,8 @@ func (g *GameDataConfig) loadItemData() {
|
||||
fileNameList := []string{"MaterialData.txt", "WeaponData.txt", "ReliquaryData.txt", "FurnitureExcelData.txt"}
|
||||
for _, fileName := range fileNameList {
|
||||
itemDataList := make([]*ItemData, 0)
|
||||
readTable[ItemData](g.tablePrefix+fileName, &itemDataList)
|
||||
readTable[ItemData](g.txtPrefix+fileName, &itemDataList)
|
||||
for _, itemData := range itemDataList {
|
||||
// list -> map
|
||||
itemData.SkillAffix = make([]int32, 0)
|
||||
if itemData.SkillAffix1 != 0 {
|
||||
itemData.SkillAffix = append(itemData.SkillAffix, itemData.SkillAffix1)
|
||||
|
||||
39
gdconf/monster_drop_data.go
Normal file
39
gdconf/monster_drop_data.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package gdconf
|
||||
|
||||
import (
|
||||
"hk4e/pkg/logger"
|
||||
)
|
||||
|
||||
// MonsterDropData 怪物掉落配置表
|
||||
type MonsterDropData struct {
|
||||
Level int32 `csv:"最小等级"`
|
||||
DropTag string `csv:"总索引"`
|
||||
DropId int32 `csv:"掉落ID,omitempty"`
|
||||
DropCount int32 `csv:"掉落次数,omitempty"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadMonsterDropData() {
|
||||
g.MonsterDropDataMap = make(map[string]map[int32]*MonsterDropData)
|
||||
monsterDropDataList := make([]*MonsterDropData, 0)
|
||||
readTable[MonsterDropData](g.txtPrefix+"MonsterDropData.txt", &monsterDropDataList)
|
||||
for _, monsterDropData := range monsterDropDataList {
|
||||
_, exist := g.MonsterDropDataMap[monsterDropData.DropTag]
|
||||
if !exist {
|
||||
g.MonsterDropDataMap[monsterDropData.DropTag] = make(map[int32]*MonsterDropData)
|
||||
}
|
||||
g.MonsterDropDataMap[monsterDropData.DropTag][monsterDropData.Level] = monsterDropData
|
||||
}
|
||||
logger.Info("MonsterDropData count: %v", len(g.MonsterDropDataMap))
|
||||
}
|
||||
|
||||
func GetMonsterDropDataByDropTagAndLevel(dropTag string, level int32) *MonsterDropData {
|
||||
value, exist := CONF.MonsterDropDataMap[dropTag]
|
||||
if !exist {
|
||||
return nil
|
||||
}
|
||||
return value[level]
|
||||
}
|
||||
|
||||
func GetMonsterDropDataMap() map[string]map[int32]*MonsterDropData {
|
||||
return CONF.MonsterDropDataMap
|
||||
}
|
||||
@@ -13,9 +13,8 @@ type PlayerLevelData struct {
|
||||
func (g *GameDataConfig) loadPlayerLevelData() {
|
||||
g.PlayerLevelDataMap = make(map[int32]*PlayerLevelData)
|
||||
playerLevelDataList := make([]*PlayerLevelData, 0)
|
||||
readTable[PlayerLevelData](g.tablePrefix+"PlayerLevelData.txt", &playerLevelDataList)
|
||||
readTable[PlayerLevelData](g.txtPrefix+"PlayerLevelData.txt", &playerLevelDataList)
|
||||
for _, playerLevelData := range playerLevelDataList {
|
||||
// list -> map
|
||||
g.PlayerLevelDataMap[playerLevelData.Level] = playerLevelData
|
||||
}
|
||||
logger.Info("PlayerLevelData count: %v", len(g.PlayerLevelDataMap))
|
||||
|
||||
@@ -75,9 +75,8 @@ func (g *GameDataConfig) loadQuestData() {
|
||||
fileNameList := []string{"QuestData.txt", "QuestData_Exported.txt"}
|
||||
for _, fileName := range fileNameList {
|
||||
questDataList := make([]*QuestData, 0)
|
||||
readTable[QuestData](g.tablePrefix+fileName, &questDataList)
|
||||
readTable[QuestData](g.txtPrefix+fileName, &questDataList)
|
||||
for _, questData := range questDataList {
|
||||
// list -> map
|
||||
// 领取条件
|
||||
questData.AcceptCondList = make([]*QuestCond, 0)
|
||||
if questData.AcceptCondType1 != 0 {
|
||||
|
||||
@@ -15,14 +15,13 @@ type ReliquaryAffixData struct {
|
||||
func (g *GameDataConfig) loadReliquaryAffixData() {
|
||||
g.ReliquaryAffixDataMap = make(map[int32]map[int32]*ReliquaryAffixData)
|
||||
reliquaryAffixDataList := make([]*ReliquaryAffixData, 0)
|
||||
readTable[ReliquaryAffixData](g.tablePrefix+"ReliquaryAffixData.txt", &reliquaryAffixDataList)
|
||||
readTable[ReliquaryAffixData](g.txtPrefix+"ReliquaryAffixData.txt", &reliquaryAffixDataList)
|
||||
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))
|
||||
|
||||
@@ -15,14 +15,13 @@ type ReliquaryMainData struct {
|
||||
func (g *GameDataConfig) loadReliquaryMainData() {
|
||||
g.ReliquaryMainDataMap = make(map[int32]map[int32]*ReliquaryMainData)
|
||||
reliquaryMainDataList := make([]*ReliquaryMainData, 0)
|
||||
readTable[ReliquaryMainData](g.tablePrefix+"ReliquaryMainData.txt", &reliquaryMainDataList)
|
||||
readTable[ReliquaryMainData](g.txtPrefix+"ReliquaryMainData.txt", &reliquaryMainDataList)
|
||||
for _, reliquaryMainData := range reliquaryMainDataList {
|
||||
// 通过主属性库ID找到
|
||||
_, ok := g.ReliquaryMainDataMap[reliquaryMainData.MainPropDepotId]
|
||||
if !ok {
|
||||
g.ReliquaryMainDataMap[reliquaryMainData.MainPropDepotId] = make(map[int32]*ReliquaryMainData)
|
||||
}
|
||||
// list -> map
|
||||
g.ReliquaryMainDataMap[reliquaryMainData.MainPropDepotId][reliquaryMainData.MainPropId] = reliquaryMainData
|
||||
}
|
||||
logger.Info("ReliquaryMainData count: %v", len(g.ReliquaryMainDataMap))
|
||||
|
||||
@@ -32,9 +32,8 @@ type RewardData struct {
|
||||
func (g *GameDataConfig) loadRewardData() {
|
||||
g.RewardDataMap = make(map[int32]*RewardData)
|
||||
rewardDataList := make([]*RewardData, 0)
|
||||
readTable[RewardData](g.tablePrefix+"RewardData.txt", &rewardDataList)
|
||||
readTable[RewardData](g.txtPrefix+"RewardData.txt", &rewardDataList)
|
||||
for _, rewardData := range rewardDataList {
|
||||
// list -> map
|
||||
// 奖励物品整合
|
||||
rewardData.RewardItemMap = map[uint32]uint32{
|
||||
uint32(rewardData.RewardItem1ID): uint32(rewardData.RewardItem1Count),
|
||||
|
||||
@@ -13,9 +13,8 @@ type SceneData struct {
|
||||
func (g *GameDataConfig) loadSceneData() {
|
||||
g.SceneDataMap = make(map[int32]*SceneData)
|
||||
sceneDataList := make([]*SceneData, 0)
|
||||
readTable[SceneData](g.tablePrefix+"SceneData.txt", &sceneDataList)
|
||||
readTable[SceneData](g.txtPrefix+"SceneData.txt", &sceneDataList)
|
||||
for _, sceneData := range sceneDataList {
|
||||
// list -> map
|
||||
g.SceneDataMap[sceneData.SceneId] = sceneData
|
||||
}
|
||||
logger.Info("SceneData count: %v", len(g.SceneDataMap))
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"hk4e/common/config"
|
||||
"hk4e/pkg/logger"
|
||||
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
@@ -19,8 +19,6 @@ const (
|
||||
SceneGroupLoaderLimit = 4 // 加载文件的并发数 此操作很耗内存 调大之前请确保你的机器内存足够
|
||||
)
|
||||
|
||||
var OBJECT_ID_COUNTER uint64
|
||||
|
||||
type SceneLuaConfig struct {
|
||||
Id int32
|
||||
SceneConfig *SceneConfig // 地图配置
|
||||
@@ -55,77 +53,27 @@ type BlockRange struct {
|
||||
}
|
||||
|
||||
type Group struct {
|
||||
Id int32 `json:"id"`
|
||||
RefreshId int32 `json:"refresh_id"`
|
||||
Area int32 `json:"area"`
|
||||
Pos *Vector `json:"pos"`
|
||||
DynamicLoad bool `json:"dynamic_load"`
|
||||
IsReplaceable *Replaceable `json:"is_replaceable"`
|
||||
MonsterList []*Monster `json:"monsters"` // 怪物
|
||||
NpcList []*Npc `json:"npcs"` // NPC
|
||||
GadgetList []*Gadget `json:"gadgets"` // 物件
|
||||
RegionList []*Region `json:"regions"`
|
||||
TriggerList []*Trigger `json:"triggers"`
|
||||
LuaStr string `json:"-"`
|
||||
LuaState *lua.LState `json:"-"`
|
||||
Id int32 `json:"id"`
|
||||
RefreshId int32 `json:"refresh_id"`
|
||||
Area int32 `json:"area"`
|
||||
Pos *Vector `json:"pos"`
|
||||
DynamicLoad bool `json:"dynamic_load"`
|
||||
IsReplaceable *Replaceable `json:"is_replaceable"`
|
||||
MonsterMap map[int32]*Monster `json:"-"` // 怪物
|
||||
NpcMap map[int32]*Npc `json:"-"` // NPC
|
||||
GadgetMap map[int32]*Gadget `json:"-"` // 物件
|
||||
RegionMap map[int32]*Region `json:"-"` // 区域
|
||||
TriggerMap map[string]*Trigger `json:"-"` // 触发器
|
||||
GroupInitConfig *GroupInitConfig `json:"-"` // 初始化配置
|
||||
SuiteList []*Suite `json:"-"` // 小组配置
|
||||
LuaStr string `json:"-"` // LUA原始字符串缓存
|
||||
LuaState *lua.LState `json:"-"` // LUA虚拟机实例
|
||||
}
|
||||
|
||||
const (
|
||||
LuaStateLruKeepNum = 1000
|
||||
)
|
||||
|
||||
type LuaStateLru struct {
|
||||
GroupId int32
|
||||
AccessTime int64
|
||||
}
|
||||
|
||||
type LuaStateLruList []*LuaStateLru
|
||||
|
||||
func (l LuaStateLruList) Len() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
func (l LuaStateLruList) Less(i, j int) bool {
|
||||
return l[i].AccessTime < l[j].AccessTime
|
||||
}
|
||||
|
||||
func (l LuaStateLruList) Swap(i, j int) {
|
||||
l[i], l[j] = l[j], l[i]
|
||||
}
|
||||
|
||||
func LuaStateLruRemove() {
|
||||
removeNum := len(CONF.LuaStateLruMap) - LuaStateLruKeepNum
|
||||
if removeNum <= 0 {
|
||||
return
|
||||
}
|
||||
luaStateLruList := make(LuaStateLruList, 0)
|
||||
for _, luaStateLru := range CONF.LuaStateLruMap {
|
||||
luaStateLruList = append(luaStateLruList, luaStateLru)
|
||||
}
|
||||
sort.Stable(luaStateLruList)
|
||||
for i := 0; i < removeNum; i++ {
|
||||
luaStateLru := luaStateLruList[i]
|
||||
group := GetSceneGroup(luaStateLru.GroupId)
|
||||
group.LuaState = nil
|
||||
delete(CONF.LuaStateLruMap, luaStateLru.GroupId)
|
||||
}
|
||||
logger.Info("lua state lru remove finish, remove num: %v", removeNum)
|
||||
}
|
||||
|
||||
func (g *Group) GetLuaState() *lua.LState {
|
||||
CONF.LuaStateLruMap[g.Id] = &LuaStateLru{
|
||||
GroupId: g.Id,
|
||||
AccessTime: time.Now().UnixMilli(),
|
||||
}
|
||||
if g.LuaState == nil {
|
||||
g.LuaState = newLuaState(g.LuaStr)
|
||||
scriptLib := g.LuaState.NewTable()
|
||||
g.LuaState.SetGlobal("ScriptLib", scriptLib)
|
||||
for _, scriptLibFunc := range SCRIPT_LIB_FUNC_LIST {
|
||||
g.LuaState.SetField(scriptLib, scriptLibFunc.fnName, g.LuaState.NewFunction(scriptLibFunc.fn))
|
||||
}
|
||||
}
|
||||
return g.LuaState
|
||||
type GroupInitConfig struct {
|
||||
Suite int32 `json:"suite"`
|
||||
EndSuite int32 `json:"end_suite"`
|
||||
RandSuite bool `json:"rand_suite"`
|
||||
}
|
||||
|
||||
type Replaceable struct {
|
||||
@@ -141,7 +89,7 @@ type Monster struct {
|
||||
Rot *Vector `json:"rot"`
|
||||
Level int32 `json:"level"`
|
||||
AreaId int32 `json:"area_id"`
|
||||
ObjectId uint64 `json:"-"`
|
||||
DropTag string `json:"drop_tag"` // 关联MonsterDropData表
|
||||
}
|
||||
|
||||
type Npc struct {
|
||||
@@ -150,18 +98,19 @@ type Npc struct {
|
||||
Pos *Vector `json:"pos"`
|
||||
Rot *Vector `json:"rot"`
|
||||
AreaId int32 `json:"area_id"`
|
||||
ObjectId uint64 `json:"-"`
|
||||
}
|
||||
|
||||
type Gadget struct {
|
||||
ConfigId int32 `json:"config_id"`
|
||||
GadgetId int32 `json:"gadget_id"`
|
||||
Pos *Vector `json:"pos"`
|
||||
Rot *Vector `json:"rot"`
|
||||
Level int32 `json:"level"`
|
||||
AreaId int32 `json:"area_id"`
|
||||
PointType int32 `json:"point_type"` // 关联GatherData表
|
||||
ObjectId uint64 `json:"-"`
|
||||
ConfigId int32 `json:"config_id"`
|
||||
GadgetId int32 `json:"gadget_id"`
|
||||
Pos *Vector `json:"pos"`
|
||||
Rot *Vector `json:"rot"`
|
||||
Level int32 `json:"level"`
|
||||
AreaId int32 `json:"area_id"`
|
||||
PointType int32 `json:"point_type"` // 关联GatherData表
|
||||
State int32 `json:"state"`
|
||||
VisionLevel int32 `json:"vision_level"`
|
||||
DropTag string `json:"drop_tag"`
|
||||
}
|
||||
|
||||
type Region struct {
|
||||
@@ -185,6 +134,22 @@ type Trigger struct {
|
||||
TriggerCount int32 `json:"trigger_count"`
|
||||
}
|
||||
|
||||
type SuiteLuaTable struct {
|
||||
MonsterConfigIdList any `json:"monsters"` // 怪物
|
||||
GadgetConfigIdList any `json:"gadgets"` // 物件
|
||||
RegionConfigIdList any `json:"regions"` // 区域
|
||||
TriggerNameList any `json:"triggers"` // 触发器
|
||||
RandWeight int32 `json:"rand_weight"`
|
||||
}
|
||||
|
||||
type Suite struct {
|
||||
MonsterConfigIdList []int32
|
||||
GadgetConfigIdList []int32
|
||||
RegionConfigIdList []int32
|
||||
TriggerNameList []string
|
||||
RandWeight int32
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, blockId int32) {
|
||||
sceneLuaPrefix := g.luaPrefix + "scene/"
|
||||
sceneIdStr := strconv.Itoa(int(sceneId))
|
||||
@@ -197,55 +162,120 @@ func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, bl
|
||||
}
|
||||
group.LuaStr = string(groupLuaData)
|
||||
luaState := newLuaState(group.LuaStr)
|
||||
// init_config
|
||||
group.GroupInitConfig = new(GroupInitConfig)
|
||||
ok := getSceneLuaConfigTable[*GroupInitConfig](luaState, "init_config", group.GroupInitConfig)
|
||||
if !ok {
|
||||
logger.Error("get init_config object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
|
||||
luaState.Close()
|
||||
return
|
||||
}
|
||||
// monsters
|
||||
group.MonsterList = make([]*Monster, 0)
|
||||
ok := getSceneLuaConfigTable[*[]*Monster](luaState, "monsters", &group.MonsterList)
|
||||
monsterList := make([]*Monster, 0)
|
||||
ok = getSceneLuaConfigTable[*[]*Monster](luaState, "monsters", &monsterList)
|
||||
if !ok {
|
||||
logger.Error("get monsters object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
|
||||
luaState.Close()
|
||||
return
|
||||
}
|
||||
for _, monster := range group.MonsterList {
|
||||
monster.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1)
|
||||
group.MonsterMap = make(map[int32]*Monster)
|
||||
for _, monster := range monsterList {
|
||||
group.MonsterMap[monster.ConfigId] = monster
|
||||
}
|
||||
// npcs
|
||||
group.NpcList = make([]*Npc, 0)
|
||||
ok = getSceneLuaConfigTable[*[]*Npc](luaState, "npcs", &group.NpcList)
|
||||
npcList := make([]*Npc, 0)
|
||||
ok = getSceneLuaConfigTable[*[]*Npc](luaState, "npcs", &npcList)
|
||||
if !ok {
|
||||
logger.Error("get npcs object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
|
||||
luaState.Close()
|
||||
return
|
||||
}
|
||||
for _, npc := range group.NpcList {
|
||||
npc.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1)
|
||||
group.NpcMap = make(map[int32]*Npc)
|
||||
for _, npc := range npcList {
|
||||
group.NpcMap[npc.ConfigId] = npc
|
||||
}
|
||||
// gadgets
|
||||
group.GadgetList = make([]*Gadget, 0)
|
||||
ok = getSceneLuaConfigTable[*[]*Gadget](luaState, "gadgets", &group.GadgetList)
|
||||
gadgetList := make([]*Gadget, 0)
|
||||
ok = getSceneLuaConfigTable[*[]*Gadget](luaState, "gadgets", &gadgetList)
|
||||
if !ok {
|
||||
logger.Error("get gadgets object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
|
||||
luaState.Close()
|
||||
return
|
||||
}
|
||||
for _, gadget := range group.GadgetList {
|
||||
gadget.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1)
|
||||
group.GadgetMap = make(map[int32]*Gadget)
|
||||
for _, gadget := range gadgetList {
|
||||
group.GadgetMap[gadget.ConfigId] = gadget
|
||||
}
|
||||
// regions
|
||||
group.RegionList = make([]*Region, 0)
|
||||
ok = getSceneLuaConfigTable[*[]*Region](luaState, "regions", &group.RegionList)
|
||||
regionList := make([]*Region, 0)
|
||||
ok = getSceneLuaConfigTable[*[]*Region](luaState, "regions", ®ionList)
|
||||
if !ok {
|
||||
logger.Error("get regions object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
|
||||
luaState.Close()
|
||||
return
|
||||
}
|
||||
group.RegionMap = make(map[int32]*Region)
|
||||
for _, region := range regionList {
|
||||
group.RegionMap[region.ConfigId] = region
|
||||
}
|
||||
// triggers
|
||||
group.TriggerList = make([]*Trigger, 0)
|
||||
ok = getSceneLuaConfigTable[*[]*Trigger](luaState, "triggers", &group.TriggerList)
|
||||
triggerList := make([]*Trigger, 0)
|
||||
ok = getSceneLuaConfigTable[*[]*Trigger](luaState, "triggers", &triggerList)
|
||||
if !ok {
|
||||
logger.Error("get triggers object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
|
||||
luaState.Close()
|
||||
return
|
||||
}
|
||||
group.TriggerMap = make(map[string]*Trigger)
|
||||
for _, trigger := range triggerList {
|
||||
group.TriggerMap[trigger.Name] = trigger
|
||||
}
|
||||
// suites
|
||||
suiteLuaTableList := make([]*SuiteLuaTable, 0)
|
||||
ok = getSceneLuaConfigTable[*[]*SuiteLuaTable](luaState, "suites", &suiteLuaTableList)
|
||||
if !ok {
|
||||
logger.Error("get suites object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
|
||||
luaState.Close()
|
||||
return
|
||||
}
|
||||
if len(suiteLuaTableList) == 0 {
|
||||
logger.Info("get suites object is nil, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
|
||||
}
|
||||
group.SuiteList = make([]*Suite, 0)
|
||||
for _, suiteLuaTable := range suiteLuaTableList {
|
||||
suite := &Suite{
|
||||
MonsterConfigIdList: make([]int32, 0),
|
||||
GadgetConfigIdList: make([]int32, 0),
|
||||
RegionConfigIdList: make([]int32, 0),
|
||||
TriggerNameList: make([]string, 0),
|
||||
RandWeight: suiteLuaTable.RandWeight,
|
||||
}
|
||||
idAnyList, ok := suiteLuaTable.MonsterConfigIdList.([]any)
|
||||
if ok {
|
||||
for _, idAny := range idAnyList {
|
||||
suite.MonsterConfigIdList = append(suite.MonsterConfigIdList, int32(idAny.(float64)))
|
||||
}
|
||||
}
|
||||
idAnyList, ok = suiteLuaTable.GadgetConfigIdList.([]any)
|
||||
if ok {
|
||||
for _, idAny := range idAnyList {
|
||||
suite.GadgetConfigIdList = append(suite.GadgetConfigIdList, int32(idAny.(float64)))
|
||||
}
|
||||
}
|
||||
idAnyList, ok = suiteLuaTable.RegionConfigIdList.([]any)
|
||||
if ok {
|
||||
for _, idAny := range idAnyList {
|
||||
suite.RegionConfigIdList = append(suite.RegionConfigIdList, int32(idAny.(float64)))
|
||||
}
|
||||
}
|
||||
nameAnyList, ok := suiteLuaTable.TriggerNameList.([]any)
|
||||
if ok {
|
||||
for _, nameAny := range nameAnyList {
|
||||
suite.TriggerNameList = append(suite.TriggerNameList, nameAny.(string))
|
||||
}
|
||||
}
|
||||
group.SuiteList = append(group.SuiteList, suite)
|
||||
}
|
||||
luaState.Close()
|
||||
block.groupMapLoadLock.Lock()
|
||||
block.GroupMap[group.Id] = group
|
||||
@@ -253,10 +283,12 @@ func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, bl
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadSceneLuaConfig() {
|
||||
OBJECT_ID_COUNTER = 0
|
||||
g.SceneLuaConfigMap = make(map[int32]*SceneLuaConfig)
|
||||
g.GroupMap = make(map[int32]*Group)
|
||||
g.LuaStateLruMap = make(map[int32]*LuaStateLru)
|
||||
if !config.GetConfig().Hk4e.LoadSceneLuaConfig {
|
||||
return
|
||||
}
|
||||
sceneLuaPrefix := g.luaPrefix + "scene/"
|
||||
for _, sceneData := range g.SceneDataMap {
|
||||
sceneId := sceneData.SceneId
|
||||
@@ -345,9 +377,9 @@ func (g *GameDataConfig) loadSceneLuaConfig() {
|
||||
for _, scene := range g.SceneLuaConfigMap {
|
||||
for _, block := range scene.BlockMap {
|
||||
for _, group := range block.GroupMap {
|
||||
monsterCount += len(group.MonsterList)
|
||||
npcCount += len(group.NpcList)
|
||||
gadgetCount += len(group.GadgetList)
|
||||
monsterCount += len(group.MonsterMap)
|
||||
npcCount += len(group.NpcMap)
|
||||
gadgetCount += len(group.GadgetMap)
|
||||
groupCount++
|
||||
}
|
||||
blockCount++
|
||||
@@ -373,3 +405,61 @@ func GetSceneGroup(groupId int32) *Group {
|
||||
}
|
||||
return groupConfig
|
||||
}
|
||||
|
||||
const (
|
||||
LuaStateLruKeepNum = 10
|
||||
)
|
||||
|
||||
type LuaStateLru struct {
|
||||
GroupId int32
|
||||
AccessTime int64
|
||||
}
|
||||
|
||||
type LuaStateLruList []*LuaStateLru
|
||||
|
||||
func (l LuaStateLruList) Len() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
func (l LuaStateLruList) Less(i, j int) bool {
|
||||
return l[i].AccessTime < l[j].AccessTime
|
||||
}
|
||||
|
||||
func (l LuaStateLruList) Swap(i, j int) {
|
||||
l[i], l[j] = l[j], l[i]
|
||||
}
|
||||
|
||||
func LuaStateLruRemove() {
|
||||
removeNum := len(CONF.LuaStateLruMap) - LuaStateLruKeepNum
|
||||
if removeNum <= 0 {
|
||||
return
|
||||
}
|
||||
luaStateLruList := make(LuaStateLruList, 0)
|
||||
for _, luaStateLru := range CONF.LuaStateLruMap {
|
||||
luaStateLruList = append(luaStateLruList, luaStateLru)
|
||||
}
|
||||
sort.Stable(luaStateLruList)
|
||||
for i := 0; i < removeNum; i++ {
|
||||
luaStateLru := luaStateLruList[i]
|
||||
group := GetSceneGroup(luaStateLru.GroupId)
|
||||
group.LuaState = nil
|
||||
delete(CONF.LuaStateLruMap, luaStateLru.GroupId)
|
||||
}
|
||||
logger.Info("lua state lru remove finish, remove num: %v", removeNum)
|
||||
}
|
||||
|
||||
func (g *Group) GetLuaState() *lua.LState {
|
||||
CONF.LuaStateLruMap[g.Id] = &LuaStateLru{
|
||||
GroupId: g.Id,
|
||||
AccessTime: time.Now().UnixMilli(),
|
||||
}
|
||||
if g.LuaState == nil {
|
||||
g.LuaState = newLuaState(g.LuaStr)
|
||||
scriptLib := g.LuaState.NewTable()
|
||||
g.LuaState.SetGlobal("ScriptLib", scriptLib)
|
||||
for _, scriptLibFunc := range SCRIPT_LIB_FUNC_LIST {
|
||||
g.LuaState.SetField(scriptLib, scriptLibFunc.fnName, g.LuaState.NewFunction(scriptLibFunc.fn))
|
||||
}
|
||||
}
|
||||
return g.LuaState
|
||||
}
|
||||
|
||||
@@ -13,9 +13,8 @@ type SceneTagData struct {
|
||||
func (g *GameDataConfig) loadSceneTagData() {
|
||||
g.SceneTagDataMap = make(map[int32]*SceneTagData)
|
||||
sceneTagDataList := make([]*SceneTagData, 0)
|
||||
readTable[SceneTagData](g.tablePrefix+"SceneTagData.txt", &sceneTagDataList)
|
||||
readTable[SceneTagData](g.txtPrefix+"SceneTagData.txt", &sceneTagDataList)
|
||||
for _, sceneTagData := range sceneTagDataList {
|
||||
// list -> map
|
||||
g.SceneTagDataMap[sceneTagData.SceneTagId] = sceneTagData
|
||||
}
|
||||
logger.Info("SceneTagData count: %v", len(g.SceneTagDataMap))
|
||||
|
||||
@@ -15,7 +15,7 @@ type TriggerData struct {
|
||||
func (g *GameDataConfig) loadTriggerData() {
|
||||
g.TriggerDataMap = make(map[int32]*TriggerData)
|
||||
triggerDataList := make([]*TriggerData, 0)
|
||||
readTable[TriggerData](g.tablePrefix+"TriggerData.txt", &triggerDataList)
|
||||
readTable[TriggerData](g.txtPrefix+"TriggerData.txt", &triggerDataList)
|
||||
for _, triggerData := range triggerDataList {
|
||||
g.TriggerDataMap[triggerData.TriggerId] = triggerData
|
||||
}
|
||||
|
||||
@@ -19,9 +19,8 @@ type WeaponLevelData struct {
|
||||
func (g *GameDataConfig) loadWeaponLevelData() {
|
||||
g.WeaponLevelDataMap = make(map[int32]*WeaponLevelData)
|
||||
weaponLevelDataList := make([]*WeaponLevelData, 0)
|
||||
readTable[WeaponLevelData](g.tablePrefix+"WeaponLevelData.txt", &weaponLevelDataList)
|
||||
readTable[WeaponLevelData](g.txtPrefix+"WeaponLevelData.txt", &weaponLevelDataList)
|
||||
for _, weaponLevelData := range weaponLevelDataList {
|
||||
// list -> map
|
||||
weaponLevelData.ExpByStarMap = map[uint32]uint32{
|
||||
1: uint32(weaponLevelData.ExpByStar1),
|
||||
2: uint32(weaponLevelData.ExpByStar2),
|
||||
|
||||
@@ -24,9 +24,8 @@ type WeaponPromoteData struct {
|
||||
func (g *GameDataConfig) loadWeaponPromoteData() {
|
||||
g.WeaponPromoteDataMap = make(map[int32]map[int32]*WeaponPromoteData)
|
||||
weaponPromoteDataList := make([]*WeaponPromoteData, 0)
|
||||
readTable[WeaponPromoteData](g.tablePrefix+"WeaponPromoteData.txt", &weaponPromoteDataList)
|
||||
readTable[WeaponPromoteData](g.txtPrefix+"WeaponPromoteData.txt", &weaponPromoteDataList)
|
||||
for _, weaponPromoteData := range weaponPromoteDataList {
|
||||
// list -> map
|
||||
_, ok := g.WeaponPromoteDataMap[weaponPromoteData.PromoteId]
|
||||
if !ok {
|
||||
g.WeaponPromoteDataMap[weaponPromoteData.PromoteId] = make(map[int32]*WeaponPromoteData)
|
||||
|
||||
@@ -15,9 +15,8 @@ type WorldAreaData struct {
|
||||
func (g *GameDataConfig) loadWorldAreaData() {
|
||||
g.WorldAreaDataMap = make(map[int32]*WorldAreaData)
|
||||
worldAreaDataList := make([]*WorldAreaData, 0)
|
||||
readTable[WorldAreaData](g.tablePrefix+"WorldAreaData.txt", &worldAreaDataList)
|
||||
readTable[WorldAreaData](g.txtPrefix+"WorldAreaData.txt", &worldAreaDataList)
|
||||
for _, worldAreaData := range worldAreaDataList {
|
||||
// list -> map
|
||||
g.WorldAreaDataMap[worldAreaData.WorldAreaId] = worldAreaData
|
||||
}
|
||||
logger.Info("WorldAreaData count: %v", len(g.WorldAreaDataMap))
|
||||
|
||||
@@ -4,12 +4,12 @@ import (
|
||||
"image"
|
||||
"image/color"
|
||||
"image/jpeg"
|
||||
"math"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"hk4e/common/constant"
|
||||
"hk4e/pkg/logger"
|
||||
|
||||
"hk4e/gs/model"
|
||||
@@ -297,8 +297,6 @@ func LoadFrameFile() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var OBJECT_ID_COUNTER uint64 = math.MaxUint64
|
||||
|
||||
func UpdateFrame(rgb bool) {
|
||||
err := LoadFrameFile()
|
||||
if err != nil {
|
||||
@@ -323,13 +321,12 @@ func UpdateFrame(rgb bool) {
|
||||
for w := 0; w < SCREEN_WIDTH; w++ {
|
||||
for h := 0; h < SCREEN_HEIGHT; h++ {
|
||||
// 创建像素点
|
||||
OBJECT_ID_COUNTER++
|
||||
if rgb {
|
||||
entityId := scene.CreateEntityGadgetNormal(&model.Vector{
|
||||
X: leftTopPos.X - float64(w)*SCREEN_DPI,
|
||||
Y: leftTopPos.Y - float64(h)*SCREEN_DPI,
|
||||
Z: leftTopPos.Z,
|
||||
}, new(model.Vector), uint32(FRAME_COLOR[w][h]), 271003, OBJECT_ID_COUNTER)
|
||||
}, new(model.Vector), uint32(FRAME_COLOR[w][h]), 271003, uint32(constant.GADGET_STATE_DEFAULT), 0)
|
||||
SCREEN_ENTITY_ID_LIST = append(SCREEN_ENTITY_ID_LIST, entityId)
|
||||
} else {
|
||||
if !FRAME[w][h] {
|
||||
@@ -337,7 +334,7 @@ func UpdateFrame(rgb bool) {
|
||||
X: leftTopPos.X - float64(w)*SCREEN_DPI,
|
||||
Y: leftTopPos.Y - float64(h)*SCREEN_DPI,
|
||||
Z: leftTopPos.Z,
|
||||
}, new(model.Vector), uint32(GADGET_ID), 271003, OBJECT_ID_COUNTER)
|
||||
}, new(model.Vector), uint32(GADGET_ID), 271003, uint32(constant.GADGET_STATE_DEFAULT), 0)
|
||||
SCREEN_ENTITY_ID_LIST = append(SCREEN_ENTITY_ID_LIST, entityId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,6 +167,11 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
|
||||
X: float64(motionInfo.Pos.X),
|
||||
Y: float64(motionInfo.Pos.Y),
|
||||
Z: float64(motionInfo.Pos.Z),
|
||||
})
|
||||
g.TriggerCheck(player, player.Pos, &model.Vector{
|
||||
X: float64(motionInfo.Pos.X),
|
||||
Y: float64(motionInfo.Pos.Y),
|
||||
Z: float64(motionInfo.Pos.Z),
|
||||
}, sceneEntity.GetId())
|
||||
// 更新玩家的位置信息
|
||||
player.Pos.X = float64(motionInfo.Pos.X)
|
||||
@@ -258,7 +263,7 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector, newPos *model.Vector, entityId uint32) {
|
||||
func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector, newPos *model.Vector) {
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
if world == nil {
|
||||
logger.Error("get player world is nil, uid: %v", player.PlayerID)
|
||||
@@ -281,167 +286,162 @@ func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector,
|
||||
oldVisionGroupMap := make(map[uint32]*gdconf.Group)
|
||||
oldGroupList := aoiManager.GetObjectListByPos(float32(oldPos.X), 0.0, float32(oldPos.Z))
|
||||
for groupId, groupAny := range oldGroupList {
|
||||
group := groupAny.(*gdconf.Group)
|
||||
distance2D := math.Sqrt(math.Pow(oldPos.X-float64(group.Pos.X), 2.0) + math.Pow(oldPos.Z-float64(group.Pos.Z), 2.0))
|
||||
groupConfig := groupAny.(*gdconf.Group)
|
||||
distance2D := math.Sqrt((oldPos.X-float64(groupConfig.Pos.X))*(oldPos.X-float64(groupConfig.Pos.X)) +
|
||||
(oldPos.Z-float64(groupConfig.Pos.Z))*(oldPos.Z-float64(groupConfig.Pos.Z)))
|
||||
if distance2D > ENTITY_LOD {
|
||||
continue
|
||||
}
|
||||
if group.DynamicLoad {
|
||||
if groupConfig.DynamicLoad {
|
||||
continue
|
||||
}
|
||||
oldVisionGroupMap[uint32(groupId)] = group
|
||||
oldVisionGroupMap[uint32(groupId)] = groupConfig
|
||||
}
|
||||
// 新位置视野范围内的group
|
||||
newVisionGroupMap := make(map[uint32]*gdconf.Group)
|
||||
newGroupList := aoiManager.GetObjectListByPos(float32(newPos.X), 0.0, float32(newPos.Z))
|
||||
for groupId, groupAny := range newGroupList {
|
||||
group := groupAny.(*gdconf.Group)
|
||||
distance2D := math.Sqrt(math.Pow(newPos.X-float64(group.Pos.X), 2.0) + math.Pow(newPos.Z-float64(group.Pos.Z), 2.0))
|
||||
groupConfig := groupAny.(*gdconf.Group)
|
||||
distance2D := math.Sqrt((newPos.X-float64(groupConfig.Pos.X))*(newPos.X-float64(groupConfig.Pos.X)) +
|
||||
(newPos.Z-float64(groupConfig.Pos.Z))*(newPos.Z-float64(groupConfig.Pos.Z)))
|
||||
if distance2D > ENTITY_LOD {
|
||||
continue
|
||||
}
|
||||
if group.DynamicLoad {
|
||||
if groupConfig.DynamicLoad {
|
||||
continue
|
||||
}
|
||||
newVisionGroupMap[uint32(groupId)] = group
|
||||
newVisionGroupMap[uint32(groupId)] = groupConfig
|
||||
}
|
||||
// 消失的场景实体
|
||||
delEntityIdList := make([]uint32, 0)
|
||||
for groupId, group := range oldVisionGroupMap {
|
||||
for groupId, groupConfig := range oldVisionGroupMap {
|
||||
_, exist := newVisionGroupMap[groupId]
|
||||
if exist {
|
||||
continue
|
||||
}
|
||||
// 旧有新没有的group即为消失的
|
||||
for _, monster := range group.MonsterList {
|
||||
entity := scene.GetEntityByObjectId(monster.ObjectId)
|
||||
if entity == nil {
|
||||
continue
|
||||
}
|
||||
scene.DestroyEntity(entity.GetId())
|
||||
delEntityIdList = append(delEntityIdList, entity.GetId())
|
||||
}
|
||||
for _, npc := range group.NpcList {
|
||||
entity := scene.GetEntityByObjectId(npc.ObjectId)
|
||||
if entity == nil {
|
||||
continue
|
||||
}
|
||||
scene.DestroyEntity(entity.GetId())
|
||||
delEntityIdList = append(delEntityIdList, entity.GetId())
|
||||
}
|
||||
for _, gadget := range group.GadgetList {
|
||||
entity := scene.GetEntityByObjectId(gadget.ObjectId)
|
||||
if entity == nil {
|
||||
continue
|
||||
}
|
||||
scene.DestroyEntity(entity.GetId())
|
||||
group := scene.GetGroupById(groupId)
|
||||
for _, entity := range group.GetAllEntity() {
|
||||
delEntityIdList = append(delEntityIdList, entity.GetId())
|
||||
}
|
||||
g.RemoveGroup(scene, groupConfig)
|
||||
}
|
||||
// 出现的场景实体
|
||||
addEntityIdList := make([]uint32, 0)
|
||||
for groupId, group := range newVisionGroupMap {
|
||||
for groupId, groupConfig := range newVisionGroupMap {
|
||||
_, exist := oldVisionGroupMap[groupId]
|
||||
if exist {
|
||||
continue
|
||||
}
|
||||
// 新有旧没有的group即为出现的
|
||||
for _, monster := range group.MonsterList {
|
||||
entityId := g.CreateConfigEntity(scene, monster.ObjectId, monster)
|
||||
addEntityIdList = append(addEntityIdList, entityId)
|
||||
}
|
||||
for _, npc := range group.NpcList {
|
||||
entityId := g.CreateConfigEntity(scene, npc.ObjectId, npc)
|
||||
addEntityIdList = append(addEntityIdList, entityId)
|
||||
}
|
||||
for _, gadget := range group.GadgetList {
|
||||
entityId := g.CreateConfigEntity(scene, gadget.ObjectId, gadget)
|
||||
addEntityIdList = append(addEntityIdList, entityId)
|
||||
g.AddSceneGroup(scene, groupConfig)
|
||||
group := scene.GetGroupById(groupId)
|
||||
for _, entity := range group.GetAllEntity() {
|
||||
addEntityIdList = append(addEntityIdList, entity.GetId())
|
||||
}
|
||||
}
|
||||
// 同步客户端消失和出现的场景实体
|
||||
g.RemoveSceneEntityNotifyToPlayer(player, proto.VisionType_VISION_MISS, delEntityIdList)
|
||||
g.AddSceneEntityNotify(player, proto.VisionType_VISION_MEET, addEntityIdList, false, false)
|
||||
// 场景区域触发器
|
||||
for _, group := range newVisionGroupMap {
|
||||
for _, region := range group.RegionList {
|
||||
shape := alg.NewShape()
|
||||
switch uint8(region.Shape) {
|
||||
case constant.REGION_SHAPE_SPHERE:
|
||||
shape.NewSphere(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z}, region.Radius)
|
||||
case constant.REGION_SHAPE_CUBIC:
|
||||
shape.NewCubic(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z},
|
||||
&alg.Vector3{X: region.Size.X, Y: region.Size.Y, Z: region.Size.Z})
|
||||
case constant.REGION_SHAPE_CYLINDER:
|
||||
shape.NewCylinder(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z},
|
||||
region.Radius, region.Height)
|
||||
case constant.REGION_SHAPE_POLYGON:
|
||||
vector2PointArray := make([]*alg.Vector2, 0)
|
||||
for _, vector := range region.PointArray {
|
||||
// z就是y
|
||||
vector2PointArray = append(vector2PointArray, &alg.Vector2{X: vector.X, Z: vector.Y})
|
||||
}
|
||||
shape.NewPolygon(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z},
|
||||
vector2PointArray, region.Height)
|
||||
}
|
||||
oldPosInRegion := shape.Contain(&alg.Vector3{
|
||||
X: float32(oldPos.X),
|
||||
Y: float32(oldPos.Y),
|
||||
Z: float32(oldPos.Z),
|
||||
})
|
||||
newPosInRegion := shape.Contain(&alg.Vector3{
|
||||
X: float32(newPos.X),
|
||||
Y: float32(newPos.Y),
|
||||
Z: float32(newPos.Z),
|
||||
})
|
||||
if !oldPosInRegion && newPosInRegion {
|
||||
logger.Debug("player enter region: %v, uid: %v", region, player.PlayerID)
|
||||
for _, trigger := range group.TriggerList {
|
||||
if trigger.Event != constant.LUA_EVENT_ENTER_REGION {
|
||||
continue
|
||||
}
|
||||
|
||||
// TriggerCheck 场景区域触发器检测
|
||||
func (g *GameManager) TriggerCheck(player *model.Player, oldPos *model.Vector, newPos *model.Vector, entityId uint32) {
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
if world == nil {
|
||||
logger.Error("get player world is nil, uid: %v", player.PlayerID)
|
||||
return
|
||||
}
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
for groupId, group := range scene.GetAllGroup() {
|
||||
groupConfig := gdconf.GetSceneGroup(int32(groupId))
|
||||
if groupConfig == nil {
|
||||
continue
|
||||
}
|
||||
for suiteId := range group.GetAllSuite() {
|
||||
suiteConfig := groupConfig.SuiteList[suiteId-1]
|
||||
for _, regionConfigId := range suiteConfig.RegionConfigIdList {
|
||||
regionConfig := groupConfig.RegionMap[regionConfigId]
|
||||
shape := alg.NewShape()
|
||||
switch uint8(regionConfig.Shape) {
|
||||
case constant.REGION_SHAPE_SPHERE:
|
||||
shape.NewSphere(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z}, regionConfig.Radius)
|
||||
case constant.REGION_SHAPE_CUBIC:
|
||||
shape.NewCubic(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z},
|
||||
&alg.Vector3{X: regionConfig.Size.X, Y: regionConfig.Size.Y, Z: regionConfig.Size.Z})
|
||||
case constant.REGION_SHAPE_CYLINDER:
|
||||
shape.NewCylinder(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z},
|
||||
regionConfig.Radius, regionConfig.Height)
|
||||
case constant.REGION_SHAPE_POLYGON:
|
||||
vector2PointArray := make([]*alg.Vector2, 0)
|
||||
for _, vector := range regionConfig.PointArray {
|
||||
// z就是y
|
||||
vector2PointArray = append(vector2PointArray, &alg.Vector2{X: vector.X, Z: vector.Y})
|
||||
}
|
||||
if trigger.Condition != "" {
|
||||
cond := CallLuaFunc(group.GetLuaState(), trigger.Condition,
|
||||
&LuaCtx{uid: player.PlayerID},
|
||||
&LuaEvt{param1: region.ConfigId, targetEntityId: entityId})
|
||||
if !cond {
|
||||
shape.NewPolygon(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z},
|
||||
vector2PointArray, regionConfig.Height)
|
||||
}
|
||||
oldPosInRegion := shape.Contain(&alg.Vector3{
|
||||
X: float32(oldPos.X),
|
||||
Y: float32(oldPos.Y),
|
||||
Z: float32(oldPos.Z),
|
||||
})
|
||||
newPosInRegion := shape.Contain(&alg.Vector3{
|
||||
X: float32(newPos.X),
|
||||
Y: float32(newPos.Y),
|
||||
Z: float32(newPos.Z),
|
||||
})
|
||||
if !oldPosInRegion && newPosInRegion {
|
||||
logger.Debug("player enter region: %v, uid: %v", regionConfig, player.PlayerID)
|
||||
for _, triggerName := range suiteConfig.TriggerNameList {
|
||||
triggerConfig := groupConfig.TriggerMap[triggerName]
|
||||
if triggerConfig.Event != constant.LUA_EVENT_ENTER_REGION {
|
||||
continue
|
||||
}
|
||||
}
|
||||
logger.Debug("scene group trigger fire, trigger: %v, uid: %v", trigger, player.PlayerID)
|
||||
if trigger.Action != "" {
|
||||
logger.Debug("scene group trigger do action, trigger: %v, uid: %v", trigger, player.PlayerID)
|
||||
ok := CallLuaFunc(group.GetLuaState(), trigger.Action,
|
||||
&LuaCtx{uid: player.PlayerID},
|
||||
&LuaEvt{})
|
||||
if !ok {
|
||||
logger.Error("trigger action fail, trigger: %v, uid: %v", trigger, player.PlayerID)
|
||||
if triggerConfig.Condition != "" {
|
||||
cond := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Condition,
|
||||
&LuaCtx{uid: player.PlayerID},
|
||||
&LuaEvt{param1: regionConfig.ConfigId, targetEntityId: entityId})
|
||||
if !cond {
|
||||
continue
|
||||
}
|
||||
}
|
||||
logger.Debug("scene group trigger fire, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
|
||||
if triggerConfig.Action != "" {
|
||||
logger.Debug("scene group trigger do action, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
|
||||
ok := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Action,
|
||||
&LuaCtx{uid: player.PlayerID},
|
||||
&LuaEvt{})
|
||||
if !ok {
|
||||
logger.Error("trigger action fail, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
|
||||
}
|
||||
}
|
||||
g.TriggerFire(player, triggerConfig)
|
||||
}
|
||||
g.TriggerFire(player, trigger)
|
||||
}
|
||||
} else if oldPosInRegion && !newPosInRegion {
|
||||
logger.Debug("player leave region: %v, uid: %v", region, player.PlayerID)
|
||||
for _, trigger := range group.TriggerList {
|
||||
if trigger.Event != constant.LUA_EVENT_LEAVE_REGION {
|
||||
continue
|
||||
}
|
||||
if trigger.Condition != "" {
|
||||
cond := CallLuaFunc(group.GetLuaState(), trigger.Condition,
|
||||
&LuaCtx{uid: player.PlayerID},
|
||||
&LuaEvt{param1: region.ConfigId, targetEntityId: entityId})
|
||||
if !cond {
|
||||
} else if oldPosInRegion && !newPosInRegion {
|
||||
logger.Debug("player leave region: %v, uid: %v", regionConfig, player.PlayerID)
|
||||
for _, triggerName := range suiteConfig.TriggerNameList {
|
||||
triggerConfig := groupConfig.TriggerMap[triggerName]
|
||||
if triggerConfig.Event != constant.LUA_EVENT_LEAVE_REGION {
|
||||
continue
|
||||
}
|
||||
}
|
||||
logger.Debug("scene group trigger fire, trigger: %v, uid: %v", trigger, player.PlayerID)
|
||||
if trigger.Action != "" {
|
||||
logger.Debug("scene group trigger do action, trigger: %v, uid: %v", trigger, player.PlayerID)
|
||||
ok := CallLuaFunc(group.GetLuaState(), trigger.Action,
|
||||
&LuaCtx{uid: player.PlayerID},
|
||||
&LuaEvt{})
|
||||
if !ok {
|
||||
logger.Error("trigger action fail, trigger: %v, uid: %v", trigger, player.PlayerID)
|
||||
if triggerConfig.Condition != "" {
|
||||
cond := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Condition,
|
||||
&LuaCtx{uid: player.PlayerID},
|
||||
&LuaEvt{param1: regionConfig.ConfigId, targetEntityId: entityId})
|
||||
if !cond {
|
||||
continue
|
||||
}
|
||||
}
|
||||
logger.Debug("scene group trigger fire, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
|
||||
if triggerConfig.Action != "" {
|
||||
logger.Debug("scene group trigger do action, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
|
||||
ok := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Action,
|
||||
&LuaCtx{uid: player.PlayerID},
|
||||
&LuaEvt{})
|
||||
if !ok {
|
||||
logger.Error("trigger action fail, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
|
||||
}
|
||||
|
||||
// 找到卡池对应的掉落组
|
||||
dropGroupDataConfig := gdconf.CONF.DropGroupDataMap[int32(gachaType)]
|
||||
dropGroupDataConfig := gdconf.CONF.GachaDropGroupDataMap[int32(gachaType)]
|
||||
if dropGroupDataConfig == nil {
|
||||
logger.Error("drop group not found, drop id: %v", gachaType)
|
||||
return false, 0
|
||||
@@ -417,7 +417,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
|
||||
PurpleTimesFixValue = WeaponPurpleTimesFixValue
|
||||
}
|
||||
if gachaPoolInfo.OrangeTimes >= OrangeTimesFixThreshold || gachaPoolInfo.PurpleTimes >= PurpleTimesFixThreshold {
|
||||
fixDropGroupDataConfig := new(gdconf.DropGroupData)
|
||||
fixDropGroupDataConfig := new(gdconf.GachaDropGroupData)
|
||||
fixDropGroupDataConfig.DropId = dropGroupDataConfig.DropId
|
||||
fixDropGroupDataConfig.WeightAll = dropGroupDataConfig.WeightAll
|
||||
// 计算4星和5星权重修正值
|
||||
@@ -430,7 +430,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
|
||||
addPurpleWeight = 0
|
||||
}
|
||||
for _, drop := range dropGroupDataConfig.DropConfig {
|
||||
fixDrop := new(gdconf.Drop)
|
||||
fixDrop := new(gdconf.GachaDrop)
|
||||
fixDrop.Result = drop.Result
|
||||
fixDrop.DropId = drop.DropId
|
||||
fixDrop.IsEnd = drop.IsEnd
|
||||
@@ -525,7 +525,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
|
||||
// 替换本次结果为5星大保底
|
||||
if gachaPoolInfo.MustGetUpOrange {
|
||||
logger.Debug("trigger must get up orange, uid: %v", userId)
|
||||
upOrangeDropGroupDataConfig := gdconf.CONF.DropGroupDataMap[upOrangeDropId]
|
||||
upOrangeDropGroupDataConfig := gdconf.CONF.GachaDropGroupDataMap[upOrangeDropId]
|
||||
if upOrangeDropGroupDataConfig == nil {
|
||||
logger.Error("drop group not found, drop id: %v", upOrangeDropId)
|
||||
return false, 0
|
||||
@@ -552,7 +552,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
|
||||
// 替换本次结果为4星大保底
|
||||
if gachaPoolInfo.MustGetUpPurple {
|
||||
logger.Debug("trigger must get up purple, uid: %v", userId)
|
||||
upPurpleDropGroupDataConfig := gdconf.CONF.DropGroupDataMap[upPurpleDropId]
|
||||
upPurpleDropGroupDataConfig := gdconf.CONF.GachaDropGroupDataMap[upPurpleDropId]
|
||||
if upPurpleDropGroupDataConfig == nil {
|
||||
logger.Error("drop group not found, drop id: %v", upPurpleDropId)
|
||||
return false, 0
|
||||
@@ -576,7 +576,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
|
||||
}
|
||||
|
||||
// 走一次完整流程的掉落组
|
||||
func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.DropGroupData) (bool, *gdconf.Drop) {
|
||||
func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.GachaDropGroupData) (bool, *gdconf.GachaDrop) {
|
||||
for {
|
||||
drop := g.doRandDropOnce(dropGroupDataConfig)
|
||||
if drop == nil {
|
||||
@@ -588,7 +588,7 @@ func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.DropGroupData)
|
||||
return true, drop
|
||||
}
|
||||
// 进行下一步掉落流程
|
||||
dropGroupDataConfig = gdconf.CONF.DropGroupDataMap[drop.Result]
|
||||
dropGroupDataConfig = gdconf.CONF.GachaDropGroupDataMap[drop.Result]
|
||||
if dropGroupDataConfig == nil {
|
||||
logger.Error("drop config tab exist error, invalid drop id: %v", drop.Result)
|
||||
return false, nil
|
||||
@@ -597,7 +597,7 @@ func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.DropGroupData)
|
||||
}
|
||||
|
||||
// 进行单次随机掉落
|
||||
func (g *GameManager) doRandDropOnce(dropGroupDataConfig *gdconf.DropGroupData) *gdconf.Drop {
|
||||
func (g *GameManager) doRandDropOnce(dropGroupDataConfig *gdconf.GachaDropGroupData) *gdconf.GachaDrop {
|
||||
randNum := random.GetRandomInt32(0, dropGroupDataConfig.WeightAll-1)
|
||||
sumWeight := int32(0)
|
||||
// 轮盘选择法
|
||||
|
||||
@@ -242,6 +242,21 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes
|
||||
player.SceneLoadState = model.SceneInitFinish
|
||||
}
|
||||
|
||||
func (g *GameManager) AddSceneGroup(scene *Scene, groupConfig *gdconf.Group) {
|
||||
initSuiteId := int(groupConfig.GroupInitConfig.Suite)
|
||||
if initSuiteId > len(groupConfig.SuiteList) {
|
||||
return
|
||||
}
|
||||
scene.AddGroupSuite(uint32(groupConfig.Id), uint8(initSuiteId))
|
||||
}
|
||||
|
||||
func (g *GameManager) RemoveGroup(scene *Scene, groupConfig *gdconf.Group) {
|
||||
group := scene.GetGroupById(uint32(groupConfig.Id))
|
||||
for suiteId := range group.GetAllSuite() {
|
||||
scene.RemoveGroupSuite(uint32(groupConfig.Id), suiteId)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.Debug("player enter scene done, uid: %v", player.PlayerID)
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
@@ -275,22 +290,15 @@ func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Mess
|
||||
objectList := aoiManager.GetObjectListByPos(float32(player.Pos.X), 0.0, float32(player.Pos.Z))
|
||||
for _, groupAny := range objectList {
|
||||
group := groupAny.(*gdconf.Group)
|
||||
distance2D := math.Sqrt(math.Pow(player.Pos.X-float64(group.Pos.X), 2.0) + math.Pow(player.Pos.Z-float64(group.Pos.Z), 2.0))
|
||||
distance2D := math.Sqrt((player.Pos.X-float64(group.Pos.X))*(player.Pos.X-float64(group.Pos.X)) +
|
||||
(player.Pos.Z-float64(group.Pos.Z))*(player.Pos.Z-float64(group.Pos.Z)))
|
||||
if distance2D > ENTITY_LOD {
|
||||
continue
|
||||
}
|
||||
if group.DynamicLoad {
|
||||
continue
|
||||
}
|
||||
for _, monster := range group.MonsterList {
|
||||
g.CreateConfigEntity(scene, monster.ObjectId, monster)
|
||||
}
|
||||
for _, npc := range group.NpcList {
|
||||
g.CreateConfigEntity(scene, npc.ObjectId, npc)
|
||||
}
|
||||
for _, gadget := range group.GadgetList {
|
||||
g.CreateConfigEntity(scene, gadget.ObjectId, gadget)
|
||||
}
|
||||
g.AddSceneGroup(scene, group)
|
||||
}
|
||||
}
|
||||
if player.SceneJump {
|
||||
@@ -385,64 +393,6 @@ func (g *GameManager) SceneEntityDrownReq(player *model.Player, payloadMsg pb.Me
|
||||
g.SendMsg(cmd.SceneEntityDrownRsp, player.PlayerID, player.ClientSeq, sceneEntityDrownRsp)
|
||||
}
|
||||
|
||||
// CreateConfigEntity 创建配置表里的实体
|
||||
func (g *GameManager) CreateConfigEntity(scene *Scene, objectId uint64, entityConfig any) uint32 {
|
||||
switch entityConfig.(type) {
|
||||
case *gdconf.Monster:
|
||||
monster := entityConfig.(*gdconf.Monster)
|
||||
return scene.CreateEntityMonster(&model.Vector{
|
||||
X: float64(monster.Pos.X),
|
||||
Y: float64(monster.Pos.Y),
|
||||
Z: float64(monster.Pos.Z),
|
||||
}, &model.Vector{
|
||||
X: float64(monster.Rot.X),
|
||||
Y: float64(monster.Rot.Y),
|
||||
Z: float64(monster.Rot.Z),
|
||||
}, uint32(monster.MonsterId), uint8(monster.Level), g.GetTempFightPropMap(), uint32(monster.ConfigId), objectId)
|
||||
case *gdconf.Npc:
|
||||
npc := entityConfig.(*gdconf.Npc)
|
||||
return scene.CreateEntityNpc(&model.Vector{
|
||||
X: float64(npc.Pos.X),
|
||||
Y: float64(npc.Pos.Y),
|
||||
Z: float64(npc.Pos.Z),
|
||||
}, &model.Vector{
|
||||
X: float64(npc.Rot.X),
|
||||
Y: float64(npc.Rot.Y),
|
||||
Z: float64(npc.Rot.Z),
|
||||
}, uint32(npc.NpcId), 0, 0, 0, uint32(npc.ConfigId), objectId)
|
||||
case *gdconf.Gadget:
|
||||
gadget := entityConfig.(*gdconf.Gadget)
|
||||
// 70500000并不是实际的装置id 根据节点类型对应采集物配置表
|
||||
if gadget.PointType != 0 && gadget.GadgetId == 70500000 {
|
||||
gatherDataConfig := gdconf.GetGatherDataByPointType(gadget.PointType)
|
||||
if gatherDataConfig == nil {
|
||||
return 0
|
||||
}
|
||||
return scene.CreateEntityGadgetGather(&model.Vector{
|
||||
X: float64(gadget.Pos.X),
|
||||
Y: float64(gadget.Pos.Y),
|
||||
Z: float64(gadget.Pos.Z),
|
||||
}, &model.Vector{
|
||||
X: float64(gadget.Rot.X),
|
||||
Y: float64(gadget.Rot.Y),
|
||||
Z: float64(gadget.Rot.Z),
|
||||
}, uint32(gatherDataConfig.GadgetId), uint32(gatherDataConfig.GatherId), uint32(gadget.ConfigId), objectId)
|
||||
} else {
|
||||
return scene.CreateEntityGadgetNormal(&model.Vector{
|
||||
X: float64(gadget.Pos.X),
|
||||
Y: float64(gadget.Pos.Y),
|
||||
Z: float64(gadget.Pos.Z),
|
||||
}, &model.Vector{
|
||||
X: float64(gadget.Rot.X),
|
||||
Y: float64(gadget.Rot.Y),
|
||||
Z: float64(gadget.Rot.Z),
|
||||
}, uint32(gadget.GadgetId), uint32(gadget.ConfigId), objectId)
|
||||
}
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketPlayerEnterSceneNotifyLogin(player *model.Player, enterType proto.EnterType) *proto.PlayerEnterSceneNotify {
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
@@ -550,8 +500,8 @@ func (g *GameManager) AddSceneEntityNotifyBroadcast(player *model.Player, scene
|
||||
continue
|
||||
}
|
||||
g.SendMsg(cmd.SceneEntityAppearNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, sceneEntityAppearNotify)
|
||||
// logger.Debug("SceneEntityAppearNotify, uid: %v, type: %v, len: %v",
|
||||
// scenePlayer.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList))
|
||||
logger.Debug("SceneEntityAppearNotify, uid: %v, type: %v, len: %v",
|
||||
scenePlayer.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,8 +511,8 @@ func (g *GameManager) RemoveSceneEntityNotifyToPlayer(player *model.Player, visi
|
||||
DisappearType: visionType,
|
||||
}
|
||||
g.SendMsg(cmd.SceneEntityDisappearNotify, player.PlayerID, player.ClientSeq, sceneEntityDisappearNotify)
|
||||
// logger.Debug("SceneEntityDisappearNotify, uid: %v, type: %v, len: %v",
|
||||
// player.PlayerID, sceneEntityDisappearNotify.DisappearType, len(sceneEntityDisappearNotify.EntityList))
|
||||
logger.Debug("SceneEntityDisappearNotify, uid: %v, type: %v, len: %v",
|
||||
player.PlayerID, sceneEntityDisappearNotify.DisappearType, len(sceneEntityDisappearNotify.EntityList))
|
||||
}
|
||||
|
||||
func (g *GameManager) RemoveSceneEntityNotifyBroadcast(scene *Scene, visionType proto.VisionType, entityIdList []uint32) {
|
||||
@@ -995,9 +945,9 @@ func (g *GameManager) PacketSceneGadgetInfoNormal(entity *Entity) *proto.SceneGa
|
||||
gadgetEntity := entity.GetGadgetEntity()
|
||||
sceneGadgetInfo := &proto.SceneGadgetInfo{
|
||||
GadgetId: gadgetEntity.GetGadgetId(),
|
||||
GroupId: 0,
|
||||
GroupId: entity.GetGroupId(),
|
||||
ConfigId: entity.GetConfigId(),
|
||||
GadgetState: 0,
|
||||
GadgetState: gadgetEntity.GetGadgetState(),
|
||||
IsEnableInteract: true,
|
||||
AuthorityPeerId: 1,
|
||||
}
|
||||
@@ -1014,9 +964,9 @@ func (g *GameManager) PacketSceneGadgetInfoGather(entity *Entity) *proto.SceneGa
|
||||
}
|
||||
sceneGadgetInfo := &proto.SceneGadgetInfo{
|
||||
GadgetId: gadgetEntity.GetGadgetId(),
|
||||
GroupId: 0,
|
||||
GroupId: entity.GetGroupId(),
|
||||
ConfigId: entity.GetConfigId(),
|
||||
GadgetState: 0,
|
||||
GadgetState: gadgetEntity.GetGadgetState(),
|
||||
IsEnableInteract: true,
|
||||
AuthorityPeerId: 1,
|
||||
Content: &proto.SceneGadgetInfo_GatherGadget{
|
||||
@@ -1071,24 +1021,3 @@ func (g *GameManager) PacketDelTeamEntityNotify(scene *Scene, player *model.Play
|
||||
}
|
||||
return delTeamEntityNotify
|
||||
}
|
||||
|
||||
func (g *GameManager) GetTempFightPropMap() map[uint32]float32 {
|
||||
fpm := map[uint32]float32{
|
||||
constant.FIGHT_PROP_CUR_HP: float32(72.91699),
|
||||
constant.FIGHT_PROP_PHYSICAL_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_CUR_DEFENSE: float32(505.0),
|
||||
constant.FIGHT_PROP_CUR_ATTACK: float32(45.679916),
|
||||
constant.FIGHT_PROP_ICE_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_BASE_ATTACK: float32(45.679916),
|
||||
constant.FIGHT_PROP_MAX_HP: float32(72.91699),
|
||||
constant.FIGHT_PROP_FIRE_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_ELEC_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_WIND_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_ROCK_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_GRASS_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_WATER_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_BASE_HP: float32(72.91699),
|
||||
constant.FIGHT_PROP_BASE_DEFENSE: float32(505.0),
|
||||
}
|
||||
return fpm
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ func (g *GameManager) CreateVehicleReq(player *model.Player, payloadMsg pb.Messa
|
||||
// 创建载具实体
|
||||
pos := &model.Vector{X: float64(req.Pos.X), Y: float64(req.Pos.Y), Z: float64(req.Pos.Z)}
|
||||
rot := &model.Vector{X: float64(req.Rot.X), Y: float64(req.Rot.Y), Z: float64(req.Rot.Z)}
|
||||
entityId := scene.CreateEntityGadgetVehicle(player.PlayerID, pos, rot, req.VehicleId)
|
||||
entityId := scene.CreateEntityGadgetVehicle(player, pos, rot, req.VehicleId)
|
||||
if entityId == 0 {
|
||||
logger.Error("vehicle entityId is 0, uid: %v", player.PlayerID)
|
||||
g.SendError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{})
|
||||
|
||||
@@ -717,14 +717,14 @@ func (w *World) RemoveWaitPlayer(uid uint32) {
|
||||
|
||||
func (w *World) CreateScene(sceneId uint32) *Scene {
|
||||
scene := &Scene{
|
||||
id: sceneId,
|
||||
world: w,
|
||||
playerMap: make(map[uint32]*model.Player),
|
||||
entityMap: make(map[uint32]*Entity),
|
||||
objectIdEntityMap: make(map[uint64]*Entity),
|
||||
gameTime: 18 * 60,
|
||||
createTime: time.Now().UnixMilli(),
|
||||
meeoIndex: 0,
|
||||
id: sceneId,
|
||||
world: w,
|
||||
playerMap: make(map[uint32]*model.Player),
|
||||
entityMap: make(map[uint32]*Entity),
|
||||
groupMap: make(map[uint32]*Group),
|
||||
gameTime: 18 * 60,
|
||||
createTime: time.Now().UnixMilli(),
|
||||
meeoIndex: 0,
|
||||
}
|
||||
w.sceneMap[sceneId] = scene
|
||||
return scene
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"hk4e/common/constant"
|
||||
"hk4e/gdconf"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/protocol/cmd"
|
||||
@@ -13,14 +14,40 @@ import (
|
||||
|
||||
// Scene 场景数据结构
|
||||
type Scene struct {
|
||||
id uint32
|
||||
world *World
|
||||
playerMap map[uint32]*model.Player
|
||||
entityMap map[uint32]*Entity
|
||||
objectIdEntityMap map[uint64]*Entity // 用于标识配置档里的唯一实体是否已被创建
|
||||
gameTime uint32 // 游戏内提瓦特大陆的时间
|
||||
createTime int64 // 场景创建时间
|
||||
meeoIndex uint32 // 客户端风元素染色同步协议的计数器
|
||||
id uint32
|
||||
world *World
|
||||
playerMap map[uint32]*model.Player
|
||||
entityMap map[uint32]*Entity
|
||||
groupMap map[uint32]*Group
|
||||
gameTime uint32 // 游戏内提瓦特大陆的时间
|
||||
createTime int64 // 场景创建时间
|
||||
meeoIndex uint32 // 客户端风元素染色同步协议的计数器
|
||||
}
|
||||
|
||||
type Group struct {
|
||||
suiteMap map[uint8]*Suite
|
||||
}
|
||||
|
||||
func (g *Group) GetAllSuite() map[uint8]*Suite {
|
||||
return g.suiteMap
|
||||
}
|
||||
|
||||
func (g *Group) GetAllEntity() map[uint32]*Entity {
|
||||
entityMap := make(map[uint32]*Entity)
|
||||
for _, suite := range g.suiteMap {
|
||||
for _, entity := range suite.entityMap {
|
||||
entityMap[entity.id] = entity
|
||||
}
|
||||
}
|
||||
return entityMap
|
||||
}
|
||||
|
||||
type Suite struct {
|
||||
entityMap map[uint32]*Entity
|
||||
}
|
||||
|
||||
func (s *Suite) GetAllEntity() map[uint32]*Entity {
|
||||
return s.entityMap
|
||||
}
|
||||
|
||||
func (s *Scene) GetId() uint32 {
|
||||
@@ -39,6 +66,14 @@ func (s *Scene) GetAllEntity() map[uint32]*Entity {
|
||||
return s.entityMap
|
||||
}
|
||||
|
||||
func (s *Scene) GetGroupById(groupId uint32) *Group {
|
||||
return s.groupMap[groupId]
|
||||
}
|
||||
|
||||
func (s *Scene) GetAllGroup() map[uint32]*Group {
|
||||
return s.groupMap
|
||||
}
|
||||
|
||||
func (s *Scene) GetGameTime() uint32 {
|
||||
return s.gameTime
|
||||
}
|
||||
@@ -161,7 +196,7 @@ func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32
|
||||
avatarId: avatarId,
|
||||
},
|
||||
}
|
||||
s.CreateEntity(entity, 0)
|
||||
s.CreateEntity(entity)
|
||||
return entity.id
|
||||
}
|
||||
|
||||
@@ -179,15 +214,11 @@ func (s *Scene) CreateEntityWeapon() uint32 {
|
||||
fightProp: nil,
|
||||
entityType: constant.ENTITY_TYPE_WEAPON,
|
||||
}
|
||||
s.CreateEntity(entity, 0)
|
||||
s.CreateEntity(entity)
|
||||
return entity.id
|
||||
}
|
||||
|
||||
func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, level uint8, fightProp map[uint32]float32, configId uint32, objectId uint64) uint32 {
|
||||
_, exist := s.objectIdEntityMap[objectId]
|
||||
if exist {
|
||||
return 0
|
||||
}
|
||||
func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, level uint8, fightProp map[uint32]float32, configId, groupId uint32) uint32 {
|
||||
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_MONSTER)
|
||||
entity := &Entity{
|
||||
id: entityId,
|
||||
@@ -205,17 +236,13 @@ func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, le
|
||||
monsterId: monsterId,
|
||||
},
|
||||
configId: configId,
|
||||
objectId: objectId,
|
||||
groupId: groupId,
|
||||
}
|
||||
s.CreateEntity(entity, objectId)
|
||||
s.CreateEntity(entity)
|
||||
return entity.id
|
||||
}
|
||||
|
||||
func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQuestId, blockId, configId uint32, objectId uint64) uint32 {
|
||||
_, exist := s.objectIdEntityMap[objectId]
|
||||
if exist {
|
||||
return 0
|
||||
}
|
||||
func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQuestId, blockId, configId, groupId uint32) uint32 {
|
||||
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_NPC)
|
||||
entity := &Entity{
|
||||
id: entityId,
|
||||
@@ -239,17 +266,13 @@ func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQue
|
||||
BlockId: blockId,
|
||||
},
|
||||
configId: configId,
|
||||
objectId: objectId,
|
||||
groupId: groupId,
|
||||
}
|
||||
s.CreateEntity(entity, objectId)
|
||||
s.CreateEntity(entity)
|
||||
return entity.id
|
||||
}
|
||||
|
||||
func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId uint32, configId uint32, objectId uint64) uint32 {
|
||||
_, exist := s.objectIdEntityMap[objectId]
|
||||
if exist {
|
||||
return 0
|
||||
}
|
||||
func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId, gadgetState, configId, groupId uint32) uint32 {
|
||||
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET)
|
||||
entity := &Entity{
|
||||
id: entityId,
|
||||
@@ -267,21 +290,18 @@ func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId uint32
|
||||
},
|
||||
entityType: constant.ENTITY_TYPE_GADGET,
|
||||
gadgetEntity: &GadgetEntity{
|
||||
gadgetId: gadgetId,
|
||||
gadgetType: GADGET_TYPE_NORMAL,
|
||||
gadgetId: gadgetId,
|
||||
gadgetState: gadgetState,
|
||||
gadgetType: GADGET_TYPE_NORMAL,
|
||||
},
|
||||
configId: configId,
|
||||
objectId: objectId,
|
||||
groupId: groupId,
|
||||
}
|
||||
s.CreateEntity(entity, objectId)
|
||||
s.CreateEntity(entity)
|
||||
return entity.id
|
||||
}
|
||||
|
||||
func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId uint32, gatherId uint32, configId uint32, objectId uint64) uint32 {
|
||||
_, exist := s.objectIdEntityMap[objectId]
|
||||
if exist {
|
||||
return 0
|
||||
}
|
||||
func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId, gadgetState, gatherId, configId, groupId uint32) uint32 {
|
||||
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET)
|
||||
entity := &Entity{
|
||||
id: entityId,
|
||||
@@ -299,20 +319,21 @@ func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId uint32
|
||||
},
|
||||
entityType: constant.ENTITY_TYPE_GADGET,
|
||||
gadgetEntity: &GadgetEntity{
|
||||
gadgetId: gadgetId,
|
||||
gadgetType: GADGET_TYPE_GATHER,
|
||||
gadgetId: gadgetId,
|
||||
gadgetState: gadgetState,
|
||||
gadgetType: GADGET_TYPE_GATHER,
|
||||
gadgetGatherEntity: &GadgetGatherEntity{
|
||||
gatherId: gatherId,
|
||||
},
|
||||
},
|
||||
configId: configId,
|
||||
objectId: objectId,
|
||||
groupId: groupId,
|
||||
}
|
||||
s.CreateEntity(entity, objectId)
|
||||
s.CreateEntity(entity)
|
||||
return entity.id
|
||||
}
|
||||
|
||||
func (s *Scene) CreateEntityGadgetClient(pos, rot *model.Vector, entityId uint32, configId, campId, campType, ownerEntityId, targetEntityId, propOwnerEntityId uint32) {
|
||||
func (s *Scene) CreateEntityGadgetClient(pos, rot *model.Vector, entityId, configId, campId, campType, ownerEntityId, targetEntityId, propOwnerEntityId uint32) {
|
||||
entity := &Entity{
|
||||
id: entityId,
|
||||
scene: s,
|
||||
@@ -340,15 +361,10 @@ func (s *Scene) CreateEntityGadgetClient(pos, rot *model.Vector, entityId uint32
|
||||
},
|
||||
},
|
||||
}
|
||||
s.CreateEntity(entity, 0)
|
||||
s.CreateEntity(entity)
|
||||
}
|
||||
|
||||
func (s *Scene) CreateEntityGadgetVehicle(uid uint32, pos, rot *model.Vector, vehicleId uint32) uint32 {
|
||||
player := USER_MANAGER.GetOnlineUser(uid)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", uid)
|
||||
return 0
|
||||
}
|
||||
func (s *Scene) CreateEntityGadgetVehicle(player *model.Player, pos, rot *model.Vector, vehicleId uint32) uint32 {
|
||||
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET)
|
||||
entity := &Entity{
|
||||
id: entityId,
|
||||
@@ -377,18 +393,15 @@ func (s *Scene) CreateEntityGadgetVehicle(uid uint32, pos, rot *model.Vector, ve
|
||||
},
|
||||
},
|
||||
}
|
||||
s.CreateEntity(entity, 0)
|
||||
s.CreateEntity(entity)
|
||||
return entity.id
|
||||
}
|
||||
|
||||
func (s *Scene) CreateEntity(entity *Entity, objectId uint64) {
|
||||
func (s *Scene) CreateEntity(entity *Entity) {
|
||||
if len(s.entityMap) >= ENTITY_MAX_SEND_NUM && !ENTITY_NUM_UNLIMIT {
|
||||
logger.Error("above max scene entity num limit: %v, id: %v, pos: %v", ENTITY_MAX_SEND_NUM, entity.id, entity.pos)
|
||||
return
|
||||
}
|
||||
if objectId != 0 {
|
||||
s.objectIdEntityMap[objectId] = entity
|
||||
}
|
||||
s.entityMap[entity.id] = entity
|
||||
}
|
||||
|
||||
@@ -398,15 +411,145 @@ func (s *Scene) DestroyEntity(entityId uint32) {
|
||||
return
|
||||
}
|
||||
delete(s.entityMap, entity.id)
|
||||
delete(s.objectIdEntityMap, entity.objectId)
|
||||
}
|
||||
|
||||
func (s *Scene) GetEntity(entityId uint32) *Entity {
|
||||
return s.entityMap[entityId]
|
||||
}
|
||||
|
||||
func (s *Scene) GetEntityByObjectId(objectId uint64) *Entity {
|
||||
return s.objectIdEntityMap[objectId]
|
||||
func (s *Scene) AddGroupSuite(groupId uint32, suiteId uint8) {
|
||||
groupConfig := gdconf.GetSceneGroup(int32(groupId))
|
||||
if groupConfig == nil {
|
||||
return
|
||||
}
|
||||
suiteConfig := groupConfig.SuiteList[suiteId-1]
|
||||
suite := &Suite{
|
||||
entityMap: make(map[uint32]*Entity),
|
||||
}
|
||||
for _, monsterConfigId := range suiteConfig.MonsterConfigIdList {
|
||||
monster, exist := groupConfig.MonsterMap[monsterConfigId]
|
||||
if !exist {
|
||||
continue
|
||||
}
|
||||
entityId := s.createConfigEntity(uint32(groupConfig.Id), monster)
|
||||
entity := s.GetEntity(entityId)
|
||||
suite.entityMap[entityId] = entity
|
||||
}
|
||||
for _, gadgetConfigId := range suiteConfig.GadgetConfigIdList {
|
||||
gadget, exist := groupConfig.GadgetMap[gadgetConfigId]
|
||||
if !exist {
|
||||
continue
|
||||
}
|
||||
entityId := s.createConfigEntity(uint32(groupConfig.Id), gadget)
|
||||
entity := s.GetEntity(entityId)
|
||||
suite.entityMap[entityId] = entity
|
||||
}
|
||||
for _, npc := range groupConfig.NpcMap {
|
||||
entityId := s.createConfigEntity(uint32(groupConfig.Id), npc)
|
||||
entity := s.GetEntity(entityId)
|
||||
suite.entityMap[entityId] = entity
|
||||
}
|
||||
group, exist := s.groupMap[groupId]
|
||||
if !exist {
|
||||
group = &Group{
|
||||
suiteMap: make(map[uint8]*Suite),
|
||||
}
|
||||
}
|
||||
group.suiteMap[suiteId] = suite
|
||||
}
|
||||
|
||||
func (s *Scene) RemoveGroupSuite(groupId uint32, suiteId uint8) {
|
||||
group := s.groupMap[groupId]
|
||||
if group == nil {
|
||||
return
|
||||
}
|
||||
suite := group.suiteMap[suiteId]
|
||||
if suite == nil {
|
||||
return
|
||||
}
|
||||
for _, entity := range suite.entityMap {
|
||||
s.DestroyEntity(entity.id)
|
||||
}
|
||||
delete(group.suiteMap, suiteId)
|
||||
}
|
||||
|
||||
// 创建配置表里的实体
|
||||
func (s *Scene) createConfigEntity(groupId uint32, entityConfig any) uint32 {
|
||||
switch entityConfig.(type) {
|
||||
case *gdconf.Monster:
|
||||
monster := entityConfig.(*gdconf.Monster)
|
||||
return s.CreateEntityMonster(&model.Vector{
|
||||
X: float64(monster.Pos.X),
|
||||
Y: float64(monster.Pos.Y),
|
||||
Z: float64(monster.Pos.Z),
|
||||
}, &model.Vector{
|
||||
X: float64(monster.Rot.X),
|
||||
Y: float64(monster.Rot.Y),
|
||||
Z: float64(monster.Rot.Z),
|
||||
}, uint32(monster.MonsterId), uint8(monster.Level), getTempFightPropMap(), uint32(monster.ConfigId), groupId)
|
||||
case *gdconf.Npc:
|
||||
npc := entityConfig.(*gdconf.Npc)
|
||||
return s.CreateEntityNpc(&model.Vector{
|
||||
X: float64(npc.Pos.X),
|
||||
Y: float64(npc.Pos.Y),
|
||||
Z: float64(npc.Pos.Z),
|
||||
}, &model.Vector{
|
||||
X: float64(npc.Rot.X),
|
||||
Y: float64(npc.Rot.Y),
|
||||
Z: float64(npc.Rot.Z),
|
||||
}, uint32(npc.NpcId), 0, 0, 0, uint32(npc.ConfigId), groupId)
|
||||
case *gdconf.Gadget:
|
||||
gadget := entityConfig.(*gdconf.Gadget)
|
||||
// 70500000并不是实际的装置id 根据节点类型对应采集物配置表
|
||||
if gadget.PointType != 0 && gadget.GadgetId == 70500000 {
|
||||
gatherDataConfig := gdconf.GetGatherDataByPointType(gadget.PointType)
|
||||
if gatherDataConfig == nil {
|
||||
return 0
|
||||
}
|
||||
return s.CreateEntityGadgetGather(&model.Vector{
|
||||
X: float64(gadget.Pos.X),
|
||||
Y: float64(gadget.Pos.Y),
|
||||
Z: float64(gadget.Pos.Z),
|
||||
}, &model.Vector{
|
||||
X: float64(gadget.Rot.X),
|
||||
Y: float64(gadget.Rot.Y),
|
||||
Z: float64(gadget.Rot.Z),
|
||||
}, uint32(gatherDataConfig.GadgetId), uint32(constant.GADGET_STATE_DEFAULT), uint32(gatherDataConfig.GatherId), uint32(gadget.ConfigId), groupId)
|
||||
} else {
|
||||
return s.CreateEntityGadgetNormal(&model.Vector{
|
||||
X: float64(gadget.Pos.X),
|
||||
Y: float64(gadget.Pos.Y),
|
||||
Z: float64(gadget.Pos.Z),
|
||||
}, &model.Vector{
|
||||
X: float64(gadget.Rot.X),
|
||||
Y: float64(gadget.Rot.Y),
|
||||
Z: float64(gadget.Rot.Z),
|
||||
}, uint32(gadget.GadgetId), uint32(gadget.State), uint32(gadget.ConfigId), groupId)
|
||||
}
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func getTempFightPropMap() map[uint32]float32 {
|
||||
fpm := map[uint32]float32{
|
||||
constant.FIGHT_PROP_CUR_HP: float32(72.91699),
|
||||
constant.FIGHT_PROP_PHYSICAL_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_CUR_DEFENSE: float32(505.0),
|
||||
constant.FIGHT_PROP_CUR_ATTACK: float32(45.679916),
|
||||
constant.FIGHT_PROP_ICE_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_BASE_ATTACK: float32(45.679916),
|
||||
constant.FIGHT_PROP_MAX_HP: float32(72.91699),
|
||||
constant.FIGHT_PROP_FIRE_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_ELEC_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_WIND_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_ROCK_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_GRASS_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_WATER_SUB_HURT: float32(0.1),
|
||||
constant.FIGHT_PROP_BASE_HP: float32(72.91699),
|
||||
constant.FIGHT_PROP_BASE_DEFENSE: float32(505.0),
|
||||
}
|
||||
return fpm
|
||||
}
|
||||
|
||||
// Entity 场景实体数据结构
|
||||
@@ -426,8 +569,8 @@ type Entity struct {
|
||||
monsterEntity *MonsterEntity
|
||||
npcEntity *NpcEntity
|
||||
gadgetEntity *GadgetEntity
|
||||
configId uint32 // 配置表相关
|
||||
objectId uint64
|
||||
configId uint32 // LUA配置相关
|
||||
groupId uint32
|
||||
}
|
||||
|
||||
func (e *Entity) GetId() uint32 {
|
||||
@@ -502,6 +645,10 @@ func (e *Entity) GetConfigId() uint32 {
|
||||
return e.configId
|
||||
}
|
||||
|
||||
func (e *Entity) GetGroupId() uint32 {
|
||||
return e.groupId
|
||||
}
|
||||
|
||||
type AvatarEntity struct {
|
||||
uid uint32
|
||||
avatarId uint32
|
||||
@@ -533,6 +680,7 @@ type NpcEntity struct {
|
||||
type GadgetEntity struct {
|
||||
gadgetType int
|
||||
gadgetId uint32
|
||||
gadgetState uint32
|
||||
gadgetClientEntity *GadgetClientEntity
|
||||
gadgetGatherEntity *GadgetGatherEntity
|
||||
gadgetVehicleEntity *GadgetVehicleEntity
|
||||
@@ -546,6 +694,10 @@ func (g *GadgetEntity) GetGadgetId() uint32 {
|
||||
return g.gadgetId
|
||||
}
|
||||
|
||||
func (g *GadgetEntity) GetGadgetState() uint32 {
|
||||
return g.gadgetState
|
||||
}
|
||||
|
||||
func (g *GadgetEntity) GetGadgetClientEntity() *GadgetClientEntity {
|
||||
return g.gadgetClientEntity
|
||||
}
|
||||
|
||||
@@ -161,9 +161,9 @@ func regionCubicContainPos(cubic *RegionCubic, pos *Vector3) bool {
|
||||
|
||||
// 检测一个点是否在球体内
|
||||
func regionSphereContainPos(sphere *RegionSphere, pos *Vector3) bool {
|
||||
distance3D := math.Sqrt(math.Pow(float64(sphere.pos.X-pos.X), 2) +
|
||||
math.Pow(float64(sphere.pos.Y-pos.Y), 2) +
|
||||
math.Pow(float64(sphere.pos.Z-pos.Z), 2))
|
||||
distance3D := math.Sqrt(float64(sphere.pos.X-pos.X)*float64(sphere.pos.X-pos.X) +
|
||||
float64(sphere.pos.Y-pos.Y)*float64(sphere.pos.Y-pos.Y) +
|
||||
float64(sphere.pos.Z-pos.Z)*float64(sphere.pos.Z-pos.Z))
|
||||
if float32(distance3D) < sphere.radius {
|
||||
return true
|
||||
} else {
|
||||
@@ -173,8 +173,8 @@ func regionSphereContainPos(sphere *RegionSphere, pos *Vector3) bool {
|
||||
|
||||
// 检测一个点是否在圆柱体内
|
||||
func regionCylinderContainPos(cylinder *RegionCylinder, pos *Vector3) bool {
|
||||
distance2D := math.Sqrt(math.Pow(float64(cylinder.pos.X-pos.X), 2) +
|
||||
math.Pow(float64(cylinder.pos.Z-pos.Z), 2))
|
||||
distance2D := math.Sqrt(float64(cylinder.pos.X-pos.X)*float64(cylinder.pos.X-pos.X) +
|
||||
float64(cylinder.pos.Z-pos.Z)*float64(cylinder.pos.Z-pos.Z))
|
||||
if float32(distance2D) >= cylinder.radius {
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user