195 lines
4.8 KiB
Go
195 lines
4.8 KiB
Go
package controller
|
|
|
|
import (
|
|
"blazing/common/data/xmlres"
|
|
"blazing/common/socket/errorcode"
|
|
"blazing/logic/service/pet"
|
|
"blazing/logic/service/player"
|
|
"blazing/modules/config/service"
|
|
"blazing/modules/player/model"
|
|
|
|
"github.com/alpacahq/alpacadecimal"
|
|
"github.com/gogf/gf/v2/util/grand"
|
|
)
|
|
|
|
const (
|
|
petFusionCost = 1000
|
|
petFusionKeepAuxItemID = 300043
|
|
petFusionFailureItemID = 300044
|
|
petFusionSoulID = 1000017
|
|
)
|
|
|
|
// PetFusion 处理控制器请求。
|
|
func (h Controller) PetFusion(data *C2S_PetFusion, c *player.Player) (result *pet.PetFusionInfo, err errorcode.ErrorCode) {
|
|
result = &pet.PetFusionInfo{
|
|
SoulID: petFusionSoulID,
|
|
}
|
|
|
|
if data.Mcatchtime == data.Auxcatchtime {
|
|
return result, errorcode.ErrorCodes.ErrPokemonNotFusionReady
|
|
}
|
|
|
|
_, masterPet, ok := c.FindPet(data.Mcatchtime)
|
|
if !ok {
|
|
return result, errorcode.ErrorCodes.ErrPokemonNotFusionReady2
|
|
}
|
|
masterCfg, ok := xmlres.PetMAP[int(masterPet.ID)]
|
|
if !ok || masterCfg.FuseMaster == 0 {
|
|
return result, errorcode.ErrorCodes.ErrPokemonNotFusionReady3
|
|
}
|
|
|
|
_, auxPet, ok := c.FindPet(data.Auxcatchtime)
|
|
if !ok {
|
|
return result, errorcode.ErrorCodes.ErrPokemonNotFusionReady2
|
|
}
|
|
auxCfg, ok := xmlres.PetMAP[int(auxPet.ID)]
|
|
if !ok || auxCfg.FuseSub == 0 {
|
|
return result, errorcode.ErrorCodes.ErrPokemonNotFusionReady3
|
|
}
|
|
|
|
materialCounts := collectItemCounts(data.Item1[:])
|
|
if !hasEnoughItems(c, materialCounts) {
|
|
return result, errorcode.ErrorCodes.ErrInsufficientItems
|
|
}
|
|
|
|
materialService := service.NewPetFusionMaterialService()
|
|
effect := int(materialService.Data(data.Item1))
|
|
if effect == 0 {
|
|
return result, errorcode.ErrorCodes.ErrSpiritOrbNotExists
|
|
}
|
|
|
|
fusionService := service.NewPetFusionService()
|
|
resultPetID := int(fusionService.Data(masterPet.ID, auxPet.ID, masterPet.Level+auxPet.Level))
|
|
|
|
if !c.GetCoins(petFusionCost) {
|
|
return result, errorcode.ErrorCodes.ErrSunDouInsufficient10016
|
|
}
|
|
|
|
if resultPetID == 0 {
|
|
failedAux := *auxPet
|
|
if auxPet.Level > 5 {
|
|
failedAux.Downgrade(auxPet.Level - 5)
|
|
} else {
|
|
failedAux.Downgrade(1)
|
|
}
|
|
txResult, errCode := c.Service.PetFusionTx(
|
|
*c.Info,
|
|
data.Mcatchtime,
|
|
data.Auxcatchtime,
|
|
materialCounts,
|
|
data.GoldItem1[:],
|
|
petFusionKeepAuxItemID,
|
|
petFusionFailureItemID,
|
|
petFusionCost,
|
|
nil,
|
|
&failedAux,
|
|
)
|
|
if errCode != 0 {
|
|
return result, errCode
|
|
}
|
|
c.Info.Coins -= petFusionCost
|
|
if txResult.CostItemUsed {
|
|
result.CostItemFlag = 1
|
|
} else if txResult.UpdatedAux != nil {
|
|
*auxPet = *txResult.UpdatedAux
|
|
}
|
|
return &pet.PetFusionInfo{}, 0
|
|
}
|
|
|
|
natureID := int32(-1)
|
|
if auxPet.Nature == masterPet.Nature {
|
|
natureID = int32(auxPet.Nature)
|
|
}
|
|
|
|
dv1 := alpacadecimal.NewFromInt(2).Div(alpacadecimal.NewFromInt(3)).Mul(alpacadecimal.NewFromInt(int64(masterPet.Dv)))
|
|
dv2 := alpacadecimal.NewFromInt(1).Div(alpacadecimal.NewFromInt(3)).Mul(alpacadecimal.NewFromInt(int64(auxPet.Dv)))
|
|
dv := dv1.Add(dv2).Add(alpacadecimal.NewFromInt(1)).IntPart()
|
|
newPet := model.GenPetInfo(resultPetID, int(dv), int(natureID), effect, 1, nil, -1)
|
|
newPet.OldCatchTime = masterPet.CatchTime
|
|
|
|
shinyChance := 1
|
|
if masterPet.IsShiny() || auxPet.IsShiny() {
|
|
shinyChance = 50
|
|
}
|
|
if masterPet.IsShiny() && auxPet.IsShiny() {
|
|
shinyChance = 100
|
|
}
|
|
if grand.Meet(shinyChance, 100) {
|
|
newPet.RandomByWeightShiny()
|
|
}
|
|
|
|
txResult, errCode := c.Service.PetFusionTx(
|
|
*c.Info,
|
|
data.Mcatchtime,
|
|
data.Auxcatchtime,
|
|
materialCounts,
|
|
data.GoldItem1[:],
|
|
petFusionKeepAuxItemID,
|
|
petFusionFailureItemID,
|
|
petFusionCost,
|
|
newPet,
|
|
nil,
|
|
)
|
|
if errCode != 0 {
|
|
return result, errCode
|
|
}
|
|
|
|
c.Info.Coins -= petFusionCost
|
|
if txResult.CostItemUsed {
|
|
result.CostItemFlag = 1
|
|
} else {
|
|
removePetFromPlayerInfo(c, data.Auxcatchtime)
|
|
}
|
|
removePetFromPlayerInfo(c, data.Mcatchtime)
|
|
|
|
if txResult.NewPet == nil {
|
|
return result, errorcode.ErrorCodes.ErrSystemError
|
|
}
|
|
c.Info.PetList = append(c.Info.PetList, *txResult.NewPet)
|
|
|
|
result.ObtainTime = txResult.NewPet.CatchTime
|
|
result.StarterCpTm = txResult.NewPet.ID
|
|
return result, 0
|
|
}
|
|
|
|
func collectItemCounts(itemIDs []uint32) map[uint32]int {
|
|
counts := make(map[uint32]int, len(itemIDs))
|
|
for _, itemID := range itemIDs {
|
|
counts[itemID]++
|
|
}
|
|
return counts
|
|
}
|
|
|
|
func hasEnoughItems(c *player.Player, itemCounts map[uint32]int) bool {
|
|
if len(itemCounts) == 0 {
|
|
return true
|
|
}
|
|
|
|
itemIDs := make([]uint32, 0, len(itemCounts))
|
|
for itemID := range itemCounts {
|
|
itemIDs = append(itemIDs, itemID)
|
|
}
|
|
|
|
hadItems := c.Service.Item.CheakItemM(itemIDs...)
|
|
ownedCounts := make(map[uint32]int64, len(hadItems))
|
|
for _, item := range hadItems {
|
|
ownedCounts[item.ItemId] = item.ItemCnt
|
|
}
|
|
|
|
for itemID, need := range itemCounts {
|
|
if ownedCounts[itemID] < int64(need) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func removePetFromPlayerInfo(c *player.Player, catchTime uint32) {
|
|
index, _, ok := c.FindPet(catchTime)
|
|
if !ok {
|
|
return
|
|
}
|
|
c.Info.PetList = append(c.Info.PetList[:index], c.Info.PetList[index+1:]...)
|
|
}
|