EquipLogic.lua 19 KB

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