| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- package hero
- import (
- capp "f1-game/internal/cherry_app"
- "f1-game/internal/code"
- "f1-game/internal/component/redis"
- "f1-game/internal/constant"
- "f1-game/internal/data"
- "f1-game/internal/enum"
- "f1-game/internal/event"
- "f1-game/internal/extend/times"
- facade "f1-game/internal/facade"
- nameRoute "f1-game/internal/name/route"
- "f1-game/internal/pb"
- "f1-game/internal/sessions"
- "f1-game/internal/types"
- "f1-game/nodes/game/internal/db"
- dbEquip "f1-game/nodes/game/internal/db/data/equip"
- dbHero "f1-game/nodes/game/internal/db/data/hero"
- gameFacade "f1-game/nodes/game/internal/facade"
- ao "f1-game/nodes/game/player/asset/origin"
- ctime "github.com/cherry-game/cherry/extend/time"
- cproto "github.com/cherry-game/cherry/net/proto"
- clog "github.com/cherry-game/cherry/logger"
- )
- var srv = &service{}
- func init() {
- }
- func Service() *service {
- return srv
- }
- type service struct {
- facade.PlayerServiceBase[*db.PlayerTable]
- }
- // func (*service) OnLogin(playerTable *db.PlayerTable, session *cproto.Session) {
- // }
- // func (*service) OnLogined(playerTable *db.PlayerTable, session *cproto.Session) {
- // }
- // func (*service) OnLogout(playerTable *db.PlayerTable) {
- // }
- func (*service) OnReset(playerTable *db.PlayerTable, _ *ctime.CherryTime, byLogin bool) {
- heroTable := db.GetHeroTable(playerTable.PlayerID)
- if playerTable.Stats.IsDayReset {
- heroTable.Recruit.FreeUsedNum = 0
- heroTable.Save2Queue()
- }
- }
- // Push 英雄数据推送
- func (*service) Push(playerTable *db.PlayerTable, session *cproto.Session) {
- heroTable := db.GetHeroTable(playerTable.PlayerID)
- //heroTable.CheckData()
- rsp := pb.HeroList{
- List: heroTable.Heroes.ToProto(),
- }
- sessions.PushWithSession(session, nameRoute.PushGamePlayer_HeroList, &rsp)
- clog.Debugf("[playerID = %d] heroesCount = %d", playerTable.PlayerID, len(rsp.List))
- //推送图鉴列表
- bookRsp := pb.I32List{}
- for _, heroID := range heroTable.Books {
- bookRsp.List = append(bookRsp.List, heroID)
- }
- sessions.PushWithSession(session, nameRoute.PushGamePlayer_HeroBookList, &bookRsp)
- clog.Debugf("[playerID = %d] heroBooksCount = %d",
- playerTable.PlayerID,
- len(bookRsp.List),
- )
- }
- func (p *service) ChangePushOne(playerID int64, hero *dbHero.Hero) {
- p.ChangePush(playerID, nil, hero)
- }
- // ChangePush 英雄变更推送
- func (p *service) ChangePush(playerID int64, removeHeroes []int64, updateHeroes ...*dbHero.Hero) {
- if len(updateHeroes) > 0 {
- rsp := &pb.HeroList{}
- for _, hero := range updateHeroes {
- rsp.List = append(rsp.List, hero.ToProto())
- }
- sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_HeroChange, rsp)
- }
- if len(removeHeroes) > 0 {
- sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_HeroDel, &pb.I64List{
- List: removeHeroes,
- })
- }
- }
- // HeroBookChangePush 英雄图鉴变更推送
- func (p *service) HeroBookChangePush(playerID int64, updateHeroBooks ...int32) {
- if len(updateHeroBooks) > 0 {
- rsp := &pb.I32List{
- List: updateHeroBooks,
- }
- sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_HeroBookChange, rsp)
- }
- }
- // SetHerosInjuryByTeamID 设置英雄重伤状态
- func (p *service) SetHerosInjuryByTeamID(playerID int64, teamID int32, injuriesEndTime int64, push bool) {
- clog.Debugf("[SetHerosInjuryByTeamID] playerID = %d, teamID = %d, injuriesEndTime = %s",
- playerID, teamID, times.SecondToDatetimeFormat(injuriesEndTime))
- // TODO 暂时屏蔽
- // teamTable := db.GetLineupTable(playerID)
- // team, ok := teamTable.Teams.GetTeam(teamID)
- // if !ok {
- // clog.Errorf("[SetHerosInjuryByTeamID] team not exist: playerID = %d, teamID = %d", playerID, teamID)
- // return
- // }
- // heroTable := db.GetHeroTable(playerID)
- // resp := &pb.I64I64List{}
- // for _, member := range team.Members {
- // hero, ok := heroTable.Heroes.Get(member.HeroGUID)
- // if !ok {
- // continue
- // }
- // hero.InjuriesEndTime = injuriesEndTime
- // resp.List = append(resp.List, &pb.I64I64{Key: member.HeroGUID, Value: injuriesEndTime})
- // }
- // heroTable.Save2Queue()
- // if push {
- // sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_HeroInjuries, resp)
- // }
- }
- // AddList 批量添加英雄(自动转碎片)
- func (p *service) AddList(playerID int64, cfgIDList []int32, origin ao.Origin, push bool) (types.Assets, int32) {
- var (
- playerTable, _ = db.GetPlayerTable(playerID)
- heroTable = db.GetHeroTable(playerID)
- retAssets types.Assets
- changeHeroes []*dbHero.Hero
- updateHeroBooks []int32
- )
- for _, cfgID := range cfgIDList {
- heroRow, found := data.Hero.GetByID(cfgID)
- if !found {
- continue
- }
- // 添加英雄
- changeHeroes, retAssets = p.NewAndAddHeroEntity(playerTable, heroTable, heroRow, changeHeroes, retAssets)
- if !heroTable.Books.Contains(cfgID) {
- heroTable.Books.Add(cfgID)
- updateHeroBooks = append(updateHeroBooks, cfgID)
- }
- }
- if len(changeHeroes) > 0 {
- // 保存英雄数据
- heroTable.Save2Queue()
- // 同步更新到redis
- p.SyncUpdateHeroToRedis(playerID, changeHeroes...)
- if push { // TODO: event dispatch
- // 推送英雄变更
- p.ChangePush(playerID, nil, changeHeroes...)
- }
- // 发送获得英雄事件
- capp.PostEvent(event.NewHeroGet(playerID, retAssets))
- }
- // 推送图鉴
- if len(updateHeroBooks) > 0 && push {
- gameFacade.Hero.HeroBookChangePush(playerID, updateHeroBooks...)
- }
- return retAssets, code.OK
- }
- func (p *service) AddOne(playerID int64, heroID int32, num int32, origin ao.Origin, push bool) (types.Assets, int32) {
- heroRow, found := data.Hero.GetByID(heroID)
- if !found {
- return nil, code.ConfigNotFound_Hero
- }
- var (
- playerTable, _ = db.GetPlayerTable(playerID)
- heroTable = db.GetHeroTable(playerID)
- retAssets types.Assets
- changeHeroes []*dbHero.Hero
- updateHeroBook bool
- )
- for range num {
- // 添加英雄
- changeHeroes, retAssets = p.NewAndAddHeroEntity(playerTable, heroTable, heroRow, changeHeroes, retAssets)
- }
- if !heroTable.Books.Contains(heroID) {
- heroTable.Books.Add(heroID)
- updateHeroBook = true
- }
- if len(changeHeroes) > 0 {
- // 保存英雄数据
- heroTable.Save2Queue()
- // 同步更新到redis
- p.SyncUpdateHeroToRedis(playerID, changeHeroes...)
- if push { // TODO: event dispatch
- // 推送英雄变更
- p.ChangePush(playerID, nil, changeHeroes...)
- }
- // 发送获得英雄事件
- capp.PostEvent(event.NewHeroGet(playerID, retAssets))
- }
- if updateHeroBook && push {
- gameFacade.Hero.HeroBookChangePush(playerID, heroID)
- }
- return retAssets, code.OK
- }
- // 创建并添加一个英雄
- func (p *service) NewAndAddHeroEntity(playerTable *db.PlayerTable, heroTable *db.HeroTable,
- heroRow *data.HeroRow, changeHeroes []*dbHero.Hero, retAssets types.Assets) ([]*dbHero.Hero, types.Assets) {
- // 添加英雄
- guid := redis.GUID.NewGUID()
- heroEntity := dbHero.NewHero(heroRow, guid, playerTable.Lord.Level)
- heroTable.Heroes.Add(heroEntity)
- // 检测初始化天赋、主动和被动技能
- p.CheckActiveHeroSkill(heroEntity)
- // 更新英雄属性
- p.UpdateAttrs(playerTable.PlayerID, heroEntity)
- changeHeroes = append(changeHeroes, heroEntity)
- retAssets.AddAsset(types.NewAssetWithGUID(heroEntity.HeroID, 1, heroEntity.GUID))
- // 更新获得英雄个数
- heroTable.HeroExtend.HeroCount += 1
- return changeHeroes, retAssets
- }
- // UpdateAttrs 更新英雄属性,不过滤不同兵种的加成,后面统一在战斗参数构建的地方处理
- func (*service) UpdateAttrs(playerID int64, heroEntity *dbHero.Hero) {
- attrs := types.Attrs{}
- for _, fn := range attrsFuncList {
- fn(playerID, heroEntity, &attrs)
- }
- // TODO 设置英雄当前血量为最大血量
- attrs.Set(enum.Attr_HP, attrs.Get(enum.Attr_MaxHP))
- heroEntity.Attrs = attrs
- }
- // GetChapterFighter 实时获取探险英雄战斗数据
- func (*service) GetChapterFighter(playerID int64, heroEntity *dbHero.Hero, lineupID int32) *pb.Fighter {
- attrs := types.Attrs{}
- for _, fn := range attrsFuncList {
- fn(playerID, heroEntity, &attrs)
- }
- // 单独处理阵型羁绊属性
- lineupFetterAttrs(playerID, heroEntity, &attrs, lineupID)
- // 过滤兵种加成
- retAttrs := types.Attrs{}
- for key, attrVal := range attrs {
- if enum.SquadKeys[key] {
- continue
- }
- retAttrs.Add(key, attrVal)
- }
- // TODO 设置英雄当前血量为最大血量
- retAttrs.Set(enum.Attr_HP, retAttrs.Get(enum.Attr_MaxHP))
- return heroEntity.ToFighter(retAttrs)
- }
- // AddExp 给英雄加经验
- func (p *service) AddExp(playerID int64, hero *dbHero.Hero, exp int32) int32 {
- // // 英雄等级已经最大
- // if hero.Level >= data.HeroLevel.MaxLevel() {
- // return code.OK
- // }
- // hero.Exp += exp
- // levelUp := false
- // // 处理升级
- // for hero.Level < data.HeroLevel.MaxLevel() {
- // levelRow, ok := data.HeroLevel.Get(hero.Level)
- // if !ok {
- // return code.ConfigNotExists
- // }
- // if hero.Exp < levelRow.Exp {
- // break
- // }
- // hero.Level++
- // hero.Exp -= levelRow.Exp
- // levelUp = true
- // }
- // if levelUp {
- // p.UpdateAttr(playerID, hero)
- // }
- // p.ChangePushOne(playerID, hero)
- return code.OK
- }
- // 英雄等级变化检测英雄技能激活
- func (p *service) CheckActiveHeroSkill(hero *dbHero.Hero) {
- if hero.Skills.Size() >= constant.HeroSkillNumLimit {
- return
- }
- heroRow, found := data.Hero.GetByID(hero.HeroID)
- if !found {
- clog.Warnf("[checkActiveHeroSkill] hero config not found: heroID=%d", hero.HeroID)
- return
- }
- // 天赋技能
- p.heroSkillInit(hero, heroRow.Talent, hero.Star)
- // 主动技能
- p.heroSkillInit(hero, heroRow.ActiveSkill, hero.Star)
- // 被动技能
- p.heroSkillInit(hero, heroRow.PassiveSkill, hero.Star)
- // 专属技能
- p.heroSkillInit(hero, heroRow.SpecialSkill, hero.Star)
- }
- // 初始化英雄技能
- func (*service) heroSkillInit(hero *dbHero.Hero, skillID, heroStar int32) {
- // 已经初始化 跳过
- if hero.GetSkillLevel(skillID) > 0 {
- return
- }
- skillRow, found := data.Skill.GetByID(skillID)
- if !found {
- clog.Warnf("[heroSkillInit] skill config not found, skillID: %d", skillID)
- return
- }
- if heroStar >= skillRow.UnlockStar {
- hero.SetSkillLevel(skillID, 1)
- }
- }
- // 删除英雄&处理
- func (p *service) RemoveHeros(playerID int64, removeHeroGUIDs ...int64) {
- if len(removeHeroGUIDs) <= 0 {
- return
- }
- var (
- heroTable = db.GetHeroTable(playerID)
- teamTable = db.GetLineupTable(playerID)
- equipTable = db.GetEquipTable(playerID)
- changeEquips = []*dbEquip.Equip{}
- equipSave = false
- )
- // 执行删除英雄前处理
- for _, heroGUID := range removeHeroGUIDs {
- hero, found := heroTable.Heroes.Get(heroGUID)
- if !found {
- continue
- }
- // 穿戴装备
- if len(hero.EquipGUIDList) > 0 {
- // 解除装备穿戴
- for _, equipGUID := range hero.EquipGUIDList {
- equip, found := equipTable.Equips.Get(equipGUID)
- if !found {
- continue
- }
- equip.WearHeroGUID = 0
- changeEquips = append(changeEquips, equip)
- equipSave = true
- }
- }
- }
- // 检测阵容数据
- updateLineups := teamTable.LineupMap.RemoveHeroClearLineup(removeHeroGUIDs...)
- if len(updateLineups) > 0 {
- teamTable.Save2Queue()
- // 通知客户端
- for lineupType, lineups := range updateLineups {
- gameFacade.Lineup.LineupChangePush(playerID, lineupType, lineups...)
- }
- }
- if equipSave {
- equipTable.Save2Queue()
- // 推送装备变更
- gameFacade.Equip.ChangePush(playerID, nil, changeEquips...)
- }
- // 删除英雄
- heroTable.Heroes.Remove(removeHeroGUIDs...)
- // 同步删除英雄到redis
- p.SyncRemoveHeroToRedis(playerID, removeHeroGUIDs...)
- }
- // 同步更新英雄到redis
- // TODO 现在根据玩家操作更新到redis,领主升级触发全部英雄同步需要优化
- func (p *service) SyncUpdateHeroToRedis(playerID int64, heroList ...*dbHero.Hero) {
- if len(heroList) <= 0 {
- return
- }
- var heroPlayerList []*pb.PlayerHero
- for _, hero := range heroList {
- heroPlayerList = append(heroPlayerList, hero.ToPlayerHero())
- }
- redis.Game.UpdatePlayerHeros(playerID, heroPlayerList...)
- }
- // 同步删除英雄到redis
- func (p *service) SyncRemoveHeroToRedis(playerID int64, heroIDList ...int64) {
- if len(heroIDList) <= 0 {
- return
- }
- redis.Game.DeletePlayerHeros(playerID, heroIDList...)
- }
|