DynamicObstacleController.lua 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. local DynamicObstacleController = class('DynamicObstacleController', framework.Mediator)
  2. DynamicObstacleController.NAME = "DynamicObstacleController"
  3. local INVALID_MAP_POS = 0xFFFF
  4. function DynamicObstacleController:ctor()
  5. DynamicObstacleController.super.ctor(self, self.NAME)
  6. self._obstacles = {}
  7. end
  8. function DynamicObstacleController:destory()
  9. if DynamicObstacleController.instance then
  10. global.Facade:removeMediator( DynamicObstacleController.NAME )
  11. DynamicObstacleController.instance = nil
  12. end
  13. end
  14. function DynamicObstacleController:Inst()
  15. if not DynamicObstacleController.instance then
  16. DynamicObstacleController.instance = DynamicObstacleController.new()
  17. global.Facade:registerMediator(DynamicObstacleController.instance)
  18. end
  19. return DynamicObstacleController.instance
  20. end
  21. function DynamicObstacleController:onRegister()
  22. DynamicObstacleController.super.onRegister(self)
  23. local function actCallback(actor, act)
  24. -- 非移动类action
  25. if not IsMoveAction(act) then
  26. return
  27. end
  28. self:dynamicPathPoints()
  29. end
  30. global.gamePlayerController:AddHandleOnActCompleted(actCallback)
  31. end
  32. function DynamicObstacleController:listNotificationInterests()
  33. local noticeTable = global.NoticeTable
  34. return
  35. {
  36. noticeTable.ActorInOfView,
  37. noticeTable.ActorOutOfView,
  38. noticeTable.ActorPlayerDie,
  39. noticeTable.ActorMonsterDie,
  40. noticeTable.ActorMonsterDeath,
  41. noticeTable.ActorRevive,
  42. noticeTable.ActorEffectInOfView,
  43. noticeTable.ActorEffectOutOfView,
  44. noticeTable.PlayerStallStatucChange,
  45. noticeTable.ActorSafeZoneChange,
  46. noticeTable.ActorMapXYChange,
  47. noticeTable.MapData_Load_Success,
  48. noticeTable.Map_Refresh_Throug_HHum,
  49. }
  50. end
  51. function DynamicObstacleController:handleNotification(notification)
  52. local noticeTable = global.NoticeTable
  53. local noticeID = notification:getName()
  54. local data = notification:getBody()
  55. if noticeID == noticeTable.ActorInOfView then
  56. self:onActorInOfView(data)
  57. elseif noticeID == noticeTable.ActorOutOfView then
  58. self:onActorOutOfView(data)
  59. elseif noticeID == noticeTable.ActorPlayerDie then
  60. self:onActorPlayerDie(data)
  61. elseif noticeID == noticeTable.ActorMonsterDie then
  62. self:onActorMonsterDie(data)
  63. elseif noticeID == noticeTable.ActorMonsterDeath then
  64. self:onActorMonsterDeath(data)
  65. elseif noticeID == noticeTable.ActorRevive then
  66. self:onActorRevive(data)
  67. elseif noticeID == noticeTable.ActorEffectInOfView then
  68. self:onActorEffectInOfView(data)
  69. elseif noticeID == noticeTable.ActorEffectOutOfView then
  70. self:onActorEffectOutOfView(data)
  71. elseif noticeID == noticeTable.PlayerStallStatucChange then
  72. self:onPlayerStallStatucChange(data)
  73. elseif noticeID == noticeTable.ActorSafeZoneChange then
  74. self:onActorSafeZoneChange(data)
  75. elseif noticeID == noticeTable.ActorMapXYChange then
  76. self:onActorMapXYChange(data)
  77. elseif noticeID == noticeTable.MapData_Load_Success then
  78. self:onMapDataLoadSuccess()
  79. elseif noticeID == noticeTable.Map_Refresh_Throug_HHum then
  80. self:onUpdateAllObstacles()
  81. end
  82. end
  83. function DynamicObstacleController:checkActorIsObstacle(actor)
  84. -- main player
  85. if actor:IsPlayer() and actor:IsMainPlayer() then
  86. return false
  87. end
  88. -- 管理员不受控制
  89. local MapProxy = global.Facade:retrieveProxy(global.ProxyTable.Map)
  90. if MapProxy:IsAdmin() and MapProxy:IsGMRunAll() then
  91. return false
  92. end
  93. -- dead
  94. if actor:IsDie() or actor:IsDeath() then
  95. return false
  96. end
  97. -- 该actor服务器控制可穿
  98. if (actor:IsNPC() or actor:IsPlayer() or actor:IsMonster()) and actor:IsThroughAble() then
  99. return false
  100. end
  101. local MapProxy = global.Facade:retrieveProxy(global.ProxyTable.Map)
  102. local isCrossAllSafeArea = MapProxy:IsCrossAllSafeArea() -- 安全区 不受控制
  103. local isForbidCrossNPCSafeArea = MapProxy:IsFirbidCrossNpcSafeArea() -- 安全区 禁止穿 NPC
  104. local isFirbidCrossStallSafeArea = MapProxy:IsFirbidCrossStallSafeArea() -- 安全区 禁止穿 摆摊玩家
  105. local isFirbidCrossOfflineSafeArea = MapProxy:IsFirbidCrossOfflineSafeArea() -- 安全区 禁止穿 离线玩家
  106. -- new obstacle data
  107. local isObstacle = 0
  108. if actor:IsNPC() then
  109. isObstacle = MapProxy:IsCrossNpcEnable() and 0 or 1
  110. if actor:GetInSafeZone() then
  111. isObstacle = isCrossAllSafeArea and 0 or isObstacle
  112. isObstacle = isFirbidCrossStallSafeArea and 1 or isObstacle
  113. end
  114. elseif actor:IsPlayer() then
  115. isObstacle = (MapProxy:IsCrossPlayerEnable() and 0 or 1)
  116. if actor:GetInSafeZone() then
  117. isObstacle = isCrossAllSafeArea and 0 or isObstacle
  118. if actor:IsStallStatus() then
  119. isObstacle = isFirbidCrossStallSafeArea and 1 or isObstacle
  120. end
  121. if actor:GetIsOffLine() then
  122. isObstacle = isFirbidCrossOfflineSafeArea and 1 or isObstacle
  123. end
  124. end
  125. elseif actor:IsDefender() then
  126. isObstacle = (MapProxy:IsCrossDefenderEnable() and 0 or 1)
  127. if actor:GetInSafeZone() then
  128. isObstacle = isCrossAllSafeArea and 0 or isObstacle
  129. end
  130. elseif actor:IsMonster() then
  131. isObstacle = (MapProxy:IsCrossMonsterEnable() and 0 or 1)
  132. if actor:GetInSafeZone() then
  133. isObstacle = isCrossAllSafeArea and 0 or isObstacle
  134. end
  135. elseif actor:IsSEffect() then
  136. local mainPlayerID = global.gamePlayerController:GetMainPlayerID()
  137. isObstacle = (actor:GetEffectType() == global.MMO.EFFECT_TYPE_EMPTY and actor:GetDuranceID() == mainPlayerID) and 1 or 0
  138. end
  139. return isObstacle == 1
  140. end
  141. function DynamicObstacleController:addRef(x, y)
  142. local key = KEY_MAP_XY(x, y)
  143. self._obstacles[key] = self._obstacles[key] or 0
  144. self._obstacles[key] = self._obstacles[key] + 1
  145. -- 第一次增加引用计数,将地图置为阻挡状态
  146. if self._obstacles[key] == 1 then
  147. local mapData = global.sceneManager:GetMapData2DPtr()
  148. if not mapData then
  149. return nil
  150. end
  151. mapData:setObstacle(x, y, 1)
  152. end
  153. end
  154. function DynamicObstacleController:decRef(x, y)
  155. local key = KEY_MAP_XY(x, y)
  156. self._obstacles[key] = self._obstacles[key] or 0
  157. self._obstacles[key] = self._obstacles[key] - 1
  158. -- 警告
  159. if self._obstacles[key] < 0 then
  160. print("WARNING, dynamic obstacle less than 0!!!", self._obstacles[key], x, y)
  161. PrintTraceback()
  162. end
  163. -- 计数 < 0, 当前位置已无动态阻挡
  164. if self._obstacles[key] <= 0 then
  165. self._obstacles[key] = nil
  166. local mapData = global.sceneManager:GetMapData2DPtr()
  167. if not mapData then
  168. return nil
  169. end
  170. mapData:setObstacle(x, y, 0)
  171. end
  172. end
  173. function DynamicObstacleController:onActorMapXYChange(data)
  174. if not data or not data.actor then
  175. return
  176. end
  177. local actor = data.actor
  178. local lastMapX = actor:GetLastMapX()
  179. local lastMapY = actor:GetLastMapY()
  180. local currMapX = actor:GetMapX()
  181. local currMapY = actor:GetMapY()
  182. -- 该Actor无阻挡标记,不进行阻挡引用计数 +-
  183. if not actor:IsObstacleFlag() then
  184. return
  185. end
  186. -- 当前坐标点无效,可能是未执行进视野先执行了刷新
  187. if currMapX == INVALID_MAP_POS and currMapY == INVALID_MAP_POS then
  188. return
  189. end
  190. if lastMapX ~= INVALID_MAP_POS and lastMapY ~= INVALID_MAP_POS then
  191. self:decRef(lastMapX, lastMapY)
  192. end
  193. self:addRef(currMapX, currMapY)
  194. end
  195. function DynamicObstacleController:checkAddObstacle(data)
  196. if not data or not data.actor then
  197. return
  198. end
  199. local actor = data.actor
  200. -- 检测是否给阻挡标记
  201. local isObstacle = self:checkActorIsObstacle(actor)
  202. actor:SetObstacleFlag(isObstacle)
  203. -- 不存在阻挡标记
  204. if not actor:IsObstacleFlag() then
  205. return
  206. end
  207. -- 增加该位置引用计数
  208. local currMapX = actor:GetMapX()
  209. local currMapY = actor:GetMapY()
  210. self:addRef(currMapX, currMapY)
  211. end
  212. function DynamicObstacleController:checkRemoveObstacle(data)
  213. if not data or not data.actor then
  214. return
  215. end
  216. local actor = data.actor
  217. -- 不存在阻挡标记
  218. if not actor:IsObstacleFlag() then
  219. return
  220. end
  221. -- ???? 是否应该置为 false
  222. actor:SetObstacleFlag(false)
  223. -- 减少该位置引用计数
  224. local currMapX = actor:GetMapX()
  225. local currMapY = actor:GetMapY()
  226. self:decRef(currMapX, currMapY)
  227. end
  228. function DynamicObstacleController:checkUpdateObstacle(data)
  229. -- 注意这里刷新,坐标无改变,应认为 同位置刷新
  230. if not data or not data.actor then
  231. return
  232. end
  233. local actor = data.actor
  234. local currMapX = actor:GetMapX()
  235. local currMapY = actor:GetMapY()
  236. -- 当前坐标点无效,可能是未执行进视野先执行了刷新
  237. if currMapX == INVALID_MAP_POS and currMapY == INVALID_MAP_POS then
  238. return
  239. end
  240. -- 否是阻挡
  241. local lastObstacleFlag = actor:IsObstacleFlag()
  242. -- 检测是否给阻挡标记
  243. local isObstacle = self:checkActorIsObstacle(actor)
  244. actor:SetObstacleFlag(isObstacle)
  245. -- 阻挡数据无变化
  246. if lastObstacleFlag == actor:IsObstacleFlag() then
  247. return
  248. end
  249. -- 上次是阻挡,减引用计数
  250. if lastObstacleFlag then
  251. self:decRef(currMapX, currMapY)
  252. end
  253. -- 当前是阻挡,加引用计数
  254. if actor:IsObstacleFlag() then
  255. self:addRef(currMapX, currMapY)
  256. end
  257. end
  258. function DynamicObstacleController:onActorInOfView(data)
  259. self:checkAddObstacle(data)
  260. end
  261. function DynamicObstacleController:onActorEffectInOfView(data)
  262. self:checkAddObstacle(data)
  263. end
  264. function DynamicObstacleController:onActorOutOfView(data)
  265. self:checkRemoveObstacle(data)
  266. end
  267. function DynamicObstacleController:onActorPlayerDie(data)
  268. self:checkRemoveObstacle(data)
  269. end
  270. function DynamicObstacleController:onActorMonsterDie(data)
  271. self:checkRemoveObstacle(data)
  272. end
  273. function DynamicObstacleController:onActorMonsterDeath(data)
  274. self:checkRemoveObstacle(data)
  275. end
  276. function DynamicObstacleController:onActorRevive(data)
  277. self:checkUpdateObstacle(data)
  278. end
  279. function DynamicObstacleController:onActorEffectOutOfView(data)
  280. self:checkRemoveObstacle(data)
  281. end
  282. function DynamicObstacleController:onPlayerStallStatucChange(data)
  283. self:checkUpdateObstacle(data)
  284. end
  285. function DynamicObstacleController:onActorSafeZoneChange(data)
  286. self:checkUpdateObstacle(data)
  287. end
  288. function DynamicObstacleController:onMapDataLoadSuccess(data)
  289. self._obstacles = {}
  290. -- npc
  291. local actors, ncount = global.npcManager:GetNpcInCurrViewField()
  292. for i = 1, ncount do
  293. local actor = actors[i]
  294. if actor then
  295. self:checkAddObstacle({actor = actor, actorID = actor:GetID()})
  296. end
  297. end
  298. -- player
  299. local actors, ncount = global.playerManager:GetPlayersInCurrViewField()
  300. for i = 1, ncount do
  301. local actor = actors[i]
  302. if actor then
  303. self:checkAddObstacle({actor = actor, actorID = actor:GetID()})
  304. end
  305. end
  306. -- monsters
  307. local actors, ncount = global.monsterManager:GetMonstersInCurrViewField()
  308. for i = 1, ncount do
  309. local actor = actors[i]
  310. if actor then
  311. self:checkAddObstacle({actor = actor, actorID = actor:GetID()})
  312. end
  313. end
  314. end
  315. function DynamicObstacleController:onUpdateAllObstacles()
  316. -- npc
  317. local actors, ncount = global.npcManager:GetNpcInCurrViewField()
  318. for i = 1, ncount do
  319. local actor = actors[i]
  320. if actor then
  321. self:checkUpdateObstacle({actor = actor, actorID = actor:GetID()})
  322. end
  323. end
  324. -- player
  325. local actors, ncount = global.playerManager:GetPlayersInCurrViewField()
  326. for i = 1, ncount do
  327. local actor = actors[i]
  328. if actor then
  329. self:checkUpdateObstacle({actor = actor, actorID = actor:GetID()})
  330. end
  331. end
  332. -- monsters
  333. local actors, ncount = global.monsterManager:GetMonstersInCurrViewField()
  334. for i = 1, ncount do
  335. local actor = actors[i]
  336. if actor then
  337. self:checkUpdateObstacle({actor = actor, actorID = actor:GetID()})
  338. end
  339. end
  340. end
  341. function DynamicObstacleController:dynamicPathPoints()
  342. local mainPlayer = global.gamePlayerController:GetMainPlayer()
  343. if not mainPlayer then
  344. return nil
  345. end
  346. local mapData = global.sceneManager:GetMapData2DPtr()
  347. if not mapData then
  348. return nil
  349. end
  350. local PlayerInputProxy = global.Facade:retrieveProxy(global.ProxyTable.PlayerInputProxy)
  351. local currPathPoint = PlayerInputProxy:GetCurrPathPoint()
  352. local pathPoints = PlayerInputProxy:GetPathFindPoints()
  353. if currPathPoint <= 0 or #pathPoints <= 0 then
  354. return nil
  355. end
  356. local startPos = cc.p(mainPlayer:GetMapX(), mainPlayer:GetMapY())
  357. local destPos = nil
  358. local destIndex = nil
  359. -- find dest pos
  360. if pathPoints[currPathPoint] then
  361. local path = pathPoints[currPathPoint]
  362. if mapData:isObstacle(path.x, path.y) == 1 then
  363. for i = currPathPoint, 1, -1 do
  364. path = pathPoints[i]
  365. if mapData:isObstacle(path.x, path.y) == 0 then
  366. destPos = path
  367. destIndex = i
  368. break
  369. end
  370. end
  371. end
  372. end
  373. -- can't find obstacle
  374. if not destPos then
  375. return nil
  376. end
  377. print("--------------------- modify path")
  378. dump(destPos)
  379. -- it's current pos,nothing to do
  380. if startPos.x == destPos.x and startPos.y == destPos.y then
  381. return nil
  382. end
  383. -- find path
  384. local findPoints = global.PathFindController:FindPathAStarLimits(startPos, destPos)
  385. -- can't find dest
  386. if #findPoints <= 0 then
  387. return nil
  388. end
  389. -- new path points
  390. local newPathPoints = {}
  391. for i, v in ipairs(pathPoints) do
  392. if i == destIndex then
  393. break
  394. end
  395. table.insert(newPathPoints, v)
  396. end
  397. for i, v in ipairs(findPoints) do
  398. table.insert(newPathPoints, v)
  399. end
  400. PlayerInputProxy:SetPathFindPoints( newPathPoints )
  401. end
  402. return DynamicObstacleController