| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537 |
- package mapLogic
- import (
- capp "f1-game/internal/cherry_app"
- "f1-game/internal/code"
- "f1-game/internal/constant"
- "f1-game/internal/data"
- "f1-game/internal/enum"
- "f1-game/internal/event"
- nameRemote "f1-game/internal/name/remote"
- "f1-game/internal/pb"
- mapCall "f1-game/nodes/map/internal/call"
- "f1-game/nodes/map/internal/db"
- dbLogic "f1-game/nodes/map/internal/db/data/logic"
- mapTypes "f1-game/nodes/map/internal/types"
- clog "github.com/cherry-game/cherry/logger"
- )
- func (p *actor) initTileBattleFunc() {
- p.tileBattleResultFunc = map[enum.TileBattleType]tileBattleResultFunc{
- enum.TileBattle_PVP_Meet: p.onTileMeetBattleResult,
- enum.TileBattle_PVP_Occupy: p.onTileOccupyBattleResult,
- enum.TileBattle_PVE_Occupy: p.onTileOccupyBattleResult,
- enum.TileBattle_PVE_SiegeGarrison: p.onTileSiegeGarrisonResult,
- enum.TileBattle_PVE_SiegeDurability: p.onTileSiegeDurabilityResult,
- enum.TileBattle_PVP_Siege: p.onTileSiegeDefendResult,
- enum.TileBattle_PVE_SnatchGarrison: p.onTileSnatchGarrisonResult,
- enum.TileBattle_PVP_Snatch: p.onTileSnatchDefendResult,
- enum.TileBattle_PVE_Crusade: p.onTileCrusadeBattleResult,
- enum.TileBattle_PVE_Snatch: p.onTileSnatchResult,
- enum.TileBattle_PVN_Snatch: p.onTileSnatchResult,
- }
- }
- func (p *actor) initTileProcess() {
- for _, tileTable := range p.TileTables {
- // 需要处理的地块
- if tileTable.IsNeedToProcess() {
- p.addTileProcess(tileTable)
- }
- }
- }
- func (p *actor) tileTimer() {
- p.updateTime()
- // 只处理需要处理的地块
- for _, tileTable := range p.processTiles {
- p.tileTicker(tileTable)
- }
- }
- func (p *actor) tileTicker(tileTable *db.LogicTileTable) {
- // 如果地块上有驻地部队,要进行范围检查
- p.tileGarrisonCheck(tileTable)
- // 处理地块
- p.tileProcess(tileTable)
- // 检查是否需要继续处理
- p.tileCheck(tileTable)
- // 保存数据
- p.tileSave(tileTable)
- }
- func (p *actor) tileCheck(tileTable *db.LogicTileTable) {
- // 不再需要处理
- if !tileTable.IsNeedToProcess() {
- tileTable.IsNeedProcess = false
- tileTable.IsDataChanged = true
- p.processTiles.Remove(tileTable.TileID)
- }
- }
- func (p *actor) tileSave(tileTable *db.LogicTileTable) {
- // 保存数据,推送通知
- if tileTable.IsDataChanged {
- tileTable.IsDataChanged = false
- tileTable.Save2Queue()
- }
- }
- func (p *actor) tileProcess(tileTable *db.LogicTileTable) {
- // 处理撤退的队伍
- if tileTable.HasRetreater() {
- p.tileRetreat(tileTable)
- }
- if tileTable.HasBattleQueue() {
- p.tileBattleQueue(tileTable)
- }
- // 处理地块的战斗
- if tileTable.HasBattleHandle() {
- p.tileBattle(tileTable)
- }
- // 处理地块的攻城
- if tileTable.HasSiege() {
- p.tileSiege(tileTable)
- }
- // 处理地块的掠夺
- if tileTable.HasSnatch() {
- p.tileSnatch(tileTable)
- }
- // 处理地块的占领
- if tileTable.HasOccupyWait() {
- p.tileOccupy(tileTable)
- }
- }
- // tileGarrisonCheck 地块驻守部队碰撞检测
- func (p *actor) tileGarrisonCheck(tileTable *db.LogicTileTable) {
- if !tileTable.HasGarrison() {
- return
- }
- checkTiles := map[int32]*db.LogicTileTable{}
- if tileTable.BuildObjectID > 0 {
- buildTable := p.BuildTables.GetValue(tileTable.BuildObjectID)
- checkTiles = buildTable.GetTileTableMap(p.TileTables, false)
- } else if tileTable.CastleObjectID > 0 {
- castleTable := p.CastleTables.GetValue(tileTable.CastleObjectID)
- checkTiles = castleTable.GetTileTableMap(p.TileTables, false)
- }
- // 驻守应该是不用是检查自己的,他会先被其它部队碰撞掉
- // TODO 不清楚,先看看会不会有问题
- if len(checkTiles) == 0 {
- return
- }
- marchList := tileTable.GarrisonList.NextCount(data.Const.MapMeetBattleQueue, mapTypes.ReadyFilter(p.nowMillis))
- for _, pair := range marchList {
- attackObjectID, attackMarchInfo := pair.Key, pair.Value
- attackLeagueID := p.getMarchLeagueID(attackObjectID, attackMarchInfo.IsLegion)
- for _, checkTile := range checkTiles {
- // 有攻击队列说明正在打遭遇战,跳过
- if checkTile.HasAttacker() {
- delete(checkTiles, checkTile.TileID)
- continue
- }
- // 提交了多场战斗,跳过
- if checkTile.BattleQueue.Size() >= int(data.Const.MapMeetBattleQueue) {
- delete(checkTiles, checkTile.TileID)
- continue
- }
- defendObjectID, defendMarchInfo, ok := checkTile.GetDefender()
- // 没有防守方,跳过
- if !ok {
- delete(checkTiles, checkTile.TileID)
- continue
- }
- // 同一阵营,那么格子里面都是自己人,跳过
- defendLeagueID := p.getMarchLeagueID(defendObjectID, defendMarchInfo.IsLegion)
- if p.isSameLeague(attackLeagueID, defendLeagueID) {
- delete(checkTiles, checkTile.TileID)
- continue
- }
- // 驻守部队是进攻方,要保存状态
- attacker := p.MarchTables.GetValue(attackObjectID)
- attacker.SaveState(p.nowMillis)
- p.buildTilePVPBattle(tileTable, enum.TileBattle_PVP_Meet, attackObjectID, defendObjectID, attackMarchInfo, defendMarchInfo)
- }
- }
- }
- func (p *actor) tileBattle(tileTable *db.LogicTileTable) {
- p.onTileBattleStart(tileTable)
- }
- func (p *actor) tileBattleQueue(tileTable *db.LogicTileTable) {
- // 处理等待中的战斗
- p.onTileBattleWait(tileTable)
- // 处理已经有结果的战斗
- p.onTileBattleResult(tileTable)
- }
- // onTileBattleStart 执行战斗开始处理
- // 1. 打遭遇战
- // 2. 打守军战
- func (p *actor) onTileBattleStart(tileTable *db.LogicTileTable) {
- if tileTable.IsMeetting && !tileTable.HasMoreMeetBattles() {
- tileTable.MarkMeetingBattle(false)
- p.onTileMeetBattleEnd(tileTable)
- }
- if tileTable.HasMoreMeetBattles() {
- tileTable.MarkMeetingBattle(true)
- p.onTileMeetBattleStart(tileTable)
- return
- }
- if tileTable.HasOccupy() {
- p.onTileOccupyBattleStart(tileTable)
- return
- }
- if tileTable.HasCrusade() {
- p.onTileCrusadeBattleStart(tileTable)
- return
- }
- }
- func (p *actor) tileSiege(tileTable *db.LogicTileTable) {
- p.onTileSiegeStart(tileTable)
- }
- func (p *actor) tileSnatch(tileTable *db.LogicTileTable) {
- buildTable, ok := tileTable.GetBuild(p.TileTables, p.BuildTables)
- if !ok {
- return
- }
- siegeTable := p.SiegeTables.GetValue(buildTable.ObjectID)
- if siegeTable.RemainGarrisonArmies() > 0 {
- // 有驻城部队,先打驻城部队
- p.onTileSnatchGarrisonStart(tileTable, buildTable, siegeTable)
- } else if p.hasAutoDefend(siegeTable) {
- // 看看有无攻城城防部队:调动的,征兵的,自动守城的
- p.onTileSnatchDefendStart(tileTable, buildTable)
- } else {
- p.onTileSnatchResStart(tileTable, buildTable, siegeTable)
- }
- tileTable.IsDataChanged = true
- }
- // onTileBattleWait 等待战斗结果
- // 当有战斗结束响应之后, 根据输赢执行继续战斗还是撤退
- func (p *actor) onTileBattleWait(tileTable *db.LogicTileTable) {
- for _, battleInfo := range tileTable.BattleQueue {
- if battleInfo.IsTimeout(p.nowMillis, 10000) {
- p.onTileBattleTimeout(tileTable, battleInfo)
- }
- }
- }
- // onTileBattleResult 处理战斗结果
- func (p *actor) onTileBattleResult(tileTable *db.LogicTileTable) {
- for _, battleInfo := range tileTable.BattleQueue {
- if battleInfo.BattleResult == nil {
- continue
- }
- clog.Debugf("tile battle result: TileID = %v, AttackObjectID = %v, BattleType = %v, win = %v",
- tileTable.TileID, battleInfo.AttackObjectID, enum.GetBattleTypeName(battleInfo.BattleType),
- battleInfo.BattleResult.IsWin)
- if f, ok := p.tileBattleResultFunc[battleInfo.BattleType]; ok {
- f(tileTable, battleInfo)
- // 战斗推送数据缓存到 map
- push := p.buildMapBattlePush(tileTable, battleInfo)
- updateID := p.newUpdateID()
- aoiUpdateBattleMap.Put(updateID, push)
- // AOI 更新
- mapCall.AOI.UpdateWithID(push.AttackMarchObjectID, enum.ObjectType_March, updateID, nameRemote.MapLogic_AOIUpdateBattle)
- } else {
- clog.Errorf("tile battle result func not found: TileID = %v, BattleType = %v",
- tileTable.TileID, battleInfo.BattleType)
- }
- tileTable.RemoveBattleQueue(battleInfo.BattleID)
- }
- }
- // tilePVPBattleResult 行军战斗结果处理
- func (p *actor) tilePVPBattleResult(winner *db.LogicMarchTable, winnerMarchInfo *mapTypes.TileMarchInfo, loser *db.LogicMarchTable, loserMarchInfo *mapTypes.TileMarchInfo, tileTable *db.LogicTileTable) {
- if loserMarchInfo.TileID == tileTable.TileID {
- p.addMarchToTileRetreat(loser, tileTable, enum.RetreatType_Rout, false)
- tileTable.RemoveDefendType(loser.ObjectID, loserMarchInfo.DefendType)
- } else {
- otherTile := p.TileTables.GetValue(loserMarchInfo.TileID)
- p.addMarchToTileRetreat(loser, otherTile, enum.RetreatType_Rout, false)
- otherTile.RemoveDefendType(loser.ObjectID, loserMarchInfo.DefendType)
- }
- winnerMarchInfo.LogicEndTime = p.nowMillis + constant.MapLeastBattleWaitTime
- winnerMarchInfo.MarkBattleWait(false)
- // 驻守列表和自动防守列表恢复状态
- if winnerMarchInfo.DefendType == enum.TileDefend_Garrison || winnerMarchInfo.DefendType == enum.TileDefend_AutoDefend {
- marchTable := p.MarchTables.GetValue(winner.ObjectID)
- p.restoreMarchState(marchTable)
- }
- }
- // tileRetreat 撤退
- func (p *actor) tileRetreat(tileTable *db.LogicTileTable) {
- retreatNum := tileTable.RetreatNumForOneTick()
- for range retreatNum {
- retreatInfo := tileTable.RestreatList.Remove(0)
- if retreatInfo == nil {
- break
- }
- var (
- marchObjectID = retreatInfo.MarchObjectID
- marchState = enum.GetMarchStateByRetreatType(retreatInfo.RetreatType)
- isRemoveRedeploy = retreatInfo.IsRemoveRedeploy
- )
- p.startMarchIDBack(marchObjectID, marchState, isRemoveRedeploy)
- }
- if retreatNum > 0 {
- tileTable.IsDataChanged = true
- }
- }
- // tileOccupy 处理地块占领事件
- func (p *actor) tileOccupy(tileTable *db.LogicTileTable) {
- // 按照占领时间来排序,拿出下一个不处于战斗等待状态的
- marchObjectID, tileMarchInfo, ok := tileTable.OccupyWaitList.Next(mapTypes.ReadyFilter(p.nowMillis))
- if !ok {
- return
- }
- // 时间未到
- if tileMarchInfo.LogicEndTime > p.nowMillis {
- return
- }
- // 等待处理中
- marchTable := p.MarchTables.GetValue(marchObjectID)
- var occupySuc bool
- resTable, ok := p.ResTables.Get(marchTable.TargetObjectID)
- if ok {
- retCode := resTable.CanOccupy(p.nowMillis, marchTable.PlayerID, marchTable.LeagueID)
- if code.IsOK(retCode) {
- occupySuc = true
- } else {
- clog.Debugf("res occupy fail: MarchObjectID = %v, ResObjectID = %v, Code = %v", marchObjectID, resTable.ObjectID, retCode)
- }
- }
- // 判断占领上限
- watcherTable := p.WatcherTables.GetValue(marchTable.PlayerID)
- if len(watcherTable.Res) >= data.Const.MapResOccupyLimit {
- clog.Debugf("Res occupy fail: num limit [MarchObjectId = %d, ResObjectID = %d]", marchObjectID, resTable.ObjectID)
- occupySuc = false
- }
- // 从占领队列移除
- tileTable.RemoveOccupyWait(marchTable.ObjectID)
- // 部队撤退
- p.addMarchToRetreat(marchTable, enum.RetreatType_Retreat, false)
- // 如果占领失败
- if !occupySuc {
- return
- }
- p.removeWatcherRes(resTable)
- // 设置拥有者
- resTable.SetOwner(marchTable.PlayerID, marchTable.LeagueID)
- // 设置免战时间
- resTable.SetInvincibleEndTime(p.nowMillis + data.Const.GetResOccupyInvincibleTime())
- // 重置战报组
- resTable.ResetReport()
- // 重置采集时间
- resTable.ResetGatherTime(p.nowMillis)
- // 推送资源点
- p.UpdateObjectFull(resTable.ObjectID, resTable.Type)
- watcherTable.AddRes(resTable.ObjectID)
- // 推送
- p.PushOwnerMapObjectAdd(resTable.PlayerID, resTable.ToOwnerMapObjectPb())
- clog.Debugf("march occupy wait success. MarchID = %v, ResID = %v, Point = %v",
- marchTable.ObjectID, resTable.ObjectID, resTable.Point)
- capp.PostEvent(event.NewTileOccupy(marchTable.PlayerID, resTable.PlayerID, resTable.ConfigID, resTable.ResLevel))
- // 推送资源点占领事件
- capp.PostEvent(event.NewResOccupy(resTable.PlayerID, &event.MapResOccupyData{
- ObjectID: resTable.ObjectID,
- TileID: resTable.GetTileID(),
- ConfigID: resTable.ConfigID,
- InLeagueArea: p.isSameLeague(tileTable.LeagueID, marchTable.LeagueID),
- }))
- }
- // isTileMeet 是否在 tile 上碰撞
- func (p *actor) isTileMeet(tileTable *db.LogicTileTable, playerID, leagueID int64) (isMet bool, isAttack bool) {
- // 碰撞顺序
- // 1. 驻守部队
- if p.checkMeetMarchList(&tileTable.GarrisonList, playerID, leagueID) {
- clog.Debugf("[isTileMeet] garrison: TileID = %v, PlayerID = %d, LeagueID = %v", tileTable.TileID, playerID, leagueID)
- return true, true
- }
- // 2. 占领部队
- if p.checkMeetMarchList(&tileTable.OccupyList, playerID, leagueID) {
- clog.Debugf("[isTileMeet] occupy: TileID = %v, PlayerID = %d, LeagueID = %v", tileTable.TileID, playerID, leagueID)
- return true, true
- }
- if p.checkMeetMarchList(&tileTable.OccupyWaitList, playerID, leagueID) {
- clog.Debugf("[isTileMeet] occupy wait: TileID = %v, PlayerID = %d, LeagueID = %v", tileTable.TileID, playerID, leagueID)
- return true, true
- }
- // 2. 讨伐部队
- if p.checkMeetMarchList(&tileTable.CrusadeList, playerID, leagueID) {
- clog.Debugf("[isTileMeet] crusade: TileID = %v, PlayerID = %d, LeagueID = %v", tileTable.TileID, playerID, leagueID)
- return true, true
- }
- // 3. 攻城部队
- if p.checkMeetMarchList(&tileTable.SiegeList, playerID, leagueID) {
- clog.Debugf("[isTileMeet] siege: TileID = %v, PlayerID = %d, LeagueID = %v", tileTable.TileID, playerID, leagueID)
- return true, true
- }
- // 4. 停留部队
- if p.checkMeetMarchList(&tileTable.StayList, playerID, leagueID) {
- clog.Debugf("[isTileMeet] stay: TileID = %v, PlayerID = %d, LeagueID = %v", tileTable.TileID, playerID, leagueID)
- return true, true
- }
- // 5. 行军部队
- if p.checkMeetMarchList(&tileTable.MarchList, playerID, leagueID) {
- clog.Debugf("[isTileMeet] march: TileID = %v, PlayerID = %d, LeagueID = %v", tileTable.TileID, playerID, leagueID)
- return true, true
- }
- // last. 攻击部队
- if p.checkMeetMarchList(&tileTable.AttackList, playerID, leagueID) {
- clog.Debugf("[isTileMeet] attack: TileID = %v, PlayerID = %d, LeagueID = %v", tileTable.TileID, playerID, leagueID)
- return true, false
- }
- return false, false
- }
- func (p *actor) checkMeetMarchList(marchList *mapTypes.MarchList, playerID, leagueID int64) bool {
- for _, pair := range marchList.List {
- thisLeagueID := p.getMarchLeagueID(pair.Key, pair.Value.IsLegion)
- // 同联盟,不碰撞
- if p.isSameLeague(thisLeagueID, leagueID) {
- return false
- }
- // 自己不跟自己碰撞
- if !pair.Value.IsLegion {
- marchTable := p.MarchTables.GetValue(pair.Key)
- return marchTable.PlayerID != playerID
- }
- // TODO: 与军团的碰撞
- }
- return false
- }
- func (p *actor) addTileProcess(tileTable *db.LogicTileTable) {
- p.processTiles.Put(tileTable.TileID, tileTable)
- }
- func (p *actor) getChildTiles(tileTable *db.LogicTileTable) map[int32]*db.LogicTileTable {
- var childTiles = map[int32]*db.LogicTileTable{}
- for _, point := range tileTable.ChildPoints() {
- tileID, ok := data.PointToTileID(point.X, point.Y)
- if !ok {
- continue
- }
- childTileTable := p.TileTables.GetValue(tileID)
- childTiles[tileID] = childTileTable
- }
- return childTiles
- }
- func (p *actor) buildMapBattlePush(tileTable *db.LogicTileTable, battle *dbLogic.TileBattle) *pb.MapBattlePush {
- push := &pb.MapBattlePush{
- AttackMarchObjectID: battle.AttackObjectID,
- DefendMarchObjectID: battle.DefendObjectID,
- BattleType: int32(battle.BattleType),
- IsWin: battle.BattleResult != nil && battle.BattleResult.IsWin,
- Point: tileTable.Point.ToProto(),
- }
- // 可能是军团
- if attacker, ok := p.MarchTables.Get(battle.AttackObjectID); ok {
- push.AttackHeroConfigID = attacker.GetMainHeroConfigID()
- push.AttackMarchView = attacker.ToMarchView()
- }
- if defender, ok := p.MarchTables.Get(battle.DefendObjectID); ok {
- push.DefendHeroConfigID = defender.GetMainHeroConfigID()
- push.DefendMarchView = defender.ToMarchView()
- } else if battle.BattleResult != nil {
- if len(battle.BattleResult.Data.Tile.Monsters) > 0 {
- push.DefendMonsterGroupID = battle.BattleResult.Data.Tile.Monsters[0]
- }
- }
- return push
- }
- // tileGarrionRetreat 地块驻守部队撤退
- func (p *actor) tileGarrionRetreat(tileTable *db.LogicTileTable) {
- if tileTable.GarrisonList.Size() == 0 {
- return
- }
- for _, pair := range tileTable.GarrisonList.List {
- // TODO: 如果 MarchTable 是战斗状态,应该设置一个标记,在战斗结束后再检查了标记再撤退
- marchTable := p.MarchTables.GetValue(pair.Key)
- p.addMarchToTileRetreat(marchTable, tileTable, enum.RetreatType_Must, false)
- }
- tileTable.GarrisonList.Clear()
- tileTable.IsDataChanged = true
- }
- func (p *actor) isSameLeague(leagueID1, leagueID2 int64) bool {
- return leagueID1 == leagueID2 && leagueID1 != 0
- }
|