feat(fight): 新增疲惫状态并优化睡眠状态机制 - 实现疲惫状态(StatusTired),仅限制攻击技能,允许属性技能正常使用 - 重构睡眠状态,改为在被攻击且未miss时立即解除,而非技能使用后 - 修复寄生种子效果触发时机,改为回合开始时触发 - 调整寄生效果的目标为技能施放者而非对手 fix(fight): 修正战斗回合逻辑和技能持续时间处理 - 修复Effect2194中状态添加函数调用,使用带时间参数的版本 - 修正Effect13中技能持续时间计算,避免额外减1的问题 - 优化回合处理逻辑,当双方都未出手时跳过动作阶段 refactor(cdk): 重构CDK配置结构和服务器冠名功能 - 将CDKConfig中的CDKType字段重命名为Type以符合GORM映射 - 优化UseServerNamingCDK方法的上下文处理逻辑 - 修复服务器冠名CDK使用时的类型检查条件 feat(player): 完善宠物经验系统和CDK兑换功能 - 增强AddPetExp方法,处理宠物等级达到100级的情况 - 添加查询当前账号有效期内服务器冠名信息的API接口 - 实现服务器服务相关的数据模型和查询方法 fix(task): 任务查询支持启用和未启用状态 - 修改任务服务中的Get、GetDaily、GetWeek方法 - 当启用状态下无结果时,自动查询未启用状态的任务配置 ```
This commit is contained in:
@@ -41,6 +41,7 @@ func (Controller) PlayerFightBoss(req *ChallengeBossInboundInfo, p *player.Playe
|
|||||||
if err != 0 {
|
if err != 0 {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
leadMonster := &monsterInfo.PetList[0]
|
||||||
|
|
||||||
p.Fightinfo.Status = fightinfo.BattleMode.FIGHT_WITH_NPC
|
p.Fightinfo.Status = fightinfo.BattleMode.FIGHT_WITH_NPC
|
||||||
p.Fightinfo.Mode = resolveMapNodeFightMode(mapNode)
|
p.Fightinfo.Mode = resolveMapNodeFightMode(mapNode)
|
||||||
@@ -52,12 +53,7 @@ func (Controller) PlayerFightBoss(req *ChallengeBossInboundInfo, p *player.Playe
|
|||||||
|
|
||||||
var fightC *fight.FightC
|
var fightC *fight.FightC
|
||||||
fightC, err = startMapBossFight(mapNode, p, ai, func(foi model.FightOverInfo) {
|
fightC, err = startMapBossFight(mapNode, p, ai, func(foi model.FightOverInfo) {
|
||||||
if mapNode.WinBonusID == 0 {
|
handleMapBossFightRewards(p, fightC, foi, mapNode, bossConfigs[0], leadMonster)
|
||||||
return
|
|
||||||
}
|
|
||||||
if shouldGrantBossWinBonus(fightC, p.Info.UserID, bossConfigs[0], foi) {
|
|
||||||
p.SptCompletedTask(mapNode.WinBonusID, 1)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -234,6 +230,95 @@ func shouldGrantBossWinBonus(fightC *fight.FightC, playerID uint32, bossConfig c
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleMapBossFightRewards(
|
||||||
|
p *player.Player,
|
||||||
|
fightC *fight.FightC,
|
||||||
|
foi model.FightOverInfo,
|
||||||
|
mapNode *configmodel.MapNode,
|
||||||
|
bossConfig configmodel.BossConfig,
|
||||||
|
leadMonster *model.PetInfo,
|
||||||
|
) {
|
||||||
|
rewards := grantMonsterFightRewards(p, foi, leadMonster)
|
||||||
|
if mapNode != nil && mapNode.WinBonusID != 0 && shouldGrantBossWinBonus(fightC, p.Info.UserID, bossConfig, foi) {
|
||||||
|
appendBossTaskReward(p, mapNode.WinBonusID, 1, rewards)
|
||||||
|
}
|
||||||
|
if rewards != nil && rewards.HasReward() {
|
||||||
|
p.SendPackCmd(8004, rewards)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func grantMonsterFightRewards(p *player.Player, foi model.FightOverInfo, monster *model.PetInfo) *fightinfo.S2C_GET_BOSS_MONSTER {
|
||||||
|
rewards := &fightinfo.S2C_GET_BOSS_MONSTER{}
|
||||||
|
if p == nil || monster == nil || foi.Reason != 0 || foi.WinnerId != p.Info.UserID || !p.CanGet() {
|
||||||
|
return rewards
|
||||||
|
}
|
||||||
|
|
||||||
|
petCfg, ok := xmlres.PetMAP[int(monster.ID)]
|
||||||
|
if !ok {
|
||||||
|
return rewards
|
||||||
|
}
|
||||||
|
|
||||||
|
exp := uint32(petCfg.YieldingExp) * monster.Level / 7
|
||||||
|
addlevel, poolevel := p.CanGetExp()
|
||||||
|
addexp := gconv.Float32(addlevel * gconv.Float32(exp))
|
||||||
|
poolexp := gconv.Float32(poolevel) * gconv.Float32(exp)
|
||||||
|
|
||||||
|
p.ItemAdd(3, int64(poolexp+addexp))
|
||||||
|
rewards.AddItem(rewardItemExpPool, uint32(poolexp))
|
||||||
|
p.AddPetExp(foi.Winpet, int64(addexp))
|
||||||
|
|
||||||
|
if p.CanGetItem() {
|
||||||
|
itemID := p.GetSpace().GetDrop()
|
||||||
|
if itemID != 0 {
|
||||||
|
count := uint32(grand.N(1, 2))
|
||||||
|
if p.ItemAdd(itemID, int64(count)) {
|
||||||
|
rewards.AddItem(uint32(itemID), count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
petType := int64(petCfg.Type)
|
||||||
|
if monster.IsShiny() && p.CanGetXUAN() && petType < 16 {
|
||||||
|
xuanID := uint32(400686 + petType)
|
||||||
|
count := uint32(grand.N(1, 2))
|
||||||
|
if p.ItemAdd(int64(xuanID), int64(count)) {
|
||||||
|
rewards.AddItem(xuanID, count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if foi.Winpet != nil {
|
||||||
|
foi.Winpet.AddEV(petCfg.YieldingEVValues)
|
||||||
|
}
|
||||||
|
return rewards
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendBossTaskReward(p *player.Player, taskID int, outState int, rewards *fightinfo.S2C_GET_BOSS_MONSTER) {
|
||||||
|
if p == nil || rewards == nil || !p.IsLogin || taskID <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if p.Info.GetTask(taskID) == model.Completed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
granted, err := p.ApplyTaskCompletion(uint32(taskID), outState, nil)
|
||||||
|
if err != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Info.SetTask(taskID, model.Completed)
|
||||||
|
rewards.BonusID = uint32(taskID)
|
||||||
|
if granted == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if granted.Pet != nil {
|
||||||
|
rewards.PetID = granted.Pet.ID
|
||||||
|
rewards.CaptureTm = granted.Pet.CatchTime
|
||||||
|
}
|
||||||
|
for _, item := range granted.Items {
|
||||||
|
rewards.AddItemInfo(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func buildNpcMonsterInfo(refPet player.OgrePetInfo, mapID uint32) (*model.PetInfo, *model.PlayerInfo, errorcode.ErrorCode) {
|
func buildNpcMonsterInfo(refPet player.OgrePetInfo, mapID uint32) (*model.PetInfo, *model.PlayerInfo, errorcode.ErrorCode) {
|
||||||
if refPet.ID == 0 {
|
if refPet.ID == 0 {
|
||||||
return nil, nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
return nil, nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||||
@@ -269,46 +354,8 @@ func buildNpcMonsterInfo(refPet player.OgrePetInfo, mapID uint32) (*model.PetInf
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleNpcFightRewards(p *player.Player, foi model.FightOverInfo, monster *model.PetInfo) {
|
func handleNpcFightRewards(p *player.Player, foi model.FightOverInfo, monster *model.PetInfo) {
|
||||||
if foi.Reason != 0 || foi.WinnerId != p.Info.UserID || !p.CanGet() {
|
rewards := grantMonsterFightRewards(p, foi, monster)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
petCfg, ok := xmlres.PetMAP[int(monster.ID)]
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
exp := uint32(petCfg.YieldingExp) * monster.Level / 7
|
|
||||||
addlevel, poolevel := p.CanGetExp()
|
|
||||||
addexp := gconv.Float32(addlevel * gconv.Float32(exp))
|
|
||||||
poolexp := gconv.Float32(poolevel) * gconv.Float32(exp)
|
|
||||||
rewards := &fightinfo.S2C_GET_BOSS_MONSTER{}
|
|
||||||
|
|
||||||
p.ItemAdd(3, int64(poolexp+addexp))
|
|
||||||
rewards.AddItem(rewardItemExpPool, uint32(poolexp))
|
|
||||||
p.AddPetExp(foi.Winpet, int64(addexp))
|
|
||||||
|
|
||||||
if p.CanGetItem() {
|
|
||||||
itemID := p.GetSpace().GetDrop()
|
|
||||||
if itemID != 0 {
|
|
||||||
count := uint32(grand.N(1, 2))
|
|
||||||
if p.ItemAdd(itemID, int64(count)) {
|
|
||||||
rewards.AddItem(uint32(itemID), count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
petType := int64(petCfg.Type)
|
|
||||||
if monster.IsShiny() && p.CanGetXUAN() && petType < 16 {
|
|
||||||
xuanID := uint32(400686 + petType)
|
|
||||||
count := uint32(grand.N(1, 2))
|
|
||||||
if p.ItemAdd(int64(xuanID), int64(count)) {
|
|
||||||
rewards.AddItem(xuanID, count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if rewards.HasReward() {
|
if rewards.HasReward() {
|
||||||
p.SendPackCmd(8004, rewards)
|
p.SendPackCmd(8004, rewards)
|
||||||
}
|
}
|
||||||
foi.Winpet.AddEV(petCfg.YieldingEVValues)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,10 +193,23 @@ func (f *FightC) collectAttackValues(inputs []*input.Input) []model.AttackValue
|
|||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FightC) buildNoteUseSkillOutboundInfo() info.NoteUseSkillOutboundInfo {
|
func (f *FightC) collectAttackValueByAction(act *action.SelectSkillAction) []model.AttackValue {
|
||||||
|
if act == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fighter := f.GetInputByAction(act, false)
|
||||||
|
if fighter == nil || fighter.AttackValue == nil || fighter.AttackValue.SkillID == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
attackValue := *fighter.AttackValue
|
||||||
|
attackValue.ActorIndex = uint32(act.GetActorIndex())
|
||||||
|
return []model.AttackValue{attackValue}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FightC) buildNoteUseSkillOutboundInfo(firstAttack, secondAttack *action.SelectSkillAction) info.NoteUseSkillOutboundInfo {
|
||||||
result := info.NoteUseSkillOutboundInfo{}
|
result := info.NoteUseSkillOutboundInfo{}
|
||||||
result.FirstAttackInfo = append(result.FirstAttackInfo, f.collectAttackValues(f.Our)...)
|
result.FirstAttackInfo = append(result.FirstAttackInfo, f.collectAttackValueByAction(firstAttack)...)
|
||||||
result.SecondAttackInfo = append(result.SecondAttackInfo, f.collectAttackValues(f.Opp)...)
|
result.SecondAttackInfo = append(result.SecondAttackInfo, f.collectAttackValueByAction(secondAttack)...)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -302,12 +315,18 @@ func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction)
|
|||||||
var currentAction *action.SelectSkillAction
|
var currentAction *action.SelectSkillAction
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
currentAction = firstAttack
|
currentAction = firstAttack
|
||||||
|
if currentAction == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
attacker, defender = f.getSkillParticipants(firstAttack)
|
attacker, defender = f.getSkillParticipants(firstAttack)
|
||||||
originalSkill = f.copySkill(firstAttack)
|
originalSkill = f.copySkill(firstAttack)
|
||||||
//先手阶段,先修复后手效果
|
//先手阶段,先修复后手效果
|
||||||
f.Second.RecoverEffect()
|
f.Second.RecoverEffect()
|
||||||
} else {
|
} else {
|
||||||
currentAction = secondAttack
|
currentAction = secondAttack
|
||||||
|
if currentAction == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
attacker, defender = f.getSkillParticipants(secondAttack)
|
attacker, defender = f.getSkillParticipants(secondAttack)
|
||||||
originalSkill = f.copySkill(secondAttack)
|
originalSkill = f.copySkill(secondAttack)
|
||||||
//取消后手历史效果
|
//取消后手历史效果
|
||||||
@@ -434,7 +453,7 @@ func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction)
|
|||||||
f.sendLegacyRoundBroadcast(firstAttack, secondAttack)
|
f.sendLegacyRoundBroadcast(firstAttack, secondAttack)
|
||||||
}
|
}
|
||||||
|
|
||||||
attackValueResult := f.buildNoteUseSkillOutboundInfo()
|
attackValueResult := f.buildNoteUseSkillOutboundInfo(firstAttack, secondAttack)
|
||||||
//因为切完才能广播,所以必须和回合结束分开结算
|
//因为切完才能广播,所以必须和回合结束分开结算
|
||||||
f.BroadcastPlayers(func(p common.PlayerI) {
|
f.BroadcastPlayers(func(p common.PlayerI) {
|
||||||
for _, switchAction := range f.Switch {
|
for _, switchAction := range f.Switch {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"blazing/common/socket/errorcode"
|
"blazing/common/socket/errorcode"
|
||||||
"blazing/logic/service/common"
|
"blazing/logic/service/common"
|
||||||
|
"blazing/logic/service/fight/action"
|
||||||
fightinfo "blazing/logic/service/fight/info"
|
fightinfo "blazing/logic/service/fight/info"
|
||||||
"blazing/logic/service/fight/input"
|
"blazing/logic/service/fight/input"
|
||||||
spaceinfo "blazing/logic/service/space/info"
|
spaceinfo "blazing/logic/service/space/info"
|
||||||
@@ -111,3 +112,38 @@ func TestBuildFightStateStartEnvelope(t *testing.T) {
|
|||||||
t.Fatalf("unexpected right fighter snapshot: %+v", envelope.Right[0])
|
t.Fatalf("unexpected right fighter snapshot: %+v", envelope.Right[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuildNoteUseSkillOutboundInfoUsesActionOrder(t *testing.T) {
|
||||||
|
ourPlayer := &stubPlayer{info: model.PlayerInfo{UserID: 1001}}
|
||||||
|
oppPlayer := &stubPlayer{info: model.PlayerInfo{UserID: 2002}}
|
||||||
|
|
||||||
|
our := input.NewInput(nil, ourPlayer)
|
||||||
|
our.InitAttackValue()
|
||||||
|
our.AttackValue.SkillID = 111
|
||||||
|
our.AttackValue.RemainHp = 80
|
||||||
|
our.AttackValue.MaxHp = 100
|
||||||
|
|
||||||
|
opp := input.NewInput(nil, oppPlayer)
|
||||||
|
opp.InitAttackValue()
|
||||||
|
opp.AttackValue.SkillID = 222
|
||||||
|
opp.AttackValue.RemainHp = 70
|
||||||
|
opp.AttackValue.MaxHp = 100
|
||||||
|
|
||||||
|
fc := &FightC{
|
||||||
|
Our: []*input.Input{our},
|
||||||
|
Opp: []*input.Input{opp},
|
||||||
|
}
|
||||||
|
|
||||||
|
firstAttack := &action.SelectSkillAction{BaseAction: action.BaseAction{PlayerID: 2002, ActorIndex: 0}}
|
||||||
|
result := fc.buildNoteUseSkillOutboundInfo(firstAttack, nil)
|
||||||
|
|
||||||
|
if len(result.FirstAttackInfo) != 1 {
|
||||||
|
t.Fatalf("expected only first attack info, got first=%d second=%d", len(result.FirstAttackInfo), len(result.SecondAttackInfo))
|
||||||
|
}
|
||||||
|
if len(result.SecondAttackInfo) != 0 {
|
||||||
|
t.Fatalf("expected no second attack info, got %d", len(result.SecondAttackInfo))
|
||||||
|
}
|
||||||
|
if result.FirstAttackInfo[0].UserID != 2002 || result.FirstAttackInfo[0].SkillID != 222 {
|
||||||
|
t.Fatalf("expected first attack info to belong to acting opponent, got %+v", result.FirstAttackInfo[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,16 +23,16 @@ type ServerService struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ServerShowInfo struct {
|
type ServerShowInfo struct {
|
||||||
OnlineID uint32 `json:"online_id"`
|
OnlineID uint32 `json:"online_id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
IP string `json:"ip"`
|
IP string `json:"ip"`
|
||||||
Port uint32 `json:"port"`
|
Port uint32 `json:"port"`
|
||||||
IsVip uint32 `json:"is_vip"`
|
IsVip uint32 `json:"is_vip"`
|
||||||
IsDebug uint8 `json:"is_debug"`
|
IsDebug uint8 `json:"is_debug"`
|
||||||
IsOpen uint8 `json:"is_open"`
|
IsOpen uint8 `json:"is_open"`
|
||||||
Owner uint32 `json:"owner"`
|
//Owner uint32 `json:"owner"`
|
||||||
ExpireTime time.Time `json:"expire_time"`
|
// ExpireTime time.Time `json:"expire_time"`
|
||||||
ServerShow *model.ServerShow `json:"servershow,omitempty"`
|
// ServerShow *model.ServerShow `json:"servershow,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DonationOwnedServerInfo struct {
|
type DonationOwnedServerInfo struct {
|
||||||
@@ -112,29 +112,33 @@ func (s *ServerService) GetPort(DepartmentID uint) []ServerShowInfo {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
items = append(items, ServerShowInfo{
|
items = append(items, ServerShowInfo{
|
||||||
OnlineID: server.OnlineID,
|
OnlineID: server.OnlineID,
|
||||||
Name: server.Name,
|
Name: server.Name,
|
||||||
IP: server.IP,
|
IP: server.IP,
|
||||||
Port: server.Port,
|
Port: server.Port,
|
||||||
IsVip: server.IsVip,
|
IsVip: server.IsVip,
|
||||||
IsDebug: server.IsDebug,
|
IsDebug: server.IsDebug,
|
||||||
IsOpen: server.IsOpen,
|
IsOpen: server.IsOpen,
|
||||||
Owner: 0,
|
//Owner: 0,
|
||||||
ExpireTime: time.Time{},
|
// ExpireTime: time.Time{},
|
||||||
})
|
})
|
||||||
for i := range showMap[server.OnlineID] {
|
for i := range showMap[server.OnlineID] {
|
||||||
show := &showMap[server.OnlineID][i]
|
show := &showMap[server.OnlineID][i]
|
||||||
|
itemOnlineID := server.OnlineID
|
||||||
|
if show.ID > 0 {
|
||||||
|
itemOnlineID = uint32(show.ID)
|
||||||
|
}
|
||||||
item := ServerShowInfo{
|
item := ServerShowInfo{
|
||||||
OnlineID: server.OnlineID,
|
OnlineID: itemOnlineID,
|
||||||
Name: server.Name,
|
Name: server.Name,
|
||||||
IP: server.IP,
|
IP: server.IP,
|
||||||
Port: server.Port,
|
Port: server.Port,
|
||||||
IsVip: server.IsVip,
|
IsVip: server.IsVip,
|
||||||
IsDebug: server.IsDebug,
|
IsDebug: server.IsDebug,
|
||||||
IsOpen: server.IsOpen,
|
IsOpen: server.IsOpen,
|
||||||
Owner: show.Owner,
|
|
||||||
ExpireTime: show.ExpireTime,
|
// ExpireTime: show.ExpireTime,
|
||||||
ServerShow: show,
|
// ServerShow: show,
|
||||||
}
|
}
|
||||||
if show.Name != "" {
|
if show.Name != "" {
|
||||||
item.Name = show.Name
|
item.Name = show.Name
|
||||||
|
|||||||
Reference in New Issue
Block a user