EquipLogic.lua 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. local Msg = require("core.Msg")
  2. local Util = require("common.Util")
  3. local Grid = require("bag.Grid")
  4. local ItemDefine = require("bag.ItemDefine")
  5. local TuJianExcel = require("excel.equip").tujian
  6. local EquipExcel = require("excel.equip").equip
  7. local ItemExcel = require("excel.item").item
  8. local EquipLogicGrid = require("equip.EquipLogicGrid")
  9. local Log = require("common.Log")
  10. local LogDefine = require("common.LogDefine")
  11. local Lang = require("common.Lang")
  12. local Broadcast = require("broadcast.Broadcast")
  13. local MailManager = require("mail.MailManager")
  14. local MailExcel = require("excel.mail")
  15. local HeroLogic = require("hero.HeroLogic")
  16. local TriggerDefine = require("trigger.TriggerDefine")
  17. local TriggerLogic = require("trigger.TriggerLogic")
  18. local effectCfg = require("excel.equip").texiao
  19. local HeroDefine = require("hero.HeroDefine")
  20. EQUIP_BAG_MAX_CNT = 500
  21. EQUIP_BAG_OP_ADD = 1 -- 增
  22. EQUIP_BAG_OP_DEL = 2 -- 删
  23. EQUIP_BAG_OP_CHANGE = 3 -- 改
  24. EQUIP_QUALITY_MAX = 5
  25. EQUIP_QUALITY = { 5000, 3000, 1500, 500 }
  26. EQUIP_QUALITY_WEIGHT = 10000
  27. EQUIP_QUALITY_BASE_RATE = { 7000, 8000, 9000, 10000, 12000 }
  28. local EQUIP_HEROEXCLUSIVE_WEIGHT = 4000 --戒指、护符随机出英雄专属属性权重
  29. local EQUIP_NO_HEROEXCLUSIVE_WEIGHT = 6000 --戒指、护符随不出英雄专属属性权重
  30. -- 转换装备洗练数据格式
  31. function AttrHashToArray(attrData)
  32. local _, attrInfo = next(attrData)
  33. if type(attrInfo) == "table" then
  34. return attrData
  35. end
  36. local len = 0
  37. local attrArray = {}
  38. for attrType, attrVal in pairs(attrData) do
  39. len = len + 1
  40. attrArray[len] = {attrType, attrVal, EquipLogicGrid.EQUIP_COLOR_3}
  41. end
  42. return attrArray
  43. end
  44. -- 随出单条洗练属性的品质 和 倍数
  45. local function randAttrValMul()
  46. local totalWeight = 0
  47. for _, weight in ipairs(EquipLogicGrid.EQUIPWASH_COLOR_WEIGHT) do
  48. totalWeight = totalWeight + weight
  49. end
  50. local color = 0
  51. local mul = 0
  52. local randNum = math.random(1, totalWeight)
  53. local weight = 0
  54. for k, v in ipairs(EquipLogicGrid.EQUIPWASH_COLOR_WEIGHT) do
  55. weight = weight + v
  56. if randNum <= weight then
  57. color = k
  58. break
  59. end
  60. end
  61. assert(color > 0, "============装备洗练配置错误===============")
  62. local mulTbl = EquipLogicGrid.EQUIPWASH_COLOR_MUL[color]
  63. mul = math.random(mulTbl[1], mulTbl[2]) / 100
  64. return color, mul
  65. end
  66. -- 随机装备品质
  67. local function randColor(randomAttrCfg)
  68. local color = 0
  69. local random = math.random(1, EQUIP_QUALITY_WEIGHT)
  70. for i = 1, #EQUIP_QUALITY do
  71. local weight = EQUIP_QUALITY[i]
  72. if random <= weight then
  73. color = i > #randomAttrCfg and #randomAttrCfg or i
  74. break
  75. else
  76. random = random - weight
  77. end
  78. end
  79. return color
  80. end
  81. -- 随机出装备洗练属性
  82. local function randAttrArray(randomAttrCfg, equipColor, excludeAttrList)
  83. --品质
  84. equipColor = equipColor or randColor(randomAttrCfg)
  85. -- 排除特定属性
  86. if excludeAttrList then
  87. for idx, attrInfo in pairs(randomAttrCfg) do
  88. local attrType = attrInfo[1]
  89. if excludeAttrList[attrType] then
  90. randomAttrCfg[idx] = nil
  91. end
  92. end
  93. end
  94. -- 计算总权重
  95. local totalWeight = 0
  96. for k, v in pairs(randomAttrCfg) do
  97. totalWeight = totalWeight + v[3]
  98. end
  99. local len = 0
  100. local attr = {}
  101. local MathRandom = math.random
  102. -- for i = 1, equipColor do
  103. -- local weight = 0
  104. -- local randmWeight = MathRandom(1, totalWeight)
  105. -- for _, v in ipairs(randomAttrCfg) do
  106. -- weight = weight + v[3]
  107. -- if randmWeight <= weight then
  108. -- len = len + 1
  109. -- local attrColor, mul = randAttrValMul()
  110. -- local finalVal = math.floor(v[2] * mul)
  111. -- attr[len] = {v[1], finalVal, attrColor}
  112. -- break
  113. -- end
  114. -- end
  115. -- end
  116. for z = 1, equipColor do
  117. local randmWeight = MathRandom(1, totalWeight)
  118. for k, v in pairs(randomAttrCfg) do
  119. local key = v[1]
  120. local value = v[2]
  121. local weight = v[3]
  122. if randmWeight <= weight then
  123. len = len + 1
  124. local attrColor, mul = randAttrValMul()
  125. local finalVal = math.floor(value * mul)
  126. attr[len] = {key, finalVal, attrColor}
  127. randomAttrCfg[k] = nil
  128. -- 排除这个权重
  129. totalWeight = totalWeight - weight
  130. break
  131. else
  132. randmWeight = randmWeight - weight
  133. end
  134. end
  135. end
  136. return attr
  137. end
  138. ---------------------------------------------------------戒指、护符随机特效---------------------------------------------------
  139. local function generateRandData(excludeTypeList)
  140. local totalWeight = 0
  141. local type2List = {}
  142. for k,v in ipairs(effectCfg) do
  143. local tp = v.type
  144. if not excludeTypeList or not excludeTypeList[tp] then
  145. local weight = v.weight
  146. type2List[tp] = type2List[tp] or {weight = 0, typeList = {}}
  147. type2List[tp].weight = type2List[tp].weight + weight
  148. table.insert(type2List[tp].typeList, {id = k, weight = weight})
  149. totalWeight = totalWeight + weight
  150. end
  151. end
  152. local len = 0
  153. local randList = {}
  154. for _, tpData in pairs(type2List) do
  155. len = len + 1
  156. randList[len] = tpData
  157. end
  158. return totalWeight, randList
  159. end
  160. local function getIndexByRand(totalWeight, randList)
  161. local tpList
  162. local weight = 0
  163. local randWeight = math.random(0, totalWeight)
  164. for _,v in ipairs(randList) do
  165. weight = weight + v.weight
  166. if randWeight <= weight then
  167. tpList = v
  168. break
  169. end
  170. end
  171. weight = 0
  172. randWeight = math.random(0, tpList.weight)
  173. for _,v in ipairs(tpList.typeList) do
  174. weight = weight + v.weight
  175. if randWeight <= weight then
  176. return v.id
  177. end
  178. end
  179. end
  180. -- 随机出戒指、护符的特效
  181. local function randEffectAttrList(equipId)
  182. local equipCfg = EquipExcel[equipId]
  183. if equipCfg.subType ~= ItemDefine.EQUIP_SUBTYPE_RING and equipCfg.subType ~= ItemDefine.EQUIP_SUBTYPE_AMULET then
  184. return
  185. end
  186. local excludeTypeList
  187. local noEffectTimes = 0
  188. local effectList = {}
  189. for i=1, 3 do
  190. local totalWeight, randList = generateRandData(excludeTypeList)
  191. local effctId = getIndexByRand(totalWeight, randList)
  192. if effctId == 1 then
  193. noEffectTimes = noEffectTimes + 1
  194. else
  195. effectList[effctId] = 1
  196. excludeTypeList = excludeTypeList or {}
  197. local excludeType = effectCfg[effctId].type
  198. excludeTypeList[excludeType] = 1
  199. end
  200. -- 保底要有一条特效
  201. if noEffectTimes >= 2 then
  202. excludeTypeList = excludeTypeList or {}
  203. local excludeType = effectCfg[1].type
  204. excludeTypeList[excludeType] = 1
  205. end
  206. end
  207. return effectList
  208. end
  209. --------------------------------------------------------------------------------------------------------------------------------
  210. ---------------------------------------------------------戒指、护符随机英雄专属---------------------------------------------------
  211. local function randHeroExclusive(equipId)
  212. local equipCfg = EquipExcel[equipId]
  213. if equipCfg.subType ~= ItemDefine.EQUIP_SUBTYPE_RING and equipCfg.subType ~= ItemDefine.EQUIP_SUBTYPE_AMULET then
  214. return
  215. end
  216. local randWeight = math.random(0, (EQUIP_HEROEXCLUSIVE_WEIGHT + EQUIP_NO_HEROEXCLUSIVE_WEIGHT))
  217. if randWeight > EQUIP_HEROEXCLUSIVE_WEIGHT then
  218. return
  219. end
  220. local heroList = HeroDefine.GetAllHighQualityHero()
  221. local len = #heroList
  222. if len <= 0 then
  223. return
  224. end
  225. local idx = math.random(1, len)
  226. return heroList[idx]
  227. end
  228. --------------------------------------------------------------------------------------------------------------------------------
  229. -- 随机属性
  230. local attrCheck = {}
  231. function checkAttr(equipGrid)
  232. local quality = equipGrid.quality
  233. local len = 0
  234. -- for key, value in pairs(equipGrid.attr) do
  235. -- len = len + 1
  236. -- attrCheck[len] = {key, value}
  237. -- end
  238. for k, v in ipairs(equipGrid.attr) do
  239. len = len + 1
  240. attrCheck[len] = {v[1], v[2], v[3]}
  241. end
  242. -- 砍掉后面的
  243. if quality < len then
  244. equipGrid.attr = {}
  245. for z = 1, quality do
  246. -- equipGrid.attr[attrCheck[z][1]] = attrCheck[z][2]
  247. equipGrid.attr[z] = {
  248. attrCheck[z][1],
  249. attrCheck[z][2],
  250. attrCheck[z][3],
  251. }
  252. end
  253. end
  254. end
  255. -- 随机属性
  256. function randomAttr(itemID, isRandom, otherData, excludeAttrList)
  257. local equipConfig = EquipExcel[itemID]
  258. if not equipConfig then return end
  259. -- 固定属性
  260. local quality = 1
  261. -- local attr = {}
  262. -- 所有装备的随机属性使用同一套规则
  263. -- if equipConfig.random == 1 and not isRandom then
  264. -- quality = #equipConfig.randomAttr
  265. -- if quality > EQUIP_QUALITY_MAX then
  266. -- quality = EQUIP_QUALITY_MAX
  267. -- end
  268. -- for i = 1, quality do
  269. -- local key = equipConfig.randomAttr[i][1]
  270. -- local value = equipConfig.randomAttr[i][2]
  271. -- attr[key] = attr[key] or 0
  272. -- attr[key] = attr[key] + value
  273. -- end
  274. -- return attr, quality
  275. -- end
  276. if not otherData then
  277. -- 随机品质
  278. quality = randColor(equipConfig.randomAttr)
  279. else
  280. if type(otherData) == "number" then
  281. otherData = otherData < 0 and 1 or otherData
  282. quality = otherData > #equipConfig.randomAttr and #equipConfig.randomAttr or otherData
  283. end
  284. end
  285. if quality > EQUIP_QUALITY_MAX then
  286. quality = EQUIP_QUALITY_MAX
  287. end
  288. -- 计算总权重
  289. -- local totalWeight = 0
  290. -- for k, v in pairs(equipConfig.randomAttr) do
  291. -- totalWeight = totalWeight + v[3]
  292. -- end
  293. -- 随机条目属性
  294. -- local MathRandom = math.random
  295. local randomAttr = Util.copyTable(equipConfig.randomAttr)
  296. -- for z = 1, quality do
  297. -- local randmWeight = MathRandom(1, totalWeight)
  298. -- for k, v in pairs(randomAttr) do
  299. -- local key = v[1]
  300. -- local value = v[2]
  301. -- local weight = v[3]
  302. -- if randmWeight <= weight then
  303. -- attr[key] = attr[key] or 0
  304. -- attr[key] = attr[key] + value
  305. -- randomAttr[k] = nil
  306. -- -- 排除这个权重
  307. -- totalWeight = totalWeight - weight
  308. -- break
  309. -- else
  310. -- randmWeight = randmWeight - weight
  311. -- end
  312. -- end
  313. -- end
  314. local attr = randAttrArray(randomAttr, quality, excludeAttrList)
  315. return attr, quality
  316. end
  317. -- 检查背包空间
  318. function checkEmptyCnt(human, itemCnt)
  319. if itemCnt > getEmptyCnt(human) then
  320. Broadcast.sendErr(human, Lang.COMMON_BAG_FULL)
  321. return
  322. end
  323. return true
  324. end
  325. -- 获取装备对基础属性的影响
  326. function getEquipBaseRate(quality)
  327. local baseRate = EQUIP_QUALITY_BASE_RATE[quality]
  328. if not baseRate then return 1 end
  329. return baseRate / 10000
  330. end
  331. -- 获取装备品质
  332. function getEquipMaxQuality(equipConfig)
  333. if not equipConfig.randomAttr then return 0 end
  334. local maxQuality = 0
  335. if equipConfig.random == 1 then
  336. maxQuality = #equipConfig.randomAttr
  337. else
  338. maxQuality = equipConfig.quality or 0
  339. end
  340. return maxQuality
  341. end
  342. -- 获取装备洗练属性
  343. function getEquipTzAttr(equipConfig)
  344. if not equipConfig.randomAttr then return end
  345. if equipConfig.random == 1 then
  346. return equipConfig.randomAttr
  347. end
  348. -- local quality
  349. -- if equipConfig.subType == ItemDefine.EQUIP_SUBTYPE_RING or equipConfig.subType == ItemDefine.EQUIP_SUBTYPE_AMULET then
  350. -- quality = equipConfig.quality
  351. -- end
  352. -- local attr = randAttrArray(Util.copyTable(equipConfig.randomAttr), quality)
  353. -- return attr
  354. end
  355. -- 返回装备背包空余格子数
  356. function getEmptyCnt(human)
  357. local emptyCnt = 0
  358. for i = 1, EQUIP_BAG_MAX_CNT do
  359. if human.db.equipBag[i] == nil then
  360. emptyCnt = emptyCnt + 1
  361. end
  362. end
  363. return emptyCnt
  364. end
  365. -- 获得装备背包第一个空格子下标
  366. function getEmptyIndex(human)
  367. for index = 1, EQUIP_BAG_MAX_CNT do
  368. local grid = human.db.equipBag[index]
  369. if grid == nil then
  370. return index
  371. end
  372. end
  373. end
  374. -- 返回装备根据uuid
  375. function getEquipByUuid(human, uuid)
  376. local emptyCnt = 0
  377. for i = 1, EQUIP_BAG_MAX_CNT do
  378. local equipGrid = human.db.equipBag[i]
  379. if equipGrid and equipGrid.uuid == uuid then
  380. return equipGrid
  381. end
  382. end
  383. end
  384. -- 返回装备根据pos
  385. function getEquipByPos(human, star, pos)
  386. local emptyCnt = 0
  387. for i = 1, EQUIP_BAG_MAX_CNT do
  388. local equipGrid = human.db.equipBag[i]
  389. if equipGrid then
  390. local conf = EquipExcel[equipGrid.id]
  391. if conf and conf.subType == pos and star >= conf.star then
  392. return equipGrid
  393. end
  394. end
  395. end
  396. end
  397. -- 修复老数据
  398. function modifyEquip(human, equipGrid)
  399. if equipGrid.putUuid == nil then return end
  400. local heroGrid = HeroLogic.getHeroGridByUuid(human, equipGrid.putUuid)
  401. if heroGrid == nil then
  402. equipGrid.putUuid = nil
  403. end
  404. end
  405. -- 兼容老数据处理 : 修改装备的 wash 和 attr 的数据格式
  406. function TransformEuipAttrData(human)
  407. for index = 1, EQUIP_BAG_MAX_CNT do
  408. local equipGrid = human.db.equipBag[index]
  409. if equipGrid then
  410. if equipGrid.attr then
  411. equipGrid.attr = AttrHashToArray(equipGrid.attr)
  412. end
  413. if equipGrid.washAttr then
  414. equipGrid.washAttr = AttrHashToArray(equipGrid.washAttr)
  415. end
  416. end
  417. end
  418. end
  419. -- 推送装备背包信息
  420. function sendEquipBagList(human)
  421. local msgRet = Msg.gc.GC_EQUIP_BAG_LIST
  422. local len = 0
  423. for index = 1, EQUIP_BAG_MAX_CNT do
  424. local equipGrid = human.db.equipBag[index]
  425. if equipGrid then
  426. equipGrid.putUuid = nil --处理数据异常的装备
  427. len = len + 1
  428. Grid.makeItem(msgRet.list[len], equipGrid.id, 1, nil, equipGrid, index, Grid.getOpflagAtBag(equipGrid.id))
  429. if len >= 30 then
  430. msgRet.list[0] = len
  431. len = 0
  432. Msg.send(msgRet, human.fd)
  433. end
  434. end
  435. end
  436. if len > 0 then
  437. msgRet.list[0] = len
  438. Msg.send(msgRet, human.fd)
  439. end
  440. end
  441. -- 制造一个获得列表
  442. function makeEquipItem(human, nets, len)
  443. if not human.getEquip then return len end
  444. for i = 1, #human.getEquip do
  445. len = len + 1
  446. if not nets[len] then
  447. len = len - 1
  448. break
  449. end
  450. local equipGrid = human.getEquip[i]
  451. Grid.makeItem(nets[len], equipGrid.id, 1, nil, equipGrid)
  452. end
  453. human.getEquip = nil
  454. return len
  455. end
  456. -- 制造一个装备获得
  457. function makeEquipItemOne(human, net)
  458. if not human.getEquip then return end
  459. local equipGrid = human.getEquip[1]
  460. Grid.makeItem(net, equipGrid.id, 1, nil, equipGrid)
  461. human.getEquip = nil
  462. end
  463. -- 制造一个装备
  464. function makeEquip(itemID, otherData)
  465. local equipGrid = EquipLogicGrid.createGrid(itemID)
  466. if not equipGrid then return end
  467. local bl = false
  468. local equipCfg = EquipExcel[equipGrid.id]
  469. if equipCfg.subType == ItemDefine.EQUIP_SUBTYPE_RING or equipCfg.subType == ItemDefine.EQUIP_SUBTYPE_AMULET then
  470. otherData = equipCfg.quality
  471. bl = true
  472. end
  473. -- 随机洗练属性
  474. local attr, quality = randomAttr(itemID, nil, otherData)
  475. equipGrid.attr = attr
  476. if not bl then
  477. equipGrid.quality = quality
  478. else
  479. -- 装备特效
  480. equipGrid.effectList = randEffectAttrList(itemID)
  481. -- 英雄专属
  482. equipGrid.exclusiveHeroId = randHeroExclusive(itemID)
  483. end
  484. checkAttr(equipGrid)
  485. return equipGrid
  486. end
  487. -- 添加装备
  488. function addEquip(human, itemID, itemCnt, logType, otherData)
  489. if not EquipExcel[itemID] then return end
  490. for i = 1, itemCnt do
  491. local equipGrid = makeEquip(itemID, otherData)
  492. if equipGrid then
  493. addByEquipGrid(human, equipGrid, logType)
  494. TriggerLogic.PublishEvent(TriggerDefine.EQUIP_GETQUALITY, human.db._id, equipGrid.quality, 1)
  495. end
  496. end
  497. end
  498. -- 通过gird添加装备
  499. function addByEquipGrid(human, equipGrid, logType, noSend)
  500. local index = getEmptyIndex(human)
  501. if not index then
  502. --邮件处理
  503. local items = {}
  504. items[1] = { equipGrid.id, equipGrid }
  505. local title = MailExcel.mail[1000].title
  506. local content = MailExcel.mail[1000].content
  507. local senderName = MailExcel.mail[1000].senderName
  508. MailManager.add(MailManager.SYSTEM, human.db._id, title, content, items, senderName)
  509. return
  510. end
  511. human.db.equipBag[index] = equipGrid
  512. sendEquipChange(human, index, equipGrid, EQUIP_BAG_OP_ADD)
  513. Log.write(Log.LOGID_OSS_EQUIP, human.db._id, human.db.account,
  514. human.db.name, human.db.lv, LogDefine.DEFINE[logType] + LogDefine.TYPE["equip"], equipGrid.id, 1, equipGrid.uuid)
  515. if not noSend then
  516. human.getEquip = human.getEquip or {}
  517. human.getEquip[#human.getEquip + 1] = equipGrid
  518. end
  519. return index
  520. end
  521. -- 从背包删除装备
  522. function delEquip(human, index, logType, sendNotify)
  523. local equipGrid = human.db.equipBag[index]
  524. if not equipGrid then return end
  525. Log.write(Log.LOGID_OSS_EQUIP, human.db._id, human.db.account,
  526. human.db.name, human.db.lv, LogDefine.DEFINE[logType] + LogDefine.TYPE["equip"], equipGrid.id, -1, equipGrid.uuid)
  527. human.db.equipBag[index] = nil
  528. if not sendNotify then
  529. sendEquipChange(human, index, nil, EQUIP_BAG_OP_DEL)
  530. end
  531. end
  532. -- 发送装备改变
  533. function sendEquipChange(human, bagIndex, equipGrid, op)
  534. local msgRet = Msg.gc.GC_EQUIP_BAG_CHANGE
  535. if op == EQUIP_BAG_OP_ADD or op == EQUIP_BAG_OP_CHANGE then
  536. msgRet.itemID = equipGrid.id
  537. msgRet.itemIndex = bagIndex
  538. msgRet.itemData[0] = 1
  539. Grid.makeItem(msgRet.itemData[1], equipGrid.id, 1, nil, equipGrid, bagIndex, Grid.getOpflagAtBag(equipGrid.id))
  540. elseif op == EQUIP_BAG_OP_DEL then
  541. msgRet.itemID = 0
  542. msgRet.itemIndex = bagIndex
  543. msgRet.itemData[0] = 0
  544. else
  545. assert(nil)
  546. end
  547. Msg.send(msgRet, human.fd)
  548. end
  549. function getNewAttrByItemID(itemID, equipGrid)
  550. local config = EquipExcel[itemID]
  551. -- if not config then return end
  552. -- for _, v in ipairs(config.randomAttr) do
  553. -- if attr[v[1]] then
  554. -- attr[v[1]] = v[2]
  555. -- end
  556. -- end
  557. equipGrid.attr = randAttrArray(Util.copyTable(config.randomAttr), equipGrid.quality)
  558. end