package hero import ( "f1-game/internal/data" "f1-game/internal/enum" "f1-game/internal/facade" nameRoute "f1-game/internal/name/route" "f1-game/internal/pb" "f1-game/internal/sessions" "f1-game/nodes/map/internal/db" dbMapPlayer "f1-game/nodes/map/internal/db/data/player" ctime "github.com/cherry-game/cherry/extend/time" cproto "github.com/cherry-game/cherry/net/proto" ) func Service() *service { return &service{} } type service struct { facade.PlayerServiceBase[*db.MapPlayerTable] } func (p *service) CheckAddEnergyTimer(mapPlayerTable *db.MapPlayerTable, nowSecond int64) { if len(mapPlayerTable.Heroes) <= 0 { return } updateHeros := []*dbMapPlayer.Hero{} for _, hero := range mapPlayerTable.Heroes { success := p.CheckAddEnergy(mapPlayerTable, hero, nowSecond) if success { updateHeros = append(updateHeros, hero) } } if len(updateHeros) <= 0 { return } p.ChangePush(mapPlayerTable.PlayerID, updateHeros...) mapPlayerTable.Save2Queue() } // Push 推送队伍信息 func (p *service) Push(mapPlayerTable *db.MapPlayerTable, session *cproto.Session) { // 推送地图英雄列表 list := mapPlayerTable.Heroes.ToProto() if len(list) <= 0 { return } resp := &pb.MapHeroList{ List: list, } sessions.PushWithSession(session, nameRoute.PushMapPlayer_HeroList, resp) } // ChangePush 推送变化的英雄信息 func (p *service) ChangePush(playerID int64, heroList ...*dbMapPlayer.Hero) { if len(heroList) <= 0 { return } rsp := &pb.MapHeroList{} for _, hero := range heroList { rsp.List = append(rsp.List, hero.ToProto()) } // 在线才推送 session, found := sessions.GetSession(playerID) if found { sessions.PushWithSession(session, nameRoute.PushMapPlayer_HeroChange, rsp) } } // CheckAddEnergy 检查添加体力 func (p *service) CheckAddEnergy(mapPlayerTable *db.MapPlayerTable, hero *dbMapPlayer.Hero, nowSecond int64) bool { // 如果体力已满,直接返回 false if p.IsEnergyFull(mapPlayerTable, hero) { return false } // 计算时间差 diffSeconds := nowSecond - hero.EnergyCoverTime if diffSeconds <= 0 { return false } // 如果时间差不足以恢复体力,直接返回 false if diffSeconds < data.Const.HeroEnergyAddInterval { return false } // 计算可以恢复的体力次数 recoverTimes := diffSeconds / data.Const.HeroEnergyAddInterval if recoverTimes <= 0 { return false } // 体力回复 isFull := p.AddEnergy(mapPlayerTable, hero, data.Const.HeroEnergyAddValue*int32(recoverTimes)) if !isFull { // 更新恢复时间 hero.EnergyCoverTime += recoverTimes * data.Const.HeroEnergyAddInterval } return true } // GetMaxEnergy 获取最大体力值 // vip 加成 func (p *service) GetMaxEnergy(mapPlayerTable *db.MapPlayerTable) int32 { maxEnergy := data.Const.HeroEnergy vipAdd := int32(0) if !mapPlayerTable.Vip.IsExpired { vipAdd = mapPlayerTable.Vip.Attrs.GetI32(enum.AttrHeroEnergyLimit) } return maxEnergy + vipAdd } // IsEnergyFull 判断体力是否已满 func (p *service) IsEnergyFull(mapPlayerTable *db.MapPlayerTable, hero *dbMapPlayer.Hero) bool { return hero.Energy >= p.GetMaxEnergy(mapPlayerTable) } // AddEnergy 恢复体力 return 是否回复满 func (p *service) AddEnergy(mapPlayerTable *db.MapPlayerTable, hero *dbMapPlayer.Hero, energy int32) bool { hero.Energy += energy // 如果体力超过上限,设置为上限值 if p.IsEnergyFull(mapPlayerTable, hero) { hero.Energy = data.Const.HeroEnergy hero.EnergyCoverTime = 0 // 重置恢复时间 hero.FatigueEndTime = 0 // 重置疲惫状态结束时间 return true } // 检测更新疲惫状态 p.checkUpdateFatigueStatus(hero) return false } // SubEnergy 扣除体力 func (p *service) SubEnergy(hero *dbMapPlayer.Hero, energy int32) bool { if hero.Energy < energy { return false } hero.Energy -= energy if hero.EnergyCoverTime == 0 { hero.EnergyCoverTime = ctime.Now().ToSecond() } // 检测更新疲惫状态 p.checkUpdateFatigueStatus(hero) return true } // 检测是否更新疲惫状态 func (p *service) checkUpdateFatigueStatus(hero *dbMapPlayer.Hero) { // 满足一次行动所需的体力 diffEnergy := data.Const.HeroEnergyActionCost - hero.Energy // 如果是=0或者负值 表示不是疲惫状态 if diffEnergy <= 0 { hero.FatigueEndTime = 0 return } // 获取恢复一点体力所需要的时间 recoverOneEnergyNeedTime := data.Const.GetRecoverOneEnergyNeedTime() // 更新疲惫状态结束时间 hero.FatigueEndTime = ctime.Now().ToSecond() + int64(diffEnergy)*recoverOneEnergyNeedTime }