This commit is contained in:
@@ -2,6 +2,8 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math/rand/v2"
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
"github.com/gogf/gf/v2/util/grand"
|
"github.com/gogf/gf/v2/util/grand"
|
||||||
@@ -32,53 +34,71 @@ func RemoveLast(s string) string {
|
|||||||
return string(runes[:len(runes)-1])
|
return string(runes[:len(runes)-1])
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************************** 函数1:核心函数(双数组+int型概率,泛型)**************************
|
// RandomByWeight 根据整数权重随机选择元素(优化后的泛型版本)
|
||||||
// randomByIntProbs 核心概率计算函数:接收任意类型元素数组 + int型概率数组,实现权重随机
|
// 入参:
|
||||||
// T any:支持任意类型的元素切片,职责单一,只处理纯int概率的核心逻辑
|
// - elements: 待随机的元素集合(非空)
|
||||||
func RandomByIntProbs[T any](natureSet []T, probs []int) (T, error) {
|
// - weights: 对应元素的权重(非负整数,长度需与elements一致;长度不匹配/总权重为0时降级为等概率随机)
|
||||||
|
//
|
||||||
|
// 返回:
|
||||||
|
// - 随机选中的元素
|
||||||
|
// - 错误(仅当elements为空/权重值为负时返回)
|
||||||
|
func RandomByWeight[Element any, Weight integer](elements []Element, weights []Weight) (Element, error) {
|
||||||
// 定义泛型零值,用于错误返回
|
// 定义泛型零值,用于错误返回
|
||||||
var zeroT T
|
var zero Element
|
||||||
|
|
||||||
// 1. 合法性校验:元素数组为空 或 概率数组与元素数组长度不匹配
|
// 1. 核心合法性校验:元素集合不能为空
|
||||||
if len(natureSet) == 0 {
|
if len(elements) == 0 {
|
||||||
return zeroT, errors.New("natureSet is empty")
|
return zero, errors.New("elements set is empty (cannot random from empty slice)")
|
||||||
}
|
|
||||||
if len(probs) == 0 || len(natureSet) != len(probs) {
|
|
||||||
// 长度不匹配,降级为等概率随机(兼容原有逻辑)
|
|
||||||
return natureSet[grand.Intn(len(natureSet))], nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 校验概率值非负,并计算总概率
|
// 2. 权重数组合法性校验:长度不匹配/为空时,降级为等概率随机(兼容原逻辑)
|
||||||
totalProb := 0
|
elemLen := len(elements)
|
||||||
for i, p := range probs {
|
if len(weights) == 0 || len(weights) != elemLen {
|
||||||
if p < 0 {
|
return elements[rand.IntN(elemLen)], nil
|
||||||
return zeroT, errors.New("invalid prob value: index " + gconv.String(i) + " (must be non-negative integer)")
|
}
|
||||||
|
|
||||||
|
// 3. 校验权重非负,并计算总权重(统一转为int64避免溢出)
|
||||||
|
var totalWeight int64
|
||||||
|
// 预转换权重为int64,避免重复类型转换
|
||||||
|
intWeights := make([]int64, elemLen)
|
||||||
|
for i, w := range weights {
|
||||||
|
intW := int64(w)
|
||||||
|
if intW < 0 {
|
||||||
|
return zero, fmt.Errorf("invalid negative weight at index %d (value: %d)", i, w)
|
||||||
}
|
}
|
||||||
totalProb += p
|
intWeights[i] = intW
|
||||||
|
totalWeight += intW
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 总概率为0,降级为等概率随机
|
// 4. 总权重为0时,降级为等概率随机
|
||||||
if totalProb == 0 {
|
if totalWeight == 0 {
|
||||||
return natureSet[grand.Intn(len(natureSet))], nil
|
return elements[rand.IntN(elemLen)], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 计算前缀和(权重随机核心逻辑)
|
// 5. 计算前缀和(权重随机核心逻辑,复用预转换的int64权重)
|
||||||
prefixSum := make([]int, len(probs))
|
prefixWeights := make([]int64, elemLen)
|
||||||
prefixSum[0] = probs[0]
|
prefixWeights[0] = intWeights[0]
|
||||||
for i := 1; i < len(probs); i++ {
|
for i := 1; i < elemLen; i++ {
|
||||||
prefixSum[i] = prefixSum[i-1] + probs[i]
|
prefixWeights[i] = prefixWeights[i-1] + intWeights[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 生成随机数匹配前缀和,返回对应元素
|
// 6. 生成随机数并匹配前缀和(用int64避免溢出)
|
||||||
randVal := grand.Intn(totalProb)
|
randomValue := grand.Intn(int(totalWeight))
|
||||||
for i, sum := range prefixSum {
|
for i, sum := range prefixWeights {
|
||||||
if randVal < sum {
|
if randomValue < int(sum) {
|
||||||
return natureSet[i], nil
|
return elements[i], nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 极端情况兜底,返回第一个元素
|
// 极端兜底:理论上不会走到这里(randomValue < totalWeight),返回第一个元素保证不panic
|
||||||
return natureSet[0], nil
|
return elements[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// integer 自定义泛型约束:匹配所有整数类型(扩展原~int的限制)
|
||||||
|
// 包含:int/int8/int16/int32/int64/uint/uint8/uint16/uint32/uint64/uintptr
|
||||||
|
type integer interface {
|
||||||
|
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
||||||
|
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************************** 函数2:封装函数(兼容string型概率,泛型)**************************
|
// ************************** 函数2:封装函数(兼容string型概率,泛型)**************************
|
||||||
@@ -89,7 +109,7 @@ func RandomByProbs[T any](natureSet []T, probs []string) (T, error) {
|
|||||||
|
|
||||||
// 1. 若string概率数组为空,直接调用核心函数(核心函数会处理降级逻辑)
|
// 1. 若string概率数组为空,直接调用核心函数(核心函数会处理降级逻辑)
|
||||||
if len(probs) == 0 {
|
if len(probs) == 0 {
|
||||||
return RandomByIntProbs(natureSet, []int{})
|
return RandomByWeight(natureSet, []int{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. string[] 转换为 int[](使用 gconv.Int 完成转换)
|
// 2. string[] 转换为 int[](使用 gconv.Int 完成转换)
|
||||||
@@ -100,5 +120,5 @@ func RandomByProbs[T any](natureSet []T, probs []string) (T, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. 调用核心函数,复用概率计算逻辑
|
// 3. 调用核心函数,复用概率计算逻辑
|
||||||
return RandomByIntProbs(natureSet, probInts)
|
return RandomByWeight(natureSet, probInts)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/common/socket/errorcode"
|
"blazing/common/socket/errorcode"
|
||||||
|
"blazing/cool"
|
||||||
"blazing/logic/service/fight"
|
"blazing/logic/service/fight"
|
||||||
"blazing/logic/service/pet"
|
"blazing/logic/service/pet"
|
||||||
"blazing/logic/service/player"
|
"blazing/logic/service/player"
|
||||||
@@ -16,5 +17,9 @@ func (h Controller) HanLiuQiang(data *pet.C2S_2608, c *player.Player) (result *f
|
|||||||
if c.ItemAdd(100245, 1) {
|
if c.ItemAdd(100245, 1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cool.Config.ServerInfo.IsVip != 0 {
|
||||||
|
c.ItemAdd(500655, 1)
|
||||||
|
}
|
||||||
return result, -1
|
return result, -1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,6 +157,9 @@ func (Controller) OnPlayerFightNpcMonster(data1 *fight.FightNpcMonsterInboundInf
|
|||||||
if !p.CanFight() {
|
if !p.CanFight() {
|
||||||
return nil, errorcode.ErrorCodes.ErrSystemError
|
return nil, errorcode.ErrorCodes.ErrSystemError
|
||||||
}
|
}
|
||||||
|
if data1.Number > 9 {
|
||||||
|
return nil, errorcode.ErrorCodes.ErrSystemError
|
||||||
|
}
|
||||||
refPet := p.OgreInfo.Data[data1.Number]
|
refPet := p.OgreInfo.Data[data1.Number]
|
||||||
if refPet.ID == 0 {
|
if refPet.ID == 0 {
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,13 @@ import (
|
|||||||
"blazing/logic/service/fight"
|
"blazing/logic/service/fight"
|
||||||
"blazing/logic/service/pet"
|
"blazing/logic/service/pet"
|
||||||
"blazing/logic/service/player"
|
"blazing/logic/service/player"
|
||||||
|
"blazing/modules/config/service"
|
||||||
"blazing/modules/player/model"
|
"blazing/modules/player/model"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/v2/util/grand"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"github.com/yudeguang/ratelimit"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetBreedInfo 获取繁殖信息协议
|
// GetBreedInfo 获取繁殖信息协议
|
||||||
@@ -18,6 +24,7 @@ func (ctl Controller) GetBreedInfo(
|
|||||||
if r == nil {
|
if r == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result = &r.Data
|
result = &r.Data
|
||||||
// TODO: 实现获取繁殖信息的具体逻辑
|
// TODO: 实现获取繁殖信息的具体逻辑
|
||||||
return result, 0
|
return result, 0
|
||||||
@@ -28,11 +35,38 @@ func (ctl Controller) GetBreedInfo(
|
|||||||
// 前端到后端
|
// 前端到后端
|
||||||
func (ctl Controller) GetBreedPet(
|
func (ctl Controller) GetBreedPet(
|
||||||
data *pet.C2S_GET_BREED_PET, playerObj *player.Player) (result *pet.S2C_GET_BREED_PET, err errorcode.ErrorCode) { //这个时候player应该是空的
|
data *pet.C2S_GET_BREED_PET, playerObj *player.Player) (result *pet.S2C_GET_BREED_PET, err errorcode.ErrorCode) { //这个时候player应该是空的
|
||||||
|
_, fPet, found := playerObj.FindPet(data.MaleCatchTime)
|
||||||
|
if !found {
|
||||||
|
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||||
|
}
|
||||||
|
if fPet.Gender != 1 {
|
||||||
|
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||||
|
}
|
||||||
|
if fPet.Generation > 9 {
|
||||||
|
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||||
|
}
|
||||||
result = &pet.S2C_GET_BREED_PET{}
|
result = &pet.S2C_GET_BREED_PET{}
|
||||||
// TODO: 实现获取可繁殖雌性精灵列表的逻辑
|
|
||||||
|
MPETS := service.NewEggService().GetData(fPet.ID)
|
||||||
|
|
||||||
// 这里只是示例,实际应该根据雄性精灵的catchTime查找可繁殖的雌性精灵
|
// 这里只是示例,实际应该根据雄性精灵的catchTime查找可繁殖的雌性精灵
|
||||||
for _, v := range playerObj.Info.PetList {
|
for _, v := range playerObj.Info.PetList {
|
||||||
|
if v.Level < 50 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
//不是雌性
|
||||||
|
if v.Gender != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if v.Generation > 9 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, ok := lo.Find(MPETS, func(item int32) bool {
|
||||||
|
return item == int32(v.ID)
|
||||||
|
})
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
// 如果是雌性精灵,且可以繁殖,则添加到列表
|
// 如果是雌性精灵,且可以繁殖,则添加到列表
|
||||||
result.FemaleList = append(result.FemaleList, v.CatchTime)
|
result.FemaleList = append(result.FemaleList, v.CatchTime)
|
||||||
}
|
}
|
||||||
@@ -44,6 +78,11 @@ func (ctl Controller) GetBreedPet(
|
|||||||
// 前端到后端
|
// 前端到后端
|
||||||
func (ctl Controller) StartBreed(
|
func (ctl Controller) StartBreed(
|
||||||
data *pet.C2S_START_BREED, player *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
data *pet.C2S_START_BREED, player *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
||||||
|
|
||||||
|
if !player.GetCoins(1000) {
|
||||||
|
return result, errorcode.ErrorCodes.ErrSunDouInsufficient10016
|
||||||
|
}
|
||||||
|
player.Info.Coins -= 1000
|
||||||
_, MalePet, found := player.FindPet(data.Male)
|
_, MalePet, found := player.FindPet(data.Male)
|
||||||
if !found {
|
if !found {
|
||||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||||
@@ -58,6 +97,16 @@ func (ctl Controller) StartBreed(
|
|||||||
if !r {
|
if !r {
|
||||||
return nil, errorcode.ErrorCodes.ErrCannotPerformAction
|
return nil, errorcode.ErrorCodes.ErrCannotPerformAction
|
||||||
}
|
}
|
||||||
|
MalePet.Generation++
|
||||||
|
|
||||||
|
Female.Generation++
|
||||||
|
|
||||||
|
r1 := grand.Meet(1, 2)
|
||||||
|
if r1 {
|
||||||
|
MalePet.Gender = 0
|
||||||
|
} else {
|
||||||
|
Female.Gender = 0
|
||||||
|
}
|
||||||
return result, 0
|
return result, 0
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -75,22 +124,36 @@ func (ctl Controller) GetEggList(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range r.EggList {
|
result.EggList = append(result.EggList, r.EggList...)
|
||||||
result.EggList = append(result.EggList, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, 0
|
return result, 0
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var limiter *ratelimit.Rule = ratelimit.NewRule()
|
||||||
|
|
||||||
|
// 简单规则案例
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
//步骤二:增加一条或者多条规则组成复合规则,此复合规则必须至少包含一条规则
|
||||||
|
limiter.AddRule(time.Second*1, 1)
|
||||||
|
//步骤三:调用函数判断某用户是否允许访问 allow:= r.AllowVisit(user)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// EffectHatch 精灵蛋互动协议
|
// EffectHatch 精灵蛋互动协议
|
||||||
// 前端到后端
|
// 前端到后端
|
||||||
func (ctl Controller) EffectHatch(
|
func (ctl Controller) EffectHatch(
|
||||||
data *pet.C2S_EFFECT_HATCH, playerObj *player.Player) (result *pet.S2C_EFFECT_HATCH, err errorcode.ErrorCode) {
|
data *pet.C2S_EFFECT_HATCH, playerObj *player.Player) (result *pet.S2C_EFFECT_HATCH, err errorcode.ErrorCode) {
|
||||||
|
if !limiter.AllowVisit(data.Head.UserID) {
|
||||||
|
return nil, errorcode.ErrorCodes.ErrCannotPerformAction
|
||||||
|
}
|
||||||
result = &pet.S2C_EFFECT_HATCH{}
|
result = &pet.S2C_EFFECT_HATCH{}
|
||||||
// TODO: 实现精灵蛋互动逻辑,根据互动ID更新亲密度
|
tt := uint32(grand.N(1, 4))
|
||||||
result.Intimacy = 1 // 悲伤
|
if tt == data.Index {
|
||||||
|
result.Intimacy = playerObj.Service.Egg.EffectHatch()
|
||||||
|
}
|
||||||
|
|
||||||
return result, 0
|
return result, 0
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -102,6 +165,10 @@ func (ctl Controller) StartHatch(
|
|||||||
|
|
||||||
// TODO: 实现开始孵化精灵蛋的具体逻辑
|
// TODO: 实现开始孵化精灵蛋的具体逻辑
|
||||||
result = &pet.S2C_START_HATCH{}
|
result = &pet.S2C_START_HATCH{}
|
||||||
|
r := playerObj.Service.Egg.StartEgg(data.OwnerID, data.EggCatchTime)
|
||||||
|
if !r {
|
||||||
|
return nil, errorcode.ErrorCodes.ErrCannotPerformAction
|
||||||
|
}
|
||||||
return result, 0
|
return result, 0
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -113,8 +180,12 @@ func (ctl Controller) GetHatchPet(
|
|||||||
|
|
||||||
result = &pet.S2C_GET_HATCH_PET{}
|
result = &pet.S2C_GET_HATCH_PET{}
|
||||||
// TODO: 实现获得孵化精灵的具体逻辑,这里暂时返回默认值
|
// TODO: 实现获得孵化精灵的具体逻辑,这里暂时返回默认值
|
||||||
result.PetID = 0
|
|
||||||
result.CatchTime = 0
|
r := playerObj.Service.Egg.GetEgg()
|
||||||
|
playerObj.Service.Pet.PetAdd(r)
|
||||||
|
|
||||||
|
result.PetID = r.ID
|
||||||
|
result.CatchTime = r.CatchTime
|
||||||
return result, 0
|
return result, 0
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -247,21 +247,24 @@ func (f *FightC) collectPlayerActions(ourID, oppID uint32) map[uint32]action.Bat
|
|||||||
//fmt.Println("玩家执行动作:", pid, paction.Priority())
|
//fmt.Println("玩家执行动作:", pid, paction.Priority())
|
||||||
|
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
f.handleTimeout(ourID, oppID, actions)
|
r := f.handleTimeout(ourID, oppID, actions)
|
||||||
return actions
|
if r {
|
||||||
|
return actions
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
// 超时处理逻辑
|
// 超时处理逻辑
|
||||||
func (f *FightC) handleTimeout(ourID, oppID uint32, actions map[uint32]action.BattleActionI) {
|
func (f *FightC) handleTimeout(ourID, oppID uint32, actions map[uint32]action.BattleActionI) bool {
|
||||||
|
|
||||||
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
|
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
|
||||||
// f.WinnerId = 0
|
// f.WinnerId = 0
|
||||||
|
|
||||||
go f.Our.GetAction() //boss出手后获取出招
|
go f.Our.GetAction() //boss出手后获取出招
|
||||||
|
return false
|
||||||
} else {
|
} else {
|
||||||
var pid uint32
|
var pid uint32
|
||||||
for _, pid = range []uint32{ourID, oppID} {
|
for _, pid = range []uint32{ourID, oppID} {
|
||||||
@@ -275,6 +278,7 @@ func (f *FightC) handleTimeout(ourID, oppID uint32, actions map[uint32]action.Ba
|
|||||||
f.WinnerId = f.GetInputByPlayer(f.getPlayerByID(pid), false).Player.GetInfo().UserID
|
f.WinnerId = f.GetInputByPlayer(f.getPlayerByID(pid), false).Player.GetInfo().UserID
|
||||||
f.Reason = info.BattleOverReason.PlayerOVerTime
|
f.Reason = info.BattleOverReason.PlayerOVerTime
|
||||||
f.closefight = true
|
f.closefight = true
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ const (
|
|||||||
// Egg 性别配置模型(替换原宠物融合配方模型)
|
// Egg 性别配置模型(替换原宠物融合配方模型)
|
||||||
type Egg struct {
|
type Egg struct {
|
||||||
*cool.Model // 保留通用Model(ID/创建时间/更新时间等)
|
*cool.Model // 保留通用Model(ID/创建时间/更新时间等)
|
||||||
//雄性
|
|
||||||
MalePetIDs []int32 `gorm:"type:int[];comment:'雄性宠物ID列表(如:[1001,1002])'" json:"male_pet_ids"`
|
|
||||||
//雌性
|
//雌性
|
||||||
|
MalePetIDs []int32 `gorm:"type:int[];comment:'雄性宠物ID列表(如:[1001,1002])'" json:"male_pet_ids"`
|
||||||
|
//雄性
|
||||||
FemalePetIDs []int32 `gorm:"type:int[];comment:'雌性宠物ID列表(如:[1001,1002])'" json:"female_pet_ids"`
|
FemalePetIDs []int32 `gorm:"type:int[];comment:'雌性宠物ID列表(如:[1001,1002])'" json:"female_pet_ids"`
|
||||||
//子代指定性别配置表名
|
//子代指定性别配置表名
|
||||||
OutputMons []int32 `gorm:"type:int[];not null;comment:'宠物类型ID'" json:"pet_type_id"`
|
OutputMons []int32 `gorm:"type:int[];not null;comment:'宠物类型ID'" json:"pet_type_id"`
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"blazing/common/utils"
|
||||||
"blazing/cool"
|
"blazing/cool"
|
||||||
"blazing/modules/config/model"
|
"blazing/modules/config/model"
|
||||||
)
|
)
|
||||||
@@ -20,13 +21,36 @@ func NewEggService() *EggService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *EggService) Get(id uint32) *model.Egg {
|
func (s *EggService) GetData(p1 uint32) []int32 {
|
||||||
if id == 0 {
|
//cacheKey := strings.Join([]string{fmt.Sprintf("%d", p1), fmt.Sprintf("%d", p2)}, ":")
|
||||||
return nil
|
m := dbm(s.Model)
|
||||||
}
|
|
||||||
var item *model.Egg
|
|
||||||
dbm(s.Model).Where("id", id).Scan(&item)
|
|
||||||
|
|
||||||
return item
|
var pet []model.Egg //一个特性应该是唯一的,但是我们要获取默认随机特性
|
||||||
|
m.Wheref(`male_pet_ids @> ARRAY[?]::integer[]`, p1).
|
||||||
|
Where("is_enable", 1).Scan(&pet)
|
||||||
|
var petIDs []int32
|
||||||
|
for _, p := range pet {
|
||||||
|
petIDs = append(petIDs, p.FemalePetIDs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return petIDs
|
||||||
|
|
||||||
|
}
|
||||||
|
func (s *EggService) GetResult(m, f uint32) uint32 {
|
||||||
|
//cacheKey := strings.Join([]string{fmt.Sprintf("%d", p1), fmt.Sprintf("%d", p2)}, ":")
|
||||||
|
md := dbm(s.Model)
|
||||||
|
|
||||||
|
var pet *model.Egg //一个特性应该是唯一的,但是我们要获取默认随机特性
|
||||||
|
md.Wheref(`male_pet_ids @> ARRAY[?]::integer[]`, m).
|
||||||
|
Wheref(`female_pet_ids @> ARRAY[?]::integer[]`, f).
|
||||||
|
Where("is_enable", 1).Scan(&pet)
|
||||||
|
if pet != nil {
|
||||||
|
|
||||||
|
t, _ := utils.RandomByWeight(pet.OutputMons, pet.Probs)
|
||||||
|
return uint32(t)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func (s *PetFusionService) Data(p1, p2, rand uint32) uint32 {
|
|||||||
props = append(props, int(v.Probability))
|
props = append(props, int(v.Probability))
|
||||||
|
|
||||||
}
|
}
|
||||||
t,_:=utils.RandomByIntProbs(pets, props)
|
t, _ := utils.RandomByWeight(pets, props)
|
||||||
return uint32(t)
|
return uint32(t)
|
||||||
//说明是失败,直接返回失败
|
//说明是失败,直接返回失败
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ type EggInfo struct {
|
|||||||
EggID uint32 `json:"eggID"` // 精灵蛋ID
|
EggID uint32 `json:"eggID"` // 精灵蛋ID
|
||||||
MalePetID uint32 `json:"male"` // 雄性精灵ID
|
MalePetID uint32 `json:"male"` // 雄性精灵ID
|
||||||
FeMalePetID uint32 `json:"female"` // 雌性精灵ID
|
FeMalePetID uint32 `json:"female"` // 雌性精灵ID
|
||||||
|
//ShinyCode uint32 `struc:"skip"` //返回记录
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName 返回表名
|
// TableName 返回表名
|
||||||
|
|||||||
@@ -422,6 +422,9 @@ func GenPetInfo(
|
|||||||
dv, natureId, abilityTypeEnum, level int, shinyid []data.GlowFilter,
|
dv, natureId, abilityTypeEnum, level int, shinyid []data.GlowFilter,
|
||||||
gen int,
|
gen int,
|
||||||
) *PetInfo {
|
) *PetInfo {
|
||||||
|
if id == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// 创建随机源
|
// 创建随机源
|
||||||
//rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
//rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
|
||||||
@@ -447,6 +450,9 @@ func GenPetInfo(
|
|||||||
if gen == -1 {
|
if gen == -1 {
|
||||||
|
|
||||||
p.Gender = grand.N(1, 4)
|
p.Gender = grand.N(1, 4)
|
||||||
|
if cool.Config.ServerInfo.IsVip != 0 {
|
||||||
|
p.Gender = grand.N(1, 2)
|
||||||
|
}
|
||||||
if p.Gender == 3 || p.Gender == 4 {
|
if p.Gender == 3 || p.Gender == 4 {
|
||||||
p.Gender = 0
|
p.Gender = 0
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"blazing/common/utils"
|
||||||
"blazing/cool"
|
"blazing/cool"
|
||||||
|
"blazing/modules/config/service"
|
||||||
"blazing/modules/player/model"
|
"blazing/modules/player/model"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/v2/util/grand"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EggService struct {
|
type EggService struct {
|
||||||
@@ -23,6 +27,16 @@ func NewEggService(id uint32) *EggService {
|
|||||||
func (s *EggService) Get() (out *model.Egg) {
|
func (s *EggService) Get() (out *model.Egg) {
|
||||||
|
|
||||||
s.TestModel(s.Model).Scan(&out)
|
s.TestModel(s.Model).Scan(&out)
|
||||||
|
if out != nil {
|
||||||
|
BreedLeftTime := int64(out.Data.StartTime+out.CurEgg.EggID*uint32(time.Hour/1000000000)) - (time.Now().Unix())
|
||||||
|
//判断是否繁殖完成
|
||||||
|
if BreedLeftTime < 0 && out.Data.HatchState == 1 {
|
||||||
|
out.Data.HatchState = 2
|
||||||
|
} else {
|
||||||
|
out.Data.HatchLeftTime = uint32(BreedLeftTime)
|
||||||
|
}
|
||||||
|
s.TestModel(s.Model).Save(out)
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -33,16 +47,124 @@ func (s *EggService) StartBreed(m, f *model.PetInfo) bool {
|
|||||||
s.TestModel(s.Model).Scan(&tt)
|
s.TestModel(s.Model).Scan(&tt)
|
||||||
if tt == nil {
|
if tt == nil {
|
||||||
tt = &model.Egg{}
|
tt = &model.Egg{}
|
||||||
|
tt.IsVip = cool.Config.ServerInfo.IsVip
|
||||||
|
}
|
||||||
|
//如果正在孵化中或者蛋列表超过4个了,就不能再开始新的繁殖了
|
||||||
|
if len(tt.EggList) > 4 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
cureff := model.EggInfo{FeMalePetID: f.ID, MalePetID: m.ID}
|
||||||
|
|
||||||
|
cureff.EggCatchTime = uint32(time.Now().Unix())
|
||||||
|
|
||||||
|
cureff.EggID = (uint32(m.Generation) + uint32(f.Generation)) / 2
|
||||||
|
if cureff.EggID == 0 {
|
||||||
|
cureff.EggID = 1
|
||||||
|
}
|
||||||
|
cureff.OwnerID = uint32(s.userid)
|
||||||
|
|
||||||
|
cureff.FeMalePetID = f.ID
|
||||||
|
|
||||||
|
cureff.MalePetID = m.ID
|
||||||
|
tt.PlayerID = uint64(s.userid)
|
||||||
|
//tt.CurEgg = cureff
|
||||||
|
tt.EggList = append(tt.EggList, cureff)
|
||||||
|
|
||||||
|
s.TestModel(s.Model).Save(tt)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
func (s *EggService) StartEgg(owner, eggc uint32) bool {
|
||||||
|
|
||||||
|
var tt *model.Egg
|
||||||
|
s.TestModel(s.Model).Scan(&tt)
|
||||||
|
if tt == nil {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
if tt.Data.HatchState != 0 {
|
if tt.Data.HatchState != 0 {
|
||||||
return false
|
return false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index, v, ok := utils.FindWithIndex(tt.EggList, func(item model.EggInfo) bool {
|
||||||
|
return item.EggCatchTime == eggc
|
||||||
|
})
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
tt.EggList = append(tt.EggList[:index], tt.EggList[index+1:]...) //删除精灵蛋
|
||||||
tt.Data.StartTime = uint32(time.Now().Unix())
|
tt.Data.StartTime = uint32(time.Now().Unix())
|
||||||
|
|
||||||
tt.Data.HatchState = 1
|
tt.Data.HatchState = 1
|
||||||
tt.Data.FeMalePetCatchTime = f.CatchTime
|
|
||||||
tt.Data.MalePetCatchTime = m.CatchTime
|
tt.Data.EggID = v.EggID
|
||||||
tt.Data.FeMalePetID = f.ID
|
|
||||||
tt.Data.MalePetID = m.ID
|
tt.Data.FeMalePetID = v.FeMalePetID
|
||||||
|
|
||||||
|
tt.Data.MalePetID = v.MalePetID
|
||||||
|
|
||||||
|
tt.PlayerID = uint64(s.userid)
|
||||||
|
tt.CurEgg = *v
|
||||||
|
|
||||||
|
tt.Data.Intimacy = 1
|
||||||
|
s.TestModel(s.Model).Save(tt)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
}
|
||||||
|
func (s *EggService) EffectHatch() uint32 {
|
||||||
|
|
||||||
|
var tt *model.Egg
|
||||||
|
s.TestModel(s.Model).Scan(&tt)
|
||||||
|
if tt == nil {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if tt.Data.HatchState != 1 {
|
||||||
|
return 1
|
||||||
|
|
||||||
|
}
|
||||||
|
tt.Data.Intimacy += 1
|
||||||
|
if tt.Data.Intimacy > 5 {
|
||||||
|
tt.Data.Intimacy = 5
|
||||||
|
}
|
||||||
|
s.TestModel(s.Model).Save(tt)
|
||||||
|
return tt.Data.Intimacy
|
||||||
|
}
|
||||||
|
func (s *EggService) GetEgg() *model.PetInfo {
|
||||||
|
|
||||||
|
var tt *model.Egg
|
||||||
|
s.TestModel(s.Model).Scan(&tt)
|
||||||
|
if tt == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if tt.Data.HatchState != 2 {
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
if tt.CurEgg.EggCatchTime == 0 {
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
mpets := service.NewEggService().GetResult(tt.CurEgg.MalePetID, tt.CurEgg.FeMalePetID)
|
||||||
|
if mpets == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dv := grand.N(int(tt.Data.Intimacy+tt.CurEgg.EggID*2), 31)
|
||||||
|
p := model.GenPetInfo(int(mpets), dv, -1, 0, 1, nil, -1)
|
||||||
|
shinycont := 0
|
||||||
|
|
||||||
|
if mpets != tt.CurEgg.MalePetID && mpets != tt.CurEgg.FeMalePetID {
|
||||||
|
shinycont = int(tt.CurEgg.EggID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if grand.Meet(shinycont, 100) {
|
||||||
|
p.FixShiny()
|
||||||
|
}
|
||||||
|
//直接覆盖当前蛋
|
||||||
|
tt.Data.HatchState = 0
|
||||||
|
p.Generation = uint16(tt.CurEgg.EggID) + 1
|
||||||
|
tt.CurEgg = model.EggInfo{}
|
||||||
|
s.TestModel(s.Model).Save(tt)
|
||||||
|
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ func (s *RoomService) Get(userid uint32) model.BaseHouseEx {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (s *RoomService) Set(id []model.FitmentShowInfo) {
|
func (s *RoomService) Set(id []model.FitmentShowInfo) {
|
||||||
//todo待测试
|
//todo待测试
|
||||||
if cool.Config.ServerInfo.IsVip != 0 {
|
if cool.Config.ServerInfo.IsVip != 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user