package model import ( "rocommon/util" "roserver/baseserver/model" "roserver/serverproto" "strings" ) const Refresh_Time_Gap = 6 * 60 * 60 //暂定6个小时刷新 /* type FriendTowerInfo struct { UUId uint64 NickName string ImgId int32 } */ type RoleTower struct { SaveObject nowTowerLevel int32 nowTowerPassTime int64 fightBeginTime int64 fightBegin bool RushRound int32 RushFightCount int32 FightCountReward int32 RankRewardRound int32 SysRewardTime uint64 //宠物印记奖励补偿(领取奖励时的时间戳) friendTower map[int32][]*serverproto.CommonPlayerBriefInfo //好友简介数据 RefreshTime int64 //好友数据刷新时间 towerLevelDayRewardTime uint64 //下次可领取奖励时间戳(馈赠奖励) } func newRoleTower(r *Role) *RoleTower { roleTower := &RoleTower{ SaveObject: SaveObject{ role: r, }, } roleTower.nowTowerLevel = 0 roleTower.nowTowerPassTime = 0 roleTower.fightBeginTime = 0 roleTower.fightBegin = false roleTower.RushRound = 0 roleTower.RushFightCount = 0 roleTower.FightCountReward = 0 roleTower.RankRewardRound = 0 roleTower.friendTower = map[int32][]*serverproto.CommonPlayerBriefInfo{} return roleTower } func (this *RoleTower) Load(msg interface{}) bool { proRole := msg.(*serverproto.Role) if proRole.RoleTower != nil { if proRole.RoleTower.NowTowerLevel >= 1 { this.nowTowerLevel = proRole.RoleTower.NowTowerLevel this.nowTowerPassTime = proRole.RoleTower.NowTowerTime if proRole.RoleTower.RushTower == nil { proRole.RoleTower.RushTower = &serverproto.RushTower{} this.SetDirty(true) } else { this.RushRound = proRole.RoleTower.RushTower.RushRound this.RushFightCount = proRole.RoleTower.RushTower.Count this.FightCountReward = proRole.RoleTower.RushTower.Reward this.RankRewardRound = proRole.RoleTower.RushTower.RankReward } } //初始化 if proRole.RoleTower.RushTower == nil { proRole.RoleTower.RushTower = &serverproto.RushTower{} proRole.RoleTower.RushTower.Count = 0 proRole.RoleTower.RushTower.RushRound = 0 proRole.RoleTower.RushTower.Reward = 0 this.SetDirty(true) } this.towerLevelDayRewardTime = proRole.RoleTower.TowerLevelDayRewardTime this.SysRewardTime = proRole.RoleTower.SysRewardTime } return true } func (this *RoleTower) OnlineProcess() { //圣典优化 后,玩家第一次查询保底奖励,根据this.RushRound作为最后一轮未领取的奖励 //保底战斗次数为0 表示,已经领取过奖励. if this.RushRound != 0 && this.RushRound > this.FightCountReward { reqMsg := &serverproto.SSGetRushBaseRewardReq{} reqMsg.Uid = this.role.GetUUid() reqMsg.RushType = model.Rush_Type_Tower reqMsg.RushRound = this.RushRound this.role.SendRank(reqMsg) } // 上线请求下冲榜是否有历史奖励可以领取 /* reqMsg := &serverproto.SSGetRushRankReq{ Uid: this.role.GetUUid(), RushType: model.Rush_Type_Tower, RushRound: this.RankRewardRound, } this.role.SendRank(reqMsg) */ //宠物印记奖励补偿 if this.SysRewardTime <= 0 { this.OnlineSysReward() } } func (this *RoleTower) Save() { this.SetDirty(false) //util.InfoF("[RoleTower] save...[%v]", this.role.GetUUid()) saveMsg := &serverproto.SSTowerDataSaveReq{ Tower: &serverproto.RoleTower{ TowerLevelDayRewardTime: this.towerLevelDayRewardTime, }, } //处理购买信息相关数据 saveMsg.Tower.SysRewardTime = this.SysRewardTime saveMsg.Tower.NowTowerLevel = this.nowTowerLevel saveMsg.Tower.NowTowerTime = this.nowTowerPassTime saveMsg.Tower.RushTower = &serverproto.RushTower{ RushRound: this.RushRound, Count: this.RushFightCount, Reward: this.FightCountReward, RankReward: this.RankRewardRound, } this.role.SendDb(saveMsg) } func (this *RoleTower) CopyData(data *serverproto.RoleTower) { data.NowTowerLevel = this.nowTowerLevel data.TowerLevelDayRewardTime = this.towerLevelDayRewardTime } func (this *RoleTower) Update(ms uint64) { } func (this *RoleTower) OnlineSysReward() { this.SysRewardTime = util.GetTimeMilliseconds() this.SetDirty(true) var rewardTower *model.ConvertSysRewardData = nil for idx := 0; idx < len(model.ConvertSysRewardList); idx++ { if this.nowTowerLevel < model.ConvertSysRewardList[idx].TowerLevel { break } rewardTower = model.ConvertSysRewardList[idx] } if rewardTower != nil && this.role.GetRolePet() != nil { this.role.GetRolePet().AddPetEquipByMapList(rewardTower.RewardList, false) } //util.InfoF("uid=%v OnlineSysReward rewardlist=%v", this.role.GetUUid(), rewardTower) } func (this *RoleTower) GetCurTower() int32 { return this.nowTowerLevel } func (this *RoleTower) IsTowerUnlock() bool { globalCfg, ok := serverproto.GlobalCfgLoader[int32(serverproto.GlobalType_Global_Climbing_Tower_Unlock)] if !ok { util.InfoF("uid=%v signup version not found", this.role.GetUUid()) return false } if this.role.GetRoleBattle().GetLevelId() < globalCfg.IVal { return false } return true } func (this *RoleTower) OnTowerFightBegin(towerLevel int32) (serverproto.ErrorCode, []*serverproto.KeyValueType) { if this.IsTowerUnlock() == false { return serverproto.ErrorCode_ERROR_CLIMBING_TOWER_IS_LOCKED, nil } if towerLevel != this.nowTowerLevel+1 { util.DebugF("[RoleTower] OnTowerFightBegin....tower level error [%v]: %v - %v", this.role.GetUUid(), towerLevel, this.nowTowerLevel) return serverproto.ErrorCode_ERROR_CLIMBING_TOWER_NOT_CUR_TOWER, nil } cfgData, ok := serverproto.ClimbingTowerCfgLoader[towerLevel] if !ok { util.DebugF("[RoleTower] OnTowerFightBegin....config not found [%v]:%v", this.role.GetUUid(), towerLevel) return serverproto.ErrorCode_ERROR_CLIMBING_TOWER_CONFIG_NOT_FOUND, nil } //先判定是否通过 this.fightBeginTime = util.GetTimeSeconds() TaskMagCheck(this.role, serverproto.TaskType_Climbing_Tower_Count, 1) util.DebugF("[RoleTower] OnTowerFightBegin....new tower battle begin [%v]", this.role.GetUUid()) //获取衰减系数 var decayList []*serverproto.KeyValueType if this.role.roleBattleAttr.curTotalFightPower > uint32(cfgData.FightCheck) { //if this.role.GetRoleFightPower().TotalFightPower > uint64(cfgData.FightCheck) { var kvList = map[int32]int32{} this.getDecayList(kvList) for k, v := range kvList { decayList = append(decayList, &serverproto.KeyValueType{Key: k, Value: v}) } } reqMsg := &serverproto.SSRushDataChangeReq{} reqMsg.Uid = this.role.GetUUid() reqMsg.RushType = model.Rush_Type_Tower reqMsg.Score = 1 this.role.SendRank(reqMsg) //todo wangzhaocan 发送到rank服务器 return serverproto.ErrorCode_ERROR_OK, decayList } func (this *RoleTower) getDecayList(kvList map[int32]int32) { convertData, ok := model.ConvertClimbPowerDecayFactorList[this.nowTowerLevel+1] if ok { convertData.GetDecayList(kvList, uint64(this.role.roleBattleAttr.curTotalFightPower)) //convertData.GetDecayList(kvList, this.role.GetRoleFightPower().TotalFightPower) } convertData, ok = model.ConvertClimbTimeDecayFactorList[this.nowTowerLevel+1] if ok { deltaTime := (util.GetTimeSeconds() - this.nowTowerPassTime) / 60 convertData.GetDecayList(kvList, uint64(deltaTime)) } cfgData, ok := model.ConvertTowerData[this.nowTowerLevel+1] if ok && cfgData.SPAdd != nil { kvList[cfgData.SPAdd.Key] += cfgData.SPAdd.Value } util.InfoF("uid=%v RoleTowerDecay kv=%v", this.role.GetUUid(), kvList) } func (this *RoleTower) OnTowerFightEnd(towerLevel, fightTime int32, recordTimeStamp uint64, ackMsg *serverproto.SCClimbingTowerEndAck) serverproto.ErrorCode { if ackMsg == nil { return serverproto.ErrorCode_ERROR_FAIL } if this.IsTowerUnlock() == false { return serverproto.ErrorCode_ERROR_CLIMBING_TOWER_IS_LOCKED } if towerLevel != this.nowTowerLevel+1 { return serverproto.ErrorCode_ERROR_CLIMBING_TOWER_NOT_CUR_TOWER } towerCfg, ok := serverproto.ClimbingTowerCfgLoader[towerLevel] if !ok { return serverproto.ErrorCode_ERROR_CLIMBING_TOWER_CONFIG_NOT_FOUND } //战斗力校验 curTotalFightPower := this.role.roleBattleAttr.curTotalFightPower if curTotalFightPower > 0 && curTotalFightPower < uint32(towerCfg.FightCheck) { return serverproto.ErrorCode_ERROR_FIGHT_CHECK } //if this.role.GetRoleFightPower() != nil && this.role.GetRoleFightPower().TotalFightPower < uint64(towerCfg.FightCheck) { // return serverproto.ErrorCode_ERROR_FIGHT_CHECK //} deltaTime := util.GetTimeSeconds() - this.nowTowerPassTime //时间判断 CloseDown tmpStrList := strings.Split(towerCfg.CloseDown, ";") if len(tmpStrList) >= 2 { tmpChallengeTime, _ := model.Str2Num(tmpStrList[0]) tmpRecharge, _ := model.Str2Num(tmpStrList[1]) //1 在对应关卡或者爬塔层的停留时间≥60分钟时,不会触发判定外挂机制 //2 玩家战力≥2.5*最低通关战力时,不会触发判定机制 fightCheck := uint64(towerCfg.FightCheck) * 25 / 10 if tmpChallengeTime > 0 && deltaTime < 60*60 && curTotalFightPower < uint32(fightCheck) && curTotalFightPower > 0 { if int(this.role.GetTotalRecharge()) < tmpRecharge && fightTime < int32(tmpChallengeTime) { this.role.GetRoleStatistic().RecordCheatData(CheatType_TowerLevel) return serverproto.ErrorCode_ERROR_BATTLE_LEVEL_CD_TIME } } } if fightTime < 0 || (towerCfg.MaxFightingTime+1 < fightTime) { //1秒修正时间 util.DebugF("[RoleTower] OnTowerFightEnd...fight time out %v, %v--%v--%v, %v ", this.role.GetUUid(), this.fightBeginTime, util.GetTimeSeconds(), fightTime, towerCfg.MaxFightingTime) return serverproto.ErrorCode_ERROR_CLIMBING_TOWER_OUT_OF_TIME } //给奖励 data, ok := model.ConvertTowerData[towerLevel] if ok { var addItemList = map[int32]int32{} for _, items := range data.ItemList { addItemList[items.Key] += items.Value } for _, exItems := range data.ExItemList { addItemList[exItems.Key] += exItems.Value } this.role.AddItemList(addItemList, AddFrom_Tower, true) } this.nowTowerLevel++ //当前关卡通过//跟新当前关卡,战力到rank,排名 this.passTowerInfoToRank(recordTimeStamp, int32(fightTime), false) this.nowTowerPassTime = util.GetTimeSeconds() this.SetDirty(true) this.onTowerLevelChange(this.nowTowerLevel - 1) ackMsg.TowerLevel = this.nowTowerLevel ackMsg.PassTime = this.nowTowerPassTime ackMsg.RewardList = data.ItemList ackMsg.ExRewardList = data.ExItemList if this.role.GetRoleCard() != nil { this.role.GetRoleCard().CheckUnLockState() } return serverproto.ErrorCode_ERROR_OK } func (this *RoleTower) onTowerLevelChange(oldTowerLevel int32) { if this.role.GetRoleCard() != nil { this.role.GetRoleCard().CheckUnLockState() } //超值礼包开启 if this.role.GetRoleActivity() != nil { this.role.GetRoleActivity().SuperChargeUnlockCheck( serverproto.UnlockChargeType_UChargeType_ClimbTowerLevel, &SuperChargeUnlockST{oldValue: oldTowerLevel}) } //跟新简介信息 this.role.GetRoleBase().UpdatePlayerBriefInfo(false) //爬塔层数 TaskMagCheck(this.role, serverproto.TaskType_Climbing_Tower_Level, this.nowTowerLevel) } func (this *RoleTower) PackFriendFightTower(towerLevel int32, ackMsg *serverproto.SCClimbingTowerEndAck) { if ackMsg == nil { return } tower, ok := this.friendTower[towerLevel] if !ok { return } info := &serverproto.FriendTowerInfo{ TowerLevel: towerLevel, } for _, brief := range tower { info.Infos = append(info.Infos, brief) } ackMsg.PassInfo = info } //通关更新榜单 func (this *RoleTower) passTowerInfoToRank(recordTimeStamp uint64, battleTime int32, isGM bool) { ntfMsg := &serverproto.SSTowerPassFightPowerNtf{ TowerBfInfo: &serverproto.TowerBriefInfo{ CommonInfo: &serverproto.CommonPlayerBriefInfo{ BattleRecordId: model.GenerateUid(), }, BattleTime: battleTime, }, RecordTimeStamp: recordTimeStamp, } levelCfgData, ok := serverproto.ClimbingTowerCfgLoader[this.nowTowerLevel] if ok { ntfMsg.TowerBfInfo.BattleVersion = levelCfgData.Version } this.role.GetRoleBriefInfo(ntfMsg.TowerBfInfo.CommonInfo) //获取当前最新战力 //ntfMsg.TowerBfInfo.CommonInfo.FightPower = int32(this.role.GetRoleFightPower().TotalFightPower) ntfMsg.TowerBfInfo.CommonInfo.FightPower = int32(this.role.roleBattleAttr.curTotalFightPower) //修正通关数据 ntfMsg.TowerBfInfo.CommonInfo.TowerLevel = this.nowTowerLevel ntfMsg.TowerBfInfo.CommonInfo.TowerTime = uint64(util.GetTimeSeconds()) this.role.SendRank(ntfMsg) } func (this *RoleTower) SendFriendInfoReqToDB(begin, end int32) { ntfMsg := &serverproto.SSGetFriendTowerInfoReq{} UidList := this.role.GetRoleSocial().GetFriendList() if UidList == nil { //清空好友爬塔数据 this.friendTower = make(map[int32][]*serverproto.CommonPlayerBriefInfo) return } for _, data := range UidList { ntfMsg.UidList = append(ntfMsg.UidList, data) } ntfMsg.Begin = begin ntfMsg.End = end this.role.SendDb(ntfMsg) } func (this *RoleTower) GetClimbingTowerInfo() { ackMsg := &serverproto.SCClimbingTowerInfoAck{} ackMsg.NowTowerLevel = this.nowTowerLevel ackMsg.PassTime = this.nowTowerPassTime ackMsg.TowerLevelDayRewardTime = this.towerLevelDayRewardTime //判断有没有到刷新时间 if this.RefreshTime != 0 && (this.RefreshTime+Refresh_Time_Gap >= util.GetTimeSeconds()) { //取[towerLevel+1 - towerLevel + 5]的数据 if len(this.friendTower) > 0 { for level := this.nowTowerLevel + 1; level <= this.nowTowerLevel+5; level++ { towerData, ok := this.friendTower[level] if !ok || len(towerData) <= 0 { continue } info := &serverproto.FriendTowerInfo{} info.TowerLevel = level for _, data := range towerData { info.Infos = append(info.Infos, data) } ackMsg.Infos = append(ackMsg.Infos, info) } } } else { //发送请求到DB刷新一遍好友信息 this.SendFriendInfoReqToDB(this.nowTowerLevel+1, this.nowTowerLevel+5) } this.role.ReplayGate(ackMsg, true) } //获得层数区间的所有好友 func (this *RoleTower) GetFriendTowerRange(begin, end int32) serverproto.ErrorCode { if begin > end || begin <= 0 || end <= 0 { return serverproto.ErrorCode_ERROR_CLIMBING_TOWER_FRIEND_ARGS } //还在刷新时间内 if this.RefreshTime != 0 && (this.RefreshTime+Refresh_Time_Gap >= util.GetTimeSeconds()) { ackMsg := &serverproto.SCFriendPassTowerInfoAck{} //取[begin, end]的数据 for level := begin; level <= end; level++ { towerData, ok := this.friendTower[level] if !ok || len(towerData) <= 0 { continue } info := &serverproto.FriendTowerInfo{} info.TowerLevel = level for _, data := range towerData { info.Infos = append(info.Infos, data) } ackMsg.Infos = append(ackMsg.Infos, info) } this.role.ReplayGate(ackMsg, true) } else { //发送请求到DB刷新一遍好友信息 this.SendFriendInfoReqToDB(begin, end) } return serverproto.ErrorCode_ERROR_OK } func (this *RoleTower) SendClimbingTowerInfo(begin int32, end int32) { ackMsg := &serverproto.SCFriendPassTowerInfoAck{} //取[begin, end]的数据 for level := begin; level <= end; level++ { towerData, ok := this.friendTower[level] if !ok || len(towerData) <= 0 { continue } info := &serverproto.FriendTowerInfo{} info.TowerLevel = level for _, data := range towerData { info.Infos = append(info.Infos, data) } ackMsg.Infos = append(ackMsg.Infos, info) } this.role.ReplayGate(ackMsg, true) } func (this *RoleTower) SetFriendBriefInfo(briefs []*serverproto.CommonPlayerBriefInfo) serverproto.ErrorCode { if briefs == nil { this.RefreshTime = util.GetTimeSeconds() return serverproto.ErrorCode_ERROR_OK } //重置 this.friendTower = make(map[int32][]*serverproto.CommonPlayerBriefInfo) for _, data := range briefs { this.friendTower[data.TowerLevel] = append(this.friendTower[data.TowerLevel], data) } this.RefreshTime = util.GetTimeSeconds() return serverproto.ErrorCode_ERROR_OK } func (this *RoleTower) SetTowerLevel(level int32) { if this.nowTowerLevel >= level { return } _, ok := serverproto.ClimbingTowerCfgLoader[level] if !ok { return } this.nowTowerLevel = level this.nowTowerPassTime = util.GetTimeSeconds() this.passTowerInfoToRank(0, 0, true) this.role.GetRoleBase().UpdatePlayerBriefInfo(false) TaskMagCheck(this.role, serverproto.TaskType_Climbing_Tower_Level, this.nowTowerLevel) this.SetDirty(true) if this.role.GetRoleCard() != nil { this.role.GetRoleCard().CheckUnLockState() } } //============================================= 爬塔冲榜 ============================================================ func (this *RoleTower) OnlineGetRushTowerBaseReward(rewardRound int32) { if rewardRound < 0 { return } if this.FightCountReward >= rewardRound { this.RushFightCount = 0 this.SetDirty(true) return } var addItemList = map[int32]int32{} model.GetRushActivityBaseReward(this.RushRound, model.Rush_Type_Tower, this.RushFightCount, addItemList) if len(addItemList) > 0 { this.role.AddMail(model.GlobalMailRushTowerBaseReward, serverproto.MailType_MailType_RushTower, addItemList, []int32{this.RushFightCount}, "", "") } this.FightCountReward = rewardRound this.SetDirty(true) } func (this *RoleTower) GetRushTowerBaseReward(ackMsg *serverproto.SCRushActivityRewardAck, rushRound int32) serverproto.ErrorCode { if ackMsg == nil { return serverproto.ErrorCode_ERROR_FAIL } if this.FightCountReward >= rushRound { return serverproto.ErrorCode_ERROR_RUSH_ACTIVITY_REWARD_FINISH } var addItemList = map[int32]int32{} model.GetRushActivityBaseReward(rushRound, model.Rush_Type_Tower, this.RushFightCount, addItemList) if len(addItemList) <= 0 { return serverproto.ErrorCode_ERROR_FAIL } for key, value := range addItemList { ackMsg.ItemList = append(ackMsg.ItemList, &serverproto.KeyValueType{ Key: key, Value: value, }) } this.role.AddItemList(addItemList, AddFrom_RushTower, true) this.FightCountReward = rushRound this.SetDirty(true) return serverproto.ErrorCode_ERROR_OK } func (this *RoleTower) GetRushTowerRankReward(ssAck *serverproto.SSGetRushRewardAck) serverproto.ErrorCode { if ssAck == nil { return serverproto.ErrorCode_ERROR_FAIL } if this.RankRewardRound >= ssAck.RushRound { return serverproto.ErrorCode_ERROR_RUSH_ACTIVITY_REWARD_FINISH } var addItemList = map[int32]int32{} for _, data := range ssAck.ItemList { addItemList[data.Key] += data.Value } this.role.AddItemList(addItemList, AddFrom_RushTower, true) this.RankRewardRound = ssAck.RushRound this.SetDirty(true) return serverproto.ErrorCode_ERROR_OK } func (this *RoleTower) GetRushTowerInfo(ackMsg *serverproto.SCTowerActivityAck, curRushRound int32) { if ackMsg == nil { return } ackMsg.FightCount = this.RushFightCount ackMsg.RankReward = false if this.RankRewardRound >= curRushRound { ackMsg.RankReward = true } ackMsg.ChallengReward = false if this.FightCountReward >= curRushRound { ackMsg.ChallengReward = true } } //增加冲榜分数 func (this *RoleTower) AddRushTowerScore(rushRound int32, score int32) { if rushRound == 0 { return } if rushRound == this.RushRound { this.RushFightCount++ } else { this.RushRound = rushRound this.RushFightCount = 1 } this.SetDirty(true) } func (this *RoleTower) CheckRankReward(finishRound int32) serverproto.ErrorCode { if this.RankRewardRound >= finishRound { return serverproto.ErrorCode_ERROR_FAIL } return serverproto.ErrorCode_ERROR_OK } func (this *RoleTower) SetRankReward(finishRound int32) { this.RankRewardRound = finishRound this.SetDirty(true) } //todo 根据round来设置 func (this *RoleTower) GetFightCountMailReward(rushRound int32) { if rushRound <= 0 { return } if this.FightCountReward < rushRound { //发送上一轮冲榜战斗次数的奖励邮件 var addItemList = map[int32]int32{} model.GetRushActivityBaseReward(this.RushRound, model.Rush_Type_Tower, this.RushFightCount, addItemList) if len(addItemList) > 0 { this.role.AddMail(model.GlobalMailRushTowerBaseReward, serverproto.MailType_MailType_RushTower, addItemList, []int32{this.RushFightCount}, "", "") } this.FightCountReward = rushRound this.RushFightCount = 0 this.SetDirty(true) } } //获取试炼馈赠 func (this *RoleTower) GetTowerLevelDayReward() serverproto.ErrorCode { curTime := util.GetTimeMilliseconds() //判断当前是否已经领取 if curTime <= this.towerLevelDayRewardTime { return serverproto.ErrorCode_ERROR_FAIL } dayRewardIdx := -1 for idx := 0; idx < len(model.GlobalClimbingTowerDayReward); idx++ { if model.GlobalClimbingTowerDayReward[idx].Key > this.nowTowerLevel { break } dayRewardIdx = idx } if dayRewardIdx < 0 || dayRewardIdx >= len(model.GlobalClimbingTowerDayReward) { return serverproto.ErrorCode_ERROR_FAIL } this.role.AddItem(int32(serverproto.ResType_Res_CreditRecharge), model.GlobalClimbingTowerDayReward[dayRewardIdx].Value, AddFrom_Tower) this.towerLevelDayRewardTime = util.GetLatest5Hour() this.SetDirty(true) // reward ack msg ackMsg := &serverproto.SCClimbingTowerDayRewardAck{ NextDayRewardTime: this.towerLevelDayRewardTime, } ackMsg.RewardList = append(ackMsg.RewardList, &serverproto.KeyValueType{ Key: int32(serverproto.ResType_Res_CreditRecharge), Value: model.GlobalClimbingTowerDayReward[dayRewardIdx].Value, }) this.role.ReplayGate(ackMsg, true) return serverproto.ErrorCode_ERROR_OK }