package controller import ( "blazing/common/socket/errorcode" "blazing/common/utils" "blazing/logic/service/fight" fightinfo "blazing/logic/service/fight/info" "blazing/logic/service/player" "blazing/logic/service/space/info" configmodel "blazing/modules/config/model" "blazing/modules/config/service" "blazing/modules/player/model" "sync/atomic" "github.com/gogf/gf/v2/util/gconv" "github.com/jinzhu/copier" ) const ( towerCmdChoiceTrial uint32 = 2428 towerCmdChoiceBrave uint32 = 2414 towerCmdFightTrial uint32 = 2429 towerCmdFightBrave uint32 = 2415 towerCmdFightDark uint32 = 2425 towerTaskDark int = 110 towerTaskBrave int = 500 towerTaskTrial int = 600 ) type towerChoiceState struct { currentLevel *uint32 maxLevel *uint32 service *service.TowerService } // 暗黑门进入boss func (h Controller) FreshOpen(data *C2S_OPEN_DARKPORTAL, c *player.Player) (result *fight.S2C_OPEN_DARKPORTAL, err errorcode.ErrorCode) { result = &fight.S2C_OPEN_DARKPORTAL{} towerBosses := service.NewTower110Service().Boss(uint32(data.Level)) bossConfig, ok := firstTowerBossConfig(towerBosses) if !ok { return nil, errorcode.ErrorCodes.ErrPokemonNotExists } bosses := service.NewBossService().Get(bossConfig.BossIds[0]) if len(bosses) == 0 { return nil, errorcode.ErrorCodes.ErrPokemonNotExists } result.CurBossID = uint32(bosses[0].MonID) c.CurDark = uint32(data.Level) defer c.GetSpace().LeaveMap(c) return result, 0 } // FreshChoiceFightLevel 处理玩家选择挑战模式(试炼之塔或勇者之塔) func (h Controller) FreshChoiceFightLevel(data *C2S_FRESH_CHOICE_FIGHT_LEVEL, c *player.Player) (result *fight.S2C_FreshChoiceLevelRequestInfo, err errorcode.ErrorCode) { result = &fight.S2C_FreshChoiceLevelRequestInfo{} c.Info.CurrentFreshStage = utils.Max(c.Info.CurrentFreshStage, 1) c.Info.CurrentStage = utils.Max(c.Info.CurrentStage, 1) choiceState, ok := towerChoiceRuntime(c, data.Head.CMD) if !ok { return nil, errorcode.ErrorCodes.ErrSystemError } if data.Level > 0 { if !canSelectTowerLevel(data.Level, *choiceState.maxLevel) { return nil, errorcode.ErrorCodes.ErrPokemonNotExists } *choiceState.currentLevel = uint32(data.Level) } result.CurFightLevel = *choiceState.currentLevel appendTowerBossPreview(&result.BossId, choiceState.service.Boss(*choiceState.currentLevel)) atomic.StoreUint32(&c.Canmon, 0) defer c.GetSpace().LeaveMap(c) return result, 0 } // FreshLeaveFightLevel 处理控制器请求。 func (h Controller) FreshLeaveFightLevel(data *FRESH_LEAVE_FIGHT_LEVEL, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { _ = data defer c.GetSpace().EnterMap(c) out := info.NewOutInfo() copier.CopyWithOption(out, c.GetInfo(), copier.Option{DeepCopy: true}) return result, 0 } // PetTawor 处理控制器请求。 func (h Controller) PetTawor(data *StartTwarInboundInfo, c *player.Player) (result *fight.S2C_ChoiceLevelRequestInfo, err errorcode.ErrorCode) { if err = c.CanFight(); err != 0 { return nil, err } bossList, currentLevel, taskID, ok := towerFightBosses(c, data.Head.CMD) if !ok { return nil, errorcode.ErrorCodes.ErrSystemError } currentBoss, ok := firstTowerBossConfig(bossList) if !ok { return nil, errorcode.ErrorCodes.ErrPokemonNotExists } result = &fight.S2C_ChoiceLevelRequestInfo{CurFightLevel: currentLevel} appendTowerNextBossPreview(&result.BossID, bossList) monsterInfo, bossScript, ok := buildTowerMonsterInfo(currentBoss) if !ok { return nil, errorcode.ErrorCodes.ErrPokemonNotExists } c.Fightinfo.Mode = fightinfo.BattleMode.MULTI_MODE c.Fightinfo.Status = fightinfo.BattleMode.FIGHT_WITH_NPC ai := player.NewAI_player(monsterInfo) ai.BossScript = bossScript _, err = fight.NewFight(c, ai, c.GetPetInfo(100), ai.GetPetInfo(0), func(foi model.FightOverInfo) { if foi.Reason != 0 || foi.WinnerId != c.Info.UserID { return } handleTowerFightWin(c, data.Head.CMD, taskID, currentLevel) }) return } func towerChoiceRuntime(c *player.Player, cmd uint32) (towerChoiceState, bool) { switch cmd { case towerCmdChoiceTrial: return towerChoiceState{ currentLevel: &c.Info.CurrentFreshStage, maxLevel: &c.Info.MaxFreshStage, service: service.NewTower600Service(), }, true case towerCmdChoiceBrave: return towerChoiceState{ currentLevel: &c.Info.CurrentStage, maxLevel: &c.Info.MaxStage, service: service.NewTower500Service(), }, true default: return towerChoiceState{}, false } } func towerFightBosses(c *player.Player, cmd uint32) ([]configmodel.BaseTowerConfig, uint32, int, bool) { switch cmd { case towerCmdFightTrial: return service.NewTower600Service().Boss(c.Info.CurrentFreshStage, c.Info.CurrentFreshStage+1), c.Info.CurrentFreshStage, towerTaskTrial, true case towerCmdFightBrave: return service.NewTower500Service().Boss(c.Info.CurrentStage, c.Info.CurrentStage+1), c.Info.CurrentStage, towerTaskBrave, true case towerCmdFightDark: return service.NewTower110Service().Boss(c.CurDark), c.CurDark, towerTaskDark, true default: return nil, 0, 0, false } } func canSelectTowerLevel(targetLevel uint, maxLevel uint32) bool { return targetLevel == 1 || targetLevel <= uint(maxLevel) } func firstTowerBossConfig(bossList []configmodel.BaseTowerConfig) (configmodel.BaseTowerConfig, bool) { if len(bossList) == 0 || len(bossList[0].BossIds) == 0 { return configmodel.BaseTowerConfig{}, false } return bossList[0], true } func appendTowerBossPreview(dst *[]uint32, bossList []configmodel.BaseTowerConfig) { bossConfig, ok := firstTowerBossConfig(bossList) if !ok { return } bosses := service.NewBossService().Get(bossConfig.BossIds[0]) for _, boss := range bosses { *dst = append(*dst, uint32(boss.MonID)) } } func appendTowerNextBossPreview(dst *[]uint32, bossList []configmodel.BaseTowerConfig) { if len(bossList) < 2 || len(bossList[1].BossIds) == 0 { return } bosses := service.NewBossService().Get(bossList[1].BossIds[0]) for _, boss := range bosses { *dst = append(*dst, uint32(boss.MonID)) } } func buildTowerMonsterInfo(towerBoss configmodel.BaseTowerConfig) (*model.PlayerInfo, string, bool) { bosses := service.NewBossService().Get(towerBoss.BossIds[0]) if len(bosses) == 0 { return nil, "", false } monsterInfo := &model.PlayerInfo{Nick: towerBoss.Name} for i, boss := range bosses { monster := model.GenPetInfo(int(boss.MonID), 24, int(boss.Nature), 0, int(boss.Lv), nil, 0) if boss.Hp != 0 { monster.Hp = uint32(boss.Hp) monster.MaxHp = uint32(boss.Hp) } for statIdx, prop := range boss.Prop { if prop != 0 { monster.Prop[statIdx] = prop } } for skillIdx := 0; skillIdx < len(monster.SkillList) && skillIdx < len(boss.SKill); skillIdx++ { if boss.SKill[skillIdx] != 0 { monster.SkillList[skillIdx].ID = boss.SKill[skillIdx] } } effects := service.NewEffectService().Args(boss.Effect) for _, effect := range effects { monster.EffectInfo = append(monster.EffectInfo, model.PetEffectInfo{ Idx: uint16(effect.ID), EID: gconv.Uint16(effect.Eid), Args: gconv.Ints(effect.Args), }) } monster.CatchTime = uint32(i) monsterInfo.PetList = append(monsterInfo.PetList, *monster) } return monsterInfo, bosses[0].Script, true } func handleTowerFightWin(c *player.Player, cmd uint32, taskID int, currentLevel uint32) { c.TawerCompletedTask(taskID, int(currentLevel)) switch cmd { case towerCmdFightTrial: c.Info.CurrentFreshStage++ if c.Info.CurrentFreshStage >= c.Info.MaxFreshStage { c.Info.MaxFreshStage = c.Info.CurrentFreshStage } case towerCmdFightBrave: c.Info.CurrentStage++ if c.Info.CurrentStage >= c.Info.MaxStage { c.Info.MaxStage = c.Info.CurrentStage } } }