actor_castle.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. package mapLogic
  2. import (
  3. "f1-game/internal/constant"
  4. "f1-game/internal/enum"
  5. "f1-game/internal/event"
  6. "f1-game/internal/pb"
  7. mapCall "f1-game/nodes/map/internal/call"
  8. "f1-game/nodes/map/internal/db"
  9. dbLogic "f1-game/nodes/map/internal/db/data/logic"
  10. mapTypes "f1-game/nodes/map/internal/types"
  11. ctime "github.com/cherry-game/cherry/extend/time"
  12. clog "github.com/cherry-game/cherry/logger"
  13. )
  14. func (p *actor) castleTimer() {
  15. for _, castleTable := range p.CastleTables {
  16. p.castleTicker(castleTable)
  17. if castleTable.IsDataChanged {
  18. castleTable.IsDataChanged = false
  19. castleTable.Save2Queue()
  20. }
  21. }
  22. }
  23. func (p *actor) castleTicker(castleTable *db.LogicCastleTable) {
  24. // 攻城地基的逻辑
  25. if castleTable.CastleType == pb.SysObjType_so_town {
  26. p.castleSiegeTownLogic(castleTable)
  27. }
  28. // 攻城判断
  29. if castleTable.IsBeingSiege() {
  30. p.castleSiegeCheck(castleTable)
  31. }
  32. }
  33. func (p *actor) castleSiegeCheck(castleTable *db.LogicCastleTable) {
  34. for tileID := range castleTable.SiegeTiles {
  35. tileTable := p.TileTables.GetValue(tileID)
  36. if !tileTable.HasSiege() {
  37. castleTable.RemoveSiegeTile(tileID)
  38. }
  39. }
  40. // 如果没有再被攻城了,通知自动防守部队解散
  41. if !castleTable.IsBeingSiege() {
  42. playerTeams := map[int64][]int32{}
  43. castleTable.AutoDefendList.Range(func(marchObjectID int64, _ *mapTypes.TileMarchInfo) bool {
  44. marchTable := p.MarchTables.GetValue(marchObjectID)
  45. playerTeams[marchTable.PlayerID] = append(playerTeams[marchTable.PlayerID], marchTable.TeamID)
  46. return true
  47. })
  48. castleTable.AutoDefendList.Clear()
  49. castleTable.IsDataChanged = true
  50. if len(playerTeams) > 0 {
  51. for playerID, teamIDs := range playerTeams {
  52. mapCall.Player.AutoDefendQuit(playerID, teamIDs...)
  53. }
  54. }
  55. }
  56. }
  57. func (p *actor) castleSiegeTownLogic(castleTable *db.LogicCastleTable) {
  58. siegeTown := &castleTable.SiegeTown
  59. // 未处于攻城阶段
  60. if !siegeTown.IsInSiegeStage() {
  61. return
  62. }
  63. // 更换阶段
  64. if p.nowMillis >= siegeTown.SiegeStageEndTime {
  65. switch siegeTown.SiegeStage {
  66. case enum.SiegeStage_Prepare: // 宣战 -> 攻城
  67. p.onCastleSiegeTownStart(castleTable)
  68. case enum.SiegeStage_Battle: // 攻城 -> 结束
  69. p.onCastleSiegeTownTimeout(castleTable)
  70. }
  71. }
  72. // 未进行攻城
  73. if siegeTown.AutoSiegeStage == enum.AutoSiegeStage_None {
  74. return
  75. }
  76. switch siegeTown.AutoSiegeStage {
  77. case enum.AutoSiegeStage_MainForce, enum.AutoSiegeStage_SiegeSquad:
  78. {
  79. p.castleSiegeTownAutoMainForce(castleTable)
  80. if siegeTown.AutoSiegeStage == enum.AutoSiegeStage_SiegeSquad {
  81. p.castleSiegeTownAutoSiegeSquad(castleTable)
  82. }
  83. }
  84. case enum.AutoSiegeStage_Siege:
  85. {
  86. p.castleSiegeTownAutoSiege(castleTable)
  87. }
  88. }
  89. // 判断是否需要切换阶段
  90. castleTable.CheckAutoSiegeStage(p.nowMillis)
  91. }
  92. // 城池攻城战开始
  93. func (p *actor) onCastleSiegeTownStart(castleTable *db.LogicCastleTable) {
  94. siegeTown := &castleTable.SiegeTown
  95. // 设置攻城阶段和结束时间
  96. siegeTown.SiegeStage = enum.SiegeStage_Battle
  97. siegeTown.SiegeStageEndTime = p.nowMillis + constant.MapCastleSiegeTime
  98. castleTable.IsDataChanged = true
  99. clog.Debugf(
  100. "castle siege town start: SiegeTownObjectID = %d, CastleObjectID = %d, LeagueID = %d, endTime = %s",
  101. castleTable.ObjectID, castleTable.ParentObjectID, castleTable.LeagueID,
  102. ctime.CreateFromTimestamp(siegeTown.SiegeStageEndTime).ToDateTimeFormat(),
  103. )
  104. p.UpdateObjectFull(castleTable.ObjectID, castleTable.Type)
  105. // 抛事件
  106. p.PostEvent(event.NewWarUpdate(castleTable.LeagueID, &event.WarUpdateData{
  107. CastleObjectID: castleTable.ParentObjectID,
  108. Stage: siegeTown.SiegeStage,
  109. StageEndTime: siegeTown.SiegeStageEndTime,
  110. MainForceNum: -1,
  111. SiegeSquadNum: -1,
  112. }))
  113. }
  114. func (p *actor) onCastleSiegeTownTimeout(castleTable *db.LogicCastleTable) {
  115. siegeTown := &castleTable.SiegeTown
  116. // 设置为结束
  117. siegeTown.SiegeStage = enum.SiegeStage_End
  118. castleTable.ResetSiegeTown(false)
  119. clog.Debugf("castle siege timeout: SiegeTownObjectID = %d, CastleObjectID = %d, LeagueID = %d",
  120. castleTable.ObjectID, castleTable.ParentObjectID, castleTable.LeagueID)
  121. // 抛事件
  122. p.PostEvent(event.NewWarUpdate(castleTable.LeagueID, &event.WarUpdateData{
  123. CastleObjectID: castleTable.ParentObjectID,
  124. Stage: siegeTown.SiegeStage,
  125. MainForceNum: -1,
  126. SiegeSquadNum: -1,
  127. }))
  128. }
  129. // 攻城大营主力自动出兵
  130. // 需要分配两段路径:攻城大营 -> 中间路径 -> 攻城点
  131. func (p *actor) castleSiegeTownAutoMainForce(castleTable *db.LogicCastleTable) {
  132. siegeTown := &castleTable.SiegeTown
  133. if siegeTown.MainForcePrepareList.Size() == 0 {
  134. return
  135. }
  136. count := len(siegeTown.MainForceDepartPath)
  137. for range count {
  138. if siegeTown.MainForcePrepareList.IsEmpty() {
  139. break
  140. }
  141. marchObjectID := siegeTown.MainForcePrepareList.Remove(0)
  142. marchTable := p.MarchTables.GetValue(marchObjectID)
  143. index := siegeTown.MainForceIndex % count
  144. // 第一段路径
  145. path1 := siegeTown.MainForceDepartPath[index]
  146. segment1 := dbLogic.NewAutoMarchSegment(enum.MarchType_Stay, path1, p.nowMillis, constant.MapMainForceWaitTimePart1)
  147. marchTable.AutoMarchInfo.Segments.Add(segment1)
  148. // 第二段路径
  149. path2 := siegeTown.MainForceArrivePath[index]
  150. segment2 := dbLogic.NewAutoMarchSegment(enum.MarchType_Siege, path2, 0, constant.MapMainForceWaitTimePart2)
  151. marchTable.AutoMarchInfo.Segments.Add(segment2)
  152. marchTable.MarkStartAutoSiege(castleTable.ParentObjectID)
  153. siegeTown.MainForceIndex++
  154. castleTable.IsDataChanged = true
  155. }
  156. }
  157. // 攻城大营拆迁队自动出兵
  158. // 需要分配两段路径:攻城大营 -> 中间路径 -> 攻城点
  159. func (p *actor) castleSiegeTownAutoSiegeSquad(castleTable *db.LogicCastleTable) {
  160. siegeTown := &castleTable.SiegeTown
  161. if siegeTown.SiegeSquadPrepareList.Size() == 0 {
  162. return
  163. }
  164. count := len(siegeTown.SiegeSquadDepartPath)
  165. for range count {
  166. if siegeTown.SiegeSquadPrepareList.IsEmpty() {
  167. break
  168. }
  169. marchObjectID := siegeTown.SiegeSquadPrepareList.Remove(0)
  170. marchTable := p.MarchTables.GetValue(marchObjectID)
  171. index := siegeTown.SiegeSquadIndex % count
  172. // 第一段路径
  173. path1 := siegeTown.SiegeSquadDepartPath[index]
  174. segment1 := dbLogic.NewAutoMarchSegment(enum.MarchType_Stay, path1, p.nowMillis, constant.MapSiegeSquadWaitTimePart1)
  175. marchTable.AutoMarchInfo.Segments.Add(segment1)
  176. // 第二段路径
  177. path2 := siegeTown.SiegeSquadArrivePath[index]
  178. segment2 := dbLogic.NewAutoMarchSegment(enum.MarchType_Siege, path2, 0, constant.MapSiegeSquadWaitTimePart2)
  179. marchTable.AutoMarchInfo.Segments.Add(segment2)
  180. marchTable.MarkStartAutoSiege(castleTable.ParentObjectID)
  181. siegeTown.SiegeSquadIndex++
  182. castleTable.IsDataChanged = true
  183. }
  184. }
  185. // 攻城大营自动出兵攻城
  186. // 只给两个列表的部队分配一段路径:攻城大营 -> 攻城点
  187. func (p *actor) castleSiegeTownAutoSiege(castleTable *db.LogicCastleTable) {
  188. siegeTown := &castleTable.SiegeTown
  189. // 给主力分配
  190. if !siegeTown.MainForcePrepareList.IsEmpty() {
  191. count := len(siegeTown.DirectPath)
  192. for range count {
  193. if siegeTown.MainForcePrepareList.IsEmpty() {
  194. break
  195. }
  196. marchObjectID := siegeTown.MainForcePrepareList.Remove(0)
  197. marchTable := p.MarchTables.GetValue(marchObjectID)
  198. // 一段路径
  199. index := siegeTown.MainForceIndex % count
  200. path := siegeTown.DirectPath[index]
  201. segment := dbLogic.NewAutoMarchSegment(enum.MarchType_Siege, path, p.nowMillis, constant.MapAutoSiegeWaitTimePart3)
  202. marchTable.AutoMarchInfo.Segments.Add(segment)
  203. marchTable.MarkStartAutoSiege(castleTable.ParentObjectID)
  204. siegeTown.MainForceIndex++
  205. castleTable.IsDataChanged = true
  206. }
  207. }
  208. // 给拆迁队分配
  209. if !siegeTown.SiegeSquadPrepareList.IsEmpty() {
  210. count := len(siegeTown.DirectPath)
  211. for range count {
  212. if siegeTown.SiegeSquadPrepareList.IsEmpty() {
  213. break
  214. }
  215. marchObjectID := siegeTown.SiegeSquadPrepareList.Remove(0)
  216. marchTable := p.MarchTables.GetValue(marchObjectID)
  217. // 一段路径
  218. index := siegeTown.SiegeSquadIndex % count
  219. path := siegeTown.DirectPath[index]
  220. segment := dbLogic.NewAutoMarchSegment(enum.MarchType_Siege, path, p.nowMillis, ctime.MillisecondsPerSecond)
  221. marchTable.AutoMarchInfo.Segments.Add(segment)
  222. marchTable.MarkStartAutoSiege(castleTable.ParentObjectID)
  223. siegeTown.SiegeSquadIndex++
  224. castleTable.IsDataChanged = true
  225. }
  226. }
  227. }