package chapter import ( "f1-game/internal/code" "f1-game/internal/constant" "f1-game/internal/data" "f1-game/internal/enum" facade "f1-game/internal/facade" nameRoute "f1-game/internal/name/route" "f1-game/internal/pb" "f1-game/internal/sessions" "f1-game/nodes/game/internal/db" "f1-game/nodes/game/player/asset" ao "f1-game/nodes/game/player/asset/origin" "f1-game/nodes/game/player/hero" "f1-game/nodes/game/player/vip" ctime "github.com/cherry-game/cherry/extend/time" clog "github.com/cherry-game/cherry/logger" cproto "github.com/cherry-game/cherry/net/proto" ) var srv = &service{ typ: newServiceType(), } func init() { } func Service() *service { return srv } type service struct { facade.PlayerServiceBase[*db.PlayerTable] typ serviceType // 星级类型类型服务类(封装各种星级完成细节) } func (p *service) OnLogin(playerTable *db.PlayerTable, session *cproto.Session) { chapterTable := db.GetChapterTable(playerTable.PlayerID) // 初始化 if chapterTable.Chapter.ChapterID == 0 && chapterTable.Chapter.LevelID == 0 { firstChapterRow, found := data.Chapter.GetFirstChapter() if !found { clog.Warnf("[playerID=%d]OnLogin chapter init fail") return } chapterTable.Chapter.ChapterID = firstChapterRow.ID chapterTable.Chapter.LevelID = firstChapterRow.StartID chapterTable.Save2Queue() } } func (p *service) OnReset(playerTable *db.PlayerTable, _ *ctime.CherryTime, byLogin bool) { var ( chapterTable = db.GetChapterTable(playerTable.PlayerID) updateLevelIDs = []int32{} ) // 跨天重置关卡挑战次数 for levelID, level := range chapterTable.Chapter.Levels { update := false // 重置挑战次数 if level.DayChallengeCount > 0 { level.DayChallengeCount = 0 update = true } // 重置购买挑战次数 if level.DayBuyChallengeCount > 0 { level.DayBuyChallengeCount = 0 update = true } if update { updateLevelIDs = append(updateLevelIDs, levelID) } } if len(updateLevelIDs) > 0 { chapterTable.Save2Queue() p.ChangePush(playerTable.PlayerID, updateLevelIDs...) clog.Infof("chapter reset level day challenge count, playerID = %d, updateLevelIDs = %v", playerTable.PlayerID, updateLevelIDs) } } // Push 探险数据推送 func (*service) Push(playerTable *db.PlayerTable, session *cproto.Session) { chapterTable := db.GetChapterTable(playerTable.PlayerID) rsp := chapterTable.Chapter.ToProto() sessions.PushWithSession(session, nameRoute.PushGamePlayer_Chapter, &rsp) } // ChangePush 关卡信息变更推送 func (p *service) ChangePush(playerID int64, updateLevelIDs ...int32) { if len(updateLevelIDs) < 1 { return } var ( chapterTable = db.GetChapterTable(playerID) levels = []*pb.ChapterLevel{} ) for _, levelID := range updateLevelIDs { level, found := chapterTable.Chapter.GetLevel(levelID) if found { levels = append(levels, level.ToChapterLevelProto(levelID)) } } if len(levels) < 1 { return } resp := &pb.UpdateChapterLevel{ ChapterID: chapterTable.Chapter.ChapterID, LevelID: chapterTable.Chapter.LevelID, Levels: levels, } sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_ChapterLevel, resp) } // 精力定时恢复 func (p *service) StaminaRecoverTimer(playerID int64, nowSecond int64) { var ( chapterTable = db.GetChapterTable(playerID) staminaID = data.Const.ChapterStaminaAddValue.ID staminaLimit = data.Const.ChapterStaminaLimit curStaminaNum = asset.Service().Get(playerID, staminaID) staminaAddInterval = data.Const.ChapterStaminaAddInterval ) // vip 精力上限加成 staminaLimit += vip.Service().GetVipAttrAdd(playerID, enum.AttrStaminaLimit) // vip 精力恢复时间加成 staminaAddInterval = max(0, staminaAddInterval-vip.Service().GetVipAttrAdd(playerID, enum.AttrStaminaRecoverTime)) // 当前精力已满 if curStaminaNum >= staminaLimit { return } diffSecond := nowSecond - chapterTable.Chapter.LastRecoverTime // 添加精力次数 addStaminaTimes := diffSecond / staminaAddInterval if addStaminaTimes <= 0 { return } // 添加精力数量 addStaminaNum := addStaminaTimes * data.Const.ChapterStaminaAddValue.Num // 超出上限 if curStaminaNum+addStaminaNum > staminaLimit { addStaminaNum = staminaLimit - curStaminaNum } _, errCode := asset.Service().Add(playerID, staminaID, addStaminaNum, ao.ChapterStaminaRecoverReward, true) if code.IsFail(errCode) { clog.Warnf("[StaminaRecoverTimer] recover stamina fail, playerID = %d, errCode = %d", playerID, errCode) return } chapterTable.Chapter.LastRecoverTime += addStaminaNum * data.Const.ChapterStaminaAddInterval chapterTable.Save2Queue() } // 检测更新下一章节或者下一关 func (p *service) CheckNextLevelOrChapter(chapterTable *db.ChapterTable, chapterRow *data.ChapterRow, levelID int32) { // 当前章节未结束 切换到下一关 并 返回 if levelID < chapterRow.EndID { chapterTable.Chapter.LevelID++ return } // 判断是否存在下一章 nextChapterID := chapterRow.ID + 1 nextChapterRow, found := data.Chapter.GetByID(nextChapterID) if !found { return } // 下一章解锁条件不满足 返回 // TODO 感觉这个没什么用处 if !chapterTable.Chapter.IsLevelPassed(nextChapterRow.UnlockID) { return } chapterTable.Chapter.ChapterID = nextChapterID chapterTable.Chapter.LevelID = nextChapterRow.StartID } // 获取探险挑战星级情况 // TODO 传入战斗结束英雄数据和结果 func (p service) GetChapterStars(playerID int64, chapterLevelRow *data.ChapterLevelRow, result *pb.BattleResult) []int32 { stars := []int32{} if chapterLevelRow == nil { return stars } for _, condition := range chapterLevelRow.Conditions { chapterStarRow, found := data.ChapterStar.GetByID(condition) if !found { clog.Warnf("[playerID=%d]chapter star config not found: %d", playerID, condition) continue } parser, errCode := p.typ.get(chapterStarRow.Type) if code.IsFail(errCode) { clog.Warnf("[playerID=%d]chapter star type not found: %d", playerID, chapterStarRow.Type) continue } if parser.IsFinish(playerID, chapterStarRow, result) { stars = append(stars, condition) } } return stars } // 获取探险阵型的战斗参数 func (p *service) GetChapterBattleCampParam(playerID int64, lineupID int32) (*pb.BattleCampParam, int32) { var ( teamTable = db.GetLineupTable(playerID) heroTable = db.GetHeroTable(playerID) ) lineups, found := teamTable.LineupMap.GetLineups(constant.Adventure_Type) if !found { return nil, code.ChapterLineupNotFound } lineup, found := lineups.GetLineup(lineupID) if !found { return nil, code.ChapterLineupNotFound } if lineup.IsNotCanFight() { return nil, code.TeamIsEmpty } ret := &pb.BattleCampParam{ Camp: enum.BattleCampType_Left, PlayerID: playerID, } for _, member := range lineup.Members { if heroEntity, found := heroTable.Heroes.Get(member.HeroGUID); found { fighter := hero.Service().GetChapterFighter(playerID, heroEntity, lineupID) ret.Squads = append(ret.Squads, &pb.BattleSquadParam{ TileIndex: member.Index, Fighter: fighter, // Soldiers: nil, // 探险没有小兵 }) } } return ret, code.OK }