EquipLogic.lua 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  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. end
  329. return maxQuality
  330. end
  331. -- 获取装备洗练属性
  332. function getEquipTzAttr(equipConfig)
  333. if not equipConfig.randomAttr then return end
  334. if equipConfig.random == 1 then
  335. return equipConfig.randomAttr
  336. end
  337. -- local quality
  338. -- if equipConfig.subType == ItemDefine.EQUIP_SUBTYPE_RING or equipConfig.subType == ItemDefine.EQUIP_SUBTYPE_AMULET then
  339. -- quality = equipConfig.quality
  340. -- end
  341. -- local attr = randAttrArray(Util.copyTable(equipConfig.randomAttr), quality)
  342. -- return attr
  343. end
  344. -- 返回装备背包空余格子数
  345. function getEmptyCnt(human)
  346. local emptyCnt = 0
  347. for i = 1, EQUIP_BAG_MAX_CNT do
  348. if human.db.equipBag[i] == nil then
  349. emptyCnt = emptyCnt + 1
  350. end
  351. end
  352. return emptyCnt
  353. end
  354. -- 获得装备背包第一个空格子下标
  355. function getEmptyIndex(human)
  356. for index = 1, EQUIP_BAG_MAX_CNT do
  357. local grid = human.db.equipBag[index]
  358. if grid == nil then
  359. return index
  360. end
  361. end
  362. end
  363. -- 返回装备根据uuid
  364. function getEquipByUuid(human, uuid)
  365. local emptyCnt = 0
  366. for i = 1, EQUIP_BAG_MAX_CNT do
  367. local equipGrid = human.db.equipBag[i]
  368. if equipGrid and equipGrid.uuid == uuid then
  369. return equipGrid
  370. end
  371. end
  372. end
  373. -- 返回装备根据pos
  374. function getEquipByPos(human, star, pos)
  375. local emptyCnt = 0
  376. for i = 1, EQUIP_BAG_MAX_CNT do
  377. local equipGrid = human.db.equipBag[i]
  378. if equipGrid then
  379. local conf = EquipExcel[equipGrid.id]
  380. if conf and conf.subType == pos and star >= conf.star then
  381. return equipGrid
  382. end
  383. end
  384. end
  385. end
  386. -- 修复老数据
  387. function modifyEquip(human, equipGrid)
  388. if equipGrid.putUuid == nil then return end
  389. local heroGrid = HeroLogic.getHeroGridByUuid(human, equipGrid.putUuid)
  390. if heroGrid == nil then
  391. equipGrid.putUuid = nil
  392. end
  393. end
  394. -- 兼容老数据处理 : 修改装备的 wash 和 attr 的数据格式
  395. function TransformEuipAttrData(human)
  396. for index = 1, EQUIP_BAG_MAX_CNT do
  397. local equipGrid = human.db.equipBag[index]
  398. if equipGrid then
  399. if equipGrid.attr then
  400. equipGrid.attr = AttrHashToArray(equipGrid.attr)
  401. end
  402. if equipGrid.washAttr then
  403. equipGrid.washAttr = AttrHashToArray(equipGrid.washAttr)
  404. end
  405. end
  406. end
  407. end
  408. -- 推送装备背包信息
  409. function sendEquipBagList(human)
  410. local msgRet = Msg.gc.GC_EQUIP_BAG_LIST
  411. local len = 0
  412. for index = 1, EQUIP_BAG_MAX_CNT do
  413. local equipGrid = human.db.equipBag[index]
  414. if equipGrid then
  415. len = len + 1
  416. Grid.makeItem(msgRet.list[len], equipGrid.id, 1, nil, equipGrid, index, Grid.getOpflagAtBag(equipGrid.id))
  417. if len >= 30 then
  418. msgRet.list[0] = len
  419. len = 0
  420. Msg.send(msgRet, human.fd)
  421. end
  422. end
  423. end
  424. if len > 0 then
  425. msgRet.list[0] = len
  426. Msg.send(msgRet, human.fd)
  427. end
  428. end
  429. -- 制造一个获得列表
  430. function makeEquipItem(human, nets, len)
  431. if not human.getEquip then return len end
  432. for i = 1, #human.getEquip do
  433. len = len + 1
  434. if not nets[len] then
  435. len = len - 1
  436. break
  437. end
  438. local equipGrid = human.getEquip[i]
  439. Grid.makeItem(nets[len], equipGrid.id, 1, nil, equipGrid)
  440. end
  441. human.getEquip = nil
  442. return len
  443. end
  444. -- 制造一个装备获得
  445. function makeEquipItemOne(human, net)
  446. if not human.getEquip then return end
  447. local equipGrid = human.getEquip[1]
  448. Grid.makeItem(net, equipGrid.id, 1, nil, equipGrid)
  449. human.getEquip = nil
  450. end
  451. -- 制造一个装备
  452. function makeEquip(itemID, otherData)
  453. local equipGrid = EquipLogicGrid.createGrid(itemID)
  454. if not equipGrid then return end
  455. local bl = false
  456. local equipCfg = EquipExcel[equipGrid.id]
  457. if equipCfg.subType == ItemDefine.EQUIP_SUBTYPE_RING or equipCfg.subType == ItemDefine.EQUIP_SUBTYPE_AMULET then
  458. otherData = equipCfg.quality
  459. bl = true
  460. end
  461. -- 随机洗练属性
  462. local attr, quality = randomAttr(itemID, nil, otherData)
  463. equipGrid.attr = attr
  464. if not bl then
  465. equipGrid.quality = quality
  466. else
  467. -- 装备特效
  468. equipGrid.effectList = randEffectAttrList(itemID)
  469. -- 英雄专属
  470. equipGrid.exclusiveHeroId = randHeroExclusive(itemID)
  471. end
  472. checkAttr(equipGrid)
  473. return equipGrid
  474. end
  475. -- 添加装备
  476. function addEquip(human, itemID, itemCnt, logType, otherData)
  477. if not EquipExcel[itemID] then return end
  478. for i = 1, itemCnt do
  479. local equipGrid = makeEquip(itemID, otherData)
  480. if equipGrid then
  481. addByEquipGrid(human, equipGrid, logType)
  482. TriggerLogic.PublishEvent(TriggerDefine.EQUIP_GETQUALITY, human.db._id, equipGrid.quality, 1)
  483. end
  484. end
  485. end
  486. -- 通过gird添加装备
  487. function addByEquipGrid(human, equipGrid, logType, noSend)
  488. local index = getEmptyIndex(human)
  489. if not index then
  490. --邮件处理
  491. local items = {}
  492. items[1] = { equipGrid.id, equipGrid }
  493. local title = MailExcel.mail[1000].title
  494. local content = MailExcel.mail[1000].content
  495. local senderName = MailExcel.mail[1000].senderName
  496. MailManager.add(MailManager.SYSTEM, human.db._id, title, content, items, senderName)
  497. return
  498. end
  499. human.db.equipBag[index] = equipGrid
  500. sendEquipChange(human, index, equipGrid, EQUIP_BAG_OP_ADD)
  501. Log.write(Log.LOGID_OSS_EQUIP, human.db._id, human.db.account,
  502. human.db.name, human.db.lv, LogDefine.DEFINE[logType] + LogDefine.TYPE["equip"], equipGrid.id, 1, equipGrid.uuid)
  503. if not noSend then
  504. human.getEquip = human.getEquip or {}
  505. human.getEquip[#human.getEquip + 1] = equipGrid
  506. end
  507. return index
  508. end
  509. -- 从背包删除装备
  510. function delEquip(human, index, logType, sendNotify)
  511. local equipGrid = human.db.equipBag[index]
  512. if not equipGrid then return end
  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. human.db.equipBag[index] = nil
  516. if not sendNotify then
  517. sendEquipChange(human, index, nil, EQUIP_BAG_OP_DEL)
  518. end
  519. end
  520. -- 发送装备改变
  521. function sendEquipChange(human, bagIndex, equipGrid, op)
  522. local msgRet = Msg.gc.GC_EQUIP_BAG_CHANGE
  523. if op == EQUIP_BAG_OP_ADD or op == EQUIP_BAG_OP_CHANGE then
  524. msgRet.itemID = equipGrid.id
  525. msgRet.itemIndex = bagIndex
  526. msgRet.itemData[0] = 1
  527. Grid.makeItem(msgRet.itemData[1], equipGrid.id, 1, nil, equipGrid, bagIndex, Grid.getOpflagAtBag(equipGrid.id))
  528. elseif op == EQUIP_BAG_OP_DEL then
  529. msgRet.itemID = 0
  530. msgRet.itemIndex = bagIndex
  531. msgRet.itemData[0] = 0
  532. else
  533. assert(nil)
  534. end
  535. Msg.send(msgRet, human.fd)
  536. end
  537. function getNewAttrByItemID(itemID, equipGrid)
  538. local config = EquipExcel[itemID]
  539. -- if not config then return end
  540. -- for _, v in ipairs(config.randomAttr) do
  541. -- if attr[v[1]] then
  542. -- attr[v[1]] = v[2]
  543. -- end
  544. -- end
  545. equipGrid.attr = randAttrArray(Util.copyTable(config.randomAttr), equipGrid.quality)
  546. end