| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269 |
- 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)
- // 刷新队伍带兵上限
- team.Service().RefreshTeamTroopsLimit(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)
- // 刷新英雄带兵上限
- team.Service().RefreshTeamTroopsLimit(playerTable, dstTeam, srcTeam)
- // 更新源队伍&目标队伍羁绊列表
- 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
- }
- var (
- changeHeroes = []*dbMapPlayer.Hero{srcHero}
- dstTeamIndexReturnTroops = false
- )
- // 更换队伍位置
- 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
- dstTeamIndexReturnTroops = true
- changeHeroes = append(changeHeroes, dstHero)
- }
- // 刷新英雄带兵上限
- team.Service().RefreshTeamTroopsLimit(playerTable, curTeam)
- // 如果被替换的位置原来是主将位置, 则需要检测是否需要返还溢出兵力 这之前需要先刷新带兵上限
- if dstTeamIndexReturnTroops {
- p.teamInnerChangeReturTroops(dstTeamMember, dstTeamIndex)
- }
- // 如果替换的位置原来是主将位置 则也需要返还溢出的兵力
- p.teamInnerChangeReturTroops(srcTeamMember, srcTeamIndex)
- // 重新刷新上阵英雄阵容位置
- 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 int32) {
- if !constant.IsTeamMainIndex(srcTeamIndex) {
- return
- }
- diffTroopsNum := teamMember.TroopsNum - teamMember.TroopsLimit
- if diffTroopsNum <= 0 {
- return
- }
- teamMember.TroopsNum = teamMember.TroopsLimit
- // 返还兵力
- 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 (
- 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
- }
- if curTroopNum+finalAddTroopsNum > member.TroopsLimit {
- finalAddTroopsNum = member.TroopsLimit - 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 {
- // 超出上限跳过
- if member.TroopsNum >= member.TroopsLimit {
- continue
- }
- // 执行补兵 超出上限直接销毁
- // 计算实际可以补兵的数量
- add := min(addTroops, member.TroopsLimit-member.TroopsNum)
- member.TroopsNum += add
- marchTroops = append(marchTroops, &pb.MarchTroops{
- TeamIndex: member.TeamIndex,
- TroopsNum: member.TroopsNum,
- TroopsMax: member.TroopsLimit,
- })
- 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()
- }
- }
- // 刷新所有队伍成员带兵上限
- refreshTeams := team.Service().RefreshTeamTroopsLimit(playerTable, playerTable.Teams...)
- if len(refreshTeams) > 0 {
- updateTeams = append(updateTeams, refreshTeams...)
- // 同步队伍兵力
- team.Service().UpdatePlayerTeams(p.playerID, refreshTeams...)
- }
- 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()
- }
- }
- }
|