SkillProxy.lua 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061
  1. local RemoteProxy = requireProxy("remote/RemoteProxy")
  2. local SkillProxy = class("SkillProxy", RemoteProxy)
  3. SkillProxy.NAME = global.ProxyTable.Skill
  4. local cjson = require("cjson")
  5. local optionsUtils = requireProxy( "optionsUtils" )
  6. local socket = require("socket")
  7. local function parseOneSkillData(data)
  8. data.id = data.MagicID
  9. data.DelayTime = data.DelayTime or 0
  10. -- extension
  11. data.isCD = false
  12. data.curTime = 0
  13. return data
  14. end
  15. function SkillProxy:ctor()
  16. SkillProxy.super.ctor(self)
  17. self._data = {}
  18. self._configs = {}
  19. --锁定技能是普攻,技能点击开启时,要进行释放(本来是内挂有设置优先级(设置为0),现在内挂好像乱了,这里就单独处理下)
  20. self._skill_on_launch = {
  21. [66] = 53,
  22. [26] = 16,
  23. [42] = -1,
  24. [43] = -1,
  25. [81] = -1
  26. }
  27. self._double_skill_cd = {
  28. [26] = {
  29. swith_data = {id=global.MMO.SERVER_OPTION_BAN_DOUBLE_FIREHIT,value=1}
  30. }
  31. } --双烈火cd
  32. self._skill_present_replace_id = {} --替代表现数据
  33. self._skill_custon_skill_fighter = {} --战士自定义攻击技能
  34. self._skill_custom_skill = {} --自定义技能
  35. self._isDelayLaunch = false -- 是否延迟(释放了一个技能之后延迟释放下一个技能)
  36. self._delayLauchEndTime = 0 -- 记录延迟结束释放时的时间戳
  37. self._skillIgnoreMon = {} -- 技能忽略怪
  38. self._comboSkillLaunchID = nil -- 释放连击ID
  39. self._canLaunchComboStatus = true -- 可释放连击状态
  40. self._configs_skill_action = {} -- 技能动作
  41. self._specialXPSpellParam = {} -- 特殊血魄消耗配置
  42. self._canLaunchComboStatus = true -- 可释放连击状态
  43. self._mootebo_with_cd = 0 -- 野蛮立即释放状态
  44. self._mootebo_with_hit_cd = 0 -- 野蛮技能释放技能动作状态可释放
  45. self:Init()
  46. end
  47. function SkillProxy:Init()
  48. -- self._configs = {
  49. -- -- global.MMO.SKILL_INDEX_BASIC
  50. -- [0] = {id = 0, launchmode = 5, action = 0, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 1,}, -- 普攻
  51. -- [1] = {id = 1, launchmode = 3, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 火球术
  52. -- [2] = {id = 2, launchmode = 4, action = 1, onoff = 0, bestPos = 1, addition = 1, lockTarget = 0, isline = 0,}, -- 治愈术
  53. -- [3] = {id = 3, launchmode = 5, action = 0, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 1,}, -- 基本剑术
  54. -- [4] = {id = 4, launchmode = 5, action = 0, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 1,}, -- 精神力剑法
  55. -- [5] = {id = 5, launchmode = 3, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 大火球
  56. -- [6] = {id = 6, launchmode = 5, action = 1, onoff = 0, bestPos = 1, addition = 2, lockTarget = 0, isline = 0,}, -- 施毒术
  57. -- [7] = {id = 7, launchmode = 5, action = 0, onoff = 1, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 攻杀
  58. -- [8] = {id = 8, launchmode = 2, action = 1, onoff = 0, bestPos = 0, addition = 1, lockTarget = 0, isline = 0,}, -- 抗拒火环
  59. -- [9] = {id = 9, launchmode = 3, action = 1, onoff = 0, bestPos = 0, addition = 2, lockTarget = 0, isline = 1,}, -- 地狱火
  60. -- [10] = {id = 10, launchmode = 3, action = 1, onoff = 0, bestPos = 0, addition = 2, lockTarget = 0, isline = 1,}, -- 疾光电影
  61. -- [11] = {id = 11, launchmode = 5, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 雷电术
  62. -- [12] = {id = 12, launchmode = 5, action = 0, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 1,}, -- 刺杀剑术
  63. -- [13] = {id = 13, launchmode = 3, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 灵魂火符
  64. -- [14] = {id = 14, launchmode = 4, action = 1, onoff = 0, bestPos = 1, addition = 1, lockTarget = 0, isline = 0,}, -- 幽灵盾 4
  65. -- [15] = {id = 15, launchmode = 4, action = 1, onoff = 0, bestPos = 1, addition = 1, lockTarget = 0, isline = 0,}, -- 神圣咒 4
  66. -- [16] = {id = 16, launchmode = 5, action = 1, onoff = 0, bestPos = 1, addition = 2, lockTarget = 0, isline = 0,}, -- 困魔咒
  67. -- [17] = {id = 17, launchmode = 2, action = 1, onoff = 0, bestPos = 0, addition = 1, lockTarget = 0, isline = 0,}, -- 召唤骷髅 4
  68. -- [18] = {id = 18, launchmode = 2, action = 1, onoff = 0, bestPos = 0, addition = 1, lockTarget = 0, isline = 0,}, -- 隐身术
  69. -- [19] = {id = 19, launchmode = 4, action = 1, onoff = 0, bestPos = 1, addition = 1, lockTarget = 0, isline = 0,}, -- 群体隐身术 4
  70. -- [20] = {id = 20, launchmode = 5, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 诱惑之光 4
  71. -- [21] = {id = 21, launchmode = 2, action = 1, onoff = 0, bestPos = 0, addition = 1, lockTarget = 0, isline = 0,}, -- 瞬息移动
  72. -- [22] = {id = 22, launchmode = 4, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 火墙
  73. -- [23] = {id = 23, launchmode = 5, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 爆裂火焰 4
  74. -- [24] = {id = 24, launchmode = 2, action = 1, onoff = 0, bestPos = 0, addition = 0, lockTarget = 1, isline = 0,}, -- 地狱雷光
  75. -- [25] = {id = 25, launchmode = 5, action = 0, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 1,}, -- 半月弯刀
  76. -- [26] = {id = 26, launchmode = 5, action = 0, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 1,}, -- 烈火剑法
  77. -- [27] = {id = 27, launchmode = 1, action = 1, onoff = 0, bestPos = 0, addition = 2, lockTarget = 0, isline = 1, maxDistance = 1}, -- 野蛮冲撞
  78. -- [28] = {id = 28, launchmode = 4, action = 1, onoff = 0, bestPos = 1, addition = 1, lockTarget = 0, isline = 0,}, -- 心灵启示
  79. -- [29] = {id = 29, launchmode = 4, action = 1, onoff = 0, bestPos = 1, addition = 1, lockTarget = 0, isline = 0,}, -- 群体治愈术
  80. -- [30] = {id = 30, launchmode = 2, action = 1, onoff = 0, bestPos = 0, addition = 1, lockTarget = 0, isline = 0,}, -- 召唤神兽
  81. -- [31] = {id = 31, launchmode = 2, action = 1, onoff = 0, bestPos = 0, addition = 1, lockTarget = 0, isline = 0,}, -- 魔法盾
  82. -- [32] = {id = 32, launchmode = 5, action = 1, onoff = 0, bestPos = 1, addition = 1, lockTarget = 0, isline = 0,}, -- 圣言术 4
  83. -- [33] = {id = 33, launchmode = 5, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 冰咆哮 4
  84. -- [34] = {id = 34, launchmode = 5, action = 0, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 1, maxDistance = 4}, -- 逐日剑法
  85. -- [36] = {id = 36, launchmode = 5, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 灭天火
  86. -- [37] = {id = 37, launchmode = 5, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 流星火雨
  87. -- [38] = {id = 38, launchmode = 2, action = 1, onoff = 0, bestPos = 0, addition = 1, lockTarget = 0, isline = 0,}, -- 气功波
  88. -- [39] = {id = 39, launchmode = 5, action = 0, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 1, maxDistance = 4}, -- 开天斩
  89. -- [40] = {id = 40, launchmode = 3, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 嗜血术
  90. -- [60] = {id = 60, launchmode = 3, action = 1, onoff = 0, bestPos = 1, addition = 0, lockTarget = 1, isline = 0,}, -- 寒冰掌
  91. -- [61] = {id = 61, launchmode = 2, action = 1, onoff = 0, bestPos = 0, addition = 1, lockTarget = 0, isline = 0,}, -- 无极真气
  92. -- [62] = {id = 62, launchmode = 2, action = 1, onoff = 0, bestPos = 0, addition = 1, lockTarget = 0, isline = 0,}, -- 护体神盾
  93. -- }
  94. -- 手机端
  95. -- 1方向.目标(不自动选): 野蛮冲撞.
  96. -- 2自己坐标: 抗拒火环.魔法盾.召唤骷髅.隐身术.召唤神兽.地狱雷光
  97. -- 3方向.目标: 火球术.大火球.灵魂火符.地狱火.疾光电影
  98. -- 4自己坐标和传入坐标: 火墙.群体治愈术.群体隐身术.幽灵盾.神圣战甲术 .雷电术.心灵启示.诱惑之光.爆裂火焰.圣言术.治愈术.困魔咒.冰咆哮.
  99. -- 5方向和目标(必须): 普攻.施毒术.基本剑法.刺杀剑术.半月弯刀.烈火剑法.精神力剑法
  100. -- id
  101. -- launchmode(释放类型)
  102. -- action(攻击/释放)
  103. -- isonoff(开关型技能)
  104. -- addition(增益型)
  105. -- mindistance(最小释放距离)
  106. -- maxdistance(最大释放距离)
  107. -- bestPos(需要走位)
  108. -- isline(直线释放)
  109. -- locktarget(锁定目标)
  110. -- pc端
  111. -- 2鼠标方向 抗拒火环.魔法盾.召唤骷髅.隐身术.召唤神兽.地狱雷光.疾光电影.地狱火
  112. -- 3鼠标坐标 火墙.群体治愈术.群体隐身术.幽灵盾.神圣战甲术.冰咆哮.雷电术.心灵启示.诱惑之光.爆裂火焰.圣言术.治愈术.困魔咒.冰咆哮.
  113. -- 4鼠标所在方向(攻击锁定) 普攻.施毒术.基本剑法.刺杀剑术.攻杀剑术.半月弯刀.烈火剑法.精神力剑法
  114. -- 5鼠标所在目标(魔法锁定) 火球术.大火球.灵魂火符.
  115. -- id
  116. -- launchmode(释放类型)
  117. -- action(攻击/释放)
  118. -- isonoff(开关型技能)
  119. -- addition(增益型)
  120. -- mindistance(最小释放距离)
  121. -- maxdistance(最大释放距离)
  122. -- bestPos(需要走位)
  123. -- isline(直线释放)
  124. -- locktarget(锁定目标)
  125. -- magiclock(魔法锁定)
  126. self._data.skills = {} -- 所有拥有技能
  127. self._data.select = nil -- 选择的技能,如范围技能
  128. self._data.custom = {} -- 自定义数据
  129. self._data.onskills = {} -- 已开启技能列表
  130. self._priorities = {}
  131. self._prioritiesT = {}
  132. self._data.ngSkills = {} -- 所有拥有内功技能
  133. self._data.setComboSkill = {} -- 设置加入连击的连击技能
  134. self._data.comboSkills = {} -- 所有拥有的连击技能
  135. self._data.openComboNum = 3 -- 默认开启三个连击
  136. end
  137. function SkillProxy:LoadConfig()
  138. self._configs = requireGameConfig("cfg_magicinfo")
  139. -- 初始化优先级
  140. local priorities = {}
  141. for k, v in pairs(self._configs) do
  142. priorities[v.MagicID] = priorities[v.MagicID] or 0
  143. priorities[v.MagicID] = math.max(v.priority or 0, priorities[v.MagicID])
  144. end
  145. self._priorities = clone(priorities)
  146. self._prioritiesT = clone(priorities)
  147. -- 加载配置表
  148. local androidFilePath = "scripts/game_config/cfg_skill_action.lua"
  149. if global.FileUtilCtl:isFileExist(androidFilePath) then
  150. self._configs_skill_action = requireGameConfig("cfg_skill_action")
  151. end
  152. end
  153. function SkillProxy:ReadLocalKey()
  154. local key = global.isWinPlayMode and "skill_key_pc" or "skill_key"
  155. local data = GET_CLOUD_DATA(key)
  156. return data or {}
  157. end
  158. function SkillProxy:WriteLocalKey()
  159. local jsonData = {}
  160. for k, v in pairs(self._data.skills) do
  161. jsonData[tostring(v.MagicID)] = v.Key
  162. end
  163. local key = global.isWinPlayMode and "skill_key_pc" or "skill_key"
  164. SET_CLOUD_DATA(key, jsonData)
  165. end
  166. function SkillProxy:SetXPSpellParam(type, value, way)
  167. if not self._specialXPSpellParam then
  168. self._specialXPSpellParam = {}
  169. end
  170. self._specialXPSpellParam.spellType = type
  171. self._specialXPSpellParam.spellValue = value
  172. self._specialXPSpellParam.spellHPWay = way -- 0:点 1:百分比
  173. end
  174. function SkillProxy:GetXPSpellParam()
  175. return self._specialXPSpellParam
  176. end
  177. function SkillProxy:SetMooteboWithCD(state)
  178. self._mootebo_with_cd = state
  179. end
  180. function SkillProxy:SetMooteboWithHitCD(state)
  181. self._mootebo_with_hit_cd = state
  182. end
  183. function SkillProxy:GetMooteboWithHitCD()
  184. return self._mootebo_with_hit_cd
  185. end
  186. -- 技能配置
  187. function SkillProxy:GetConfigs()
  188. return self._configs
  189. end
  190. function SkillProxy:FindConfigBySkillID(skillID)
  191. return self._configs[skillID]
  192. end
  193. function SkillProxy:FindAllSkillsByJob(job)
  194. if not job then
  195. local PlayerProperty = global.Facade:retrieveProxy(global.ProxyTable.PlayerProperty)
  196. job = PlayerProperty:GetRoleJob()
  197. end
  198. local configs = self:GetConfigs()
  199. local items = {}
  200. for _, v in pairs(configs) do
  201. if v.job == job or v.job == 3 or job == 3 then
  202. table.insert(items, v)
  203. end
  204. end
  205. return items
  206. end
  207. -- 优先级
  208. function SkillProxy:GetPriorityBySkillID(skillID)
  209. if not skillID then
  210. return 0
  211. end
  212. return self._prioritiesT[skillID] or 0
  213. end
  214. -- 本地表的优先级(开启了持续攻击时 优先级读取本地)
  215. function SkillProxy:GetLocalPriorityBySkillID(skillID)
  216. if not skillID then
  217. return 0
  218. end
  219. return self._priorities[skillID] or 0
  220. end
  221. -- 优先级相关
  222. function SkillProxy:GetLaunchMode(skillID)
  223. local config = self:FindConfigBySkillID(skillID)
  224. if not config then
  225. return 1
  226. end
  227. local launchmode = global.isWinPlayMode and config.launchmode_pc or config.launchmode
  228. return launchmode or 1
  229. end
  230. -- 获取技能名字
  231. function SkillProxy:GetSkillNameByID(skillID)
  232. local config = self:FindConfigBySkillID(skillID)
  233. if not config then
  234. return "ERROR SKILL NAME"
  235. end
  236. return config.magicName
  237. end
  238. -- 根据名字获取技能ID
  239. function SkillProxy:GetSkillIDByName(skillName)
  240. for _, v in pairs(self._configs) do
  241. if v.magicName == skillName then
  242. return v.MagicID
  243. end
  244. end
  245. return nil
  246. end
  247. -- 获取技能Icon 圆形
  248. function SkillProxy:GetIconPathByID(skillID, isCombo)
  249. if skillID == 0 then
  250. local PlayerInputProxy = global.Facade:retrieveProxy(global.ProxyTable.PlayerInputProxy)
  251. if PlayerInputProxy:CheckMiningAble() then
  252. skillID = 999
  253. end
  254. end
  255. local config = self:FindConfigBySkillID(skillID)
  256. if not config then
  257. local path = string.format("%s%s.jpg", global.MMO.PATH_RES_SKILL_ICON_C, "default")
  258. if global.FileUtilCtl:isFileExist(path) then
  259. return path
  260. end
  261. return string.format("%s%s.png", global.MMO.PATH_RES_SKILL_ICON_C, "default")
  262. end
  263. local data = isCombo and self:GetComboSkillByID(skillID) or self:GetSkillByID(skillID)
  264. if not data or not data.LevelUpIcon or data.LevelUpIcon <= 0 then
  265. local path = string.format("%s%s.jpg", global.MMO.PATH_RES_SKILL_ICON_C, config.icon)
  266. if global.FileUtilCtl:isFileExist(path) then
  267. return path
  268. end
  269. return string.format("%s%s.png", global.MMO.PATH_RES_SKILL_ICON_C, config.icon)
  270. end
  271. local path = string.format("%s%s_%s.jpg", global.MMO.PATH_RES_SKILL_ICON_C, config.icon, data.LevelUpIcon)
  272. if global.FileUtilCtl:isFileExist(path) then
  273. return path
  274. end
  275. return string.format("%s%s_%s.png", global.MMO.PATH_RES_SKILL_ICON_C, config.icon, data.LevelUpIcon)
  276. end
  277. -- 获取技能Icon 矩形
  278. function SkillProxy:GetIconRectPathByID(skillID, isCombo)
  279. local config = self:FindConfigBySkillID(skillID)
  280. if not config then
  281. local path = string.format("%s%s.png", global.MMO.PATH_RES_SKILL_ICON, "default")
  282. if global.FileUtilCtl:isFileExist(path) then
  283. return path
  284. end
  285. return string.format("%s%s.jpg", global.MMO.PATH_RES_SKILL_ICON, "default")
  286. end
  287. local data = isCombo and self:GetComboSkillByID(skillID) or self:GetSkillByID(skillID)
  288. if not data or not data.LevelUpIcon or data.LevelUpIcon <= 0 then
  289. local path = string.format("%s%s.png", global.MMO.PATH_RES_SKILL_ICON, config.icon)
  290. if global.FileUtilCtl:isFileExist(path) then
  291. return path
  292. end
  293. return string.format("%s%s.jpg", global.MMO.PATH_RES_SKILL_ICON, config.icon)
  294. end
  295. local path = string.format("%s%s_%s.png", global.MMO.PATH_RES_SKILL_ICON, config.icon, data.LevelUpIcon)
  296. if global.FileUtilCtl:isFileExist(path) then
  297. return path
  298. end
  299. return string.format("%s%s_%s.jpg", global.MMO.PATH_RES_SKILL_ICON, config.icon, data.LevelUpIcon)
  300. end
  301. -- 最小攻击距离
  302. function SkillProxy:GetMinDistance(skillID)
  303. local config = self:FindConfigBySkillID(skillID)
  304. if not config then
  305. return 1
  306. end
  307. -- 寻路阻塞
  308. local inputProxy = global.Facade:retrieveProxy(global.ProxyTable.PlayerInputProxy)
  309. if inputProxy:IsMoveBlocked() then
  310. return config.minDis or 1
  311. end
  312. -- 刺杀剑术 文华 2020.07.20 PC端不要此功能
  313. -- 2023.08.28 wt/hd 商量PC端也要生效移动刺杀
  314. if skillID == global.MMO.SKILL_INDEX_CSJS then
  315. return CHECK_SETTING(global.MMO.SETTING_IDX_MOVE_GEWEI_CISHA) == 1 and 2 or 0
  316. end
  317. -- 自动走位
  318. local autoProxy = global.Facade:retrieveProxy(global.ProxyTable.Auto)
  319. if (autoProxy:IsAFKState() and CHECK_SETTING(13) == 1) then
  320. return config.autoMinDis or 1
  321. end
  322. return config.minDis or 1
  323. end
  324. -- 最大攻击距离
  325. function SkillProxy:GetMaxDistance(skillID)
  326. local config = self:FindConfigBySkillID(skillID)
  327. if not config then
  328. return 1
  329. end
  330. -- 刺杀剑术
  331. if skillID == global.MMO.SKILL_INDEX_CSJS then
  332. return (CHECK_SETTING(global.MMO.SETTING_IDX_DAODAOCISHA) ~= 1 and CHECK_SETTING(global.MMO.SETTING_IDX_GEWEICISHA) ~= 1) and 1 or 2
  333. end
  334. -- 自动战斗使用手机端范围
  335. local autoProxy = global.Facade:retrieveProxy(global.ProxyTable.Auto)
  336. if autoProxy:IsAFKState() then
  337. return config.maxDis
  338. end
  339. local maxDis = global.isWinPlayMode and config.maxDis_pc or config.maxDis
  340. return maxDis
  341. end
  342. -- 是否需要进入公共CD
  343. function SkillProxy:IsNeedEnterGlobalCD(skillID)
  344. -- 2021.12.21 孙同让写死
  345. if skillID == global.MMO.SKILL_INDEX_YMCZ then
  346. return false
  347. end
  348. return true
  349. end
  350. -- 是否必须寻找目标
  351. function SkillProxy:IsNeedTarget(skillID)
  352. local launchmode = self:GetLaunchMode(skillID)
  353. return launchmode == 3 or launchmode == 5
  354. end
  355. -- 需输入坐标技能
  356. function SkillProxy:IsInputDestSkill(skillID)
  357. local config = self:FindConfigBySkillID(skillID)
  358. if not config then
  359. return false
  360. end
  361. -- 特殊处理
  362. -- 道士治愈
  363. if skillID == 2 and CHECK_SETTING(33) == 1 then
  364. return false
  365. end
  366. return config.launchmode == 4
  367. end
  368. -- 持续攻击技能
  369. function SkillProxy:IsLockTargetSkill(skillID,force)
  370. if global.isWinPlayMode and not force then
  371. return false
  372. end
  373. local config = self:FindConfigBySkillID(skillID)
  374. if not config then
  375. return false
  376. end
  377. return config.locktarget == 1
  378. end
  379. -- 增益buff技能
  380. function SkillProxy:IsAdditionSkill(skillID)
  381. local config = self:FindConfigBySkillID(skillID)
  382. if not config then
  383. return false
  384. end
  385. return config.addition == 1
  386. end
  387. -- 开关技能
  388. function SkillProxy:IsOnoffSkill(skillID)
  389. local config = self:FindConfigBySkillID(skillID)
  390. if not config then
  391. return false
  392. end
  393. return config.isonoff == 1
  394. end
  395. -- 直线攻击技能
  396. function SkillProxy:IsLineSlopeSkill(skillID)
  397. local config = self:FindConfigBySkillID(skillID)
  398. if not config then
  399. return false
  400. end
  401. return config.isline == 1
  402. end
  403. -- 主动技能
  404. function SkillProxy:IsActiveSkill(skillID)
  405. local config = self:FindConfigBySkillID(skillID)
  406. if not config then
  407. return false
  408. end
  409. return config.type == 1
  410. end
  411. -- 魔法锁定
  412. function SkillProxy:IsMagicLockSkill(skillID)
  413. local config = self:FindConfigBySkillID(skillID)
  414. if not config then
  415. return false
  416. end
  417. return config.magiclock == 1
  418. end
  419. -- 检测配置内挂(烈火不是开关型的情况)
  420. function SkillProxy:GetMagicSettingID(skillID)
  421. if not skillID then
  422. return nil
  423. end
  424. local config = self:FindConfigBySkillID(skillID)
  425. if not config then
  426. return nil
  427. end
  428. return config.checkSetting
  429. end
  430. -- 技能数据
  431. function SkillProxy:GetSkills(noBasicSkill, activeOnly, noAutoLaunch)
  432. -- 已有技能数据 param1:是否排除普攻 param2:是否只获取主动技能 param3:是否排除不主动释放
  433. local skills = {}
  434. for _, v in pairs(self._data.skills) do
  435. local config = self:FindConfigBySkillID(v.MagicID)
  436. if (noBasicSkill and v.MagicID == global.MMO.SKILL_INDEX_BASIC) then
  437. elseif activeOnly and false == self:IsActiveSkill(v.MagicID) then
  438. elseif noAutoLaunch and 0 == self:GetPriorityBySkillID(v.MagicID) then
  439. else
  440. skills[v.MagicID] = v
  441. end
  442. end
  443. return skills
  444. end
  445. function SkillProxy:GetSkillByID(skillID)
  446. -- 获取技能数据
  447. return self._data.skills[skillID]
  448. end
  449. function SkillProxy:GetSkillByKey(key)
  450. -- 获取技能数据
  451. for _, skill in pairs(self._data.skills) do
  452. if skill.Key == key then
  453. return skill
  454. end
  455. end
  456. return nil
  457. end
  458. function SkillProxy:GetLevel(skillID)
  459. -- 技能等级
  460. local data = self:GetSkillByID(skillID)
  461. if data then
  462. return data.Level
  463. end
  464. return -1
  465. end
  466. -- 获取起手式动作
  467. function SkillProxy:GetActionID(skillID)
  468. local data = self:GetSkillByID(skillID)
  469. if data then
  470. return data.ActionId
  471. else
  472. data = self:GetComboSkillByID(skillID)
  473. if data then
  474. return data.ActionId
  475. end
  476. end
  477. return nil
  478. end
  479. function SkillProxy:AddSkill(data)
  480. --增加技能
  481. -- dump(data)
  482. if not data then
  483. return false
  484. end
  485. if self._data.skills[data.MagicID] then
  486. return false
  487. end
  488. local config = self:FindConfigBySkillID(data.MagicID)
  489. if not config then
  490. print("add skill error, skill config is nil " .. tostring(data.MagicID))
  491. return false
  492. end
  493. -- 增加技能
  494. self._data.skills[data.MagicID] = data
  495. -- 广播新增技能
  496. global.Facade:sendNotification(global.NoticeTable.SkillAdd, data)
  497. if self:IsCustomSkill(data.MagicID) and config then
  498. self._skill_custom_skill[data.MagicID] = data.MagicID
  499. if config.action == 0 and config.job == global.MMO.ACTOR_PLAYER_JOB_FIGHTER then
  500. self._skill_custon_skill_fighter[data.MagicID]=data.MagicID
  501. end
  502. end
  503. end
  504. function SkillProxy:DelSkill(skillID)
  505. --删除技能
  506. if not skillID then
  507. return false
  508. end
  509. if not self._data.skills[skillID] then
  510. return false
  511. end
  512. -- 删除技能
  513. local data = self._data.skills[skillID]
  514. self._data.skills[skillID] = nil
  515. self._skill_custom_skill[skillID] = nil
  516. self._skill_custon_skill_fighter[skillID] = nil
  517. -- 广播
  518. global.Facade:sendNotification(global.NoticeTable.SkillDel, data)
  519. ssr.ssrBridge:OnSkillDel(data)
  520. SLBridge:onLUAEvent(LUA_EVENT_SKILL_DEL, data)
  521. end
  522. function SkillProxy:UpdateSkillData(data)
  523. -- 更新技能数据
  524. if not data then
  525. return
  526. end
  527. if not data.skillID then
  528. return nil
  529. end
  530. local skill = self:GetSkillByID(data.skillID)
  531. if not skill then
  532. return nil
  533. end
  534. -- 更新技能属性
  535. for k, v in pairs(data) do
  536. skill[k] = v
  537. end
  538. global.Facade:sendNotification(global.NoticeTable.SkillUpdate, skill)
  539. ssr.ssrBridge:OnSkillUpdate(skill)
  540. SLBridge:onLUAEvent(LUA_EVENT_SKILL_UPDATE, skill)
  541. end
  542. function SkillProxy:GetSkillTrainData(skillID)
  543. -- 技能等级>3的全部特殊处理下
  544. local maxStr = "-"
  545. if not skillID or not self._data.skills[skillID] then
  546. return maxStr
  547. end
  548. if skillID == global.MMO.SKILL_INDEX_BASIC then
  549. return maxStr
  550. end
  551. local skillData = self._data.skills[skillID]
  552. local isBaseSkill = skillData.Level <= 3
  553. local skillLevel = skillData.Level
  554. local maxSkillLevel = skillData.TrainLv
  555. if skillLevel >= maxSkillLevel then
  556. return maxStr
  557. end
  558. local skillMaxTrain = {
  559. [0] = skillData.MaxTrain1,
  560. [1] = skillData.MaxTrain2,
  561. [2] = skillData.MaxTrain3,
  562. [3] = skillData.MaxTrain4
  563. }
  564. local curTrain = skillData.CurTrain or 0
  565. local maxTrain = (isBaseSkill and skillMaxTrain[skillLevel] or skillData.MaxTrain1) or 0
  566. return curTrain >= maxTrain and maxStr or string.format(GET_STRING(1053), curTrain, maxTrain)
  567. end
  568. --
  569. --是否使用技能书 通过书名
  570. function SkillProxy:CheckAbleToUseBookByName(bookname)
  571. local allSkills = self:FindAllSkillsByJob()
  572. local tskillID = nil
  573. for _, v in pairs(allSkills) do
  574. if v.magicName == bookname then
  575. tskillID = v.MagicID
  576. break
  577. end
  578. end
  579. if not tskillID then
  580. return false
  581. end
  582. -- 已学习
  583. if self:IsLearned(tskillID) then
  584. return false
  585. end
  586. return true
  587. end
  588. -- 是否已经学习
  589. function SkillProxy:IsLearned(skillID)
  590. local skillData = self:GetSkillByID(skillID) or self:GetComboSkillByID(skillID)
  591. return skillData and true or false
  592. end
  593. -- 特殊怪物忽略技能攻击
  594. function SkillProxy:CheckAbleToAttack(skillID, monsterID)
  595. local config = self:FindConfigBySkillID(skillID)
  596. if not config then
  597. return true
  598. end
  599. if not config.IgnoreMaster then
  600. return true
  601. end
  602. for _,v in pairs(string.split(config.IgnoreMaster, "#")) do
  603. if tonumber(v) and monsterID == tonumber(v) then
  604. return false
  605. end
  606. end
  607. return true
  608. end
  609. function SkillProxy:CheckIgnoreMon(skillID, monsterID)
  610. if skillID ~= 25 then
  611. return true
  612. end
  613. -- 配置半月忽略怪
  614. if not self._skillIgnoreMon[skillID] then
  615. self._skillIgnoreMon[skillID] = {}
  616. local ignoreStr = string.split( SL:GetMetaValue("GAME_DATA", "IgnoreMon"), "#" )
  617. for _,v in pairs(ignoreStr) do
  618. if tonumber( v ) then
  619. self._skillIgnoreMon[skillID][tonumber(v)] = true
  620. end
  621. end
  622. end
  623. if self._skillIgnoreMon[skillID][monsterID] then
  624. return false
  625. end
  626. return true
  627. end
  628. -- 检测是否开启了连续多技能开关
  629. function SkillProxy:CheckDoubleCDSwith( skillid )
  630. if not skillid or not self._double_skill_cd[skillid] then
  631. return false
  632. end
  633. if skillid == 26 and CHECK_SETTING(16) == 1 then --开启了自动烈火,不走双烈火
  634. return false
  635. end
  636. local swithData = self._double_skill_cd[skillid].swith_data or {}
  637. local id = swithData.id
  638. local value = swithData.value
  639. local value1 = swithData.value1
  640. if id then --不禁止双烈火
  641. if ( value and CHECK_SERVER_OPTION(id) ~= value ) or ( value1 and CHECK_SERVER_OPTION(id) == value1 ) then
  642. return true
  643. end
  644. end
  645. return false
  646. end
  647. function SkillProxy:UpdateDoubleCD( skillid )
  648. if not self:CheckDoubleCDSwith( skillid ) then
  649. return
  650. end
  651. local isCheck = true
  652. if self:IsOnoffSkill( skillid ) then
  653. if not self:IsOnSkill(skillid) then
  654. isCheck = false
  655. end
  656. end
  657. if not self._double_skill_cd[skillid] then
  658. self._double_skill_cd[skillid] = {}
  659. end
  660. self._double_skill_cd[skillid].cd_timer_stamp = isCheck and GetServerTime() or nil
  661. end
  662. -- 检测是否有双烈火
  663. function SkillProxy:GetDoubleSkillCDTime( skillid,maxCDTime )
  664. if not self:CheckDoubleCDSwith( skillid ) then
  665. return maxCDTime
  666. end
  667. local doubledata = self._double_skill_cd[skillid] or {}
  668. local cd_timer_stamp = doubledata.cd_timer_stamp
  669. if cd_timer_stamp and cd_timer_stamp > 0 then
  670. local currTime = GetServerTime()
  671. local remainCD = currTime - doubledata.cd_timer_stamp
  672. local cd = math.max(0,maxCDTime-remainCD)
  673. print("cd: ",cd)
  674. return maxCDTime-remainCD,true
  675. end
  676. return maxCDTime
  677. end
  678. -- 是否在CD
  679. function SkillProxy:IsInCD(skillID)
  680. local skillData = self:GetSkillByID(skillID) or self:GetComboSkillByID(skillID)
  681. if skillData then
  682. return skillData.isCD, skillData.curTime
  683. end
  684. return false
  685. end
  686. -- 是否发送提示
  687. function SkillProxy:IsCDHint( skillID )
  688. if global.isWinPlayMode then
  689. local AutoProxy = global.Facade:retrieveProxy(global.ProxyTable.Auto)
  690. if AutoProxy:IsAFKState() then
  691. return false
  692. end
  693. local cfg = self:FindConfigBySkillID(skillID)
  694. local showCDHint = cfg and tonumber(cfg.showCDHint) or nil
  695. if showCDHint then
  696. return showCDHint == 1
  697. end
  698. local skillData = self:GetSkillByID(skillID) or self:GetComboSkillByID(skillID)
  699. if skillData and skillData.HideCDHint then
  700. return skillData.HideCDHint == 0
  701. end
  702. end
  703. return false
  704. end
  705. -- MP 是否满足
  706. function SkillProxy:IsEnoughMana(skillID)
  707. local skill = self:GetSkillByID(skillID) or self:GetComboSkillByID(skillID)
  708. if not skill then
  709. return false
  710. end
  711. if skill.SpellType and skill.SpellType ~= 0 then -- 非耗蓝
  712. return true
  713. end
  714. if not skill.Spell or not skill.DefSpell then
  715. -- 没有告诉我是否耗蓝
  716. return true
  717. end
  718. local propertyProxy = global.Facade:retrieveProxy(global.ProxyTable.PlayerProperty)
  719. local currMP = propertyProxy:GetRoleCurrMP()
  720. return currMP and currMP >= (skill.Spell + skill.DefSpell)
  721. end
  722. -- 内力值 是否满足
  723. function SkillProxy:IsEnoughIValue(skillID)
  724. local skill = self:GetSkillByID(skillID) or self:GetComboSkillByID(skillID)
  725. if not skill then
  726. return false
  727. end
  728. if not skill.SpellType or skill.SpellType ~= 1 then -- 非耗内力
  729. return true
  730. end
  731. if not skill.Spell or not skill.DefSpell then
  732. return true
  733. end
  734. local propertyProxy = global.Facade:retrieveProxy(global.ProxyTable.PlayerProperty)
  735. local curForce = propertyProxy:GetInternalData().force
  736. return curForce and curForce >= (skill.Spell + skill.DefSpell)
  737. end
  738. -- 内力值/蓝值不满足 耗血 [仅血魄一击技能]
  739. function SkillProxy:IsEnoughHPSpecialCost(skillID)
  740. if not (skillID == global.MMO.SKILL_INDEX_XP_Z or skillID == global.MMO.SKILL_INDEX_XP_F or skillID == global.MMO.SKILL_INDEX_XP_D) then
  741. return false
  742. end
  743. local skill = self:GetSkillByID(skillID) or self:GetComboSkillByID(skillID)
  744. if not skill then
  745. return false
  746. end
  747. if not self._specialXPSpellParam.spellType then
  748. return false
  749. end
  750. local spellValue = self._specialXPSpellParam.spellValue
  751. local spellHPWay = self._specialXPSpellParam.spellHPWay
  752. local propertyProxy = global.Facade:retrieveProxy(global.ProxyTable.PlayerProperty)
  753. local curHP = propertyProxy:GetRoleCurrHP()
  754. local curHPPercent = propertyProxy:GetRoleHPPercent()
  755. if spellHPWay == 0 then
  756. return curHP and curHP >= spellValue, true
  757. elseif spellHPWay == 1 then
  758. return curHPPercent and curHPPercent >= spellValue, true
  759. end
  760. return false
  761. end
  762. -- 是否是自定义技能
  763. function SkillProxy:IsCustomSkill(skillID)
  764. if skillID and skillID > 1000 then
  765. return true
  766. end
  767. return false
  768. end
  769. function SkillProxy:GetCustomSkill()
  770. return self._skill_custon_skill_fighter or {}
  771. end
  772. function SkillProxy:GetAllCustomSkill()
  773. return self._skill_custom_skill or {}
  774. end
  775. function SkillProxy:IsFightCustomSkill( skillID )
  776. return skillID and self._skill_custon_skill_fighter[skillID]
  777. end
  778. -- 能不能释放
  779. function SkillProxy:CheckAbleToLaunch(skillID, isUserInput)
  780. --[[
  781. 1: able
  782. -1: not learned
  783. -2: is cd
  784. -3: not enough mana
  785. -4: buff not allowed
  786. -5: not enough mount mana
  787. -6: map limit
  788. -8: stiffness
  789. -9: isOff
  790. -10: horse
  791. -11: 延迟释放
  792. -12: 内力值不够
  793. -13: 目标buff有禁止技能 launch
  794. -14: 目标buff有禁止技能 User Input
  795. -15: 血量不足
  796. ]]
  797. -- 挖矿使用普普攻CD
  798. if skillID == global.MMO.SKILL_INDEX_DIG and not self:IsInCD(global.MMO.SKILL_INDEX_BASIC) then
  799. return 1
  800. end
  801. if not self:IsLearned(skillID) then
  802. return -1
  803. end
  804. local skillData = self:GetSkillByID(skillID) or self:GetComboSkillByID(skillID)
  805. local isCD, currCDTime = self:IsInCD(skillID)
  806. if isCD then
  807. if self:IsCDHint(skillID) then
  808. currCDTime = currCDTime or 0
  809. local lastHintTime = skillData.lastHintTime or 0
  810. if lastHintTime - currCDTime >= 1 or (lastHintTime == 0 and skillData.DelayTime > 1000) then
  811. local proxy = global.Facade:retrieveProxy(global.ProxyTable.Chat)
  812. local CHANNEL = proxy.CHANNEL
  813. local data = {}
  814. data.ChannelId = CHANNEL.System
  815. data.BColor = 249
  816. data.FColor = 255
  817. data.Msg = string.format(GET_STRING(310000101), math.ceil(currCDTime))
  818. global.Facade:sendNotification(global.NoticeTable.AddChatItem, data)
  819. skillData.lastHintTime = currCDTime
  820. end
  821. end
  822. return -2
  823. end
  824. if not self:IsEnoughMana(skillID) then
  825. local isEnoughHp, canCostHp = self:IsEnoughHPSpecialCost(skillID)
  826. if not canCostHp then
  827. return -3
  828. elseif not isEnoughHp then
  829. return -15
  830. end
  831. end
  832. if not self:IsEnoughIValue(skillID) then
  833. local isEnoughHp, canCostHp = self:IsEnoughHPSpecialCost(skillID)
  834. if not canCostHp then
  835. return -12
  836. elseif not isEnoughHp then
  837. return -15
  838. end
  839. end
  840. -- 智能野蛮特殊处理
  841. if self:IsOnoffSkill(skillID) and not self:IsOnSkill(skillID) then
  842. return -9
  843. end
  844. local HorseProxy = global.Facade:retrieveProxy( global.ProxyTable.HorseProxy )
  845. if not HorseProxy:IsLaunch(skillID) then
  846. return -10
  847. end
  848. local proxy = global.Facade:retrieveProxy(global.ProxyTable.Buff)
  849. if not proxy:CheckSkillEnable(skillID) then
  850. return -4
  851. end
  852. local MapProxy = global.Facade:retrieveProxy(global.ProxyTable.Map)
  853. if MapProxy:IsForbidLaunchSkill(skillID) then
  854. return -6
  855. end
  856. if self:IsDelayLaunch( skillID ) then
  857. return -11
  858. end
  859. local inputProxy = global.Facade:retrieveProxy(global.ProxyTable.PlayerInputProxy)
  860. local targetID = inputProxy:GetAttackTargetID() or inputProxy:GetTargetID()
  861. if targetID then
  862. if isUserInput then
  863. local buffID = global.BuffManager:CheckLaunchBuffBySkillID(targetID, skillID)
  864. if buffID then
  865. return -13, buffID
  866. end
  867. elseif global.BuffManager:CheckAutoBuffBySkillID(targetID, skillID) then
  868. return -14
  869. end
  870. end
  871. if skillData then
  872. skillData.lastHintTime = 0
  873. end
  874. return 1
  875. end
  876. -- skill key
  877. function SkillProxy:GetSkillKey(skillID)
  878. if not skillID then
  879. return nil
  880. end
  881. local skill = self:GetSkillByID(skillID)
  882. if not skill then
  883. return nil
  884. end
  885. return skill.Key
  886. end
  887. function SkillProxy:DelSkillKey(skillID, isChange)
  888. local skill = self:GetSkillByID(skillID)
  889. if not skill then
  890. return nil
  891. end
  892. local nData = {}
  893. nData.skill = clone(skill)
  894. nData.delKey = skill.Key
  895. skill.Key = 0
  896. nData.change = isChange
  897. global.Facade:sendNotification(global.NoticeTable.SkillDeleteKey, nData)
  898. self:ResuestChangeKey(skillID, 0)
  899. end
  900. function SkillProxy:SetSkillKey(skillID, key)
  901. if not skillID then
  902. return nil
  903. end
  904. local skill = self:GetSkillByID(skillID)
  905. if not skill then
  906. return nil
  907. end
  908. -- del key
  909. local keySkill = self:GetSkillByKey(key)
  910. if keySkill then
  911. if keySkill.MagicID and keySkill.MagicID == skillID then
  912. self:DelSkillKey(keySkill.MagicID, true)
  913. else
  914. self:DelSkillKey(keySkill.MagicID)
  915. end
  916. end
  917. -- new key
  918. local last = clone(skill)
  919. skill.Key = key
  920. global.Facade:sendNotification(global.NoticeTable.SkillChangeKey, {last = last, skill = skill})
  921. self:ResuestChangeKey(skillID, key)
  922. end
  923. -- 优先级替换技能(只符合第一次学习)
  924. function SkillProxy:ReplaceSkillKeyByID( skillID )
  925. local config = self:FindConfigBySkillID(skillID)
  926. if not config then
  927. return true
  928. end
  929. local success = false
  930. local replaceArray = string.split( config.drivingreplace or "", "#" )
  931. local key = tonumber(replaceArray[1])
  932. local priority = tonumber(replaceArray[2])
  933. if key and priority then
  934. local keySkill = self:GetSkillByKey(key)
  935. local keySkillPriority = keySkill and keySkill.Key or 0
  936. if keySkill then
  937. local keySkillConfig = self:FindConfigBySkillID(keySkill.MagicID)
  938. local keySkillReplaceArray = keySkillConfig and string.split( keySkillConfig.drivingreplace or "","#" )
  939. keySkillPriority = tonumber(keySkillReplaceArray[2]) or keySkillPriority
  940. end
  941. if not keySkill or (keySkillPriority and priority > keySkillPriority) then
  942. success = true
  943. self:SetSkillKey(skillID, key)
  944. end
  945. end
  946. return success
  947. end
  948. function SkillProxy:GetEmptySlot()
  949. if global.isWinPlayMode then
  950. for i = 1, 16 do
  951. if not self:GetSkillByKey(i) then
  952. return i
  953. end
  954. end
  955. else
  956. for i = 2, 9 do
  957. if not self:GetSkillByKey(i) then
  958. return i
  959. end
  960. end
  961. end
  962. return 0
  963. end
  964. -- 正在释放范围技能
  965. function SkillProxy:GetSelectSkill()
  966. return self._data.select
  967. end
  968. function SkillProxy:SelectSkill(skillID)
  969. self._data.select = skillID
  970. end
  971. function SkillProxy:ClearSelectSkill()
  972. local skillID = self._data.select
  973. self._data.select = nil
  974. global.Facade:sendNotification(global.NoticeTable.ClearSelectSkill, skillID)
  975. end
  976. -- 技能释放逻辑特征 数据
  977. function SkillProxy:GetSkillCustomData(skillID)
  978. if not skillID then
  979. return nil
  980. end
  981. return self._data.custom[skillID]
  982. end
  983. function SkillProxy:SetSkillCustomData(skillID, value)
  984. if not skillID then
  985. return nil
  986. end
  987. self._data.custom[skillID] = value
  988. end
  989. -- 开启/关闭
  990. function SkillProxy:SkillOn(skillID)
  991. self._data.onskills[skillID] = true
  992. global.Facade:sendNotification(global.NoticeTable.SkillOn, {skillID = skillID})
  993. SLBridge:onLUAEvent(LUA_EVENT_SKILL_ONOFF, {skillID = skillID, isOn = true})
  994. local autoProxy = global.Facade:retrieveProxy(global.ProxyTable.Auto)
  995. local optionID = self._skill_on_launch[skillID]
  996. if optionID and autoProxy:GetAutoLockSkillID() and (CHECK_SETTING(optionID) ~= 1 or optionID == -1) then
  997. autoProxy:SetLaunchFirstSkill( skillID )
  998. end
  999. if self:IsComboSkill(skillID) and CHECK_SETTING(global.MMO.SETTING_IDX_AUTO_COMBO) ~= 1 then
  1000. self:SetComboLanunchID(skillID)
  1001. end
  1002. end
  1003. function SkillProxy:SkillOff(skillID)
  1004. self._data.onskills[skillID] = nil
  1005. global.Facade:sendNotification(global.NoticeTable.SkillOff, {skillID = skillID})
  1006. SLBridge:onLUAEvent(LUA_EVENT_SKILL_ONOFF, {skillID = skillID, isOn = false})
  1007. end
  1008. function SkillProxy:IsOnSkill(skillID)
  1009. return (self._data.onskills[skillID] == true)
  1010. end
  1011. -- 技能开关更改
  1012. function SkillProxy:SkillSettingChange(settingID)
  1013. if not settingID then
  1014. return
  1015. end
  1016. if settingID == global.MMO.SETTING_IDX_DAODAOCISHA and self:IsLearned(global.MMO.SKILL_INDEX_CSJS) and self:IsOnoffSkill(global.MMO.SKILL_INDEX_CSJS) then
  1017. if CHECK_SETTING(settingID) == 1 and not self:IsOnSkill(global.MMO.SKILL_INDEX_CSJS) then
  1018. self:RequestSkillOnoff(global.MMO.SKILL_INDEX_CSJS)
  1019. elseif CHECK_SETTING(settingID) ~= 1 and self:IsOnSkill(global.MMO.SKILL_INDEX_CSJS) then
  1020. self:RequestSkillOnoff(global.MMO.SKILL_INDEX_CSJS)
  1021. end
  1022. end
  1023. end
  1024. -- 施法是否要检测是否距离
  1025. function SkillProxy:IsForceDis(skillID)
  1026. local config = self:FindConfigBySkillID(skillID)
  1027. if not config then
  1028. return false
  1029. end
  1030. return tonumber(config.forceDis) == 1
  1031. end
  1032. -- 设置解析替代表现的字符串
  1033. function SkillProxy:SetSkillPresentReplaceID( idStr )
  1034. self._skill_present_replace_id = {}
  1035. local parseStrArray = string.split(idStr or "",",")
  1036. for i,v in ipairs(parseStrArray) do
  1037. if v and v ~= "" then
  1038. local vArray = string.split(v,"=")
  1039. local id = tonumber(vArray[1])
  1040. local newid = tonumber(vArray[2])
  1041. if id and newid then
  1042. self._skill_present_replace_id[id] = newid
  1043. end
  1044. end
  1045. end
  1046. end
  1047. -- 获取替代表现
  1048. function SkillProxy:GetSkillPresentReplaceID( skillID )
  1049. local replaceID = self._skill_present_replace_id[skillID]
  1050. if replaceID and replaceID > 0 then
  1051. return replaceID
  1052. end
  1053. return skillID
  1054. end
  1055. -- 是否延迟释放
  1056. function SkillProxy:IsDelayLaunch( skillID )
  1057. if not skillID or skillID == global.MMO.SKILL_INDEX_BASIC or skillID == global.MMO.SKILL_INDEX_DIG then
  1058. return false
  1059. end
  1060. if not self._isDelayLaunch then
  1061. return false
  1062. end
  1063. local tTime = socket.gettime() * 1000
  1064. if tTime >= self._delayLauchEndTime then
  1065. self._isDelayLaunch = false
  1066. end
  1067. return self._isDelayLaunch
  1068. end
  1069. -- 重置技能延迟释放
  1070. function SkillProxy:ResetDelaySkillLaunch( skillID )
  1071. if not skillID or skillID == global.MMO.SKILL_INDEX_BASIC or skillID == global.MMO.SKILL_INDEX_DIG then
  1072. return
  1073. end
  1074. self._isDelayLaunch = false
  1075. local skillData = self:GetSkillByID( skillID )
  1076. local delayTimeEX = skillData and skillData.DelayTimeEX or 0
  1077. if delayTimeEX > 0 then
  1078. self._isDelayLaunch = true
  1079. self._delayLauchEndTime = socket.gettime() * 1000 + delayTimeEX
  1080. end
  1081. end
  1082. function SkillProxy:RespPlayerSkillData(msg)
  1083. local localKey = self:ReadLocalKey()
  1084. local jsonData = ParseRawMsgToJson(msg)
  1085. -- dump(jsonData)
  1086. if jsonData then
  1087. for _, v in ipairs(jsonData) do
  1088. local skill = parseOneSkillData(v)
  1089. if skill.SkillType == 6 then -- 人物连击技能
  1090. -- LJBJRate 连击暴击几率
  1091. self._data.comboSkills[skill.MagicID] = skill
  1092. SLBridge:onLUAEvent(LUA_EVENT_PLAYER_COMBO_SKILL_ADD, skill)
  1093. else
  1094. skill.Key = localKey[tostring(skill.MagicID)] or 0
  1095. self:AddSkill(skill)
  1096. SLBridge:onLUAEvent(LUA_EVENT_SKILL_INIT, skill)
  1097. end
  1098. end
  1099. end
  1100. -- 默认加个普攻
  1101. local keySkill = self:GetSkillByKey(1)
  1102. local basicKey = (keySkill and 0 or 1)
  1103. local skill = {
  1104. MagicID = global.MMO.SKILL_INDEX_BASIC,
  1105. Level = 0,
  1106. TrainLv = 1,
  1107. Key = global.isWinPlayMode and 0 or (localKey[tostring(global.MMO.SKILL_INDEX_BASIC)] or basicKey),
  1108. Name = "",
  1109. EffectType = 0,
  1110. LevelUp = 0,
  1111. LevelUpIcon = 0,
  1112. }
  1113. skill = parseOneSkillData(skill)
  1114. self:AddSkill(skill)
  1115. SLBridge:onLUAEvent(LUA_EVENT_SKILL_INIT, skill)
  1116. self:SkillSettingChange(global.MMO.SETTING_IDX_DAODAOCISHA)
  1117. end
  1118. function SkillProxy:RespPlayerAddSkill(msg)
  1119. local jsonData = ParseRawMsgToJson(msg)
  1120. -- dump(jsonData)
  1121. local skill = parseOneSkillData(jsonData)
  1122. if skill.SkillType == 6 then -- 人物连击技能
  1123. self._data.comboSkills[skill.MagicID] = skill
  1124. SLBridge:onLUAEvent(LUA_EVENT_PLAYER_COMBO_SKILL_ADD, skill)
  1125. else
  1126. self:AddSkill(skill)
  1127. -- 技能自动设置键位
  1128. local config = self:FindConfigBySkillID(skill.MagicID)
  1129. local success = self:ReplaceSkillKeyByID( skill.MagicID )
  1130. if not success and config and config.replace == 1 then
  1131. -- xxx技能强行替换普攻
  1132. self:SetSkillKey(skill.MagicID, 1)
  1133. elseif not success and self:IsActiveSkill(skill.MagicID) and skill.Key == 0 then
  1134. local slot = self:GetEmptySlot()
  1135. if slot > 0 then
  1136. self:SetSkillKey(skill.MagicID, slot)
  1137. end
  1138. end
  1139. ssr.ssrBridge:OnSkillAdd(skill)
  1140. SLBridge:onLUAEvent(LUA_EVENT_SKILL_ADD, skill)
  1141. end
  1142. end
  1143. --删除技能
  1144. function SkillProxy:RespPlayerDelSkill(msg)
  1145. local header = msg:GetHeader()
  1146. local skillID = header.recog
  1147. local skillType = header.param1
  1148. if skillType == 6 then -- 人物连击技能
  1149. local data = self._data.comboSkills[skillID]
  1150. if data then
  1151. self._data.comboSkills[skillID] = nil
  1152. SLBridge:onLUAEvent(LUA_EVENT_PLAYER_COMBO_SKILL_DEL, data)
  1153. end
  1154. else
  1155. -- 查找删除的老技能
  1156. self:DelSkill(skillID)
  1157. local skills = self:GetSkills(true, true) --没有技能时,强制设置普攻
  1158. local skill = self:GetSkillByKey(1)
  1159. if not skills or not next(skills) or not skill then
  1160. if not global.isWinPlayMode then
  1161. self:SetSkillKey(global.MMO.SKILL_INDEX_BASIC, 1)
  1162. end
  1163. end
  1164. end
  1165. end
  1166. function SkillProxy:RespPlayerUpdateSkill(msg)
  1167. local dataLen = msg:GetDataLength()
  1168. if dataLen <= 0 then
  1169. return
  1170. end
  1171. local msgHdr = msg:GetHeader()
  1172. local dataString = msg:GetData():ReadString(dataLen)
  1173. local iconID = tonumber(dataString)
  1174. local skillType = nil
  1175. local LJBJRate = nil
  1176. if not iconID then
  1177. local data = string.split(dataString, "#")
  1178. iconID = tonumber(data[1]) or 0
  1179. skillType = data[2] and tonumber(data[2])
  1180. LJBJRate = data[3] and tonumber(data[3])
  1181. end
  1182. local data = {
  1183. skillID = msgHdr.recog,
  1184. Level = msgHdr.param1,
  1185. LevelUp = msgHdr.param2,
  1186. CurTrain = msgHdr.param3,
  1187. LevelUpIcon = iconID,
  1188. }
  1189. if skillType == 6 then -- 人物连击
  1190. data.LJBJRate = LJBJRate
  1191. self:UpdateComboSkillData(data)
  1192. elseif skillType == 2 or skillType == 4 then -- 人物内功
  1193. self:UpdateNGSkillData(data, skillType)
  1194. else
  1195. self:UpdateSkillData(data)
  1196. end
  1197. end
  1198. -- 更改技能cd时间
  1199. function SkillProxy:RespSkillUpdateSkillCD(msg)
  1200. local msgHdr = msg:GetHeader()
  1201. local skillID = msgHdr.recog
  1202. local skill = self:GetSkillByID(skillID)
  1203. local config = self:FindConfigBySkillID(skillID)
  1204. if not skill or not config then
  1205. return
  1206. end
  1207. skill.DelayTime = msgHdr.param1
  1208. if self:IsInCD(skillID) and skill.curTime > 0 then
  1209. local player = global.gamePlayerController:GetMainPlayer()
  1210. if not player then
  1211. return nil
  1212. end
  1213. -- globalCD
  1214. local attackglobalCD = SL:GetMetaValue("GAME_DATA","attackglobalCD") or 900
  1215. local magicglobalCD = SL:GetMetaValue("GAME_DATA","magicglobalCD") or 1000
  1216. local globalCD = (config.action == 1 and magicglobalCD or attackglobalCD) * 0.001
  1217. -- skillCD
  1218. local attackCD = (player:GetAttackStepTime() / player:GetAttackSpeed())
  1219. local magicCD = (player:GetMagicStepTime() / player:GetMagicSpeed())
  1220. local launchCD = (config.action == 1 and magicCD or attackCD)
  1221. launchCD = math.max(globalCD, launchCD)
  1222. local maxTime = math.max(launchCD, skill.DelayTime*0.001)
  1223. local excessTime = maxTime - skill.maxTime
  1224. skill.maxTime = maxTime
  1225. skill.curTime = math.max(skill.curTime + excessTime, 0)
  1226. end
  1227. end
  1228. function SkillProxy:ResuestChangeKey(skillID, key)
  1229. self:WriteLocalKey()
  1230. end
  1231. function SkillProxy:RequestSkillOnoff(skillID, isCombo)
  1232. if not self:IsLearned(skillID) then
  1233. return nil
  1234. end
  1235. if self:IsCustomSkill(skillID) then --自定义技能 开关型技能单控
  1236. local isOn = self:IsOnSkill(skillID) and 0 or 1 --0关闭; 1打开
  1237. LuaSendMsg(global.MsgType.MSG_CS_MagicOnOff, skillID, isOn, 0, 0)
  1238. return
  1239. end
  1240. local sendData = {
  1241. skillID = skillID,
  1242. }
  1243. local sendJson = cjson.encode(sendData)
  1244. LuaSendMsg(global.MsgType.MSG_CS_PLAYER_SKILL_LAUNCH, skillID, 0, 0, 0, sendJson, string.len(sendJson))
  1245. end
  1246. function SkillProxy:RespSkillOnoff(msg)
  1247. local msgLen = msg:GetDataLength()
  1248. if msgLen <= 0 then
  1249. return 1
  1250. end
  1251. local msgData = msg:GetData()
  1252. local dataStr = msgData:ReadString(msgLen)
  1253. local jsonData = cjson.decode(dataStr)
  1254. -- dump(jsonData)
  1255. if jsonData.Flag == 1 then
  1256. self:SkillOn(jsonData.Id)
  1257. elseif jsonData.Flag == 0 then
  1258. self:SkillOff(jsonData.Id)
  1259. end
  1260. self:UpdateDoubleCD( jsonData.Id )
  1261. end
  1262. function SkillProxy:actorEnterAction(jsonData, isMagic)
  1263. local skillID = jsonData.MagicID
  1264. local actorID = jsonData.UserID
  1265. local dX = jsonData.X
  1266. local dY = jsonData.Y
  1267. local dir = jsonData.Dir
  1268. local launcher = global.actorManager:GetActor(actorID)
  1269. if nil == launcher then
  1270. print("launcher is miss!")
  1271. return nil
  1272. end
  1273. if launcher:IsDie() then
  1274. print("launcher is death!")
  1275. return nil
  1276. end
  1277. local config = self:FindConfigBySkillID(skillID)
  1278. if not config then
  1279. print("warning, can not find skill info!")
  1280. end
  1281. local action =
  1282. {
  1283. actor = launcher,
  1284. dir = dir,
  1285. skillID = skillID,
  1286. isMagic = isMagic,
  1287. X = dX,
  1288. Y = dY,
  1289. NoHitAct = jsonData.NoHitAct,
  1290. ActionId = jsonData.ActionId
  1291. }
  1292. if not config then
  1293. global.Facade:sendNotification(global.NoticeTable.ActorEnterAttackAction, action)
  1294. elseif config and config.action == 0 then
  1295. global.Facade:sendNotification(global.NoticeTable.ActorEnterAttackAction, action)
  1296. elseif config and config.action == 1 then
  1297. global.Facade:sendNotification(global.NoticeTable.ActorEnterSkillAction, action)
  1298. end
  1299. if launcher:IsHero() or launcher:IsNetPlayer() or launcher:IsHumanoid() then
  1300. launcher:SetConfirmed(true)
  1301. end
  1302. end
  1303. function SkillProxy:requestSkillPresent(jsonData, skillStage)
  1304. local skillID = jsonData.MagicID
  1305. local launcherID = jsonData.UserID
  1306. local dX = jsonData.X
  1307. local dY = jsonData.Y
  1308. local dir = jsonData.Dir
  1309. if skillStage == 2 and skillID == 75 then --护体神盾
  1310. skillStage = 3
  1311. end
  1312. local launcher = global.actorManager:GetActor(launcherID)
  1313. if nil == launcher then
  1314. print("launcher is miss!")
  1315. return nil
  1316. end
  1317. if launcher:IsDie() then
  1318. print("launcher is death!")
  1319. return nil
  1320. end
  1321. local present_param = nil
  1322. if jsonData.TargetUserID and string.len(jsonData.TargetUserID) > 0 then
  1323. present_param = jsonData.TargetUserID
  1324. end
  1325. -- for monster baisc skill
  1326. if launcher:IsMonster() and skillID == global.MMO.SKILL_INDEX_BASIC then
  1327. local raceServer = launcher:GetRaceServer() or 0
  1328. local raceImg = launcher:GetRaceImg() or 0
  1329. local t = string.format("%s%s", raceServer, raceImg)
  1330. t = tonumber(t) or 0
  1331. skillID = t + 100000
  1332. -- print("raceImg+++++++++++++++++++++", raceServer, raceImg, t, skillID)
  1333. end
  1334. -- 替代skillID
  1335. local replaceID = jsonData.ScriptEffect
  1336. local newSkillID = (replaceID and replaceID > 0) and replaceID or skillID
  1337. -- 主玩家技能表现
  1338. if launcherID == global.gamePlayerController:GetMainPlayerID() then
  1339. newSkillID = self:GetSkillPresentReplaceID(skillID)
  1340. end
  1341. -- skill present
  1342. local present =
  1343. {
  1344. skillID = newSkillID,
  1345. launchX = launcher:GetMapX(),
  1346. launchY = launcher:GetMapY(),
  1347. hitX = dX,
  1348. hitY = dY,
  1349. dir = dir,
  1350. param = present_param,
  1351. skillStage = skillStage,
  1352. launcherID = launcherID
  1353. }
  1354. global.Facade:sendNotification(global.NoticeTable.RequestSkillPresent, present)
  1355. end
  1356. -- 是否不需要结束状态后进入技能action(野蛮不需要结束就能进入) skillID: 技能id
  1357. function SkillProxy:IsNotNeedEnterAction(skillID)
  1358. if skillID == global.MMO.SKILL_INDEX_YMCZ then
  1359. -- 禁止移动状态释放
  1360. if self._mootebo_with_cd == 1 and SL:GetMetaValue("ACTOR_IS_MOVE", SL:GetMetaValue("MAIN_ACTOR_ID")) then
  1361. return false
  1362. end
  1363. -- 禁止释放技能状态释放
  1364. if self._mootebo_with_hit_cd == 1 and SL:GetMetaValue("ACTOR_IS_LAUNCH_ACTION", SL:GetMetaValue("MAIN_ACTOR_ID")) then
  1365. return false
  1366. end
  1367. return true
  1368. end
  1369. return false
  1370. end
  1371. -- 立即施法 skillID: 技能id
  1372. function SkillProxy:RequestLaunchImmediate(skillID)
  1373. local mainPlayer = global.gamePlayerController:GetMainPlayer()
  1374. if not mainPlayer then
  1375. return nil
  1376. end
  1377. global.Facade:sendNotification(global.NoticeTable.RequestLaunchSkill, {skillID = skillID})
  1378. end
  1379. -- 个人的技能表现修改列表
  1380. function SkillProxy:handle_MSG_SC_SENDMAGICSCRIPTEFFECT( msg )
  1381. local msgLen = msg:GetDataLength()
  1382. local dataString = ""
  1383. if msgLen > 0 then
  1384. dataString = msg:GetData():ReadString(msgLen)
  1385. end
  1386. self:SetSkillPresentReplaceID( dataString )
  1387. end
  1388. -- 所有CD归0
  1389. function SkillProxy:handle_MSG_SC_INITMAGICCD( msg )
  1390. for _skillid, _skilldata in pairs(self._data.skills or {}) do
  1391. if _skillid then
  1392. global.Facade:sendNotification(global.NoticeTable.SkillEnterCD, _skillid)
  1393. end
  1394. end
  1395. end
  1396. --------------------------- 内功技能 ----------------------------------
  1397. function SkillProxy:GetNGSkills()
  1398. return self._data.ngSkills
  1399. end
  1400. function SkillProxy:GetNGSkillsList()
  1401. local list = {}
  1402. for _, data in pairs(self._data.ngSkills) do
  1403. for i, skill in pairs(data) do
  1404. table.insert(list, skill)
  1405. end
  1406. end
  1407. table.sort(list, function(a, b)
  1408. if a.MagicID ~= b.MagicID then
  1409. return a.MagicID < b.MagicID
  1410. end
  1411. return a.SkillType < b.SkillType
  1412. end)
  1413. return list
  1414. end
  1415. function SkillProxy:GetNGSkillData(skillID, skillType)
  1416. return self._data.ngSkills[skillType] and self._data.ngSkills[skillType][skillID]
  1417. end
  1418. -- skill 开关
  1419. function SkillProxy:GetNGSkillOnOff(skillID, skillType)
  1420. if not skillID then
  1421. return nil
  1422. end
  1423. local skill = self:GetNGSkillData(skillID, skillType)
  1424. if not skill then
  1425. return nil
  1426. end
  1427. return skill.Key
  1428. end
  1429. function SkillProxy:SetNGSkillOnOff(skillID, skillType, key)
  1430. if not skillID then
  1431. return nil
  1432. end
  1433. local skill = self:GetNGSkillData(skillID, skillType)
  1434. if not skill then
  1435. return nil
  1436. end
  1437. skill.Key = key
  1438. self:RequestNGSkillOnOff(skillID, skillType, key)
  1439. end
  1440. function SkillProxy:GetNGSkillName(skillID, skillType)
  1441. local config = self:FindConfigBySkillID(skillID)
  1442. if not config then
  1443. return "ERROR SKILL NAME"
  1444. end
  1445. if skillType == 2 then
  1446. return config.nMagicName
  1447. elseif skillType == 4 then
  1448. return config.jMagicName
  1449. end
  1450. end
  1451. function SkillProxy:GetNGSkillDesc(skillID, skillType)
  1452. local config = self:FindConfigBySkillID(skillID)
  1453. if not config then
  1454. return "ERROR SKILL DESC"
  1455. end
  1456. if skillType == 2 then
  1457. return config.nDesc
  1458. elseif skillType == 4 then
  1459. return config.jDesc
  1460. end
  1461. end
  1462. -- 获取内功技能Icon 矩形
  1463. function SkillProxy:GetNGIconRectPath(skillID, skillType)
  1464. local config = self:FindConfigBySkillID(skillID)
  1465. if not config then
  1466. local path = string.format("%s%s.png", global.MMO.PATH_RES_SKILL_ICON, "default")
  1467. if global.FileUtilCtl:isFileExist(path) then
  1468. return path
  1469. end
  1470. return string.format("%s%s.jpg", global.MMO.PATH_RES_SKILL_ICON, "default")
  1471. end
  1472. local data = self:GetNGSkillData(skillID, skillType)
  1473. local icon = nil
  1474. if skillType == 2 then -- 怒
  1475. icon = config.nIcon
  1476. elseif skillType == 4 then -- 静
  1477. icon = config.jIcon
  1478. end
  1479. icon = icon or config.icon
  1480. if not data or not data.LevelUpIcon or data.LevelUpIcon <= 0 then
  1481. local path = string.format("%s%s.png", global.MMO.PATH_RES_SKILL_ICON, icon)
  1482. if global.FileUtilCtl:isFileExist(path) then
  1483. return path
  1484. end
  1485. return string.format("%s%s.jpg", global.MMO.PATH_RES_SKILL_ICON, icon)
  1486. end
  1487. local path = string.format("%s%s_%s.png", global.MMO.PATH_RES_SKILL_ICON, icon, data.LevelUpIcon)
  1488. if global.FileUtilCtl:isFileExist(path) then
  1489. return path
  1490. end
  1491. return string.format("%s%s_%s.jpg", global.MMO.PATH_RES_SKILL_ICON, icon, data.LevelUpIcon)
  1492. end
  1493. --key 0 开启 1关闭
  1494. --type 0人物 1内功 2连击
  1495. --skillType 0=人物技能, 1=英雄技能 2=人物怒内功技能 3=英雄怒内功技能 4=人物静内功技能 5=英雄静内功技能 6=人物连击技能 7=英雄连击技能
  1496. function SkillProxy:RequestNGSkillOnOff(skillID, skillType, key)
  1497. LuaSendMsg(global.MsgType.MSG_CS_PLAYER_ONOFF_INTERNAL_SKILL, skillID, key, skillType or 0, 0)
  1498. end
  1499. -- 0: 人物 1:英雄
  1500. function SkillProxy:RequestNGSkillData(isHero)
  1501. local type = isHero and 1 or 0
  1502. LuaSendMsg(global.MsgType.MSG_CS_GET_NG_SKILL_DATA, type, 0, 0, 0)
  1503. end
  1504. function SkillProxy:GetNGSkillTrainData(skillID, skillType)
  1505. -- 技能等级>3的全部特殊处理下
  1506. local maxStr = "-"
  1507. if not skillID or not self._data.ngSkills[skillType] or not self._data.ngSkills[skillType][skillID] then
  1508. return maxStr
  1509. end
  1510. if skillID == global.MMO.SKILL_INDEX_BASIC then
  1511. return maxStr
  1512. end
  1513. local skillData = self._data.ngSkills[skillType][skillID]
  1514. local isBaseSkill = skillData.Level <= 3
  1515. local skillLevel = skillData.Level
  1516. local maxSkillLevel = skillData.TrainLv
  1517. if skillLevel >= maxSkillLevel then
  1518. return maxStr
  1519. end
  1520. local skillMaxTrain = {
  1521. [0] = skillData.MaxTrain1,
  1522. [1] = skillData.MaxTrain2,
  1523. [2] = skillData.MaxTrain3,
  1524. [3] = skillData.MaxTrain4
  1525. }
  1526. local curTrain = skillData.CurTrain or 0
  1527. local maxTrain = (isBaseSkill and skillMaxTrain[skillLevel] or skillData.MaxTrain1) or 0
  1528. return curTrain >= maxTrain and maxStr or string.format(GET_STRING(1053), curTrain, maxTrain)
  1529. end
  1530. function SkillProxy:UpdateNGSkillData(data, skillType)
  1531. -- 更新技能数据
  1532. if not data then
  1533. return
  1534. end
  1535. if not data.skillID then
  1536. return nil
  1537. end
  1538. local skill = self:GetNGSkillData(data.skillID, skillType)
  1539. if not skill then
  1540. return nil
  1541. end
  1542. -- 更新技能属性
  1543. for k, v in pairs(data) do
  1544. skill[k] = v
  1545. end
  1546. SLBridge:onLUAEvent(LUA_EVENT_INTERNAL_SKILL_UPDATE, skill)
  1547. end
  1548. function SkillProxy:RespPlayerNGSkillData(msg)
  1549. local jsonData = ParseRawMsgToJson(msg)
  1550. if jsonData then
  1551. for _, v in ipairs(jsonData) do
  1552. local skill = parseOneSkillData(v)
  1553. if not self._data.ngSkills[skill.SkillType] then
  1554. self._data.ngSkills[skill.SkillType] = {}
  1555. end
  1556. self._data.ngSkills[skill.SkillType][skill.MagicID] = skill
  1557. end
  1558. -- SLBridge:onLUAEvent(LUA_EVENT_INTERNAL_SKILL_INIT)
  1559. end
  1560. end
  1561. function SkillProxy:RespPlayerAddNGSkill(msg)
  1562. local jsonData = ParseRawMsgToJson(msg)
  1563. local skill = parseOneSkillData(jsonData)
  1564. if not self._data.ngSkills[skill.SkillType] then
  1565. self._data.ngSkills[skill.SkillType] = {}
  1566. end
  1567. self._data.ngSkills[skill.SkillType][skill.MagicID] = skill
  1568. SLBridge:onLUAEvent(LUA_EVENT_INTERNAL_SKILL_ADD, skill)
  1569. end
  1570. --删除技能
  1571. function SkillProxy:RespPlayerDelNGSkill(msg)
  1572. local header = msg:GetHeader()
  1573. local skillID = header.recog
  1574. local skillType = header.param1
  1575. local data = self._data.ngSkills[skillType] and self._data.ngSkills[skillType][skillID]
  1576. if data then
  1577. self._data.ngSkills[skillType][skillID] = nil
  1578. SLBridge:onLUAEvent(LUA_EVENT_INTERNAL_SKILL_DEL, data)
  1579. end
  1580. end
  1581. --------------------------- 连击技能 ----------------------------------
  1582. function SkillProxy:haveSetComboSkill()
  1583. return self._data.setComboSkill
  1584. end
  1585. function SkillProxy:SetComboSkill(idx, skillID)
  1586. self._data.setComboSkill[idx] = skillID
  1587. end
  1588. function SkillProxy:GetComboSkills()
  1589. return self._data.comboSkills
  1590. end
  1591. function SkillProxy:GetComboSkillByID(skillID)
  1592. -- 获取技能数据
  1593. return self._data.comboSkills[skillID]
  1594. end
  1595. function SkillProxy:IsComboSkill(skillID)
  1596. if self._data.comboSkills[skillID] then
  1597. return true
  1598. else
  1599. return false
  1600. end
  1601. end
  1602. function SkillProxy:SetComboLanunchID(skillID)
  1603. self._comboSkillLaunchID = skillID
  1604. end
  1605. function SkillProxy:GetComboLanunchID()
  1606. return self._comboSkillLaunchID
  1607. end
  1608. function SkillProxy:ClearComboLanunchID()
  1609. self._comboSkillLaunchID = nil
  1610. end
  1611. function SkillProxy:SetlaunchComboStatus(state)
  1612. self._canLaunchComboStatus = state
  1613. end
  1614. function SkillProxy:GetlaunchComboStatus()
  1615. return self._canLaunchComboStatus
  1616. end
  1617. function SkillProxy:GetComboSkillTrainData(skillID)
  1618. -- 技能等级>3的全部特殊处理下
  1619. local maxStr = "-"
  1620. if not skillID or not self._data.comboSkills[skillID] then
  1621. return maxStr
  1622. end
  1623. local skillData = self._data.comboSkills[skillID]
  1624. local isBaseSkill = skillData.Level <= 3
  1625. local skillLevel = skillData.Level
  1626. local maxSkillLevel = skillData.TrainLv
  1627. if skillLevel >= maxSkillLevel then
  1628. return maxStr
  1629. end
  1630. local skillMaxTrain = {
  1631. [0] = skillData.MaxTrain1,
  1632. [1] = skillData.MaxTrain2,
  1633. [2] = skillData.MaxTrain3,
  1634. [3] = skillData.MaxTrain4
  1635. }
  1636. local curTrain = skillData.CurTrain or 0
  1637. local maxTrain = (isBaseSkill and skillMaxTrain[skillLevel] or skillData.MaxTrain1) or 0
  1638. return curTrain >= maxTrain and maxStr or string.format(GET_STRING(1053), curTrain, maxTrain)
  1639. end
  1640. function SkillProxy:UpdateComboSkillData(data)
  1641. -- 更新技能数据
  1642. if not data then
  1643. return
  1644. end
  1645. if not data.skillID then
  1646. return nil
  1647. end
  1648. local skill = self:GetComboSkillByID(data.skillID)
  1649. if not skill then
  1650. return nil
  1651. end
  1652. -- 更新技能属性
  1653. for k, v in pairs(data) do
  1654. skill[k] = v
  1655. end
  1656. SLBridge:onLUAEvent(LUA_EVENT_PLAYER_COMBO_SKILL_UPDATE, skill)
  1657. end
  1658. function SkillProxy:RequestSetComboSkill(key, skillID, isHero)
  1659. if not key then
  1660. return
  1661. end
  1662. skillID = skillID or 0
  1663. local type = isHero and 1 or 0
  1664. LuaSendMsg(global.MsgType.MSG_CS_SET_COMBO_SKILL, type, key, skillID, 0)
  1665. end
  1666. function SkillProxy:RespSetComboSkill(msg)
  1667. local header = msg:GetHeader()
  1668. local type = header.recog
  1669. local key = header.param1
  1670. local skillID = header.param2
  1671. if key ~= 0 then
  1672. if type == 0 then -- 人物
  1673. if skillID == 0 then
  1674. self:SetComboSkill(key, nil)
  1675. else
  1676. self:SetComboSkill(key, skillID)
  1677. end
  1678. SL:onLUAEvent(LUA_EVENT_PLAYER_SET_COMBO_REFRESH, key)
  1679. elseif type == 1 then -- 英雄
  1680. local HeroSkillProxy = global.Facade:retrieveProxy(global.ProxyTable.HeroSkillProxy)
  1681. if skillID == 0 then
  1682. HeroSkillProxy:SetComboSkill(key, nil)
  1683. else
  1684. HeroSkillProxy:SetComboSkill(key, skillID)
  1685. end
  1686. SL:onLUAEvent(LUA_EVENT_HERO_SET_COMBO_REFRESH, key)
  1687. end
  1688. end
  1689. end
  1690. function SkillProxy:GetComboOpenNum()
  1691. return self._data.openComboNum
  1692. end
  1693. function SkillProxy:RespSetComboSkillOpenNum(msg)
  1694. local header = msg:GetHeader()
  1695. local type = header.recog
  1696. local openNum = header.param1
  1697. if openNum and openNum > 0 then
  1698. if type == 0 then -- 人物
  1699. self._data.openComboNum = openNum
  1700. SLBridge:onLUAEvent(LUA_EVENT_PLAYER_OPEN_COMBO_NUM, openNum)
  1701. elseif type == 1 then -- 英雄
  1702. local HeroSkillProxy = global.Facade:retrieveProxy(global.ProxyTable.HeroSkillProxy)
  1703. HeroSkillProxy:SetComboOpenNum(openNum)
  1704. SLBridge:onLUAEvent(LUA_EVENT_HERO_OPEN_COMBO_NUM, openNum)
  1705. end
  1706. end
  1707. end
  1708. -- 重置技能cd
  1709. function SkillProxy:handle_MSG_SC_REST_SKILL_CD(msg)
  1710. local header = msg:GetHeader()
  1711. local skillID = header.recog
  1712. local remainCD = header.param1
  1713. local skillData = self:GetSkillByID(skillID)
  1714. if skillData then
  1715. remainCD = skillData.curTime - remainCD / 1000
  1716. skillData.curTime = math.max(remainCD, 0)
  1717. end
  1718. end
  1719. --------------------------------------------------------------------------
  1720. --------------------------------------- 技能动作 begin---------------------
  1721. function SkillProxy:GetSkillActionTime(action, clothID, sex)
  1722. if not action then
  1723. return nil
  1724. end
  1725. action = action - global.MMO.ACTION_YTPD + 1
  1726. local configs = self._configs_skill_action[action]
  1727. if not configs then
  1728. return nil
  1729. end
  1730. if not configs.pcs then
  1731. return nil
  1732. end
  1733. if clothID == 0 then
  1734. clothID = 9999
  1735. end
  1736. local clothTime = 0.1
  1737. if clothID then
  1738. local ModelConfigProxy = global.Facade:retrieveProxy( global.ProxyTable.ModelConfigProxy )
  1739. local anmindID = GetFrameAnimConfigID( clothID, sex or 0, global.MMO.SFANIM_TYPE_PLAYER )
  1740. local modelConfig = ModelConfigProxy:GetConfig( anmindID )
  1741. if configs and configs.actionspeed == 0 then
  1742. clothTime = modelConfig.attack_interval
  1743. elseif configs and configs.actionspeed == 1 then
  1744. clothTime = modelConfig.magic_interval
  1745. end
  1746. end
  1747. return configs.pcs * clothTime
  1748. end
  1749. function SkillProxy:GetSkillActionSpeed(action)
  1750. if not action then
  1751. return nil
  1752. end
  1753. if action > global.MMO.ANIM_WJGZ then
  1754. action = action + 2
  1755. end
  1756. action = action - global.MMO.ANIM_YTPD + 1
  1757. local configs = self._configs_skill_action[action]
  1758. if not configs then
  1759. return nil
  1760. end
  1761. return configs.actionspeed
  1762. end
  1763. --------------------------------------- 技能动作 end---------------------
  1764. function SkillProxy:RegisterMsgHandler()
  1765. SkillProxy.super.RegisterMsgHandler(self)
  1766. local msgType = global.MsgType
  1767. LuaRegisterMsgHandler(msgType.MSG_SC_PLAYER_SKILL_DATA, handler(self, self.RespPlayerSkillData)) -- 主角 已学技能 信息
  1768. LuaRegisterMsgHandler(msgType.MSG_SC_PLAYER_ADD_SKILL, handler(self, self.RespPlayerAddSkill)) -- 新增技能
  1769. LuaRegisterMsgHandler(msgType.MSG_SC_PLAYER_DEL_SKILL, handler(self, self.RespPlayerDelSkill)) -- 删除技能
  1770. LuaRegisterMsgHandler(msgType.MSG_SC_PLAYER_UP_SKILL, handler(self, self.RespPlayerUpdateSkill)) -- 技能数据更新
  1771. LuaRegisterMsgHandler(msgType.MSG_SC_SKILL_ONOFF, handler(self, self.RespSkillOnoff)) -- 技能开关
  1772. LuaRegisterMsgHandler(msgType.MSG_SC_PLAYER_UP_SKILL_CD, handler(self, self.RespSkillUpdateSkillCD)) -- 技能CD改变
  1773. LuaRegisterMsgHandler(msgType.MSG_SC_SENDMAGICSCRIPTEFFECT, handler(self, self.handle_MSG_SC_SENDMAGICSCRIPTEFFECT)) --个人的技能表现修改列表
  1774. LuaRegisterMsgHandler(msgType.MSG_SC_INITMAGICCD, handler(self, self.handle_MSG_SC_INITMAGICCD)) --所有CD归0
  1775. LuaRegisterMsgHandler(msgType.MSG_SC_REST_SKILL_CD, handler(self, self.handle_MSG_SC_REST_SKILL_CD)) --重置技能cd
  1776. LuaRegisterMsgHandler(msgType.MSG_SC_PLAYER_NG_SKILL_DATA, handler(self, self.RespPlayerNGSkillData)) -- 内功技能
  1777. LuaRegisterMsgHandler(msgType.MSG_SC_PLAYER_ADD_NG_SKILL, handler(self, self.RespPlayerAddNGSkill))
  1778. LuaRegisterMsgHandler(msgType.MSG_SC_PLAYER_DEL_NG_SKILL, handler(self, self.RespPlayerDelNGSkill))
  1779. LuaRegisterMsgHandler(msgType.MSG_SC_SET_COMBO_SKILL, handler(self, self.RespSetComboSkill))
  1780. LuaRegisterMsgHandler(msgType.MSG_SC_SET_COMBO_SKILL_OPEN_NUM, handler(self, self.RespSetComboSkillOpenNum)) -- 连击技能开启个数
  1781. end
  1782. return SkillProxy