| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268 |
- package mapPlayer
- import (
- "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"
- nameEvent "f1-game/internal/name/event"
- nameLocal "f1-game/internal/name/local"
- nameRemote "f1-game/internal/name/remote"
- nameRoute "f1-game/internal/name/route"
- "f1-game/internal/pb"
- "f1-game/internal/sessions"
- "f1-game/internal/types"
- ao "f1-game/nodes/game/player/asset/origin"
- mapCall "f1-game/nodes/map/internal/call"
- "f1-game/nodes/map/internal/db"
- dbMapPlayer "f1-game/nodes/map/internal/db/data/player"
- mapFacade "f1-game/nodes/map/internal/facade"
- "f1-game/nodes/map/player/hero"
- "f1-game/nodes/map/player/team"
- ctime "github.com/cherry-game/cherry/extend/time"
- cfacade "github.com/cherry-game/cherry/facade"
- cproto "github.com/cherry-game/cherry/net/proto"
- )
- func (p *actorPlayer) initPlayerTeam() {
- p.Local().Register(nameLocal.MapPlayer_TeamUp, p.teamUp)
- p.Local().Register(nameLocal.MapPlayer_TeamLeave, p.teamLeave)
- p.Local().Register(nameLocal.MapPlayer_TeamChange, p.teamChange)
- p.Local().Register(nameLocal.MapPlayer_TeamInnerChange, p.teamInnerChange)
- p.Local().Register(nameLocal.MapPlayer_TeamLineup, p.teamLineup)
- p.Local().Register(nameLocal.MapPlayer_TeamTroops, p.teamTroops)
- p.Local().Register(nameLocal.MapPlayer_TeamAutoTroops, p.teamAutoTroops)
- p.Local().Register(nameLocal.MapPlayer_TeamOutsideTroops, p.teamOutsideTroops)
- p.Local().Register(nameLocal.MapPlayer_TeamOutsideTroopsCancel, p.teamOutsideTroopsCancel)
- p.Local().Register(nameLocal.MapPlayer_TeamOutsideAutoTroopsSet, p.teamOutsideAutoTroopsSet)
- p.Remote().Register(nameRemote.MapPlayer_UseMedicine, p.useMedicine)
- p.Remote().Register(nameRemote.MapPlayer_SubTeamTroopsNum, p.subTeamTroopsNum)
- p.Remote().Register(nameRemote.MapPlayer_UpdateTeamState, p.updateTeamState)
- p.Remote().Register(nameRemote.MapPlayer_SetTeamInjury, p.setTeamInjury)
- p.Remote().Register(nameRemote.MapPlayer_MarchArrive, p.marchArrive)
- // TODO: 可以把上面的更新都合并到这里
- p.Remote().Register(nameRemote.MapPlayer_UpdateTeam, p.updateTeam)
- //p.EventRegister(nameEvent.Map_MarchArrive, p.marchArrive)
- p.EventRegister(nameEvent.Lord_FacilityUp, p.onFacilityUpRefreshTeam)
- }
- // teamUp 英雄上阵
- func (p *actorPlayer) teamUp(session *cproto.Session, req *pb.TeamUpRequest) {
- playerTable := db.GetMapPlayerTable(p.playerID)
- var (
- heroGUID = req.HeroGUID
- teamID = req.TeamID
- teamIndex = req.TeamIndex
- index = req.Index
- )
- // 部队位置是否合法
- if !constant.ValidateTeamMemberTeamIndex(teamIndex) {
- p.ResponseCode(session, code.TeamIndexError)
- return
- }
- // 检测阵容位置是否正确
- if !constant.ValidateTeamMemberIndex(index) {
- p.ResponseCode(session, code.TeamLineupIndexError)
- return
- }
- // 获取英雄数据
- heroEntity, found := playerTable.GetHero(heroGUID)
- if !found {
- p.ResponseCode(session, code.HeroNotExist)
- return
- }
- if heroEntity.IsAlreadyTeamUp() {
- p.ResponseCode(session, code.TeamHeroAlreadyUp)
- return
- }
- if _, ok := data.HeroTeam.Get(teamID); !ok {
- p.ResponseCode(session, code.ConfigNotFound_HeroTeam)
- return
- }
- curTeam, ok := playerTable.Teams.GetTeam(teamID)
- if !ok {
- p.ResponseCode(session, code.TeamNotUnlock)
- return
- }
- if curTeam.IsNotStandby() {
- p.ResponseCode(session, code.TeamIsBusy)
- return
- }
- //检测是否存在相同英雄 过滤上阵位置英雄
- if team.Service().CheckTeamSameHero(playerTable, heroEntity.HeroID, 0, 0, teamID, teamIndex) {
- p.ResponseCode(session, code.TeamAlreadySameHero)
- return
- }
- updateHeros := []*dbMapPlayer.Hero{}
- // 先下阵旧的英雄 如果存在
- oldHero, errCode := team.Service().DoTeamLeave(playerTable, curTeam, teamIndex)
- if code.IsOK(errCode) && oldHero != nil {
- updateHeros = append(updateHeros, oldHero)
- }
- // 当前位置不存在英雄 判断上阵人数上限
- if curTeam.IsTeamMemberLimit() {
- p.ResponseCode(session, code.TeamMemberLimit)
- return
- }
- // 检测阵容位置是否存在英雄
- if curTeam.IsLineupMemberExist(index) {
- p.ResponseCode(session, code.TeamIndexHasHero)
- return
- }
- // 英雄上阵
- curTeam.NewAndAddTeamMember(heroGUID, teamIndex, index, heroEntity.InjuriesEndTime)
- // 重新刷新上阵英雄阵容位置
- team.Service().RefreshTeamLineup(playerTable, curTeam)
- // 更新队伍羁绊列表
- p.updateTeamFetterList(curTeam)
- heroEntity.TeamID = teamID
- playerTable.Save2Queue()
- updateHeros = append(updateHeros, heroEntity)
- // 推送英雄变化
- hero.Service().ChangePush(p.playerID, updateHeros...)
- proto := curTeam.ToProto()
- p.Response(session, &proto)
- // 同步到 redis 队伍信息
- team.Service().UpdatePlayerTeams(p.playerID, curTeam)
- p.PostEvent(event.NewTeamUp(p.playerID, teamID))
- }
- // teamLeave 英雄下阵
- func (p *actorPlayer) teamLeave(session *cproto.Session, req *pb.I32I32) {
- var (
- playerTable = db.GetMapPlayerTable(p.playerID)
- teamID, teamIndex = req.Key, req.Value
- )
- if playerTable == nil {
- p.ResponseCode(session, code.PlayerNotFound)
- return
- }
- curTeam, ok := playerTable.Teams.GetTeam(teamID)
- if !ok {
- p.ResponseCode(session, code.TeamNotUnlock)
- return
- }
- if curTeam.IsNotStandby() {
- p.ResponseCode(session, code.TeamIsBusy)
- return
- }
- //执行英雄下阵
- heroEntity, errCode := team.Service().DoTeamLeave(playerTable, curTeam, teamIndex)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- if heroEntity != nil {
- // 更新队伍羁绊列表
- p.updateTeamFetterList(curTeam)
- playerTable.Save2Queue()
- // 推送英雄变化
- hero.Service().ChangePush(p.playerID, heroEntity)
- // 同步到 redis 队伍信息
- team.Service().UpdatePlayerTeams(p.playerID, curTeam)
- }
- proto := curTeam.ToProto()
- p.Response(session, &proto)
- }
- // teamChange 英雄换阵
- func (p *actorPlayer) teamChange(session *cproto.Session, req *pb.TeamChangeRequest) {
- var (
- playerTable = db.GetMapPlayerTable(p.playerID)
- changeHeroes []*dbMapPlayer.Hero
- srcTeamID = req.SrcTeamID
- dstTeamID = req.DstTeamID
- srcTeamIndex = req.SrcTeamIndex
- dstTeamIndex = req.DstTeamIndex
- dstIndex = req.DstIndex
- )
- if srcTeamID == dstTeamID && srcTeamIndex == dstTeamIndex {
- p.ResponseCode(session, code.TeamIndexNotChange)
- return
- }
- //判断队伍位置是否合法
- if !constant.ValidateTeamMemberTeamIndex(srcTeamIndex, dstTeamIndex) {
- p.ResponseCode(session, code.TeamIndexError)
- return
- }
- // 判断队伍阵容位置是否合法
- if !constant.ValidateTeamMemberIndex(dstIndex) {
- p.ResponseCode(session, code.TeamLineupIndexError)
- return
- }
- srcTeam, ok := playerTable.Teams.GetTeam(srcTeamID)
- if !ok {
- p.ResponseCode(session, code.TeamNotUnlock)
- return
- }
- if srcTeam.IsNotStandby() {
- p.ResponseCode(session, code.TeamIsBusy)
- return
- }
- srcTeamMember, ok := srcTeam.GetTeamMember(srcTeamIndex)
- if !ok || srcTeamMember.HeroGUID == 0 {
- p.ResponseCode(session, code.HeroNotInTeam)
- return
- }
- srcHero, ok := playerTable.Heroes.Get(srcTeamMember.HeroGUID)
- if !ok {
- p.ResponseCode(session, code.HeroNotExist)
- return
- }
- dstTeam, ok := playerTable.Teams.GetTeam(dstTeamID)
- if !ok {
- p.ResponseCode(session, code.TeamNotUnlock)
- return
- }
- if dstTeam.IsNotStandby() {
- p.ResponseCode(session, code.TeamIsBusy)
- return
- }
- //不同队伍 检测是否上阵相同英雄
- if team.Service().CheckTeamSameHero(playerTable, srcHero.HeroID, srcTeamID, srcTeamIndex, dstTeamID, dstTeamIndex) {
- p.ResponseCode(session, code.TeamAlreadySameHero)
- return
- }
- // 被替换位置检测英雄下阵
- dstHero, errCode := team.Service().DoTeamLeave(playerTable, dstTeam, dstTeamIndex)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- if dstHero != nil {
- changeHeroes = append(changeHeroes, dstHero)
- }
- // 判断当前目标队伍是否达到队伍成员上限
- if srcTeamID != dstTeamID && dstTeam.IsTeamMemberLimit() {
- p.ResponseCode(session, code.TeamMemberLimit)
- return
- }
- // 判断目标队伍阵容位置是否存在英雄
- if dstTeam.IsLineupMemberExist(dstIndex) {
- p.ResponseCode(session, code.TeamIndexHasHero)
- return
- }
- srcTeam.DelTeamMember(srcTeamIndex)
- // 更新英雄所属队伍ID 换成目标队伍位置并添加到目标队伍中 删除原来队伍的位置数据
- srcHero.TeamID = dstTeamID
- srcTeamMember.TeamIndex = dstTeamIndex
- srcTeamMember.Index = dstIndex
- if dstHero != nil {
- srcTeamMember.InjureEndTime = dstHero.InjuriesEndTime
- }
- dstTeam.AddTeamMember(srcTeamMember)
- // 重新刷新上阵英雄阵容位置
- team.Service().RefreshTeamLineup(playerTable, dstTeam)
- // 更新源队伍&目标队伍羁绊列表
- p.updateTeamFetterList(srcTeam, dstTeam)
- playerTable.Save2Queue()
- changeHeroes = append(changeHeroes, srcHero)
- // 推送英雄变化
- hero.Service().ChangePush(p.playerID, changeHeroes...)
- // 同步队伍变更信息
- team.Service().ChangePush(p.playerID, srcTeam, dstTeam)
- // 同步到 redis 队伍信息
- team.Service().UpdatePlayerTeams(p.playerID, srcTeam, dstTeam)
- p.ResponseCode(session, code.OK)
- }
- // teamInnerChange 同队伍内换队伍位置
- func (p *actorPlayer) teamInnerChange(session *cproto.Session, req *pb.TeamInnerChangeRequest) {
- var (
- playerTable = db.GetMapPlayerTable(p.playerID)
- teamID = req.TeamID
- srcTeamIndex = req.SrcTeamIndex
- dstTeamIndex = req.DstTeamIndex
- )
- // 位置无变化
- if srcTeamIndex == dstTeamIndex {
- p.ResponseCode(session, code.TeamIndexNotChange)
- return
- }
- curTeam, found := playerTable.Teams.GetTeam(teamID)
- if !found {
- p.ResponseCode(session, code.TeamNotUnlock)
- return
- }
- if curTeam.IsNotStandby() {
- p.ResponseCode(session, code.TeamIsBusy)
- return
- }
- if !constant.ValidateTeamMemberTeamIndex(srcTeamIndex, dstTeamIndex) {
- p.ResponseCode(session, code.TeamIndexError)
- return
- }
- srcTeamMember, found := curTeam.GetTeamMember(srcTeamIndex)
- if !found {
- p.ResponseCode(session, code.HeroNotInTeam)
- return
- }
- srcHero, found := playerTable.Heroes.Get(srcTeamMember.HeroGUID)
- if !found {
- p.ResponseCode(session, code.HeroNotExist)
- return
- }
- changeHeroes := []*dbMapPlayer.Hero{srcHero}
- // 更换队伍位置
- dstTeamMember, found := curTeam.GetTeamMember(dstTeamIndex)
- if !found {
- srcTeamMember.TeamIndex = dstTeamIndex
- } else {
- dstHero, found := playerTable.Heroes.Get(dstTeamMember.HeroGUID)
- if !found {
- p.ResponseCode(session, code.HeroNotExist)
- return
- }
- srcTeamMember.TeamIndex, dstTeamMember.TeamIndex = dstTeamMember.TeamIndex, srcTeamMember.TeamIndex
- // 如果被替换的位置原来是主将位置, 则需要检测是否需要返还溢出兵力
- p.teamInnerChangeReturTroops(dstTeamMember, dstTeamIndex, srcTeamIndex)
- changeHeroes = append(changeHeroes, dstHero)
- }
- // 如果替换的位置原来是主将位置 则也需要返还溢出的兵力
- p.teamInnerChangeReturTroops(srcTeamMember, srcTeamIndex, dstTeamIndex)
- // 重新刷新上阵英雄阵容位置
- team.Service().RefreshTeamLineup(playerTable, curTeam)
- playerTable.Save2Queue()
- // 推送英雄变化
- hero.Service().ChangePush(p.playerID, changeHeroes...)
- // 同步到 redis 队伍信息
- team.Service().UpdatePlayerTeams(p.playerID, curTeam)
- proto := curTeam.ToProto()
- p.Response(session, &proto)
- }
- // 队伍内位置切换 如果原来位置是主将位置 当前位置不是主将位置 则返还溢出的兵力
- func (p *actorPlayer) teamInnerChangeReturTroops(teamMember *dbMapPlayer.TeamMember, srcTeamIndex, dstTeamIndex int32) {
- if !constant.IsTeamMainIndex(srcTeamIndex) {
- return
- }
- playerTable := db.GetMapPlayerTable(p.playerID)
- heroEntity, found := playerTable.Heroes.Get(teamMember.HeroGUID)
- if !found {
- p.Warn("teamInnerChangeReturTroops: hero not found, heroGUID: %d", teamMember.HeroGUID)
- return
- }
- curTroopsNumLimit := team.Service().GetHeroTroopsNum(p.playerID, heroEntity.HeroID, dstTeamIndex)
- diffTroopsNum := teamMember.TroopsNum - curTroopsNumLimit
- if diffTroopsNum <= 0 {
- return
- }
- teamMember.TroopsNum = curTroopsNumLimit
- // 返还兵力
- mapFacade.Storage.AssetAddOne(p.playerID, teamMember.TroopsID, int64(diffTroopsNum), ao.TeamInnerChangeReturn)
- }
- // teamLineup 英雄阵容设置
- func (p *actorPlayer) teamLineup(session *cproto.Session, req *pb.TeamLineupRequest) {
- var (
- playerTable = db.GetMapPlayerTable(p.playerID)
- teamID = req.TeamID
- index = req.Index
- toIndex = req.ToIndex
- )
- curTeam, ok := playerTable.Teams.GetTeam(teamID)
- if !ok {
- p.ResponseCode(session, code.TeamNotUnlock)
- return
- }
- //检测部队位置是否合法
- if !constant.ValidateTeamMemberIndex(index, toIndex) {
- p.ResponseCode(session, code.TeamIndexError)
- return
- }
- fromTeamMember, ok := curTeam.GetTeamMemberByIndex(index)
- if !ok || fromTeamMember.HeroGUID == 0 {
- p.ResponseCode(session, code.HeroNotInTeam)
- return
- }
- if fromTeamMember.Index == toIndex {
- p.ResponseCode(session, code.TeamIndexNotChange)
- return
- }
- //获取交换对象 如果原来位置存在英雄 则交换阵容位置 否则直接修改位置
- toTeamMember, found := curTeam.GetTeamMemberByIndex(toIndex)
- if found {
- //交换
- fromTeamMember.Index, toTeamMember.Index = toTeamMember.Index, fromTeamMember.Index
- } else {
- fromTeamMember.Index = toIndex
- }
- // 检测刷新阵容
- team.Service().RefreshTeamLineup(playerTable, curTeam)
- playerTable.Save2Queue()
- proto := curTeam.ToProto()
- p.Response(session, &proto)
- // TODO 后面如果阵容有加成也需要同步到 redis
- // team.Service().UpdatePlayerTeams(p.playerID, curTeam)
- }
- // teamTroops 队伍补兵
- func (p *actorPlayer) teamTroops(session *cproto.Session, req *pb.TeamTroopsRequest) {
- var (
- playerTable = db.GetMapPlayerTable(p.playerID)
- memberTroops = req.MemberTroops
- )
- if len(memberTroops) <= 0 {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- curTeam, ok := playerTable.Teams.GetTeam(req.TeamID)
- if !ok {
- p.ResponseCode(session, code.TeamNotUnlock)
- return
- }
- if curTeam.IsNotStandby() {
- p.ResponseCode(session, code.TeamIsBusy)
- return
- }
- // 分兵等级分组 key : 士兵ID value: 成员队伍位置 value 分兵数量
- groupMemberTroopMap, errCode := p.groupTroops(memberTroops)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- var (
- // 最终统兵情况 key: 队伍位置 value: key: 士兵ID 士兵等级表ID value: 分兵数量
- finalMemberTroops = map[int32]*pb.I32I32{}
- costAssets = types.Assets{}
- )
- for troopsID, troopsMap := range groupMemberTroopMap {
- _, found := data.ArmLevel.GetByID(troopsID)
- if !found {
- p.ResponseCode(session, code.ConfigNotExist_Conscript)
- return
- }
- // 获取最终分兵情况&消耗士兵数量
- costTroopsNum := p.GetFinalTeamTroopNum(curTeam, troopsID, troopsMap, finalMemberTroops)
- if costTroopsNum <= 0 {
- p.ResponseCode(session, code.TeamArmExceed)
- return
- }
- costAssets.Add(troopsID, int64(costTroopsNum))
- }
- // 消耗士兵
- _, errCode = mapFacade.Storage.AssetSubs(p.playerID, costAssets, ao.TeamTroopsCost)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- // 返还&重置英雄原带兵数量&更新英雄带兵ID
- p.returnAndResetTeamMemberTroopsNum(curTeam, groupMemberTroopMap)
- // 更新队伍上阵英雄带兵数量
- curTeam.UpdateTeamMemberTroopsNum(finalMemberTroops)
- playerTable.Save2Queue()
- // 同步到 redis 队伍信息
- team.Service().UpdatePlayerTeams(p.playerID, curTeam)
- proto := curTeam.ToProto()
- p.Response(session, &proto)
- // 发送分兵事件
- p.PostEvent(event.NewTeamTroops(p.playerID, curTeam.TeamID))
- }
- // teamAutoTroops 自动补兵设置
- func (p *actorPlayer) teamAutoTroops(session *cproto.Session, req *pb.I32) {
- var (
- playerTable = db.GetMapPlayerTable(p.playerID)
- teamID = req.Value
- )
- team, ok := playerTable.Teams.GetTeam(teamID)
- if !ok {
- p.ResponseCode(session, code.TeamNotUnlock)
- return
- }
- team.AutoAddTroops = !team.AutoAddTroops
- playerTable.Save2Queue()
- p.ResponseCode(session, code.OK)
- }
- // 分兵分组 key: 士兵ID value: 队伍阵容位置 value 分兵数量
- func (p *actorPlayer) groupTroops(memberTroops []*pb.TeamMemberTroops) (map[int32]map[int32]int32, int32) {
- memberTroopMap := map[int32]map[int32]int32{}
- for _, memberTroop := range memberTroops {
- // 检测队伍位置是否正确
- if !constant.ValidateTeamMemberTeamIndex(memberTroop.TeamIndex) {
- return nil, code.TeamIndexError
- }
- if memberTroop.TroopsNum <= 0 {
- return nil, code.TeamTroopsNumError
- }
- troopsMap, exist := memberTroopMap[memberTroop.TroopsID]
- if !exist {
- troopsMap = map[int32]int32{}
- memberTroopMap[memberTroop.TroopsID] = troopsMap
- }
- troopsMap[memberTroop.TeamIndex] = memberTroop.TroopsNum
- }
- return memberTroopMap, code.OK
- }
- // 获取队伍最终分兵数
- func (p *actorPlayer) GetFinalTeamTroopNum(curTeam *dbMapPlayer.Team, troopsID int32, memberTroops map[int32]int32, finalMemberTroops map[int32]*pb.I32I32) int32 {
- var (
- playerTable = db.GetMapPlayerTable(p.playerID)
- costTroopsNum int32
- curTroopNum int32
- finalAddTroopsNum int32
- )
- for teamIndex, addTroopNum := range memberTroops {
- if addTroopNum < 1 {
- continue
- }
- member, ok := curTeam.GetTeamMember(teamIndex)
- if !ok {
- continue
- }
- // 当前带兵数
- curTroopNum = member.TroopsNum
- finalAddTroopsNum = addTroopNum
- // 切换士兵等级 最终会返还英雄当前带兵数量
- if troopsID != member.TroopsID {
- curTroopNum = 0
- }
- heroEntity, found := playerTable.Heroes.Get(member.HeroGUID)
- if !found {
- p.Warn("GetFinalTeamTroopNum hero not found, heroGUID: %d", member.HeroGUID)
- continue
- }
- // 获取英雄带兵上限
- heroArmsLimit := team.Service().GetHeroTroopsNum(p.playerID, heroEntity.HeroID, member.TeamIndex)
- if curTroopNum+finalAddTroopsNum > heroArmsLimit {
- finalAddTroopsNum = heroArmsLimit - curTroopNum
- }
- costTroopsNum += finalAddTroopsNum
- data := pb.I32I32{
- Key: troopsID,
- Value: finalAddTroopsNum,
- }
- finalMemberTroops[teamIndex] = &data
- }
- return costTroopsNum
- }
- // 更新队伍士兵ID(士兵-等级表士兵ID)
- func (p *actorPlayer) updateTeamMemberTroopsID(teamMember *dbMapPlayer.TeamMember, level int32) {
- playerTable := db.GetMapPlayerTable(p.playerID)
- hero, found := playerTable.Heroes.Get(teamMember.HeroGUID)
- if !found {
- p.Warn("updateTeamMemberTroopsID hero not found, heroGUID: %d", teamMember.HeroGUID)
- return
- }
- heroRow, found := data.Hero.GetByID(hero.HeroID)
- if !found {
- p.Warn("updateTeamMemberTroopsID hero not found, heroID: %d", hero.HeroID)
- return
- }
- armLevelRow, found := data.ArmType.GetByTypeLevel(heroRow.Job, level)
- if !found {
- p.Warn("updateTeamMemberTroopsID hero not found, heroID: %d, job: %d, level: %d", hero.HeroID, heroRow.Job, level)
- return
- }
- teamMember.TroopTypeID = armLevelRow.ID
- }
- // 返还队伍兵力&重置英雄带兵数量&更新上阵英雄兵种ID
- func (p *actorPlayer) returnAndResetTeamMemberTroopsNum(team *dbMapPlayer.Team, groupMemberTroops map[int32]map[int32]int32) {
- if len(groupMemberTroops) <= 0 {
- return
- }
- returnAssets := types.Assets{}
- for troopsID, troopsMap := range groupMemberTroops {
- armLevelRow, exist := data.ArmLevel.GetByID(troopsID)
- for teamIndex := range troopsMap {
- teamMember, found := team.GetTeamMember(teamIndex)
- // 上阵英雄带兵ID改变 重置当前带兵数量&更新兵种ID
- if found && troopsID != teamMember.TroopsID {
- // 原来是否带兵 有兵返还 无兵不返还
- if teamMember.TroopsID != 0 && teamMember.TroopsNum > 0 {
- returnAssets.Add(teamMember.TroopsID, int64(teamMember.TroopsNum))
- teamMember.TroopsNum = 0
- }
- // 更新英雄兵种ID
- if exist {
- p.updateTeamMemberTroopsID(teamMember, armLevelRow.Level)
- }
- }
- }
- }
- // 返还下阵士兵
- if len(returnAssets) > 0 {
- _, errCode := mapFacade.Storage.AssetAdds(p.playerID, returnAssets, ao.TeamUpdateTroopsReturn)
- if code.IsFail(errCode) {
- p.Warn("returnAndResetTeamMemberTroopsNum error, teamID: %d, returnAssets: %v, errCode: %d", team.TeamID, returnAssets, errCode)
- }
- push := &pb.AssetList{
- List: returnAssets.ToProto(),
- }
- // 推送返还兵力
- sessions.PushPlayer(p.playerID, nameRoute.PushMapPlayer_TeamTroopReturn, push)
- }
- }
- func (p *actorPlayer) updateTeamState(req *pb.I32I32) {
- teamID := req.Key
- state := enum.TeamState(req.Value)
- playerTable := db.GetMapPlayerTable(p.playerID)
- if playerTable == nil {
- return
- }
- dbTeam, ok := playerTable.Teams.GetTeam(teamID)
- if !ok {
- return
- }
- // 更新队伍状态
- team.Service().UpdateTeamState(playerTable, dbTeam, state)
- }
- // 战败设置部队重伤
- func (p *actorPlayer) setTeamInjury(req *pb.I32I64) {
- var (
- playerID = p.playerID
- playerTable = db.GetMapPlayerTable(playerID)
- teamID, injuriesEndTime = req.Key, req.Value
- )
- p.Debug("[setTeamInjury] playerID = %d, teamID = %d, injuriesEndTime = %s", playerID, teamID, times.SecondToDatetimeFormat(injuriesEndTime))
- team, ok := playerTable.Teams.GetTeam(teamID)
- if !ok {
- p.Warn("[setTeamInjury] team not exist: playerID = %d, teamID = %d", playerID, teamID)
- return
- }
- resp := &pb.HeroStateResponse{}
- for _, member := range team.Members {
- // 恢复受伤的士兵
- if member.InjureTroops > 0 {
- member.TroopsNum += member.InjureTroops
- // 重置伤兵数
- member.InjureTroops = 0
- }
- hero, ok := playerTable.Heroes.Get(member.HeroGUID)
- if !ok {
- continue
- }
- hero.InjuriesEndTime = injuriesEndTime
- member.InjureEndTime = injuriesEndTime
- resp.HeroState = append(resp.HeroState, hero.ToHeroStateProto())
- }
- playerTable.Save2Queue()
- // 同步到march
- mapCall.Logic.MarchSyncInjure(team.MarchObjectID, injuriesEndTime)
- // 推送给客户端
- sessions.PushPlayer(playerID, nameRoute.PushMapPlayer_HeroState, resp)
- p.Debug("[setTeamInjury] teamID = %d, endTime = %s", teamID, times.MillisToDatetimeFormat(injuriesEndTime))
- }
- // 更新队伍羁绊列表
- func (p *actorPlayer) updateTeamFetterList(updateTeams ...*dbMapPlayer.Team) {
- if len(updateTeams) < 1 {
- return
- }
- playerTable := db.GetMapPlayerTable(p.playerID)
- for _, curTeam := range updateTeams {
- if len(curTeam.Members) < 1 {
- curTeam.FetterIDs.Clear()
- continue
- }
- // 获取英雄列表
- heroIDSet := types.Set[int32]{}
- for _, member := range curTeam.Members {
- curHeroEntity, found := playerTable.Heroes.Get(member.HeroGUID)
- if found {
- heroIDSet.Add(curHeroEntity.HeroID)
- }
- }
- // 刷新队伍羁绊
- fetterIDs := team.Service().GetFetterListByHeroList(p.playerID, heroIDSet)
- curTeam.FetterIDs = fetterIDs
- // 给部队的成员计算羁绊属性
- team.Service().TeamFetterAttrs(curTeam, playerTable.Heroes)
- }
- }
- // 使用药品
- func (p *actorPlayer) useMedicine(req *pb.I32I32) int32 {
- var (
- playerTable = db.GetMapPlayerTable(p.playerID)
- teamID = req.Key
- medicineID = req.Value
- )
- medicineRow, found := data.ItemMedicine.GetByMedicineID(medicineID)
- if !found {
- return code.ConfigNotFound_Medicine
- }
- curTeam, found := playerTable.Teams.GetTeam(teamID)
- if !found {
- return code.MapTeamNotFound
- }
- errCode := code.ItemUseTypeError
- switch medicineRow.UseType {
- case enum.MedicineType_Energy:
- // 使用体力药
- errCode = p.useEnergyMedicine(playerTable, curTeam, medicineRow)
- case enum.MedicineType_Troops:
- // 使用补兵药
- errCode = p.useTroopsMedicine(playerTable, curTeam, medicineRow)
- case enum.MedicineType_Injured:
- // 使用重伤药
- errCode = p.useInjuredMedicine(playerTable, curTeam)
- }
- if code.IsFail(errCode) {
- return errCode
- }
- // 推送队伍数据变更
- team.Service().ChangePush(p.playerID, curTeam)
- return code.OK
- }
- // 使用体力药
- func (p *actorPlayer) useEnergyMedicine(playerTable *db.MapPlayerTable, team *dbMapPlayer.Team, medicineRow *data.ItemMedicineRow) int32 {
- var (
- addEnergy = medicineRow.Value
- heroEnergyLimit = data.Const.HeroEnergy
- updateHeros = []*dbMapPlayer.Hero{}
- )
- // 检测是否能添加体力
- for _, member := range team.Members {
- dbHero, found := playerTable.Heroes.Get(member.HeroGUID)
- if !found {
- return code.HeroNotExist
- }
- if dbHero.Energy+addEnergy > heroEnergyLimit {
- return code.HeroEnergyOverflow
- }
- updateHeros = append(updateHeros, dbHero)
- }
- // 如果不存在可以恢复的英雄,则不进行恢复
- if len(updateHeros) < 1 {
- return code.HeroNotNeedRecovery
- }
- // 增加体力
- for _, dbHero := range updateHeros {
- hero.Service().AddEnergy(playerTable, dbHero, addEnergy)
- }
- // 保存英雄数据
- playerTable.Save2Queue()
- return code.OK
- }
- // 使用补兵药
- func (p *actorPlayer) useTroopsMedicine(playerTable *db.MapPlayerTable, curTeam *dbMapPlayer.Team, medicineRow *data.ItemMedicineRow) int32 {
- var (
- addTroops = medicineRow.Value
- update = false
- marchTroops []*pb.MarchTroops
- )
- // 城外征兵中 无法使用补兵药
- if curTeam.IsOutsideTroops() {
- return code.TeamOutsideTroops
- }
- for _, member := range curTeam.Members {
- heroEntity, found := playerTable.Heroes.Get(member.HeroGUID)
- if !found {
- return code.HeroNotExist
- }
- // 当前英雄带兵上限
- heroTroopsLimit := team.Service().GetHeroTroopsNum(p.playerID, heroEntity.HeroID, member.TeamIndex)
- // 超出上限跳过
- if member.TroopsNum >= heroTroopsLimit {
- continue
- }
- // 执行补兵 超出上限直接销毁
- // 计算实际可以补兵的数量
- add := min(addTroops, heroTroopsLimit-member.TroopsNum)
- member.TroopsNum += add
- marchTroops = append(marchTroops, &pb.MarchTroops{
- TeamIndex: member.TeamIndex,
- TroopsNum: add,
- })
- update = true
- }
- // 不需要补兵
- if !update {
- return code.TeamNotNeedAddTroops
- }
- playerTable.Save2Queue()
- // 更新地图队伍兵力数据
- mapCall.Logic.MarchSyncTroops(curTeam.TeamID, curTeam.MarchObjectID, marchTroops)
- // 同步队伍兵力
- team.Service().UpdatePlayerTeams(p.playerID, curTeam)
- // 推送队伍信息变更
- team.Service().ChangePush(p.playerID, curTeam)
- return code.OK
- }
- // 使用重伤药
- func (p *actorPlayer) useInjuredMedicine(playerTable *db.MapPlayerTable, curTeam *dbMapPlayer.Team) int32 {
- // 判断队伍当前状态
- if curTeam.IsNotStandby() {
- return code.TeamIsBusy
- }
- var (
- curTime = ctime.Now().ToSecond()
- updateHeros = []*dbMapPlayer.Hero{}
- )
- for _, member := range curTeam.Members {
- hero, found := playerTable.Heroes.Get(member.HeroGUID)
- if !found {
- return code.HeroNotExist
- }
- if curTime < hero.InjuriesEndTime {
- updateHeros = append(updateHeros, hero)
- }
- }
- if len(updateHeros) < 1 {
- return code.HeroNotNeedRecovery
- }
- for _, hero := range updateHeros {
- hero.InjuriesEndTime = 0
- }
- // 保存英雄数据
- playerTable.Save2Queue()
- if len(playerTable.NodeID) > 0 {
- // 同步地图队伍数据
- mapCall.Logic.MarchSyncInjure(curTeam.MarchObjectID, 0)
- }
- // 通知客户端更新
- team.Service().HeroStateChangePush(p.playerID, updateHeros...)
- return code.OK
- }
- // 战斗后执行扣除的兵力 增量扣除
- func (p *actorPlayer) subTeamTroopsNum(req *pb.TeamBattleDamage) {
- playerTable := db.GetMapPlayerTable(p.playerID)
- dbTeam, found := playerTable.Teams.GetTeam(req.TeamID)
- if !found {
- return
- }
- for _, battleTeamMember := range req.Members {
- teamMember, found := dbTeam.GetTeamMember(battleTeamMember.TeamIndex)
- if !found {
- p.Warn("subTeamTroopsNum teamMember not found. teamIndex: %d, troopsNum: %d, soldierNum: %d, teamID: %d",
- battleTeamMember.TeamIndex, battleTeamMember.TroopsNum, battleTeamMember.SoldierNum, req.TeamID)
- continue
- }
- // 战损兵力
- troopsDamage := max(0, battleTeamMember.TroopsNum-battleTeamMember.SoldierNum)
- teamMember.TroopsNum = max(0, teamMember.TroopsNum-troopsDamage)
- // 根据战损计算伤兵,回城\调度点\营帐再恢复伤兵
- diedNum := troopsDamage * data.Const.MapBattleLossTroops / constant.RatioBase
- injureNum := max(0, troopsDamage-diedNum)
- teamMember.InjureTroops += injureNum
- }
- playerTable.Save2Queue()
- // 兵力同步到redis
- team.Service().UpdatePlayerTeams(p.playerID, dbTeam)
- // 同步兵力给客户端
- team.Service().ChangePush(p.playerID, dbTeam)
- }
- func (p *actorPlayer) GetHero(playerTable *db.MapPlayerTable, heroGUID int64) (*dbMapPlayer.Hero, int32) {
- hero, ok := playerTable.Heroes.Get(heroGUID)
- if ok {
- return hero, code.OK
- }
- heroMap := redis.Game.GetPlayerHeros(p.playerID, heroGUID)
- if len(heroMap) > 0 {
- hero, found := heroMap[heroGUID]
- if !found {
- return nil, code.HeroNotExist
- }
- newHero := &dbMapPlayer.Hero{
- GUID: hero.Id,
- HeroID: hero.ConfigID,
- }
- playerTable.Heroes.Add(newHero)
- return newHero, code.OK
- }
- return nil, code.HeroNotExist
- }
- // 城外征兵
- func (p *actorPlayer) teamOutsideTroops(session *cproto.Session, req *pb.TeamOutsideTroops) {
- var (
- teamID = req.TeamID
- troopNums = req.TroopsNums
- playerTable = db.GetMapPlayerTable(p.playerID)
- )
- curTeam, found := playerTable.Teams.GetTeam(teamID)
- if !found {
- p.ResponseCode(session, code.TeamNotUnlock)
- return
- }
- // 不可以征兵
- if !curTeam.CanOutsideTroops {
- p.ResponseCode(session, code.TeamIsBusy)
- return
- }
- // 执行城外征兵
- errCode := team.Service().DoTeamOutsideTroops(p.playerID, curTeam, troopNums)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- playerTable.Save2Queue()
- resp := curTeam.ToOutsideTroopsProto()
- p.Response(session, resp)
- }
- // 城外取消征兵
- func (p *actorPlayer) teamOutsideTroopsCancel(session *cproto.Session, req *pb.TeamOutsideTroopsCancel) {
- var (
- teamID = req.TeamID
- teamIndexs = req.TeamIndexs
- playerTable = db.GetMapPlayerTable(p.playerID)
- )
- if len(teamIndexs) <= 0 {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- curTeam, found := playerTable.Teams.GetTeam(teamID)
- if !found {
- p.ResponseCode(session, code.TeamNotUnlock)
- return
- }
- // 取消城外征兵
- errCode := team.Service().TeamOutsideTroopsCancel(playerTable, curTeam, teamIndexs)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- playerTable.Save2Queue()
- resp := curTeam.ToOutsideTroopsProto()
- p.Response(session, resp)
- }
- // 设置城外自动征兵
- func (p *actorPlayer) teamOutsideAutoTroopsSet(session *cproto.Session, req *pb.I32) {
- teamID := req.Value
- playerTable := db.GetMapPlayerTable(p.playerID)
- team, found := playerTable.Teams.GetTeam(teamID)
- if !found {
- p.ResponseCode(session, code.TeamNotUnlock)
- return
- }
- team.IsAutoTroops = !team.IsAutoTroops
- playerTable.Save2Queue()
- resp := &pb.I32Bool{Key: teamID, Value: team.IsAutoTroops}
- p.Response(session, resp)
- }
- // 行军取消城外征兵
- func (p *actorPlayer) marchOutsideTroopsCancel(playerTable *db.MapPlayerTable, curTeam *dbMapPlayer.Team) {
- // 取消城外征兵
- errCode := team.Service().TeamOutsideTroopsCancel(playerTable, curTeam, curTeam.GetTeamIndexs())
- if code.IsFail(errCode) {
- return
- }
- // 去掉可征兵标识
- curTeam.CanOutsideTroops = false
- playerTable.Save2Queue()
- // 通知客户端取消城外征兵
- team.Service().TeamOutsideTroopsChangePush(playerTable.PlayerID, curTeam)
- }
- func (p *actorPlayer) marchArrive(eventData cfacade.IEventData) {
- e, ok := eventData.(*event.MarchArrive)
- if !ok {
- return
- }
- d := e.Data()
- playerTable := db.GetMapPlayerTable(p.playerID)
- if playerTable == nil {
- p.Warn("[marchArrive] fail, playerTable not found. playerID:%d, eventData: %v", p.playerID, eventData)
- return
- }
- dbTeam, found := playerTable.Teams.GetTeam(d.TeamID)
- if !found {
- p.Warn("[marchArrive] fail, team not found. playerID:%d, eventData: %v", p.playerID, eventData)
- return
- }
- // 如果部队是调动|待命,回复伤兵
- if d.MarchState == enum.MarchState_Redeploy || d.MarchState == enum.MarchState_Standby {
- // 回复伤兵
- team.Service().RecoveryInjureTroops(playerTable, dbTeam)
- }
- // 如果是调动,检查是否可以自动征兵
- if d.MarchState == enum.MarchState_Redeploy {
- // 检查调动的建筑是否可以自动征兵
- canOutsideConscript := team.Service().CheckCanOusideConscript(playerTable.PlayerID, d.TargetConfigID)
- if !canOutsideConscript {
- return
- }
- // 设置当前可以自动征兵检测
- dbTeam.CanOutsideTroops = true
- // 开启自动征兵状态
- if dbTeam.IsAutoTroops {
- team.Service().OutsideAutoTroops(playerTable, dbTeam)
- }
- playerTable.Save2Queue()
- }
- }
- // 刷新队伍
- func (p *actorPlayer) onFacilityUpRefreshTeam(c cfacade.IEventData) {
- var (
- playerTable = db.GetMapPlayerTable(p.playerID)
- updateTeams = []*dbMapPlayer.Team{}
- )
- teamCount := playerTable.Facilities.Attrs.GetI32(enum.AttrTeamCount)
- for i := int32(1); i <= teamCount; i++ {
- team, success := playerTable.Teams.AddTeam(i)
- if success {
- updateTeams = append(updateTeams, team)
- playerTable.SetChangeData()
- }
- }
- if len(updateTeams) > 0 {
- team.Service().ChangePush(p.playerID, updateTeams...)
- }
- }
- func (p *actorPlayer) updateTeam(req *pb.UpdateTeam) {
- playerTable := db.GetMapPlayerTable(p.playerID)
- dbTeam, ok := playerTable.Teams.GetTeam(req.TeamID)
- if !ok {
- p.Warn("[updateTeam] fail, team not found. playerID:%d, req: %+v", p.playerID, req)
- return
- }
- p.Debug("[updateTeam] req: %+v", req)
- switch enum.TeamUpdateType(req.TeamUpdateType) {
- case enum.TeamUpdate_Redeploy:
- {
- dbTeam.RedeployObject.Set(req.RedeployObjectID, enum.ObjectType(req.RedeployObjectType))
- playerTable.SetChangeData()
- }
- }
- }
|