actor_castle.go 8.5 KB

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