ActorEffectManager.lua 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. local DebugMediator = requireMediator("DebugMediator")
  2. local ActorEffectManager = class("ActorEffectManager", DebugMediator)
  3. ActorEffectManager.NAME = "ActorEffectManager"
  4. local cjson = require("cjson")
  5. local optionsUtils = requireProxy( "optionsUtils" )
  6. function ActorEffectManager:ctor()
  7. ActorEffectManager.super.ctor(self, self.NAME)
  8. self._effects = {}
  9. self._rootNodeB = nil
  10. self._rootNodeF = nil
  11. self._npcEffects= {}
  12. end
  13. function ActorEffectManager:destory()
  14. if ActorEffectManager.instance then
  15. global.Facade:removeMediator( ActorEffectManager.NAME )
  16. ActorEffectManager.instance = nil
  17. end
  18. end
  19. function ActorEffectManager:Inst()
  20. if not ActorEffectManager.instance then
  21. ActorEffectManager.instance = ActorEffectManager.new()
  22. global.Facade:registerMediator(ActorEffectManager.instance)
  23. end
  24. return ActorEffectManager.instance
  25. end
  26. function ActorEffectManager:listNotificationInterests()
  27. local noticeTable = global.NoticeTable
  28. return
  29. {
  30. noticeTable.ActorOutOfView,
  31. noticeTable.ActorInOfView,
  32. noticeTable.DropItemOutOfView,
  33. }
  34. end
  35. function ActorEffectManager:handleNotification(notification)
  36. local noticeTable = global.NoticeTable
  37. local noticeID = notification:getName()
  38. local data = notification:getBody()
  39. if noticeTable.ActorOutOfView == noticeID then
  40. self:OnActorOutOfView(data)
  41. elseif noticeTable.ActorInOfView == noticeID then
  42. self:OnActorInOfView(data)
  43. elseif noticeTable.DropItemOutOfView == noticeID then
  44. self:OnDropItemOutOfView(data)
  45. end
  46. end
  47. function ActorEffectManager:getRoots()
  48. if not self._rootNodeB then
  49. self._rootNodeB = global.sceneGraphCtl:GetSceneNode(global.MMO.NODE_SKILL_BEHIND)
  50. end
  51. if not self._rootNodeF then
  52. self._rootNodeF = global.sceneGraphCtl:GetSceneNode(global.MMO.NODE_SKILL)
  53. end
  54. end
  55. function ActorEffectManager:Tick(dt)
  56. local removed = {}
  57. for actorID, items in pairs(self._effects) do
  58. for sfxID, item in pairs(items) do
  59. if self:CheckInvalid(item) then
  60. table.insert(removed, {actorID = actorID, sfxID = sfxID})
  61. end
  62. end
  63. end
  64. for _, v in pairs(removed) do
  65. self:RmvEffect({actorID = v.actorID, sfxID = v.sfxID})
  66. end
  67. end
  68. function ActorEffectManager:CheckInvalid(item)
  69. -- forever
  70. if item.count == 0 then
  71. return false
  72. end
  73. -- count compare
  74. if item.counting >= item.count then
  75. return true
  76. end
  77. return false
  78. end
  79. function ActorEffectManager:IsEmpty(actorID)
  80. local items = self._effects[actorID]
  81. if not items or not next(items) then
  82. return true
  83. end
  84. return false
  85. end
  86. function ActorEffectManager:Cleanup()
  87. local removed = {}
  88. for _, items in pairs(self._effects) do
  89. for _, item in pairs(items) do
  90. table.insert(removed, item.actorID)
  91. end
  92. end
  93. for _, v in pairs(removed) do
  94. self:CleanupByActorID(v)
  95. end
  96. self._effects = {}
  97. end
  98. function ActorEffectManager:CleanupByActorID(actorID)
  99. if (self:IsEmpty(actorID)) then
  100. return
  101. end
  102. local items = self:GetItemsByActorID(actorID)
  103. local removed = {}
  104. for _, item in pairs(items) do
  105. table.insert(removed, {actorID = item.actorID, sfxID = item.sfxID})
  106. end
  107. for _, v in pairs(removed) do
  108. self:RmvEffect(v)
  109. end
  110. end
  111. function ActorEffectManager:OnActorOutOfView(data)
  112. self:CleanupByActorID(data.actorID)
  113. end
  114. function ActorEffectManager:OnActorInOfView(data)
  115. self:CheckAddNPCEffect(data.actorID)
  116. end
  117. function ActorEffectManager:OnDropItemOutOfView(data)
  118. self:CleanupByActorID(data.actorID)
  119. end
  120. function ActorEffectManager:GetItemsByActorID(actorID)
  121. if not self._effects[actorID] then
  122. self._effects[actorID] = {}
  123. end
  124. return self._effects[actorID]
  125. end
  126. function ActorEffectManager:setPosition(actorID, x, y)
  127. if self:IsEmpty(actorID) then
  128. return nil
  129. end
  130. local items = self._effects[actorID]
  131. if not items then
  132. return nil
  133. end
  134. local offset = cc.p(0,0)
  135. local position = cc.p(0,0)
  136. for _, item in pairs(items) do
  137. offset = cc.p(item.offsetX or 0, item.offsetY or 0)
  138. position = cc.pAdd(cc.p(x, y), global.MMO.PLAYER_AVATAR_OFFSET)
  139. position = cc.pAdd(position, offset)
  140. item.anim:setPosition(position)
  141. end
  142. end
  143. function ActorEffectManager:AddEffect(item)
  144. self:getRoots()
  145. -- error param
  146. local actorID = item.actorID
  147. local sfxID = item.sfxID
  148. if not actorID or not sfxID then
  149. return false
  150. end
  151. -- can't find actor
  152. local actor = global.actorManager:GetActor(actorID)
  153. if not actor then
  154. print("+++++++++++++++++++ AddEffect can't find actor")
  155. return false
  156. end
  157. self._effects[actorID] = self._effects[actorID] or {}
  158. local items = self._effects[actorID]
  159. local visible = type(item.visible) ~= "boolean" and true or item.visible
  160. visible = visible and CHECK_SETTING(global.MMO.SETTING_IDX_EFFECT_SHOW) ~= 1
  161. if actor:IsPlayer() and actor:IsDoubleHorse() then
  162. visible = false
  163. end
  164. -- exist
  165. if items[sfxID] then
  166. items[sfxID].anim:setVisible(visible)
  167. return false
  168. end
  169. local dir = 0
  170. if item.dirfollow then
  171. local actor = global.actorManager:GetActor(actorID)
  172. if actor and actor.GetDirection then
  173. dir = actor:GetDirection()
  174. end
  175. end
  176. -- add sfx
  177. local root = (item.front == true and self._rootNodeF or self._rootNodeB)
  178. local anim = global.FrameAnimManager:CreateSFXAnim(sfxID)
  179. anim:SetGlobalElapseEnable(item.count == 0)
  180. root:addChild(anim, sfxID)
  181. anim:Play(0, dir, true, item.speed)
  182. anim:SetAnimEventCallback(function()
  183. item.counting = item.counting + 1
  184. end)
  185. anim:setVisible(visible)
  186. -- fix param
  187. item.counting = 0
  188. item.anim = anim
  189. items[sfxID] = item
  190. --
  191. local position = actor:getPosition()
  192. self:setPosition(actorID, position.x, position.y)
  193. return true
  194. end
  195. function ActorEffectManager:RmvEffect(data)
  196. -- error param
  197. local actorID = data.actorID
  198. local sfxID = data.sfxID
  199. if not actorID or not sfxID then
  200. return false
  201. end
  202. if self:IsEmpty(actorID) then
  203. return false
  204. end
  205. local items = self._effects[actorID]
  206. -- can'd find item
  207. if nil == items[sfxID] then
  208. return false
  209. end
  210. items[sfxID].anim:removeFromParent()
  211. items[sfxID] = nil
  212. -- cleanup, when empty
  213. if self:IsEmpty(actorID) then
  214. self._effects[actorID] = nil
  215. end
  216. end
  217. function ActorEffectManager:UpdateEffectDir(actor, actorID)
  218. if not actor or not actorID then
  219. return false
  220. end
  221. if self:IsEmpty(actorID) then
  222. return false
  223. end
  224. local items = self._effects[actorID] or {}
  225. for sfxID, item in pairs(items) do
  226. if item.dirfollow then
  227. local sfx = item.anim
  228. if sfx and actor.GetDirection then
  229. sfx:Stop()
  230. sfx:Play(0, actor:GetDirection(), true, item.speed)
  231. end
  232. end
  233. end
  234. end
  235. function ActorEffectManager:ActorEffectRefresh(data)
  236. --
  237. -- dump(data)
  238. if not data or not data.action or not data.items then
  239. return false
  240. end
  241. --
  242. local action = data.action
  243. local items = data.items
  244. for _, v in ipairs(items) do
  245. local data =
  246. {
  247. actorID = v.iUserId,
  248. sfxID = tonumber(v.sEffSrc),
  249. frame = v.iFrame or 0,
  250. speed = v.iSpeed or 1,
  251. count = v.iCount or 0,
  252. front = not (v.iBehind == 1),
  253. offsetX = v.offsetX or 0,
  254. offsetY = v.offsetY or 0,
  255. visible = v.visible,
  256. dirfollow = tonumber(v.dirfollow) == 1
  257. }
  258. if action == 1 then
  259. self:AddEffect(data)
  260. elseif action == 0 then
  261. self:RmvEffect(data)
  262. end
  263. end
  264. end
  265. function ActorEffectManager:handle_ActorEffectUpdate(msgHdr, msgData)
  266. if msgData == "" then
  267. return nil
  268. end
  269. local action = msgHdr.recog -- 1.增加 0.删除
  270. local jsonData = cjson.decode(msgData)
  271. if not jsonData then
  272. return nil
  273. end
  274. --
  275. -- print("+++++++++++++++++++++++++++++++++action", action)
  276. -- dump(jsonData)
  277. self:ActorEffectRefresh({action = action, items = jsonData})
  278. end
  279. -------------------------------------------------------------------
  280. -------------------------------------------------------------------
  281. function ActorEffectManager:CheckAddNPCEffect(actorID)
  282. local actor = global.actorManager:GetActor(actorID)
  283. if not actor then
  284. return nil
  285. end
  286. local effect = self._npcEffects[actorID]
  287. if not effect then
  288. return nil
  289. end
  290. local data =
  291. {
  292. actorID = actorID,
  293. sfxID = effect.sfxID,
  294. frame = 0,
  295. speed = 1,
  296. count = 0,
  297. front = true,
  298. offsetX = effect.offsetX,
  299. offsetY = effect.offsetY,
  300. }
  301. self:AddEffect(data)
  302. end
  303. function ActorEffectManager:CheckRmvNPCEffect(actorID)
  304. local effect = self._npcEffects[actorID]
  305. if not effect then
  306. return nil
  307. end
  308. local actor = global.actorManager:GetActor(actorID)
  309. if not actor then
  310. return nil
  311. end
  312. local data =
  313. {
  314. actorID = actorID,
  315. sfxID = effect.sfxID,
  316. frame = 0,
  317. speed = 1,
  318. count = 0,
  319. front = true,
  320. offsetX = effect.offsetX,
  321. offsetY = effect.offsetY,
  322. }
  323. self:RmvEffect(data)
  324. end
  325. function ActorEffectManager:RespAddNPCEffect(msg)
  326. local header = msg:GetHeader()
  327. local msgLen = msg:GetDataLength()
  328. if msgLen <= 0 then
  329. return nil
  330. end
  331. local npcID = msg:GetData():ReadString(msgLen)
  332. self._npcEffects[npcID] =
  333. {
  334. sfxID = header.param1,
  335. offsetX = header.param2,
  336. offsetY = header.param3,
  337. }
  338. self:CheckAddNPCEffect(npcID)
  339. end
  340. function ActorEffectManager:RespRmvNPCEffect(msg)
  341. local header = msg:GetHeader()
  342. local msgLen = msg:GetDataLength()
  343. if msgLen <= 0 then
  344. return nil
  345. end
  346. local npcID = msg:GetData():ReadString(msgLen)
  347. self:CheckRmvNPCEffect(npcID)
  348. self._npcEffects[npcID] = nil
  349. end
  350. function ActorEffectManager:RefreshActorEffectVisible( actorID,visible )
  351. if not actorID then
  352. return
  353. end
  354. local effects = self._effects[actorID]
  355. if not effects or not next(effects) then
  356. return
  357. end
  358. local actor = global.actorManager:GetActor(actorID)
  359. if actor and actor:IsPlayer() and actor:IsDoubleHorse() then
  360. visible = false
  361. end
  362. if visible and actor:GetValueByKey(global.MMO.HUD_SNEAK) then
  363. visible = false
  364. end
  365. for sfxid,item in pairs(effects) do
  366. local itemVisible = visible
  367. if visible then
  368. itemVisible = item.visible or visible
  369. end
  370. item.anim:setVisible(itemVisible==true)
  371. end
  372. end
  373. function ActorEffectManager:onRegister()
  374. local msgType = global.MsgType
  375. LuaRegisterMsgHandler(msgType.MSG_SC_ADD_NPC_EFFECT, handler(self, self.RespAddNPCEffect))
  376. LuaRegisterMsgHandler(msgType.MSG_SC_RMV_NPC_EFFECT, handler(self, self.RespRmvNPCEffect))
  377. end
  378. return ActorEffectManager