UnionTecLogic.lua 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. Json = Json or require("common.Json")
  2. local Log = require("common.Log")
  3. local Msg = require("core.Msg")
  4. local Broadcast = require("broadcast.Broadcast")
  5. local Grid = require("bag.Grid")
  6. local UnionExcel = require("excel.union")
  7. local ItemDefine = require("bag.ItemDefine")
  8. local BagLogic = require("bag.BagLogic")
  9. local ObjHuman = require("core.ObjHuman")
  10. local Lang = require("common.Lang")
  11. local HeroExcel = require("excel.hero")
  12. local RoleAttr = require("role.RoleAttr")
  13. local ChengjiuLogic = require("chengjiu.ChengjiuLogic")
  14. local UnionDBLogic = require("union.UnionDBLogic")
  15. local Util = require("common.Util")
  16. local UnionLivenessLogic = require("union.UnionLivenessLogic")
  17. local UnionDefine = require("union.UnionDefine")
  18. TEC_OCCU_CNT = 4
  19. TEC_TIER_CNT = 6
  20. -- 获取科技配置
  21. local function getTechnologyCfg(job, tier)
  22. local config = UnionExcel.technology
  23. local cfg = nil
  24. for i = 1, #config do
  25. cfg = config[i]
  26. if cfg ~= nil and cfg.occu == job and cfg.tier == tier then
  27. return cfg
  28. end
  29. end
  30. end
  31. -- 计算科技属性
  32. function doCalcHero(human, grid, attrs)
  33. if not human then return end
  34. if not human.db.unionUuid or human.db.unionUuid == "" then
  35. return
  36. end
  37. if not human.db.technology then return end
  38. local heroConfig = HeroExcel.hero[grid.id]
  39. local technology = human.db.technology[heroConfig.job]
  40. if technology == nil then return end
  41. local techCfg = nil
  42. for i = 1,TEC_TIER_CNT do
  43. local tech = technology[i]
  44. if tech ~= nil and tech.lv ~= nil then
  45. techCfg = getTechnologyCfg(heroConfig.job, i)
  46. if techCfg ~= nil then
  47. for k, v in pairs(techCfg.fortify) do
  48. local addValue = v[2] * tech.lv
  49. RoleAttr.updateValue(v[1],addValue,attrs)
  50. end
  51. end
  52. end
  53. end
  54. end
  55. function getTechLvByJob(human, job)
  56. if not human then return 0 end
  57. if not human.db.technology then return 0 end
  58. local technology = human.db.technology[job]
  59. return technology and technology.lv or 0
  60. end
  61. function lvAllUpByGm(human)
  62. if human.db.unionUuid == nil then
  63. return
  64. end
  65. human.db.technology = human.db.technology or {}
  66. local technology = human.db.technology
  67. local config = UnionExcel.technology
  68. local len = #config
  69. for i = 1, TEC_OCCU_CNT do
  70. technology[i] = technology[i] or {}
  71. local techOccu = technology[i]
  72. for j = 1, TEC_TIER_CNT do
  73. techOccu[j] = techOccu[j] or {}
  74. for z = 1, len do
  75. local v = config[z]
  76. if v.occu == i and v.tier == j then
  77. techOccu[j].lv = v.lvMax
  78. break
  79. end
  80. end
  81. end
  82. end
  83. end
  84. -- 获取其他科技的总等级
  85. function getOtherLv(human, occu)
  86. local lv = 9999
  87. if human.db.technology then
  88. local technology = human.db.technology
  89. for i = 1, TEC_OCCU_CNT do
  90. if technology[i] and i ~= occu then
  91. local thisLv = technology[i].lv or 0
  92. if lv >= thisLv then
  93. lv = thisLv
  94. end
  95. elseif not technology[i] then
  96. lv = 0
  97. end
  98. end
  99. end
  100. lv = lv ~= 9999 and lv or 0
  101. return lv
  102. end
  103. function getID(occu, tier)
  104. local id = 0
  105. for k, v in ipairs(UnionExcel.technology) do
  106. if v and v.occu == occu and v.tier == tier then
  107. id = k
  108. break
  109. end
  110. end
  111. return id
  112. end
  113. -- 获取该等级所需要的 磨坊等级 和其他 科技等级
  114. function getNeedMillOhter(lv, occu, tier)
  115. local needMill = 0
  116. local needOther = 0
  117. local id = getID(occu, tier)
  118. local config = UnionExcel.technology[id]
  119. for k, v in ipairs(config.needMill) do
  120. if v and v[1] <= lv then
  121. needMill = v[2]
  122. end
  123. end
  124. local changeLv = config.needSumLv[1]
  125. local initLv = config.needSumLv[2]
  126. if lv < changeLv then
  127. needOther = 0
  128. else
  129. needOther = initLv + (lv - changeLv ) * 1
  130. end
  131. return needMill,needOther
  132. end
  133. function techQuery(human, occu)
  134. -- 没有加入公会查什么科技
  135. if human.db.unionUuid == nil then
  136. return
  137. end
  138. -- 对不起,你要查的科技这里没得卖,请你出去
  139. if occu == nil then return end
  140. if occu < 1 or occu > TEC_OCCU_CNT then
  141. return
  142. end
  143. local union = UnionDBLogic.getUnion(human.db.unionUuid)
  144. if not union then
  145. return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
  146. end
  147. local millLv = UnionDBLogic.getMillLv(union)
  148. local config = UnionExcel.technology
  149. local msgRet = Msg.gc.GC_UNION_TECHNOLOGY_QUERY
  150. if human.db.technology == nil or human.db.technology[occu] == nil then
  151. msgRet.techLv = 1
  152. local consumeConfig = UnionExcel.tecConsume[1]
  153. for i = 1,TEC_TIER_CNT do
  154. if i == 1 then
  155. msgRet.technology[i].canLvUp = 1
  156. else
  157. msgRet.technology[i].canLvUp = 3
  158. end
  159. local getID = getID(occu, i)
  160. local needMillLv, needOther = getNeedMillOhter(0, occu, i)
  161. local thisConfig = UnionExcel.technology[getID]
  162. msgRet.technology[i].lv = 0
  163. msgRet.technology[i].tier = i
  164. msgRet.technology[i].techMsg[0] = 0
  165. msgRet.technology[i].techMsgNext[0] = 0
  166. msgRet.technology[i].name = thisConfig.name
  167. msgRet.technology[i].maxLV = thisConfig.lvMax
  168. -- msgRet.technology[i].needMillLv = needMillLv
  169. -- msgRet.technology[i].otherLv = getOtherLv(human, occu)
  170. -- msgRet.technology[i].needOhterLv = needOther
  171. msgRet.technology[i].banner = thisConfig.banner
  172. for k = 1, #thisConfig.fortify do
  173. msgRet.technology[i].techMsg[k].key = thisConfig.fortify[k][1]
  174. msgRet.technology[i].techMsg[k].value = thisConfig.fortify[k][2] * msgRet.technology[i].lv
  175. -- msgRet.technology[i].techMsg[k].name = thisConfig.techName[k]
  176. msgRet.technology[i].techMsg[0] = msgRet.technology[i].techMsg[0] + 1
  177. msgRet.technology[i].techMsgNext[k].key = thisConfig.fortify[k][1]
  178. msgRet.technology[i].techMsgNext[k].value = thisConfig.fortify[k][2] * (msgRet.technology[i].lv + 1)
  179. -- msgRet.technology[i].techMsgNext[k].name = thisConfig.techName[k]
  180. msgRet.technology[i].techMsgNext[0] = msgRet.technology[i].techMsgNext[0] + 1
  181. end
  182. msgRet.technology[i].lvUpNeed[0] = 2
  183. msgRet.technology[i].tier = i
  184. local jinbiCnt = consumeConfig["location"..i][1][2]
  185. local coinCnt = consumeConfig["location"..i][2][2]
  186. Grid.makeItem(msgRet.technology[i].lvUpNeed[1], ItemDefine.ITEM_JINBI_ID, jinbiCnt)
  187. Grid.makeItem(msgRet.technology[i].lvUpNeed[2], ItemDefine.ITEM_UNION_COIN_ID, coinCnt)
  188. -- msgRet.technology[i].needMillLv = 0
  189. end
  190. msgRet.technology[0] = TEC_TIER_CNT
  191. else
  192. msgRet.techLv = 1
  193. if human.db.technology[occu] and human.db.technology[occu].lv then
  194. msgRet.techLv = human.db.technology[occu].lv
  195. end
  196. for i = 1, TEC_TIER_CNT do
  197. human.db.technology[occu][i] = human.db.technology[occu][i] or {}
  198. human.db.technology[occu][i].lv = human.db.technology[occu][i].lv or 0
  199. if i == 1 then
  200. if human.db.technology[occu][i].lv >= config[i].lvMax then
  201. msgRet.technology[i].canLvUp = 2
  202. msgRet.techLv = config[i].lvMax
  203. else
  204. if human.db.technology[occu][i].lv == 0 then
  205. msgRet.technology[i].canLvUp = 1
  206. else
  207. if human.db.technology[occu][TEC_TIER_CNT] and human.db.technology[occu][TEC_TIER_CNT].lv == human.db.technology[occu][i].lv then
  208. msgRet.technology[i].canLvUp = 1
  209. else
  210. msgRet.technology[i].canLvUp = 2
  211. end
  212. end
  213. end
  214. else
  215. if human.db.technology[occu][i].lv >= config[i].lvMax then
  216. msgRet.technology[i].canLvUp = 2
  217. else
  218. if human.db.technology[occu][i - 1].lv == human.db.technology[occu][i].lv + 1 then
  219. msgRet.technology[i].canLvUp = 1
  220. elseif human.db.technology[occu][i].lv == human.db.technology[occu][1].lv and human.db.technology[occu][1].lv ~= 0 then
  221. if human.db.technology[occu].lv == human.db.technology[occu][i].lv then
  222. msgRet.technology[i].canLvUp = 3
  223. else
  224. msgRet.technology[i].canLvUp = 2
  225. end
  226. else
  227. msgRet.technology[i].canLvUp = 3
  228. end
  229. end
  230. end
  231. local getID = getID(occu, i)
  232. local needMillLv, needOther = getNeedMillOhter(human.db.technology[occu][i].lv , occu, i)
  233. local thisConfig = UnionExcel.technology[getID]
  234. msgRet.technology[i].lv = human.db.technology[occu][i].lv
  235. msgRet.technology[i].tier = i
  236. msgRet.technology[i].techMsg[0] = 0
  237. msgRet.technology[i].techMsgNext[0] = 0
  238. -- msgRet.technology[i].needMillLv = needMillLv
  239. -- msgRet.technology[i].otherLv = getOtherLv(human, occu)
  240. -- msgRet.technology[i].needOhterLv = needOther
  241. msgRet.technology[i].maxLV = thisConfig.lvMax
  242. msgRet.technology[i].name = thisConfig.name
  243. msgRet.technology[i].banner = thisConfig.banner
  244. for k = 1, #thisConfig.fortify do
  245. msgRet.technology[i].techMsg[k].key = thisConfig.fortify[k][1]
  246. msgRet.technology[i].techMsg[k].value = thisConfig.fortify[k][2] * msgRet.technology[i].lv
  247. -- msgRet.technology[i].techMsg[k].name = thisConfig.techName[k]
  248. msgRet.technology[i].techMsg[0] = msgRet.technology[i].techMsg[0] + 1
  249. if msgRet.technology[i].lv < config[i].lvMax then
  250. msgRet.technology[i].techMsgNext[k].key = thisConfig.fortify[k][1]
  251. msgRet.technology[i].techMsgNext[k].value = thisConfig.fortify[k][2] * (msgRet.technology[i].lv + 1)
  252. -- msgRet.technology[i].techMsgNext[k].name = thisConfig.techName[k]
  253. msgRet.technology[i].techMsgNext[0] = msgRet.technology[i].techMsgNext[0] + 1
  254. end
  255. end
  256. msgRet.technology[i].lvUpNeed[0] = 2
  257. local consumeConfig = UnionExcel.tecConsume[msgRet.technology[i].lv + 1]
  258. if consumeConfig then
  259. local jinbiCnt = consumeConfig["location"..i][1][2]
  260. local coinCnt = consumeConfig["location"..i][2][2]
  261. Grid.makeItem(msgRet.technology[i].lvUpNeed[1], ItemDefine.ITEM_JINBI_ID, jinbiCnt)
  262. Grid.makeItem(msgRet.technology[i].lvUpNeed[2], ItemDefine.ITEM_UNION_COIN_ID, coinCnt)
  263. else
  264. msgRet.technology[i].lvUpNeed[0] = 0
  265. end
  266. end
  267. msgRet.technology[0] = TEC_TIER_CNT
  268. end
  269. Msg.send(msgRet,human.fd)
  270. --Msg.trace(msgRet)
  271. end
  272. function techLvUp(human,occu,tier)
  273. -- 没公会升什么玩意科技
  274. if human.db.unionUuid == nil then
  275. return Broadcast.sendErr(human,Lang.UNION_PLAYER_IN_NO)
  276. end
  277. if occu < 1 or occu >TEC_OCCU_CNT then
  278. return
  279. end
  280. if tier < 1 or tier >TEC_TIER_CNT then
  281. return
  282. end
  283. --
  284. local config = UnionExcel.technology
  285. local flag = 1
  286. local isFirst = false
  287. if human.db.technology == nil then-- 先升第一层的科技嘛,干啥要跳级呢
  288. if tier ~= 1 then
  289. return Broadcast.sendErr(human,Lang.UNION_TECH_LAST_LV_ERR)
  290. end
  291. local consumeConfig = UnionExcel.tecConsume[1]
  292. local jinbiCnt = consumeConfig["location"..tier][1][2]
  293. local coinCnt = consumeConfig["location"..tier][2][2]
  294. if human.db.jinbi < jinbiCnt or human.db.bag[ItemDefine.ITEM_UNION_COIN_ID] == nil or human.db.bag[ItemDefine.ITEM_UNION_COIN_ID] < coinCnt then
  295. return Broadcast.sendErr(human,Lang.UNION_TECH_LV_MATERIALS)
  296. end
  297. human.db.technology = {}
  298. human.db.technology[occu] = {}
  299. ObjHuman.updateJinbi(human,-jinbiCnt,"techUp")
  300. BagLogic.delItem(human, ItemDefine.ITEM_UNION_COIN_ID,coinCnt, "techUp")
  301. human.db.technology[occu][tier] = human.db.technology[occu][tier] or {}
  302. human.db.technology[occu][tier].lv = human.db.technology[occu][tier].lv or 0
  303. human.db.technology[occu][tier].lv = human.db.technology[occu][tier].lv + 1
  304. isFirst = true
  305. else
  306. -- 不要跳级
  307. if tier ~= 1 then
  308. if not human.db.technology or not human.db.technology[occu] or next(human.db.technology[occu]) == nil then
  309. return
  310. end
  311. end
  312. local union = UnionDBLogic.getUnion(human.db.unionUuid)
  313. if not union then
  314. return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
  315. end
  316. human.db.technology[occu] = human.db.technology[occu] or {}
  317. human.db.technology[occu][tier] = human.db.technology[occu][tier] or {}
  318. human.db.technology[occu][tier].lv = human.db.technology[occu][tier].lv or 0
  319. local getID = getID(occu, tier)
  320. local thisConfig = UnionExcel.technology[getID]
  321. -- 都顶级了还升个锤子
  322. if human.db.technology[occu][tier].lv >= thisConfig.lvMax then
  323. return Broadcast.sendErr(human,Lang.UNION_TECH_LV_ERR)
  324. end
  325. -- 前置科技等级没有达标
  326. if tier~= 1 then
  327. if human.db.technology[occu][tier - 1] == nil or human.db.technology[occu][tier - 1].lv == nil or human.db.technology[occu][tier - 1].lv <= human.db.technology[occu][tier].lv then
  328. return Broadcast.sendErr(human,Lang.UNION_TECH_LAST_LV_ERR)
  329. end
  330. else
  331. if human.db.technology[occu][tier].lv > 0 and human.db.technology[occu][TEC_TIER_CNT].lv ~= human.db.technology[occu][tier].lv then
  332. return Broadcast.sendErr(human,Lang.UNION_TECH_LAST_LV_ERR)
  333. end
  334. end
  335. local millLv = UnionDBLogic.getMillLv(union)
  336. local needMillLv, needOther = getNeedMillOhter(human.db.technology[occu][tier].lv, occu, tier)
  337. local otherLv = getOtherLv(human, occu)
  338. -- 公会聚义堂 等级没有达到需求
  339. if millLv < needMillLv then
  340. return Broadcast.sendErr(human, Util.format(Lang.UNION_TECH_MILL_ERR, needMillLv) )
  341. end
  342. -- 其他科技没有达标
  343. if otherLv < needOther then
  344. return Broadcast.sendErr(human, Util.format(Lang.UNION_TECH_OTHER_ERR, needOther ) )
  345. end
  346. local consumeConfig = UnionExcel.tecConsume[human.db.technology[occu][tier].lv + 1]
  347. if not consumeConfig then return end
  348. local jinbiCnt = consumeConfig["location"..tier][1][2]
  349. local coinCnt = consumeConfig["location"..tier][2][2]
  350. if human.db.jinbi < jinbiCnt or human.db.bag[ItemDefine.ITEM_UNION_COIN_ID] == nil or human.db.bag[ItemDefine.ITEM_UNION_COIN_ID] < coinCnt then
  351. return Broadcast.sendErr(human,Lang.UNION_TECH_LV_MATERIALS)
  352. end
  353. ObjHuman.updateJinbi(human,-jinbiCnt,"techUp")
  354. BagLogic.delItem(human, ItemDefine.ITEM_UNION_COIN_ID,coinCnt, "techUp")
  355. human.db.technology[occu][tier].lv = human.db.technology[occu][tier].lv or 0
  356. human.db.technology[occu][tier].lv = human.db.technology[occu][tier].lv + 1
  357. if tier == TEC_TIER_CNT then
  358. human.db.technology[occu].lv = human.db.technology[occu][tier].lv
  359. -- 公会科技等级记录
  360. Log.write(Log.LOGID_OSS_UNION_TECH, human.db._id, human.db.account, human.db.name, occu, human.db.technology[occu].lv or 0)
  361. end
  362. end
  363. if isFirst then
  364. Broadcast.sendErr(human,Lang.UNION_TECH_LV_UP_OPEN)
  365. -- else
  366. -- Broadcast.sendErr(human,Lang.UNION_TECH_LV_UP_SUCCESS)
  367. end
  368. ObjHuman.save(human)
  369. techQuery(human,occu)
  370. UnionLivenessLogic.touchLiveness(human,UnionDefine.UNION_LIVENESS_TEC,1)
  371. RoleAttr.cleanHeroAttrCache(human)
  372. end
  373. function checkisFirstRest(human)
  374. local isFirst = true
  375. if human.db.technology and human.db.technology.restCnt and human.db.technology.restCnt > 0 then
  376. isFirst = false
  377. end
  378. return isFirst
  379. end
  380. function getResetNeedZuanshi(human, lv)
  381. local config = UnionExcel.techReset[1]
  382. if checkisFirstRest(human) then
  383. return config.firstRest
  384. else
  385. local surLv = lv - config.lv
  386. surLv = surLv > 0 and surLv or 0
  387. return config.consume + surLv * config.add
  388. end
  389. end
  390. -- 重置 返回道具查询
  391. function techResetQuery(human, occu)
  392. -- 没点科技,你重置个锤子
  393. if human.db.technology == nil then
  394. return Broadcast.sendErr(human,Lang.UNION_TECH_LV_ZERO_ERR)
  395. end
  396. if human.db.technology[occu] == nil or human.db.technology[occu][1].lv == 0 then
  397. return Broadcast.sendErr(human, Lang.UNION_TECH_LV_ZERO_ERR)
  398. end
  399. -- 先把消耗计算出来
  400. local jinbiCnt = 0
  401. local coinCnt = 0
  402. local config = UnionExcel.tecConsume
  403. local lv = human.db.technology[occu][1].lv
  404. for j = 1,#human.db.technology[occu] do
  405. for k = 1,human.db.technology[occu][j].lv do
  406. jinbiCnt = jinbiCnt + config[k]["location"..j][1][2]
  407. coinCnt = coinCnt + config[k]["location"..j][2][2]
  408. end
  409. end
  410. jinbiCnt = math.floor(jinbiCnt * 0.5)
  411. local zuanshiCnt = getResetNeedZuanshi(human, human.db.technology[occu][1].lv )
  412. local msgRet = Msg.gc.GC_UNION_TECHNOLOGY_RESET_QUERY
  413. Grid.makeItem(msgRet.item[1], ItemDefine.ITEM_JINBI_ID, jinbiCnt)
  414. Grid.makeItem(msgRet.item[2], ItemDefine.ITEM_UNION_COIN_ID, coinCnt)
  415. msgRet.zuanshiCnt = zuanshiCnt
  416. msgRet.item[0] = 2
  417. Msg.send(msgRet,human.fd)
  418. end
  419. function techReset(human,occu)
  420. if occu < 1 or occu >TEC_OCCU_CNT then
  421. return
  422. end
  423. local flag = 1
  424. -- 没点科技,你重置个锤子
  425. if human.db.technology == nil then
  426. return Broadcast.sendErr(human,Lang.UNION_TECH_LV_ZERO_ERR)
  427. end
  428. human.db.technology.restCnt = human.db.technology.restCnt or 0
  429. if human.db.technology[occu] == nil or human.db.technology[occu][1].lv == 0 then
  430. return Broadcast.sendErr(human, Lang.UNION_TECH_LV_ZERO_ERR)
  431. else
  432. local zuanshiCnt = getResetNeedZuanshi(human, human.db.technology[occu][1].lv )
  433. if not ObjHuman.checkRMB(human, zuanshiCnt) then
  434. return
  435. end
  436. ObjHuman.decZuanshi(human, -zuanshiCnt, "reset_technology")
  437. end
  438. -- 先把消耗计算出来
  439. local jinbiCnt = 0
  440. local coinCnt = 0
  441. local config = UnionExcel.tecConsume
  442. for j = 1,#human.db.technology[occu] do
  443. for k = 1,human.db.technology[occu][j].lv do
  444. jinbiCnt = jinbiCnt + config[k]["location"..j][1][2]
  445. coinCnt = coinCnt + config[k]["location"..j][2][2]
  446. end
  447. end
  448. jinbiCnt = math.floor(jinbiCnt * 0.5)
  449. human.db.technology.restCnt = human.db.technology.restCnt + 1
  450. human.db.technology[occu] = nil
  451. BagLogic.cleanMomentItemList()
  452. BagLogic.updateMomentItem(2, ItemDefine.ITEM_JINBI_ID, jinbiCnt)
  453. BagLogic.updateMomentItem(2, ItemDefine.ITEM_UNION_COIN_ID, coinCnt)
  454. BagLogic.addMomentItemList(human, "reset_technology")
  455. Broadcast.sendErr(human,Lang.UNION_TECH_LV_RESET_SUCCESS)
  456. techQuery(human,occu)
  457. RoleAttr.cleanHeroAttrCache(human)
  458. local msgRet = Msg.gc.GC_UNION_TECHNOLOGY_RESET
  459. msgRet.flag = 1
  460. Msg.send(msgRet,human.fd)
  461. end
  462. function getTechnologyLv(human)
  463. local lv = 0
  464. if human.db.technology then
  465. for k, v in pairs(human.db.technology) do
  466. if v then
  467. for j, h in pairs(v) do
  468. if h and h.lv and h.lv > 0 then
  469. lv = lv + h.lv
  470. end
  471. end
  472. end
  473. end
  474. end
  475. return lv
  476. end