givera12

Untitled

Mar 23rd, 2021
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 112.72 KB | None | 0 0
  1.  
  2. STATS_SYSTEM_CONFIG = {
  3. -- BASIC CONFIG STARTS HERE
  4. -- enable/disable features so script will execute only what you want
  5. monsterLoot = false,
  6. addSlotAction = true,
  7. addLevelAction = true,
  8. PVEStat = true,
  9. xpStat = true,
  10. lootStat = true,
  11. combatStats = true,
  12. conditionStats = true,
  13.  
  14. -- don't forget to register them in actions or they will not work
  15. GEM_BASIC_LEVEL = 36191,
  16. GEM_ADD_SLOT = 8303,
  17. GEM_RANDOM = 8303,
  18. GEM_RARE = 8303,
  19. GEM_EPIC = 8303,
  20. GEM_LEGENDARY = 36189,
  21. gems_power = {
  22. [36191] = {min_wl = 0, max_wl = 4, min_el = 0.3, max_el = 0.6, sl = function() return 2 end}, -- rare
  23. [36190] = {min_wl = 3, max_wl = 6, min_el = 0.6, max_el = 0.7, sl = function() return 3 end}, -- epic
  24. [36189] = {min_wl = 7, max_wl = 9, min_el = 0.3, max_el = 0.5, sl = function() return 3 end}, -- legendary
  25. [8305] = {min_wl = 0, max_wl = 9, min_el = 0.3, max_el = 1, sl = function() return math.random(2, 4) end} -- random
  26. },
  27.  
  28. maxSlotCount = 4,
  29. slotChances = {
  30. [1] = 1000,
  31. [2] = 5000,
  32. [3] = 15000,
  33. [4] = 25000
  34. },
  35. tiers = { -- item name based on slots looted (if more than 1)
  36. [2] = 'rare',
  37. [3] = 'epic',
  38. [4] = 'legendary'
  39. },
  40. weapon_levels = {
  41. -- weapon name if no slots were assigned, chance(1000 = 1%)
  42. [-9] = {'useless', 300},
  43. [-8] = {'broken', 500},
  44. [-7] = {'trash', 1000},
  45. [-6] = {'ruined', 1500},
  46. [-5] = {'damaged', 2000},
  47. [-4] = {'worthless', 2500},
  48. [-3] = {'blunt', 4000},
  49. [-2] = {'cheap', 7000},
  50. [-1] = {'common', 9000},
  51. [1] = {'uncommon', 25000},
  52. [2] = {'strengthened', 20000},
  53. [3] = {'fine', 15000},
  54. [4] = {'superior', 10000},
  55. [5] = {'rare', 7500},
  56. [6] = {'unique', 3500},
  57. [7] = {'flawless', 2500},
  58. [8] = {'epic', 1000},
  59. [9] = {'legendary', 500}
  60. },
  61. ignoredIds = {}, -- items with these ids will be banned from upgrading
  62. upgradeMagicItems = true, -- items with xml-sided bonuses, examples: magma coat, fire axe, boots of haste
  63. upgradeItemsWithNoArmor = true, -- allow upgrading clothes without arm value
  64. lootUpgradedItems = true,
  65. rare_popup = true,
  66. rare_text = "*rare*",
  67. rare_effect = true,
  68. rare_effect_id = CONST_ME_MAGIC_GREEN,
  69. rare_loot_level = true, -- set to false if you want to disable levels on looted weapons
  70. rare_negative_level = true, -- set to false if you want to disable it
  71. rare_min_level = -9,
  72.  
  73. useSkill = true, -- enchanting power based on player's skill, set to false if you want it random
  74. skillTriesStorage = 3866,
  75.  
  76. simple = { -- upgrade by jewels
  77. enabled = true,
  78. usePerks = false, -- unused
  79. randomSpells = true, -- todo: modal with selecting attr if false
  80. downgradeOnFail = true, -- item level only
  81. },
  82.  
  83. -- BASIC CONFIG ENDS HERE
  84. -- do not touch things below unless you are a advanced scripter
  85. skillFormula = function(lv) return math.ceil(((1 * lv^3) - (2 * lv^2) + (4 * lv)) / (90 + lv) + lv) end,
  86. maxLevel = 30,
  87.  
  88. levelUpgradeFormula = function(lv, minl)
  89. if STATS_SYSTEM_CONFIG.rare_negative_level then
  90. return math.ceil((lv/minl) * 25) + math.min(math.ceil(lv/minl * 5) +70, 75)
  91. else
  92. return 65 - math.ceil((lv/minl) * 3)
  93. end
  94. end,
  95.  
  96. -- spells and values for certain types of item
  97. UPGRADE_STATS_VALUES_PER_LVL = {
  98. -- value per level
  99. atk = 1,
  100. def = 1,
  101. extradef = 1,
  102. arm = 1,
  103. hitchance = 1,
  104. shootrange = 1
  105. },
  106.  
  107. UPGRADE_SPELLS = {
  108. necklace = {
  109. {'hp', 600, 20}, -- normal, percent
  110. {'mp', 200, 20},
  111. {'physical', 10, 16},
  112. {'energy', 10, 16},
  113. {'earth', 10, 16},
  114. {'fire', 10, 16},
  115. {'ice', 10, 16},
  116. {'holy', 10, 16},
  117. {'death', 10, 16}
  118. },
  119. helmet = {
  120. {'ml', 6, 12},
  121. {'melee', 6, 12},
  122. {'dist', 6, 12},
  123. {'physical', 8, 6},
  124. {'energy', 8, 10},
  125. {'earth', 8, 10},
  126. {'fire', 8, 10},
  127. {'ice', 8, 10},
  128. {'holy', 8, 10},
  129. {'death', 8, 10},
  130. {'arm', 10, 40},
  131. },
  132. weapon = {
  133. {'melee', 8, 16},
  134. {'physical', 200, 20},
  135. {'energy', 200, 20},
  136. {'earth', 200, 20},
  137. {'fire', 200, 20},
  138. {'ice', 200, 20},
  139. {'holy', 200, 20},
  140. {'death', 200, 20},
  141. {'animals', 300, 20},
  142. {'humans', 200, 6},
  143. {'undeads', 300, 20},
  144. {'insects', 300, 20},
  145. {'atk', 10, 30},
  146. {'def', 10, 60},
  147. {'extra def', 10, 60},
  148. {'drainHP', 200, 16},
  149. },
  150. distance = {
  151. {'dist', 8, 16},
  152. {'physical', 200, 20},
  153. {'energy', 200, 20},
  154. {'earth', 200, 20},
  155. {'fire', 200, 20},
  156. {'ice', 200, 20},
  157. {'holy', 200, 20},
  158. {'death', 200, 20},
  159. {'animals', 300, 20},
  160. {'humans', 200, 6},
  161. {'undeads', 300, 20},
  162. {'insects', 300, 20},
  163. {'atk', 10, 100},
  164. {'accuracy', 20, 100},
  165. {'range', 6, 100},
  166. {'drainHP', 200, 16},
  167. },
  168. wand = {
  169. {'ml', 8, 16},
  170. {'physical', 200, 20},
  171. {'energy', 200, 20},
  172. {'earth', 200, 20},
  173. {'fire', 200, 20},
  174. {'ice', 200, 20},
  175. {'holy', 200, 20},
  176. {'death', 200, 20},
  177. {'animals', 300, 20},
  178. {'humans', 200, 6},
  179. {'undeads', 300, 20},
  180. {'insects', 300, 20},
  181. {'range', 6, 100},
  182. {'drainHP', 200, 16},
  183. },
  184. armor = {
  185. {'hp', 1000, 30},
  186. {'mp', 1600, 40},
  187. {'ml', 6, 12},
  188. {'melee', 6, 12},
  189. {'shield', 6, 12},
  190. {'dist', 6, 12},
  191. {'physical', 8, 6},
  192. {'energy', 8, 10},
  193. {'earth', 8, 10},
  194. {'fire', 8, 10},
  195. {'ice', 8, 10},
  196. {'holy', 8, 10},
  197. {'death', 8, 10},
  198. {'arm', 10, 40},
  199. },
  200. shield = {
  201. {'ml', 6, 12},
  202. {'melee', 6, 12},
  203. {'shield', 6, 12},
  204. {'dist', 6, 12},
  205. {'physical', 8, 6},
  206. {'energy', 8, 10},
  207. {'earth', 8, 10},
  208. {'fire', 8, 10},
  209. {'ice', 8, 10},
  210. {'holy', 8, 10},
  211. {'death', 8, 10},
  212. {'def', 24, 80},
  213. },
  214. ring = {
  215. {'hp', 800, 20},
  216. {'mp', 1000, 20},
  217. {'physical', 10, 16},
  218. {'energy', 10, 16},
  219. {'earth', 10, 16},
  220. {'fire', 10, 16},
  221. {'ice', 10, 16},
  222. {'holy', 10, 16},
  223. {'death', 10, 16},
  224. {'exp', 3000, 60},
  225. {'loot', 2, 100},
  226. },
  227. legs = {
  228. {'ml', 6, 10},
  229. {'melee', 6, 10},
  230. {'shield', 6, 10},
  231. {'dist', 6, 10},
  232. {'physical', 8, 6},
  233. {'energy', 8, 10},
  234. {'earth', 8, 10},
  235. {'fire', 8, 10},
  236. {'ice', 8, 10},
  237. {'holy', 8, 10},
  238. {'death', 8, 10},
  239. {'arm', 8, 60},
  240. },
  241. boots = {
  242. {'hp', 600, 20},
  243. {'mp', 800, 20},
  244. {'physical', 8, 6},
  245. {'energy', 8, 10},
  246. {'earth', 8, 10},
  247. {'fire', 8, 10},
  248. {'ice', 8, 10},
  249. {'holy', 8, 10},
  250. {'death', 8, 10},
  251. {'arm', 10, 200},
  252. },
  253. charges = {
  254. {'charges', 500, 45},
  255. },
  256. decay = {
  257. {'time', 1200000, 50},
  258. },
  259. },
  260.  
  261. STATS = {
  262. {
  263. name = 'hp',
  264.  
  265. weaponLootName = {'',''},
  266. armorLootName = {'','of improved health'},
  267. otherLootName = {'','of improved health'},
  268.  
  269. spellName = 'Health',
  270. enabledValues = true,
  271. enabledPercent = true
  272. },
  273.  
  274. {
  275. name = 'mp',
  276.  
  277. spellName = 'Mana',
  278. enabledValues = true,
  279.  
  280. weaponLootName = {'',''},
  281. armorLootName = {'','of improved mana'},
  282. otherLootName = {'','of improved mana'},
  283. enabledPercent = true
  284. },
  285.  
  286. {
  287. name = 'ml',
  288.  
  289. weaponLootName = {'magic',''},
  290. armorLootName = {'enchanted',''},
  291. otherLootName = {'magic',''},
  292.  
  293. spellName = 'Magic Level',
  294. enabledValues = true,
  295. enabledPercent = true
  296. },
  297.  
  298. {
  299. name = 'melee',
  300.  
  301. weaponLootName = {'','of power'},
  302. armorLootName = {'warrior',''},
  303. otherLootName = {'','of power'},
  304.  
  305. spellName = 'Melee Skill',
  306. enabledValues = true,
  307. enabledPercent = true
  308. },
  309.  
  310. {
  311. name = 'shield',
  312.  
  313. weaponLootName = {'','of defense'},
  314. armorLootName = {'fortified',''},
  315. otherLootName = {'','of defense'},
  316.  
  317. spellName = 'Shielding',
  318. enabledValues = true,
  319. enabledPercent = true
  320. },
  321.  
  322. {
  323. name = 'dist',
  324.  
  325. weaponLootName = {'','of hunting'},
  326. armorLootName = {'hunter',''},
  327. otherLootName = {'','of hunting'},
  328.  
  329. spellName = 'Distance Skill',
  330. enabledValues = true,
  331. enabledPercent = true
  332. },
  333.  
  334. -- element types
  335. -- on weapon: value = more or less element damage
  336. -- on armor: value = when something hits you, hit value may increase or decrease depending on value
  337. {
  338. name = 'physical',
  339. combatType = COMBAT_PHYSICALDAMAGE,
  340.  
  341. weaponLootName = {'','of bleeding'},
  342. armorLootName = {'strong',''},
  343. otherLootName = {'stone',''},
  344.  
  345. spellName = 'Physical',
  346. enabledValues = true,
  347. enabledPercent = true,
  348.  
  349. effect = CONST_ME_BLOCKHIT
  350. },
  351.  
  352.  
  353. {
  354. name = 'energy',
  355. combatType = COMBAT_ENERGYDAMAGE,
  356.  
  357. weaponLootName = {'','of thunders'},
  358. armorLootName = {'','of sparks'},
  359. otherLootName = {'','of lightning'},
  360.  
  361. oppositeSpell = 'earth', -- unused values
  362. spellName = 'Energy',
  363. enabledValues = true,
  364. enabledPercent = true,
  365.  
  366. effect = CONST_ME_ENERGYHIT
  367. },
  368.  
  369. {
  370. name = 'earth',
  371. combatType = COMBAT_EARTHDAMAGE,
  372.  
  373. weaponLootName = {'poison',''},
  374. armorLootName = {'earthproof',''},
  375. otherLootName = {'','of antidote'},
  376.  
  377. oppositeSpell = 'energy',
  378. spellName = 'Earth',
  379. enabledValues = true,
  380. enabledPercent = true,
  381. effect = CONST_ME_SMALLPLANTS
  382. },
  383.  
  384. {
  385. name = 'fire',
  386. combatType = COMBAT_FIREDAMAGE,
  387.  
  388. weaponLootName = {'burning',''},
  389. armorLootName = {'fireproof',''},
  390. otherLootName = {'','of fire protection'},
  391.  
  392. oppositeSpell = 'ice',
  393. spellName = 'Fire',
  394. enabledValues = true,
  395. enabledPercent = true,
  396. effect = CONST_ME_FIREATTACK
  397. },
  398.  
  399. {
  400. -- exist in tfs, not in use by default
  401. name = 'undefined',
  402. combatType = COMBAT_UNDEFINEDDAMAGE,
  403.  
  404. weaponLootName = {'ghost',''},
  405. armorLootName = {'',''},
  406. otherLootName = {'',''},
  407.  
  408. spellName = 'None',
  409. enabledValues = false,
  410. enabledPercent = false,
  411. effect = CONST_ME_GROUNDSHAKER
  412. },
  413.  
  414. {
  415. name = 'lifedrain',
  416. combatType = COMBAT_LIFEDRAIN,
  417.  
  418. weaponLootName = {'cursed',''},
  419. armorLootName = {'enchanted',''},
  420. otherLootName = {'blessed',''},
  421.  
  422. oppositeSpell = 'healing',
  423. spellName = 'Lifedrain',
  424. enabledValues = true,
  425. enabledPercent = true,
  426. effect = CONST_ME_MAGIC_RED
  427. },
  428.  
  429. {
  430. name = 'manadrain',
  431. combatType = COMBAT_MANADRAIN,
  432.  
  433. weaponLootName = {'','of dark magic'},
  434. armorLootName = {'sealed',''},
  435. otherLootName = {'','of mana protection'},
  436.  
  437. spellName = 'Manadrain',
  438. enabledValues = true,
  439. enabledPercent = true,
  440. effect = CONST_ME_LOSEENERGY
  441. },
  442.  
  443. {
  444. -- should not be used by weapons
  445. name = 'healing',
  446. combatType = COMBAT_HEALING,
  447.  
  448. weaponLootName = {'healer',''},
  449. armorLootName = {'','of healing'},
  450. otherLootName = {'','of healing'},
  451.  
  452. oppositeSpell = 'lifedrain',
  453. spellName = 'Healing',
  454. enabledValues = true,
  455. enabledPercent = true,
  456. effect = CONST_ME_MAGIC_BLUE
  457. },
  458.  
  459. {
  460. name = 'water',
  461. combatType = COMBAT_DROWNDAMAGE,
  462.  
  463. weaponLootName = {'','of fear'},
  464. armorLootName = {'','of the deep'},
  465. otherLootName = {'','of the deep'},
  466.  
  467. spellName = 'Water',
  468. enabledValues = true,
  469. enabledPercent = true,
  470. effect = CONST_ME_LOSEENERGY
  471. },
  472.  
  473. {
  474. name = 'ice',
  475. combatType = COMBAT_ICEDAMAGE,
  476.  
  477. weaponLootName = {'icy',''},
  478. armorLootName = {'frozen',''},
  479. otherLootName = {'','of cold'},
  480.  
  481. oppositeSpell = 'fire',
  482. spellName = 'Ice',
  483. enabledValues = true,
  484. enabledPercent = true,
  485. effect = CONST_ME_ICEATTACK
  486. },
  487.  
  488. {
  489. name = 'holy',
  490. combatType = COMBAT_HOLYDAMAGE,
  491.  
  492. weaponLootName = {'divine',''},
  493. armorLootName = {'','of darkness'},
  494. otherLootName = {'dark',''},
  495.  
  496. oppositeSpell = 'death',
  497. spellName = 'Holy',
  498. enabledValues = true,
  499. enabledPercent = true,
  500. effect = CONST_ME_HOLYDAMAGE
  501. },
  502.  
  503. {
  504. name = 'death',
  505. combatType = COMBAT_DEATHDAMAGE,
  506.  
  507. weaponLootName = {'','of darkness'},
  508. armorLootName = {'','of inquisition'},
  509. otherLootName = {'holy',''},
  510.  
  511. oppositeSpell = 'holy',
  512. spellName = 'Death',
  513. enabledValues = true,
  514. enabledPercent = true,
  515. effect = CONST_ME_MORTAREA
  516. },
  517.  
  518. -- weapon only
  519. {
  520. name = 'drainHP',
  521. drain = COMBAT_LIFEDRAIN,
  522.  
  523. weaponLootName = {'vampire',''},
  524. armorLootName = {'',''},
  525. otherLootName = {'',''},
  526.  
  527. spellName = 'Drain Health',
  528. enabledValues = true,
  529. enabledPercent = true
  530. },
  531.  
  532. {
  533. name = 'drainMP',
  534. drain = COMBAT_MANADRAIN,
  535.  
  536. weaponLootName = {'','of weakness'},
  537. armorLootName = {'',''},
  538. otherLootName = {'',''},
  539.  
  540. spellName = 'Drain Mana',
  541. enabledValues = true,
  542. enabledPercent = true
  543. },
  544.  
  545. {
  546. name = 'animals',
  547. weaponLootName = {'hunting',''},
  548. armorLootName = {'',''},
  549. otherLootName = {'',''},
  550. spellName = 'Animals',
  551. enabledValues = true,
  552. enabledPercent = true
  553. },
  554.  
  555. {
  556. name = 'humans',
  557.  
  558. weaponLootName = {'',''},
  559. armorLootName = {'',''},
  560. otherLootName = {'',''},
  561.  
  562. spellName = 'Humans',
  563. enabledValues = true,
  564. enabledPercent = true
  565. },
  566.  
  567. {
  568. name = 'undeads',
  569.  
  570. weaponLootName = {'','of inquisition'},
  571. armorLootName = {'',''},
  572. otherLootName = {'',''},
  573.  
  574. spellName = 'Undeads',
  575. enabledValues = true,
  576. enabledPercent = true
  577. },
  578.  
  579. {
  580. name = 'insects',
  581.  
  582. weaponLootName = {'','of insect hunting'},
  583. armorLootName = {'',''},
  584. otherLootName = {'',''},
  585.  
  586. spellName = 'Insects',
  587. enabledValues = true,
  588. enabledPercent = true
  589. },
  590.  
  591.  
  592. -- attr based stats
  593. {
  594. name = 'charges',
  595.  
  596. weaponLootName = {'',''},
  597. armorLootName = {'',''},
  598. otherLootName = {'charged',''},
  599.  
  600. spellName = 'Charges',
  601. enabledValues = true,
  602. enabledPercent = true
  603. },
  604.  
  605. {
  606. name = 'time',
  607.  
  608. weaponLootName = {'',''},
  609. armorLootName = {'',''},
  610. otherLootName = {'fine',''},
  611.  
  612. spellName = 'Duration',
  613. enabledValues = true,
  614. enabledPercent = true
  615. },
  616.  
  617. {
  618. name = 'atk',
  619.  
  620. weaponLootName = {'sharpened',''},
  621. armorLootName = {'',''},
  622. otherLootName = {'',''},
  623.  
  624. spellName = 'Attack',
  625. enabledValues = true,
  626. enabledPercent = true
  627. },
  628.  
  629. {
  630. name = 'def',
  631.  
  632. weaponLootName = {'strong',''},
  633. armorLootName = {'fortified',''},
  634. otherLootName = {'',''},
  635.  
  636. spellName = 'Defense',
  637. enabledValues = true,
  638. enabledPercent = true
  639. },
  640.  
  641. {
  642. name = 'extra def',
  643.  
  644. weaponLootName = {'','of balance'},
  645. armorLootName = {'',''},
  646. otherLootName = {'',''},
  647.  
  648. spellName = 'Extra Defense',
  649. enabledValues = true,
  650. enabledPercent = true
  651. },
  652.  
  653. {
  654. name = 'arm',
  655.  
  656. weaponLootName = {'',''},
  657. armorLootName = {'masterpiece of',''},
  658. otherLootName = {'',''},
  659.  
  660. spellName = 'Armor',
  661. enabledValues = true,
  662. enabledPercent = true
  663. },
  664.  
  665. {
  666. name = 'accuracy',
  667.  
  668. weaponLootName = {'accurate',''},
  669. armorLootName = {'',''},
  670. otherLootName = {'',''},
  671.  
  672. spellName = 'Hit Chance',
  673. enabledValues = true, -- hit% + x%
  674. enabledPercent = true -- hit% + hit%*x%
  675. },
  676.  
  677. {
  678. name = 'range',
  679.  
  680. weaponLootName = {'sniper',''},
  681. armorLootName = {'',''},
  682. otherLootName = {'',''},
  683.  
  684. spellName = 'Range',
  685. enabledValues = true,
  686. enabledPercent = true
  687. },
  688.  
  689. {
  690. name = 'PVE death',
  691.  
  692. weaponLootName = {'',''},
  693. armorLootName = {'',''},
  694. otherLootName = {'','of good fate'},
  695.  
  696. spellName = 'PVE Death',
  697. enabledValues = true,
  698. enabledPercent = true
  699. },
  700. -- xp, loot
  701. {
  702. name = 'exp',
  703.  
  704. weaponLootName = {'',''},
  705. armorLootName = {'',''},
  706. otherLootName = {'','of experience'},
  707.  
  708. spellName = 'Extra Exp',
  709. enabledValues = true,
  710. enabledPercent = true
  711. },
  712.  
  713. {
  714. name = 'loot',
  715.  
  716. weaponLootName = {'',''},
  717. armorLootName = {'',''},
  718. otherLootName = {'','of luck'},
  719.  
  720. spellName = 'Luck',
  721. enabledValues = false,
  722. enabledPercent = true
  723. },
  724. },
  725. }
  726.  
  727. function getItemAttribute(uid, key, force)
  728. local i = ItemType(Item(uid):getId())
  729. local string_attributes = {
  730. [ITEM_ATTRIBUTE_NAME] = i:getName(),
  731. [ITEM_ATTRIBUTE_ARTICLE] = i:getArticle(),
  732. [ITEM_ATTRIBUTE_PLURALNAME] = i:getPluralName(),
  733. ["name"] = i:getName(),
  734. ["article"] = i:getArticle(),
  735. ["pluralname"] = i:getPluralName()
  736. }
  737.  
  738. local numeric_attributes = {
  739. [ITEM_ATTRIBUTE_WEIGHT] = i:getWeight(),
  740. [ITEM_ATTRIBUTE_ATTACK] = i:getAttack(),
  741. [ITEM_ATTRIBUTE_DEFENSE] = i:getDefense(),
  742. [ITEM_ATTRIBUTE_EXTRADEFENSE] = i:getExtraDefense(),
  743. [ITEM_ATTRIBUTE_ARMOR] = i:getArmor(),
  744. [ITEM_ATTRIBUTE_HITCHANCE] = i:getHitChance(),
  745. [ITEM_ATTRIBUTE_SHOOTRANGE] = i:getShootRange(),
  746. ["weight"] = i:getWeight(),
  747. ["attack"] = i:getAttack(),
  748. ["defense"] = i:getDefense(),
  749. ["extradefense"] = i:getExtraDefense(),
  750. ["armor"] = i:getArmor(),
  751. ["hitchance"] = i:getHitChance(),
  752. ["shootrange"] = i:getShootRange()
  753. }
  754.  
  755. local item = Item(uid)
  756. local attr = item:getAttribute(key)
  757. if tonumber(attr) then
  758. if numeric_attributes[key] then
  759. if force and item:getActionId() == 101 then
  760. return attr
  761. else
  762. return attr ~= 0 and attr or numeric_attributes[key]
  763. end
  764. end
  765. else
  766. if string_attributes[key] then
  767. if attr == "" then
  768. return string_attributes[key]
  769. end
  770. end
  771. end
  772. return attr
  773. end
  774.  
  775. function doItemSetAttribute(uid, key, value)
  776. return Item(uid):setAttribute(key, value)
  777. end
  778.  
  779. function doItemEraseAttribute(uid, key)
  780. return Item(uid):removeAttribute(key)
  781. end
  782.  
  783. local element_stats = {}
  784. local drain_stats = {}
  785.  
  786. for i = 1, #STATS_SYSTEM_CONFIG.STATS do
  787. local stat = STATS_SYSTEM_CONFIG.STATS[i]
  788. if stat.drain then
  789. drain_stats[stat.name] = stat.drain
  790. end
  791.  
  792. if stat.combatType then
  793. element_stats[stat.name] = {combat = stat.combatType, effect = stat.effect}
  794. end
  795. end
  796.  
  797. local stat_conditions = {
  798. [1] = {['hp'] = {}, ['mp'] = {}, ['ml'] = {}, ['melee'] = {}, ['shield'] = {}, ['dist'] = {}}, -- normal
  799. [2] = {['hp'] = {}, ['mp'] = {}, ['ml'] = {}, ['melee'] = {}, ['shield'] = {}, ['dist'] = {}} -- percent
  800. }
  801.  
  802. for i = -95, 300 do
  803. -- % stats and skills
  804. stat_conditions[2]['hp'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  805. setConditionParam(stat_conditions[2]['hp'][i], CONDITION_PARAM_SUBID, 50)
  806. setConditionParam(stat_conditions[2]['hp'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  807. setConditionParam(stat_conditions[2]['hp'][i], CONDITION_PARAM_TICKS, -1)
  808. setConditionParam(stat_conditions[2]['hp'][i], CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT, 100+i)
  809.  
  810. stat_conditions[2]['mp'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  811. setConditionParam(stat_conditions[2]['mp'][i], CONDITION_PARAM_SUBID, 51)
  812. setConditionParam(stat_conditions[2]['mp'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  813. setConditionParam(stat_conditions[2]['mp'][i], CONDITION_PARAM_TICKS, -1)
  814. setConditionParam(stat_conditions[2]['mp'][i], CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT, 100+i)
  815.  
  816. stat_conditions[2]['ml'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  817. setConditionParam(stat_conditions[2]['ml'][i], CONDITION_PARAM_SUBID, 52)
  818. setConditionParam(stat_conditions[2]['ml'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  819. setConditionParam(stat_conditions[2]['ml'][i], CONDITION_PARAM_TICKS, -1)
  820. setConditionParam(stat_conditions[2]['ml'][i], CONDITION_PARAM_STAT_MAGICPOINTSPERCENT, 100+i)
  821.  
  822. stat_conditions[2]['melee'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  823. setConditionParam(stat_conditions[2]['melee'][i], CONDITION_PARAM_SUBID, 53)
  824. setConditionParam(stat_conditions[2]['melee'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  825. setConditionParam(stat_conditions[2]['melee'][i], CONDITION_PARAM_TICKS, -1)
  826. setConditionParam(stat_conditions[2]['melee'][i], CONDITION_PARAM_SKILL_MELEEPERCENT, 100+i)
  827.  
  828. stat_conditions[2]['shield'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  829. setConditionParam(stat_conditions[2]['shield'][i], CONDITION_PARAM_SUBID, 54)
  830. setConditionParam(stat_conditions[2]['shield'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  831. setConditionParam(stat_conditions[2]['shield'][i], CONDITION_PARAM_TICKS, -1)
  832. setConditionParam(stat_conditions[2]['shield'][i], CONDITION_PARAM_SKILL_SHIELDPERCENT, 100+i)
  833.  
  834. stat_conditions[2]['dist'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  835. setConditionParam(stat_conditions[2]['dist'][i], CONDITION_PARAM_SUBID, 55)
  836. setConditionParam(stat_conditions[2]['dist'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  837. setConditionParam(stat_conditions[2]['dist'][i], CONDITION_PARAM_TICKS, -1)
  838. setConditionParam(stat_conditions[2]['dist'][i], CONDITION_PARAM_SKILL_DISTANCEPERCENT, 100+i)
  839. end
  840.  
  841. for i = -1500, 1500 do
  842. -- hp mp normal
  843. stat_conditions[1]['hp'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  844. setConditionParam(stat_conditions[1]['hp'][i], CONDITION_PARAM_SUBID, 56)
  845. setConditionParam(stat_conditions[1]['hp'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  846. setConditionParam(stat_conditions[1]['hp'][i], CONDITION_PARAM_TICKS, -1)
  847. setConditionParam(stat_conditions[1]['hp'][i], CONDITION_PARAM_STAT_MAXHITPOINTS, i)
  848.  
  849. stat_conditions[1]['mp'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  850. setConditionParam(stat_conditions[1]['mp'][i], CONDITION_PARAM_SUBID, 57)
  851. setConditionParam(stat_conditions[1]['mp'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  852. setConditionParam(stat_conditions[1]['mp'][i], CONDITION_PARAM_TICKS, -1)
  853. setConditionParam(stat_conditions[1]['mp'][i], CONDITION_PARAM_STAT_MAXMANAPOINTS, i)
  854. end
  855.  
  856. for i = -100, 100 do
  857. -- skills
  858. stat_conditions[1]['ml'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  859. setConditionParam(stat_conditions[1]['ml'][i], CONDITION_PARAM_SUBID, 58)
  860. setConditionParam(stat_conditions[1]['ml'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  861. setConditionParam(stat_conditions[1]['ml'][i], CONDITION_PARAM_TICKS, -1)
  862. setConditionParam(stat_conditions[1]['ml'][i], CONDITION_PARAM_STAT_MAGICPOINTS, i)
  863.  
  864. stat_conditions[1]['melee'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  865. setConditionParam(stat_conditions[1]['melee'][i], CONDITION_PARAM_SUBID, 59)
  866. setConditionParam(stat_conditions[1]['melee'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  867. setConditionParam(stat_conditions[1]['melee'][i], CONDITION_PARAM_TICKS, -1)
  868. setConditionParam(stat_conditions[1]['melee'][i], CONDITION_PARAM_SKILL_MELEE, i)
  869.  
  870. stat_conditions[1]['shield'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  871. setConditionParam(stat_conditions[1]['shield'][i], CONDITION_PARAM_SUBID, 60)
  872. setConditionParam(stat_conditions[1]['shield'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  873. setConditionParam(stat_conditions[1]['shield'][i], CONDITION_PARAM_TICKS, -1)
  874. setConditionParam(stat_conditions[1]['shield'][i], CONDITION_PARAM_SKILL_SHIELD, i)
  875.  
  876. stat_conditions[1]['dist'][i] = createConditionObject(CONDITION_ATTRIBUTES)
  877. setConditionParam(stat_conditions[1]['dist'][i], CONDITION_PARAM_SUBID, 61)
  878. setConditionParam(stat_conditions[1]['dist'][i], CONDITION_PARAM_BUFF_SPELL, 1)
  879. setConditionParam(stat_conditions[1]['dist'][i], CONDITION_PARAM_TICKS, -1)
  880. setConditionParam(stat_conditions[1]['dist'][i], CONDITION_PARAM_SKILL_DISTANCE, i)
  881. end
  882.  
  883. local magic_words = { -- see upgradeMagicItems in config
  884. 'physical',
  885. 'fire',
  886. 'ice',
  887. 'earth',
  888. 'energy',
  889. 'poison',
  890. 'drown',
  891. 'holy',
  892. 'death',
  893. 'lifedrain',
  894. 'manadrain',
  895. 'protection',
  896. 'magic',
  897. 'fighting',
  898. 'shielding',
  899. 'speed',
  900. 'invisibility',
  901. 'drinking',
  902. }
  903.  
  904. local upgrade_types = {
  905. none = false,
  906. necklace = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.necklace,
  907. helmet = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.helmet,
  908. weapon = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.weapon,
  909. distance = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.distance,
  910. wand = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.wand,
  911. armor = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.armor,
  912. shield = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.shield,
  913. ring = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.ring,
  914. legs = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.legs,
  915. boots = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.boots,
  916. charges = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.charges,
  917. decay = STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.decay,
  918. }
  919.  
  920. function Item:getUpgradeType()
  921. local it_id = self:getType()
  922. if it_id:isStackable() or it_id:isContainer() then
  923. return upgrade_types.none
  924. end
  925.  
  926. local wp = it_id:getWeaponType()
  927. if self:getAttribute(ITEM_ATTRIBUTE_CHARGES) > 0 then
  928. if wp > 0 then
  929. return upgrade_types.none
  930. end
  931. return upgrade_types.charges
  932. end
  933.  
  934. if self:getAttribute(ITEM_ATTRIBUTE_DURATION) > 0 then
  935. if wp > 0 then
  936. return upgrade_types.none
  937. end
  938. return upgrade_types.decay
  939. else
  940. if self:getBaseDuration() > 0 then
  941. if wp > 0 then
  942. return upgrade_types.none
  943. end
  944. return upgrade_types.decay
  945. end
  946. end
  947.  
  948. if wp > 0 then
  949. if wp == WEAPON_SHIELD then
  950. return upgrade_types.shield
  951. elseif wp == WEAPON_DISTANCE then
  952. return upgrade_types.distance
  953. elseif wp == WEAPON_WAND then
  954. return upgrade_types.wand
  955. elseif isInArray({WEAPON_SWORD, WEAPON_CLUB, WEAPON_AXE}, wp) then
  956. return upgrade_types.weapon
  957. end
  958. else
  959. local slot = it_id:getSlotPosition() - SLOTP_LEFT - SLOTP_RIGHT
  960. if it_id:getArmor() > 0 or STATS_SYSTEM_CONFIG.upgradeItemsWithNoArmor then
  961. if slot == SLOTP_HEAD then
  962. return upgrade_types.helmet
  963. elseif slot == SLOTP_ARMOR then
  964. return upgrade_types.armor
  965. elseif slot == SLOTP_LEGS then
  966. return upgrade_types.legs
  967. elseif slot == SLOTP_FEET then
  968. return upgrade_types.boots
  969. end
  970. end
  971.  
  972. if slot == SLOTP_NECKLACE then
  973. return upgrade_types.necklace
  974. end
  975.  
  976. if slot == SLOTP_RING then
  977. return upgrade_types.ring
  978. end
  979. end
  980.  
  981. return upgrade_types.none
  982. end
  983.  
  984. function Item:getStatSlotCount()
  985. local c = 0
  986. for _ in self:getAttribute(ITEM_ATTRIBUTE_DESCRIPTION):gmatch('%[(.-)%]') do
  987. c = c+1
  988. end
  989. return c
  990. end
  991.  
  992. function Item:getStatSlots()
  993. local t = {}
  994. for _ in self:getAttribute(ITEM_ATTRIBUTE_DESCRIPTION):gmatch('(%[.-%])') do
  995. if _ then
  996. if _:match('%[(.+)%]') then
  997. local n = _:match('%[(.+)%]')
  998. if n ~= '?' then
  999. local n1 = n:split(".")
  1000. local i = #t + 1
  1001. t[i] = {n1[1], n1[2]}
  1002. end
  1003. end
  1004. end
  1005. end
  1006. return t
  1007. end
  1008.  
  1009. function Item:addStatSlot(spell, val, suffix)
  1010. if spell and val then
  1011. if not suffix then suffix = "" end
  1012. self:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, self:getAttribute(ITEM_ATTRIBUTE_DESCRIPTION) .. "[" .. spell .. "." .. (val >= 0 and "+" .. val or val) .. suffix .. "]")
  1013. else
  1014. return false
  1015. end
  1016. return true
  1017. end
  1018.  
  1019. function Item:addSlot(name, val, percent)
  1020. val = tonumber(val)
  1021. if name and val then
  1022. if self:addStat(name, val, (percent and "%" or "")) then
  1023. return true
  1024. end
  1025. end
  1026. return false
  1027. end
  1028.  
  1029. function Item:getBaseDuration()
  1030. local it_id = self:getId()
  1031. local tid = ItemType(it_id):getTransformEquipId()
  1032. local vx = self:getAttribute(ITEM_ATTRIBUTE_DURATION)
  1033.  
  1034. if tid > 0 then
  1035. self:transform(tid)
  1036. vx = self:getAttribute(ITEM_ATTRIBUTE_DURATION)
  1037. self:transform(it_id)
  1038. self:removeAttribute(ITEM_ATTRIBUTE_DURATION)
  1039. end
  1040. return vx
  1041. end
  1042.  
  1043. function Item:getBaseStatsInfo()
  1044. local it_id = self:getType()
  1045. local t = {
  1046. attack = it_id:getAttack(),
  1047. defense = it_id:getDefense(),
  1048. extraDefense = it_id:getExtraDefense(),
  1049. armor = it_id:getArmor(),
  1050. hitChance = it_id:getHitChance(),
  1051. shootRange = it_id:getShootRange(),
  1052. charges = it_id:getCharges(),
  1053. duration = self:getBaseDuration()
  1054. }
  1055. return t
  1056. end
  1057.  
  1058. function getEnchantingSkill(tries)
  1059. local xp = 0
  1060. local level = 0
  1061. for lv = 1, STATS_SYSTEM_CONFIG.maxLevel do
  1062. xp = STATS_SYSTEM_CONFIG.skillFormula(lv) -- alternative: xp = xp + STATS_SYSTEM_CONFIG.skillFormula(lv)
  1063. if tries < xp then
  1064. level = lv
  1065. break
  1066. end
  1067. level = lv
  1068. end
  1069. return level
  1070. end
  1071.  
  1072. local SPELL_TYPE_VALUE = 1
  1073. local SPELL_TYPE_PERCENT = 2
  1074. local attrkeys = {
  1075. ['charges'] = ITEM_ATTRIBUTE_CHARGES,
  1076. ['time'] = ITEM_ATTRIBUTE_DURATION,
  1077. ['atk'] = ITEM_ATTRIBUTE_ATTACK,
  1078. ['def'] = ITEM_ATTRIBUTE_DEFENSE,
  1079. ['extra def'] = ITEM_ATTRIBUTE_EXTRADEFENSE,
  1080. ['arm'] = ITEM_ATTRIBUTE_ARMOR,
  1081. ['accuracy'] = ITEM_ATTRIBUTE_HITCHANCE,
  1082. ['range'] = ITEM_ATTRIBUTE_SHOOTRANGE
  1083. }
  1084.  
  1085. function Item.addStat(item, spellname, spellvalue, suffix, cid)
  1086. if isInArray({'charges', 'time', 'atk', 'def', 'extra def', 'arm', 'accuracy', 'range'}, spellname) then
  1087. local basestats = item:getBaseStatsInfo()
  1088. local basestats2 = {
  1089. ['charges'] = basestats.charges,
  1090. ['time'] = basestats.duration,
  1091. ['atk'] = basestats.attack,
  1092. ['def'] = basestats.defense,
  1093. ['extra def'] = basestats.extraDefense,
  1094. ['arm'] = basestats.armor,
  1095. ['accuracy'] = basestats.hitChance,
  1096. ['range'] = basestats.shootRange
  1097. }
  1098. local gainstats = {
  1099. ['atk'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.atk,
  1100. ['def'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.def,
  1101. ['extra def'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.extradef,
  1102. ['arm'] =STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.arm,
  1103. ['accuracy'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.hitchance,
  1104. ['range'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.shootrange
  1105. }
  1106.  
  1107. local uid = item:getUniqueId()
  1108. local fullstats = {
  1109. ['charges'] = getItemAttribute(uid, ITEM_ATTRIBUTE_CHARGES),
  1110. ['time'] = item:getBaseDuration(),
  1111. ['atk'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACK),
  1112. ['def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_DEFENSE),
  1113. ['extra def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_EXTRADEFENSE),
  1114. ['arm'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ARMOR),
  1115. ['accuracy'] = getItemAttribute(uid, ITEM_ATTRIBUTE_HITCHANCE),
  1116. ['range'] = getItemAttribute(uid, ITEM_ATTRIBUTE_SHOOTRANGE)
  1117. }
  1118.  
  1119.  
  1120. if suffix == "%" then
  1121. if basestats2[spellname] == 0 then
  1122. if cid then
  1123. Player(cid):sendTextMessage(MESSAGE_INFO_DESCR, "Spell " .. spellname .. "% is not available for this item.")
  1124. end
  1125. return false
  1126. end
  1127. if spellname ~= 'charges' or 'time' then
  1128. item:setAttribute(attrkeys[spellname], basestats2[spellname] + (gainstats[spellname]*item:getLevel()) + math.abs(math.floor((basestats2[spellname] * spellvalue/100))))
  1129. else
  1130. item:setAttribute(attrkeys[spellname], fullstats[spellname] + math.abs(math.floor((basestats2[spellname] * spellvalue/100))))
  1131. end
  1132. --item:setAttribute(attrkeys[spellname], fullstats[spellname] + math.abs(math.floor((basestats2[spellname] * spellvalue/100)))) -- basestat intended to prevent too high values when combined with upgrade system
  1133. else
  1134. if spellname ~= 'charges' or 'time' then
  1135. item:setAttribute(attrkeys[spellname], basestats2[spellname] + (gainstats[spellname]*item:getLevel()) + math.abs(spellvalue))
  1136. else
  1137. item:setAttribute(attrkeys[spellname], fullstats[spellname] + math.abs(spellvalue))
  1138. end
  1139. end
  1140. end
  1141. item:addStatSlot(spellname, spellvalue, suffix)
  1142. return true
  1143. end
  1144.  
  1145. local upgradable_stats = {
  1146. [1] = {ITEM_ATTRIBUTE_ATTACK, function(id) return id:getAttack() end, STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.atk},
  1147. [2] = {ITEM_ATTRIBUTE_DEFENSE, function(id) return id:getDefense() end, STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.def},
  1148. [3] = {ITEM_ATTRIBUTE_EXTRADEFENSE, function(id) return id:getExtraDefense() end, STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.extradef},
  1149. [4] = {ITEM_ATTRIBUTE_ARMOR, function(id) return id:getArmor() end, STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.arm},
  1150. [5] = {ITEM_ATTRIBUTE_HITCHANCE, function(id) return id:getHitChance() end, STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.hitchance},
  1151. [6] = {ITEM_ATTRIBUTE_SHOOTRANGE, function(id) return id:getShootRange() > 1 and id:getShootRange() or 0 end, STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.shootrange}
  1152. }
  1153.  
  1154. function stat_onUse(player, item, fromPosition, itemEx, toPosition, attempt)
  1155. if item.itemid == STATS_SYSTEM_CONFIG.GEM_BASIC_LEVEL then
  1156. if STATS_SYSTEM_CONFIG.addLevelAction then
  1157. local it_id = ItemType(itemEx.itemid)
  1158. if it_id then
  1159. if not it_id:isStackable() then
  1160. if it_id:getTransformEquipId() < 1 then
  1161. if it_id:getCharges() < 1 then
  1162. local item_sp_slot = it_id:getSlotPosition() - SLOTP_LEFT - SLOTP_RIGHT
  1163. if item_sp_slot ~= SLOTP_NECKLACE and item_sp_slot ~= SLOTP_RING and (item_sp_slot > 0 or it_id:getWeaponType() > 0) then
  1164. local stat_min = 1
  1165. if STATS_SYSTEM_CONFIG.rare_negative_level then
  1166. stat_min = STATS_SYSTEM_CONFIG.rare_min_level
  1167. end
  1168.  
  1169. local stat_max = #STATS_SYSTEM_CONFIG.weapon_levels
  1170. local stat_lvl = tonumber(getItemAttribute(itemEx.uid, ITEM_ATTRIBUTE_NAME):match("%s%+%d+") or getItemAttribute(itemEx.uid, ITEM_ATTRIBUTE_NAME):match("%s%-%d+"))
  1171. if stat_lvl == stat_max then
  1172. player:sendTextMessage(MESSAGE_INFO_DESCR, "This item is on max level already.")
  1173. return true
  1174. end
  1175.  
  1176. local n_lvl = stat_lvl
  1177. if not stat_lvl then
  1178. stat_lvl = 0
  1179. end
  1180.  
  1181. local chance = STATS_SYSTEM_CONFIG.levelUpgradeFormula(stat_lvl, stat_min)
  1182. local it_u = Item(itemEx.uid)
  1183. local it_name = it_u:getName()
  1184. if stat_lvl > 0 then
  1185. it_name = getItemAttribute(itemEx.uid, ITEM_ATTRIBUTE_NAME):split("+")[1]
  1186. elseif stat_lvl < 0 then
  1187. it_name = getItemAttribute(itemEx.uid, ITEM_ATTRIBUTE_NAME):split("-")[1]
  1188. end
  1189.  
  1190. it_name = it_name:gsub("^%s*(.-)%s*$", "%1")
  1191.  
  1192. if math.random(1, 100) <= chance then
  1193. n_lvl = stat_lvl + 1
  1194. else
  1195. if STATS_SYSTEM_CONFIG.simple.downgradeOnFail then
  1196. n_lvl = stat_lvl - 1
  1197. end
  1198. end
  1199.  
  1200. for i = 1, #upgradable_stats do
  1201. local n_item_stat = upgradable_stats[i][2](it_id)
  1202. it_u:setAttribute(upgradable_stats[i][1], getItemAttribute(itemEx.uid, upgradable_stats[i][1], true) + (upgradable_stats[i][3] * (n_lvl - stat_lvl)))
  1203. end
  1204.  
  1205. it_u:setActionId(101)
  1206. Item(item.uid):remove(1)
  1207. if (n_lvl - stat_lvl) > 0 then
  1208. player:sendTextMessage(MESSAGE_INFO_DESCR, it_name:gsub("^%l", string.upper) .. " upgraded to " .. (n_lvl > 0 and "+" or "") .. n_lvl .. ".")
  1209. toPosition:sendMagicEffect(CONST_ME_MAGIC_GREEN)
  1210. else
  1211. player:sendTextMessage(MESSAGE_INFO_DESCR, "Attempt to upgrade failed.")
  1212. toPosition:sendMagicEffect(CONST_ME_HITAREA)
  1213. end
  1214.  
  1215. it_u:setAttribute(ITEM_ATTRIBUTE_NAME, it_name .. (n_lvl ~= 0 and (" " .. (n_lvl > 0 and "+" or "") .. n_lvl) or ""))
  1216. return true
  1217. end
  1218. end
  1219. end
  1220. end
  1221. end
  1222. end
  1223. return false
  1224. end
  1225.  
  1226. if item.itemid == STATS_SYSTEM_CONFIG.GEM_ADD_SLOT then
  1227. if not STATS_SYSTEM_CONFIG.addSlotAction then
  1228. return false
  1229. end
  1230.  
  1231. if not attempt then
  1232. attempt = 1
  1233. end
  1234.  
  1235. if attempt == 10 then
  1236. player:sendTextMessage(MESSAGE_INFO_DESCR, "Unable to add slot.")
  1237. return true
  1238. end
  1239.  
  1240. local it_u = Item(itemEx.uid)
  1241. if not it_u then
  1242. return false
  1243. end
  1244.  
  1245. if not STATS_SYSTEM_CONFIG.simple.enabled then
  1246. return false
  1247. end
  1248.  
  1249. if not STATS_SYSTEM_CONFIG.simple.randomSpells then
  1250. -- popup modal
  1251. -- popUpStatModal_index(player, item.uid)
  1252. print("todo: modal window")
  1253. return true
  1254. end
  1255.  
  1256. if isInArray(STATS_SYSTEM_CONFIG.ignoredIds, itemEx.itemid) then
  1257. -- player:sendTextMessage(MESSAGE_INFO_DESCR, "You cannot upgrade this item.")
  1258. return false
  1259. end
  1260.  
  1261. local it_id = ItemType(itemEx.itemid)
  1262. local u = it_u:getUpgradeType()
  1263.  
  1264. if not u then
  1265. -- player:sendTextMessage(MESSAGE_INFO_DESCR, "You cannot upgrade this item.")
  1266. return false
  1267. end
  1268.  
  1269. if not STATS_SYSTEM_CONFIG.upgradeMagicItems then
  1270. local atr = it_u:getDescription():match('%((.+)%)')
  1271. if atr and magic_words then
  1272. if #magic_words > 0 then
  1273. for i = 1, #magic_words do
  1274. if atr:match(magic_words[i]) then
  1275. player:sendTextMessage(MESSAGE_INFO_DESCR, "You cannot upgrade magic items.")
  1276. return true
  1277. end
  1278. end
  1279. end
  1280. end
  1281. end
  1282.  
  1283. local stat = math.random(1, #u)
  1284.  
  1285. local tries = player:getStorageValue(STATS_SYSTEM_CONFIG.skillTriesStorage)
  1286. if tries < 0 then
  1287. player:setStorageValue(STATS_SYSTEM_CONFIG.skillTriesStorage, 0)
  1288. end
  1289.  
  1290. local level = STATS_SYSTEM_CONFIG.useSkill and getEnchantingSkill(tries) or math.random(1, STATS_SYSTEM_CONFIG.maxLevel)
  1291.  
  1292. local spellname = u[stat][1]
  1293. local spelltype = 0
  1294. local available_spell_types = {}
  1295.  
  1296. for i = 1, #STATS_SYSTEM_CONFIG.STATS do
  1297. if STATS_SYSTEM_CONFIG.STATS[i].name == spellname then
  1298. if STATS_SYSTEM_CONFIG.STATS[i].enabledValues then
  1299. table.insert(available_spell_types, SPELL_TYPE_VALUE)
  1300. end
  1301.  
  1302. if STATS_SYSTEM_CONFIG.STATS[i].enabledPercent then
  1303. table.insert(available_spell_types, SPELL_TYPE_PERCENT)
  1304. end
  1305.  
  1306. if #available_spell_types > 0 then
  1307. spelltype = available_spell_types[math.random(1, #available_spell_types)]
  1308. end
  1309. break
  1310. end
  1311. end
  1312.  
  1313. if spelltype == 0 then
  1314. player:sendTextMessage(MESSAGE_INFO_DESCR, "Error: spell is unavailable.")
  1315. return true
  1316. end
  1317.  
  1318. local spellattr = nil
  1319. for i = 1, #STATS_SYSTEM_CONFIG.STATS do
  1320. if STATS_SYSTEM_CONFIG.STATS[i].name == spellname then
  1321. spellattr = STATS_SYSTEM_CONFIG.STATS[i]
  1322. break
  1323. end
  1324. end
  1325.  
  1326. if not spellattr then
  1327. player:sendTextMessage(MESSAGE_INFO_DESCR, "Error: spell is unavailable.")
  1328. return true
  1329. end
  1330.  
  1331. local prc = (level * 100/STATS_SYSTEM_CONFIG.maxLevel)/100
  1332. local attrval = 0
  1333. local attrstr = ""
  1334.  
  1335. if spelltype == SPELL_TYPE_VALUE then
  1336. attrval = math.floor(prc * u[stat][2])
  1337. elseif spelltype == SPELL_TYPE_PERCENT then
  1338. attrval = math.floor(prc * u[stat][3])
  1339. attrstr = "%"
  1340. end
  1341.  
  1342. if attrval == 0 then
  1343. player:sendTextMessage(MESSAGE_INFO_DESCR, "Error: spell is unavailable.")
  1344. return true
  1345. end
  1346.  
  1347. local slotc = it_u:getStatSlotCount()
  1348. if slotc == STATS_SYSTEM_CONFIG.maxSlotCount then
  1349. player:sendTextMessage(MESSAGE_INFO_DESCR, "Slot limit reached.")
  1350. return true
  1351. end
  1352.  
  1353. local cur_slots = it_u:getStatSlots()
  1354. for i = 1, slotc do
  1355. if spellname == cur_slots[i][1] then
  1356. -- player:sendTextMessage(MESSAGE_INFO_DESCR, "Duplicate stat, try again.")
  1357. stat_onUse(player, item, fromPosition, itemEx, toPosition, attempt + 1)
  1358. return true
  1359. end
  1360. end
  1361.  
  1362. if it_u:addStat(spellname, attrval, attrstr, player:getId()) then
  1363. toPosition:sendMagicEffect(CONST_ME_MAGIC_GREEN)
  1364. player:sendTextMessage(MESSAGE_INFO_DESCR, "Upgrade successful.\n" .. spellattr.spellName .. " " .. (attrval >= 0 and "+" .. attrval or attrval) .. attrstr)
  1365. doRemoveItem(item.uid, 1)
  1366. if STATS_SYSTEM_CONFIG.useSkill then
  1367. player:setStorageValue(STATS_SYSTEM_CONFIG.skillTriesStorage, player:getStorageValue(STATS_SYSTEM_CONFIG.skillTriesStorage) + 1)
  1368. local nlevel = STATS_SYSTEM_CONFIG.useSkill and getEnchantingSkill(player:getStorageValue(STATS_SYSTEM_CONFIG.skillTriesStorage)) or math.random(1, STATS_SYSTEM_CONFIG.maxLevel)
  1369. if nlevel > level then
  1370. player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You advanced to enchanting Level " .. (nlevel < STATS_SYSTEM_CONFIG.maxLevel and nlevel or nlevel .. " [max]") .. ".")
  1371. end
  1372. end
  1373. end
  1374. return true
  1375. end
  1376.  
  1377. if isInArray({STATS_SYSTEM_CONFIG.GEM_RARE, STATS_SYSTEM_CONFIG.GEM_EPIC, STATS_SYSTEM_CONFIG.GEM_LEGENDARY, STATS_SYSTEM_CONFIG.GEM_RANDOM}, item.itemid) then
  1378. local item2 = Item(itemEx.uid)
  1379. if item2 then
  1380. local u = item2:getUpgradeType()
  1381. if u then
  1382. if item2:generateStats(u, STATS_SYSTEM_CONFIG.gems_power[item.itemid].sl(), math.random(STATS_SYSTEM_CONFIG.gems_power[item.itemid].min_wl, STATS_SYSTEM_CONFIG.gems_power[item.itemid].max_wl), math.floor(STATS_SYSTEM_CONFIG.maxLevel * STATS_SYSTEM_CONFIG.gems_power[item.itemid].min_el), math.ceil(STATS_SYSTEM_CONFIG.maxLevel * STATS_SYSTEM_CONFIG.gems_power[item.itemid].max_el)) then
  1383. toPosition:sendMagicEffect(CONST_ME_MAGIC_GREEN)
  1384. doRemoveItem(item.uid, 1)
  1385. player:sendTextMessage(MESSAGE_INFO_DESCR, "Item modification successful.")
  1386. return true
  1387. end
  1388. end
  1389. end
  1390. return false
  1391. end
  1392. return false
  1393. end
  1394.  
  1395. local slots = {
  1396. CONST_SLOT_HEAD,
  1397. CONST_SLOT_NECKLACE,
  1398. CONST_SLOT_BACKPACK,
  1399. CONST_SLOT_ARMOR,
  1400. CONST_SLOT_RIGHT,
  1401. CONST_SLOT_LEFT,
  1402. CONST_SLOT_LEGS,
  1403. CONST_SLOT_FEET,
  1404. CONST_SLOT_RING,
  1405. CONST_SLOT_AMMO
  1406. }
  1407.  
  1408. local human_looktypes = {
  1409. 57, 58, 62, 63, 64, 66, 69, 70, 71, 72, 73, 75, 93, 96, 97,
  1410. 98, 126, 127, 128, 129, 130, 131, 132, 133, 134, 136, 137,
  1411. 138, 139, 140, 141, 142, 143, 144, 145, 145, 147, 148, 149,
  1412. 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 193,
  1413. 194, 203, 251, 252, 253, 254, 255, 264, 266, 268, 269, 270,
  1414. 273, 278, 279, 288, 289, 302, 324, 325, 328, 329, 331, 332,
  1415. 366, 367, 386, 416, 423, 430, 431, 432, 433, 463, 464, 465,
  1416. 466, 471, 472, 493, 507, 512, 513, 513, 516, 537, 538, 539,
  1417. 541, 542, 574, 575, 577, 578, 610, 618, 619, 620
  1418. }
  1419.  
  1420. function stat_onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
  1421. if origin == 2 then return primaryDamage, primaryType, secondaryDamage, secondaryType end
  1422. if not creature then return primaryDamage, primaryType, secondaryDamage, secondaryType end
  1423. if not attacker then return primaryDamage, primaryType, secondaryDamage, secondaryType end
  1424. local cid = creature:getId()
  1425. local aid = attacker:getId()
  1426.  
  1427. -- weapon extra damage
  1428. if attacker:isPlayer() then
  1429. for i = CONST_SLOT_RIGHT, CONST_SLOT_LEFT do
  1430. local item = attacker:getSlotItem(slots[i])
  1431. if item then
  1432. local cur_slots = item:getStatSlots()
  1433. local it_id = ItemType(item:getId())
  1434. if it_id:getWeaponType() > 0 and it_id:getWeaponType() ~= WEAPON_SHIELD then
  1435. local slotc = item:getStatSlotCount()
  1436. if slotc > 0 then
  1437. for i = 1, slotc do
  1438. if element_stats[cur_slots[i][1]] then
  1439. if cur_slots[i][2]:match("%%") then
  1440. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1441. local dmg = math.floor((primaryDamage * (tonumber(a..b)/100)))
  1442. if dmg > 0 then
  1443. doTargetCombatHealth(aid, cid, element_stats[cur_slots[i][1]].combat, 1, dmg, element_stats[cur_slots[i][1]].effect)
  1444. end
  1445. else
  1446. local dmg = math.floor(math.random(0, tonumber(cur_slots[i][2])))
  1447. if dmg > 0 then
  1448. doTargetCombatHealth(aid, cid, element_stats[cur_slots[i][1]].combat, 1, dmg, element_stats[cur_slots[i][1]].effect)
  1449. end
  1450. end
  1451. else
  1452. if creature and attacker then
  1453. if creature:getId() ~= attacker:getId() then
  1454. if cur_slots[i][1] == 'drainHP' then
  1455. if cur_slots[i][2]:match("%%") then
  1456. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1457. local hp_d = math.floor((primaryDamage * (tonumber(a..b)/100)))
  1458. if hp_d > 0 then
  1459. doTargetCombatHealth(aid, cid, COMBAT_LIFEDRAIN, -hp_d, -hp_d, CONST_ME_MAGIC_RED)
  1460. attacker:addHealth(hp_d)
  1461. end
  1462. else
  1463. local hp_d = math.random(1, math.floor(math.random(0, tonumber(cur_slots[i][2]))))
  1464. if hp_d > 0 then
  1465. doTargetCombatHealth(aid, cid, COMBAT_LIFEDRAIN, -hp_d, -hp_d, CONST_ME_MAGIC_RED)
  1466. attacker:addHealth(hp_d)
  1467. end
  1468. end
  1469. end
  1470.  
  1471. if cur_slots[i][1] == 'drainMP' then
  1472. if creature:getMana() > 0 then
  1473. if cur_slots[i][2]:match("%%") then
  1474. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1475. local mp_d = math.floor((primaryDamage * (tonumber(a..b)/100)))
  1476. doTargetCombatMana(aid, cid, -mp_d, -mp_d)
  1477. attacker:addMana(mp_d)
  1478. else
  1479. local mp_d = math.random(1, math.floor(math.random(0, tonumber(cur_slots[i][2]))))
  1480. doTargetCombatMana(aid, cid, -mp_d, -mp_d)
  1481. attacker:addMana(mp_d)
  1482. end
  1483. end
  1484. end
  1485. end
  1486. end
  1487.  
  1488. if (creature:isPlayer() or isInArray(human_looktypes, creature:getOutfit().lookType)) and cur_slots[i][1] == 'humans' then
  1489. if cur_slots[i][2]:match("%%") then
  1490. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1491. primaryDamage = primaryDamage + math.floor((primaryDamage * (tonumber(a..b)/100)))
  1492. else
  1493. primaryDamage = primaryDamage + math.random(1, math.floor(math.random(0, tonumber(cur_slots[i][2]))))
  1494. end
  1495. end
  1496.  
  1497. if creature:isMonster() then
  1498. local race = MonsterType(creature:getName()):getRace()
  1499. local name = creature:getName():lower()
  1500. if cur_slots[i][1] == 'insects' then
  1501. if race == 1 then
  1502. if cur_slots[i][2]:match("%%") then
  1503. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1504. primaryDamage = primaryDamage + math.floor((primaryDamage * (tonumber(a..b)/100)))
  1505. else
  1506. primaryDamage = primaryDamage + math.random(1, math.floor(math.random(0, tonumber(cur_slots[i][2]))))
  1507. end
  1508. end
  1509. elseif cur_slots[i][1] == 'animals' then
  1510. if race == 2 and not isInArray(human_looktypes, creature:getOutfit().lookType) then
  1511. if cur_slots[i][2]:match("%%") then
  1512. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1513. primaryDamage = primaryDamage + math.floor((primaryDamage * (tonumber(a..b)/100)))
  1514. else
  1515. primaryDamage = primaryDamage + math.random(1, math.floor(math.random(0, tonumber(cur_slots[i][2]))))
  1516. end
  1517. end
  1518. elseif cur_slots[i][1] == 'undeads' then
  1519. if race == 3 then
  1520. if cur_slots[i][2]:match("%%") then
  1521. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1522. primaryDamage = primaryDamage + math.floor((primaryDamage * (tonumber(a..b)/100)))
  1523. else
  1524. primaryDamage = primaryDamage + math.random(1, math.floor(math.random(0, tonumber(cur_slots[i][2]))))
  1525. end
  1526. end
  1527. elseif cur_slots[i][1] == 'elementals' then
  1528. if race == 4 or race == 5 or name:match("elemental") then
  1529. if cur_slots[i][2]:match("%%") then
  1530. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1531. primaryDamage = primaryDamage + math.floor((primaryDamage * (tonumber(a..b)/100)))
  1532. else
  1533. primaryDamage = primaryDamage + math.random(1, math.floor(math.random(0, tonumber(cur_slots[i][2]))))
  1534. end
  1535. end
  1536. elseif cur_slots[i][1] == 'dragons' then
  1537. if name:match("dragon") then
  1538. if cur_slots[i][2]:match("%%") then
  1539. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1540. primaryDamage = primaryDamage + math.floor((primaryDamage * (tonumber(a..b)/100)))
  1541. else
  1542. primaryDamage = primaryDamage + math.random(1, math.floor(math.random(0, tonumber(cur_slots[i][2]))))
  1543. end
  1544. end
  1545. elseif cur_slots[i][1] == 'lizards' then
  1546. if name:match("lizard") or name:match("draken") then
  1547. if cur_slots[i][2]:match("%%") then
  1548. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1549. primaryDamage = primaryDamage + math.floor((primaryDamage * (tonumber(a..b)/100)))
  1550. else
  1551. primaryDamage = primaryDamage + math.random(1, math.floor(math.random(0, tonumber(cur_slots[i][2]))))
  1552. end
  1553. end
  1554. end
  1555. end
  1556. end
  1557. end
  1558. end
  1559. end
  1560. end
  1561. end
  1562. end
  1563.  
  1564. -- armor elemental protection
  1565. if creature:isPlayer() then
  1566. for i = 1, #slots do
  1567. local item = creature:getSlotItem(slots[i])
  1568. if item then
  1569. local it_id = ItemType(item:getId())
  1570.  
  1571. if it_id:getWeaponType() == WEAPON_SHIELD or it_id:getWeaponType() == 0 then
  1572. local slotc = item:getStatSlotCount()
  1573. if slotc > 0 then
  1574. local cur_slots = item:getStatSlots()
  1575. for i = 1, slotc do
  1576. if element_stats[cur_slots[i][1]] then
  1577. if cur_slots[i][2]:match("%%") then
  1578. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1579. if primaryType == element_stats[cur_slots[i][1]] then
  1580. primaryDamage = math.floor(primaryDamage - (primaryDamage * (tonumber(a..b)/100)))
  1581. end
  1582.  
  1583. if secondaryType == element_stats[cur_slots[i][1]] then
  1584. secondaryDamage = math.floor(secondaryDamage - (secondaryDamage * (tonumber(a..b)/100)))
  1585. end
  1586. else
  1587. if primaryType == element_stats[cur_slots[i][1]] then
  1588. primaryDamage = math.floor(primaryDamage - math.random(0, tonumber(cur_slots[i][2])))
  1589. end
  1590.  
  1591. if secondaryType == element_stats[cur_slots[i][1]] then
  1592. secondaryDamage = math.floor(secondaryDamage - math.random(0, tonumber(cur_slots[i][2])))
  1593. end
  1594. end
  1595. end
  1596. end
  1597. end
  1598. end
  1599. end
  1600. end
  1601. end
  1602. return primaryDamage, primaryType, secondaryDamage, secondaryType
  1603. end
  1604.  
  1605. function stat_onManaChange(creature, attacker, manaChange, origin)
  1606. if not creature:isPlayer() then
  1607. return manaChange
  1608. end
  1609. for i = 1, #slots do
  1610. local item = creature:getSlotItem(slots[i])
  1611. if item then
  1612. local it_id = ItemType(item:getId())
  1613.  
  1614. if it_id:getWeaponType() == WEAPON_SHIELD or it_id:getWeaponType() == 0 then
  1615. local slotc = item:getStatSlotCount()
  1616. if slotc > 0 then
  1617. local cur_slots = item:getStatSlots()
  1618. for i = 1, slotc do
  1619. if cur_slots[i][1] == 'manadrain' then
  1620. if cur_slots[i][2]:match("%%") then
  1621. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1622. manaChange = manaChange + (manaChange * (tonumber(a..b)/100))
  1623. else
  1624. manaChange = manaChange + math.random(0, tonumber(cur_slots[i][2]))
  1625. end
  1626. end
  1627. end
  1628. end
  1629. end
  1630. end
  1631. end
  1632. return manaChange
  1633. end
  1634.  
  1635. function isWeapon(uid) return (getItemWeaponType(uid) > 0 and getItemWeaponType(uid) ~= 4) end
  1636. function isShield(uid) return getItemWeaponType(uid) == 4 end
  1637. function isBow(uid) return (getItemWeaponType(uid) == 5 and (not ItemType(getThing(uid).itemid):isStackable())) end
  1638.  
  1639. function check_slot(aab, i)
  1640. if i == 5 or i == 6 then
  1641. if isWeapon(aab) or isShield(aab) or isBow(aab) then
  1642. return true
  1643. end
  1644. else
  1645. return true
  1646. end
  1647. return false
  1648. end
  1649.  
  1650.  
  1651. local eq_stat_conditions = {'hp', 'mp', 'ml', 'melee', 'shield', 'dist'}
  1652. function stat_load(cid)
  1653. local player = Player(cid)
  1654. local v_stat_percent = {}
  1655. local v_stat_normal = {}
  1656. for j = 1, 9 do
  1657. local item = player:getSlotItem(j)
  1658. if item then
  1659. local slotc = item:getStatSlotCount()
  1660. if slotc > 0 then
  1661. local cur_slots = item:getStatSlots()
  1662. for i = 1, slotc do
  1663. if isInArray(eq_stat_conditions, cur_slots[i][1]) then
  1664. if cur_slots[i][2]:match("%%") then
  1665. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1666. if not v_stat_percent[cur_slots[i][1]] then
  1667. v_stat_percent[cur_slots[i][1]] = 0
  1668. end
  1669. v_stat_percent[cur_slots[i][1]] = v_stat_percent[cur_slots[i][1]] + (tonumber(a..b)/100)
  1670. else
  1671. if not v_stat_normal[cur_slots[i][1]] then
  1672. v_stat_normal[cur_slots[i][1]] = 0
  1673. end
  1674. v_stat_normal[cur_slots[i][1]] = v_stat_normal[cur_slots[i][1]] + tonumber(cur_slots[i][2])
  1675. end
  1676. end
  1677. end
  1678. end
  1679. end
  1680. end
  1681.  
  1682. local fu = 0 -- functions used
  1683. local ca = {} -- conditions assigned
  1684. for i = 1, #eq_stat_conditions do
  1685. if eq_stat_conditions[i] == 'hp' then
  1686. if v_stat_normal[eq_stat_conditions[i]] then
  1687. fu = fu+1
  1688. doAddCondition(cid,stat_conditions[1][eq_stat_conditions[i]][math.max(math.min(1500, v_stat_normal[eq_stat_conditions[i]]), -1500)])
  1689. ca[56] = 1
  1690. end
  1691.  
  1692. if v_stat_percent[eq_stat_conditions[i]] then
  1693. fu = fu+1
  1694. doAddCondition(cid,stat_conditions[2][eq_stat_conditions[i]][math.max(math.min(300, v_stat_percent[eq_stat_conditions[i]] * 100), -95)])
  1695. ca[50] = 1
  1696. end
  1697. elseif eq_stat_conditions[i] == 'mp' then
  1698. if v_stat_normal[eq_stat_conditions[i]] then
  1699. fu = fu+1
  1700. doAddCondition(cid,stat_conditions[1][eq_stat_conditions[i]][math.max(math.min(1500, v_stat_normal[eq_stat_conditions[i]]), -1500)])
  1701. ca[57] = 1
  1702. end
  1703.  
  1704. if v_stat_percent[eq_stat_conditions[i]] then
  1705. fu = fu+1
  1706. doAddCondition(cid,stat_conditions[2][eq_stat_conditions[i]][math.max(math.min(300, v_stat_percent[eq_stat_conditions[i]] * 100), -95)])
  1707. ca[51] = 1
  1708. end
  1709. elseif eq_stat_conditions[i] == 'ml' then
  1710. if v_stat_normal[eq_stat_conditions[i]] then
  1711. fu = fu+1
  1712. doAddCondition(cid,stat_conditions[1][eq_stat_conditions[i]][math.max(math.min(100, v_stat_normal[eq_stat_conditions[i]]), -100)])
  1713. ca[58] = 1
  1714. end
  1715.  
  1716. if v_stat_percent[eq_stat_conditions[i]] then
  1717. fu = fu+1
  1718. doAddCondition(cid,stat_conditions[2][eq_stat_conditions[i]][math.max(math.min(300, v_stat_percent[eq_stat_conditions[i]] * 100), -95)])
  1719. ca[52] = 1
  1720. end
  1721. elseif eq_stat_conditions[i] == 'melee' then
  1722. if v_stat_normal[eq_stat_conditions[i]] then
  1723. fu = fu+1
  1724. doAddCondition(cid,stat_conditions[1][eq_stat_conditions[i]][math.max(math.min(100, v_stat_normal[eq_stat_conditions[i]]), -100)])
  1725. ca[59] = 1
  1726. end
  1727.  
  1728. if v_stat_percent[eq_stat_conditions[i]] then
  1729. fu = fu+1
  1730. doAddCondition(cid,stat_conditions[2][eq_stat_conditions[i]][math.max(math.min(300, v_stat_percent[eq_stat_conditions[i]] * 100), -95)])
  1731. ca[53] = 1
  1732. end
  1733. elseif eq_stat_conditions[i] == 'shield' then
  1734. if v_stat_normal[eq_stat_conditions[i]] then
  1735. fu = fu+1
  1736. doAddCondition(cid,stat_conditions[1][eq_stat_conditions[i]][math.max(math.min(100, v_stat_normal[eq_stat_conditions[i]]), -100)])
  1737. ca[60] = 1
  1738. end
  1739.  
  1740. if v_stat_percent[eq_stat_conditions[i]] then
  1741. fu = fu+1
  1742. doAddCondition(cid,stat_conditions[2][eq_stat_conditions[i]][math.max(math.min(300, v_stat_percent[eq_stat_conditions[i]] * 100), -95)])
  1743. ca[54] = 1
  1744. end
  1745. elseif eq_stat_conditions[i] == 'dist' then
  1746. if v_stat_normal[eq_stat_conditions[i]] then
  1747. fu = fu+1
  1748. doAddCondition(cid,stat_conditions[1][eq_stat_conditions[i]][math.max(math.min(100, v_stat_normal[eq_stat_conditions[i]]), -100)])
  1749. ca[61] = 1
  1750. end
  1751.  
  1752. if v_stat_percent[eq_stat_conditions[i]] then
  1753. fu = fu+1
  1754. doAddCondition(cid,stat_conditions[2][eq_stat_conditions[i]][math.max(math.min(300, v_stat_percent[eq_stat_conditions[i]] * 100), -95)])
  1755. ca[55] = 1
  1756. end
  1757. end
  1758. end
  1759. if fu > 0 then
  1760. for i=50,61 do
  1761. if not ca[i] then
  1762. doRemoveCondition(cid,CONDITION_ATTRIBUTES,i)
  1763. end
  1764. end
  1765. else
  1766. for i=50,61 do
  1767. doRemoveCondition(cid,CONDITION_ATTRIBUTES,i)
  1768. end
  1769. end
  1770.  
  1771. return true
  1772. end
  1773.  
  1774. function loadSet(cid)
  1775. local t = {}
  1776. for slot=1,9 do
  1777. t[slot] = ''
  1778. local s = getPlayerSlotItem(cid,slot).uid
  1779. if s ~= 0 then
  1780. t[slot] = Item(s):getAttribute(ITEM_ATTRIBUTE_DESCRIPTION)
  1781. end
  1782. end
  1783. return t
  1784. end
  1785.  
  1786. function chk(cid,f)
  1787. if not isPlayer(cid) then return false end
  1788. local t = loadSet(cid)
  1789. for i=1,#f do
  1790. if f[i] ~= t[i] then
  1791. stat_load(cid)
  1792. break
  1793. end
  1794. end
  1795. addEvent(chk,2000,cid,t)
  1796. end
  1797.  
  1798. function stat_onLogin(player)
  1799. if STATS_SYSTEM_CONFIG.combatStats then
  1800. player:registerEvent("statHP")
  1801. player:registerEvent("statMP")
  1802. end
  1803.  
  1804. if STATS_SYSTEM_CONFIG.PVEStat then
  1805. player:registerEvent("statPVE")
  1806. end
  1807.  
  1808. if STATS_SYSTEM_CONFIG.monsterLoot or STATS_SYSTEM_CONFIG.xpStat or STATS_SYSTEM_CONFIG.lootStat then
  1809. player:registerEvent("statLoot")
  1810. end
  1811.  
  1812. if STATS_SYSTEM_CONFIG.conditionStats then
  1813. local cid = player:getId()
  1814. stat_load(cid)
  1815. addEvent(chk,2000,cid,loadSet(cid))
  1816. end
  1817. return true
  1818. end
  1819.  
  1820. function stat_onPrepareDeath(creature, lastHitKiller, mostDamageKiller)
  1821. local necklace = creature:getSlotItem(CONST_SLOT_NECKLACE)
  1822.  
  1823. if not Player(lastHitKiller) then
  1824. if necklace then
  1825. local slotc = necklace:getStatSlotCount()
  1826. if slotc > 0 then
  1827. local cur_slots = necklace:getStatSlots()
  1828. for i = 1, slotc do
  1829. if cur_slots[i][1] == 'PVE death' then
  1830. if cur_slots[i][2]:match("%%") then
  1831. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  1832. if math.random(1, 100) > tonumber(a..b) then
  1833. necklace:remove()
  1834. return true
  1835. end
  1836. end
  1837. local maxhp = creature:getMaxHealth()
  1838. creature:addHealth(maxhp)
  1839. addEvent(doCreatureAddHealth, 100, creature:getId(), maxhp)
  1840. creature:teleportTo(creature:getTown():getTemplePosition())
  1841. necklace:remove()
  1842. return true
  1843. end
  1844. end
  1845. end
  1846. end
  1847. end
  1848. return true
  1849. end
  1850.  
  1851. function stat_onTargetCombat(self, target)
  1852. if STATS_SYSTEM_CONFIG.combatStats then
  1853. if Player(self) then
  1854. target:registerEvent("statHP")
  1855. target:registerEvent("statDeath")
  1856. end
  1857. end
  1858. return true
  1859. end
  1860.  
  1861. function assign_loot_Stat(c)
  1862. local wp_string = {"", ""}
  1863. local arm_string = {"", ""}
  1864. local other_string = {"", ""}
  1865. local rares = 0
  1866. local h = c:getItemHoldingCount()
  1867. if h > 0 then
  1868. for i = 1, h do
  1869. wp_string = {"", ""}
  1870. arm_string = {"", ""}
  1871. other_string = {"", ""}
  1872. local it_u = c:getItem(i - 1)
  1873. local u = it_u:getUpgradeType()
  1874. local upgrade = true
  1875. local it_id = ItemType(it_u:getId())
  1876. local slotc = 0
  1877.  
  1878. if not isInArray(STATS_SYSTEM_CONFIG.ignoredIds, it_u:getId()) then
  1879. if it_u:isContainer() then
  1880. local crares = assign_loot_Stat(it_u)
  1881. rares = rares + crares
  1882. upgrade = false
  1883. else
  1884. if it_id:isStackable() then
  1885. upgrade = false
  1886. end
  1887.  
  1888. if u then
  1889. local atr = it_u:getDescription():match('%((.+)%)')
  1890. if atr and magic_words then
  1891. if #magic_words > 0 then
  1892. for j = 1, #magic_words do
  1893. if atr:match(magic_words[j]) then
  1894. if not STATS_SYSTEM_CONFIG.upgradeMagicItems then
  1895. upgrade = false
  1896. end
  1897. end
  1898. end
  1899. end
  1900. end
  1901. end
  1902. end
  1903.  
  1904. if u and upgrade then
  1905. for n = 1, #STATS_SYSTEM_CONFIG.slotChances do
  1906. if math.random(1, 100000) <= STATS_SYSTEM_CONFIG.slotChances[n] then
  1907. if slotc + 1 == n then
  1908. local stat = math.random(1, #u)
  1909. local level = math.random(1, STATS_SYSTEM_CONFIG.maxLevel)
  1910. local spellname = u[stat][1]
  1911. local spelltype = 0
  1912. local available_spell_types = {}
  1913. local statdone = false
  1914. for k = 1, #STATS_SYSTEM_CONFIG.STATS do
  1915. if not statdone then
  1916. if STATS_SYSTEM_CONFIG.STATS[k].name == spellname then
  1917. if STATS_SYSTEM_CONFIG.STATS[k].enabledValues then
  1918. table.insert(available_spell_types, SPELL_TYPE_VALUE)
  1919. end
  1920.  
  1921. if STATS_SYSTEM_CONFIG.STATS[k].enabledPercent then
  1922. table.insert(available_spell_types, SPELL_TYPE_PERCENT)
  1923. end
  1924.  
  1925. if #available_spell_types > 0 then
  1926. spelltype = available_spell_types[math.random(1, #available_spell_types)]
  1927. end
  1928.  
  1929. wp_string = (STATS_SYSTEM_CONFIG.STATS[k].weaponLootName or wp_string)
  1930. arm_string = (STATS_SYSTEM_CONFIG.STATS[k].armorLootName or arm_string)
  1931. other_string = (STATS_SYSTEM_CONFIG.STATS[k].otherLootName or other_string)
  1932.  
  1933. statdone = true
  1934. end
  1935. end
  1936. end
  1937.  
  1938. if spelltype == 0 then
  1939. upgrade = false
  1940. end
  1941.  
  1942. local spellattr = nil
  1943. for l = 1, #STATS_SYSTEM_CONFIG.STATS do
  1944. if not spellattr then
  1945. if STATS_SYSTEM_CONFIG.STATS[l].name == spellname then
  1946. spellattr = STATS_SYSTEM_CONFIG.STATS[l]
  1947. end
  1948. end
  1949. end
  1950.  
  1951. if not spellattr then
  1952. upgrade = false
  1953. end
  1954.  
  1955. if upgrade then
  1956. local prc = (level * 100/STATS_SYSTEM_CONFIG.maxLevel)/100
  1957. local attrval = 0
  1958. local attrstr = ""
  1959.  
  1960. if spelltype == SPELL_TYPE_VALUE then
  1961. attrval = math.floor(prc * u[stat][2])
  1962. elseif spelltype == SPELL_TYPE_PERCENT then
  1963. attrval = math.floor(prc * u[stat][3])
  1964. attrstr = "%"
  1965. end
  1966.  
  1967. if attrval == 0 then
  1968. upgrade = false
  1969. end
  1970.  
  1971. local slotcx = it_u:getStatSlotCount()
  1972. if slotcx == STATS_SYSTEM_CONFIG.maxSlotCount and upgrade then
  1973. upgrade = false
  1974. end
  1975.  
  1976. if upgrade then
  1977. local cur_slots = it_u:getStatSlots()
  1978. for m = 1, slotcx do
  1979. if spellname == cur_slots[m][1] then
  1980. upgrade = false
  1981. end
  1982. end
  1983. end
  1984.  
  1985. if upgrade then
  1986. if it_u:addStat(spellname, attrval, attrstr) then
  1987. it_u:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
  1988. rares = rares + 1
  1989. slotc = slotc + 1
  1990. end
  1991. end
  1992. end
  1993. end
  1994. end
  1995. end
  1996. local uid = it_u:getUniqueId()
  1997. if slotc > 1 then
  1998. it_u:setAttribute(ITEM_ATTRIBUTE_NAME, (STATS_SYSTEM_CONFIG.tiers[slotc] .. " " or "") .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME))
  1999. elseif slotc == 1 then
  2000. local wp = it_id:getWeaponType()
  2001. if wp > 0 then
  2002. if wp == WEAPON_SHIELD then
  2003. it_u:setAttribute(ITEM_ATTRIBUTE_NAME, (arm_string[1] ~= "" and arm_string[1] .. " " or "") .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME) .. (arm_string[2] ~= "" and " " .. arm_string[2] or ""))
  2004. elseif isInArray({WEAPON_SWORD, WEAPON_CLUB, WEAPON_AXE, WEAPON_DISTANCE, WEAPON_WAND}, wp) then -- weapon
  2005. it_u:setAttribute(ITEM_ATTRIBUTE_NAME, ((wp_string[1] ~= "" and wp_string[1] .. " " or "") .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME) .. (wp_string[2] ~= "" and " " .. wp_string[2] or "")))
  2006. end
  2007. else
  2008. if it_id:getArmor() > 0 then -- armor
  2009. it_u:setAttribute(ITEM_ATTRIBUTE_NAME, ((arm_string[1] ~= "" and arm_string[1] .. " " or "") .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME) .. (arm_string[2] ~= "" and " " .. arm_string[2] or "")))
  2010. else
  2011. it_u:setAttribute(ITEM_ATTRIBUTE_NAME, ((other_string[1] ~= "" and other_string[1] .. " " or "") .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME) .. (other_string[2] ~= "" and " " .. other_string[2] or "")))
  2012. end
  2013. end
  2014. end
  2015. end
  2016. end
  2017.  
  2018. if STATS_SYSTEM_CONFIG.rare_loot_level then
  2019. if not it_id:isStackable() then
  2020. if it_id:getTransformEquipId() < 1 then
  2021. if it_id:getCharges() < 1 then
  2022. local item_sp_slot = it_id:getSlotPosition() - SLOTP_LEFT - SLOTP_RIGHT
  2023. if item_sp_slot ~= SLOTP_NECKLACE and item_sp_slot ~= SLOTP_RING then
  2024. local stat_min = 1
  2025. if STATS_SYSTEM_CONFIG.rare_negative_level then
  2026. stat_min = STATS_SYSTEM_CONFIG.rare_min_level
  2027. end
  2028.  
  2029. local stat_max = #STATS_SYSTEM_CONFIG.weapon_levels
  2030. local it_lvl = math.random(stat_min, stat_max)
  2031.  
  2032. if STATS_SYSTEM_CONFIG.weapon_levels[it_lvl] then
  2033. if math.random(1, 100000) <= STATS_SYSTEM_CONFIG.weapon_levels[it_lvl][2] then
  2034. for o = 1, #upgradable_stats do
  2035. local n_item_stat = upgradable_stats[o][2](it_id)
  2036. if n_item_stat ~= 0 then
  2037. it_u:setAttribute(upgradable_stats[o][1], n_item_stat + (upgradable_stats[o][3] * it_lvl))
  2038. end
  2039. end
  2040.  
  2041. local uid = it_u:getUniqueId()
  2042. if slotc == 0 then
  2043. it_u:setAttribute(ITEM_ATTRIBUTE_NAME, STATS_SYSTEM_CONFIG.weapon_levels[it_lvl][1] .. " " .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME))
  2044. end
  2045. it_u:setAttribute(ITEM_ATTRIBUTE_NAME, getItemAttribute(uid, ITEM_ATTRIBUTE_NAME) .. " " .. (it_lvl > 0 and "+" or "") .. it_lvl)
  2046.  
  2047. if it_lvl > 0 then
  2048. rares = rares + 1
  2049. end
  2050. end
  2051. end
  2052. end
  2053. end
  2054. end
  2055. end
  2056. end
  2057. end
  2058. end
  2059. return rares
  2060. end
  2061.  
  2062. function improveChance(c, monsterName, extraPercent, killer)
  2063. local m = MonsterType(monsterName):getLoot()
  2064. if math.random(1, 100) <= extraPercent then
  2065. local t = {}
  2066. for i = 1, #m do
  2067. t[i] = {itemId = m[i].itemId, chance = m[i].chance}
  2068. end
  2069.  
  2070. local min = 1
  2071. local t_s = {}
  2072. local low5 = #t-5
  2073. while #t > low5 do
  2074. min = 1
  2075. for i = 1, #t do
  2076. if math.min(t[i].chance, t[min].chance) == t[i].chance then
  2077. min = i
  2078. end
  2079. end
  2080. t_s[#t_s + 1] = {itemId = t[min].itemId, chance = t[min].chance}
  2081. table.remove(t, min)
  2082. end
  2083.  
  2084. local chosenId = math.random(1, #t_s)
  2085.  
  2086. local h = c:getItemHoldingCount()
  2087. if h > 0 then
  2088. local extra = true
  2089. for i = 1, h do
  2090. if ItemType(c:getItem(i - 1):getId()) == t_s[chosenId].itemId then
  2091. extra = false
  2092. break
  2093. end
  2094. end
  2095.  
  2096. if extra then
  2097. if math.random(1, 100000) <= (t_s[chosenId].chance + (t_s[chosenId].chance * extraPercent / 100)) * configManager.getNumber(configKeys.RATE_LOOT) then
  2098. c:addItem(m[chosenId].itemId, 1)
  2099. if killer then
  2100. local iid = ItemType(m[chosenId].itemId)
  2101. Player(killer):sendTextMessage(MESSAGE_EVENT_ADVANCE, "Extra loot: " .. (iid:getArticle() ~= "" and iid:getArticle() .. " " or "") .. iid:getName())
  2102. end
  2103. end
  2104. end
  2105. end
  2106. end
  2107. return true
  2108. end
  2109.  
  2110. function improveStackables(c, v)
  2111. local h = c:getItemHoldingCount()
  2112. if h > 0 then
  2113. for i = 1, h do
  2114. local it_u = c:getItem(i - 1)
  2115. --local it_id = ItemType(it_u) --not working with isStackable
  2116. local it_id = it_u:getType()
  2117.  
  2118. if it_id:isStackable() then
  2119. local amount = math.random(0, v)
  2120. if amount > 0 then
  2121. c:addItem(it_u:getId(), amount)
  2122. end
  2123. elseif it_u:isContainer() then
  2124. improveStackables(it_u, v)
  2125. end
  2126. end
  2127. end
  2128. return true
  2129. end
  2130.  
  2131. function find_loot_Container(pos, extraPercent, monsterName, extraStackable, killer)
  2132. local rares = 0
  2133. local c = Tile(pos):getTopDownItem()
  2134. if c ~= nil then
  2135. if c:isContainer() then
  2136. if STATS_SYSTEM_CONFIG.monsterLoot then
  2137. rares = rares + assign_loot_Stat(c)
  2138. end
  2139.  
  2140. if rares > 0 then
  2141. if STATS_SYSTEM_CONFIG.rare_popup then
  2142. local spectators = Game.getSpectators(pos, false, true, 7, 7, 5, 5)
  2143. for i = 1, #spectators do
  2144. spectators[i]:say(STATS_SYSTEM_CONFIG.rare_text, TALKTYPE_MONSTER_SAY, false, spectators[i], pos)
  2145. end
  2146. end
  2147.  
  2148. if STATS_SYSTEM_CONFIG.rare_effect then
  2149. pos:sendMagicEffect(STATS_SYSTEM_CONFIG.rare_effect_id)
  2150. end
  2151. end
  2152.  
  2153. if extraPercent then
  2154. if extraPercent > 0 then
  2155. if monsterName then
  2156. improveChance(c, monsterName, extraPercent, killer)
  2157. end
  2158. end
  2159. end
  2160.  
  2161. if extraStackable then
  2162. if extraStackable > 0 then
  2163. improveStackables(c, extraStackable)
  2164. end
  2165. end
  2166. end
  2167. end
  2168. end
  2169.  
  2170. function Creature:isSummon()
  2171. return self:getMaster()
  2172. end
  2173.  
  2174. function stat_onKill(player, target, lastHit)
  2175. local extraPercent = 0
  2176. local extraStackable = 0
  2177.  
  2178. if target:isMonster() then
  2179. local ring = player:getSlotItem(CONST_SLOT_RING)
  2180. local monster = MonsterType(target:getName())
  2181. if ring then
  2182. local slotc = ring:getStatSlotCount()
  2183. local cur_slots = ring:getStatSlots()
  2184. if slotc > 0 then
  2185. for i = 1, slotc do
  2186. if cur_slots[i][1] == 'exp' and STATS_SYSTEM_CONFIG.xpStat then
  2187. local nexp = monster:getExperience()
  2188. local k = getRateFromTable(experienceStages, player:getLevel(), configManager.getNumber(configKeys.RATE_EXP))
  2189. local st = player:getStamina()
  2190. if st > 2400 then
  2191. nexp = nexp * k*1.5
  2192. elseif st < 1 then
  2193. nexp = 0
  2194. elseif st < 841 then
  2195. nexp = math.floor(nexp/2)
  2196. else
  2197. nexp = nexp
  2198. end
  2199.  
  2200. if cur_slots[i][2]:match("%%") then
  2201. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  2202. player:addExperience(math.ceil((nexp * tonumber(a..b)) / 100), true)
  2203. else
  2204. player:addExperience(math.random(1, tonumber(cur_slots[i][2])), true)
  2205. end
  2206. elseif cur_slots[i][1] == 'loot' and STATS_SYSTEM_CONFIG.lootStat then
  2207. if cur_slots[i][2]:match("%%") then
  2208. local a, b = cur_slots[i][2]:match('([+-])(%d+)%%')
  2209. extraPercent = extraPercent + tonumber(a..b)
  2210. else
  2211. extraStackable = extraStackable + tonumber(cur_slots[i][2])
  2212. end
  2213. end
  2214. end
  2215. end
  2216. end
  2217. end
  2218.  
  2219. if not STATS_SYSTEM_CONFIG.lootUpgradedItems then
  2220. return true
  2221. end
  2222.  
  2223. if target:isPlayer() or target:isSummon() then
  2224. return true
  2225. end
  2226.  
  2227. addEvent(find_loot_Container, 2, target:getPosition(), extraPercent, target:getName(), extraStackable, player:getId())
  2228. return true
  2229. end
  2230.  
  2231. function Item:removeSlot(slotid)
  2232. if not tonumber(slotid) then slotid = 0 end
  2233. local slots = self:getStatSlotCount()
  2234. if slotid == 0 then
  2235. slotid = slots
  2236. end
  2237. local first_desc = self:getAttribute(ITEM_ATTRIBUTE_DESCRIPTION)
  2238. local slot_t = self:getStatSlots()
  2239. --print("Item Upgrade; Total slots: " .. slots .. " , current slotid: " .. slotid .. ".")
  2240. self:removeAttribute(ITEM_ATTRIBUTE_DESCRIPTION)
  2241. for i = 1, slots do
  2242. -- i slot number
  2243. --print("Item Upgrade; slot name: " .. slot_t[i][1] .. " " .. slot_t[i][2])
  2244. if i == slotid then -- its the slot to remove
  2245. local spellname = slot_t[i][1]
  2246. if isInArray({'charges', 'time', 'atk', 'def', 'extra def', 'arm', 'accuracy', 'range'}, spellname) then
  2247. local enchantGain
  2248. local lvlItem
  2249. lvlItem = self:getLevel()
  2250. local basestats = self:getBaseStatsInfo()
  2251. local basestats2 = {
  2252. ['charges'] = basestats.charges,
  2253. ['time'] = basestats.duration,
  2254. ['atk'] = basestats.attack,
  2255. ['def'] = basestats.defense,
  2256. ['extra def'] = basestats.extraDefense,
  2257. ['arm'] = basestats.armor,
  2258. ['accuracy'] = basestats.hitChance,
  2259. ['range'] = basestats.shootRange
  2260. }
  2261.  
  2262. local gainstats = {
  2263. ['atk'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.atk,
  2264. ['def'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.def,
  2265. ['extra def'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.extradef,
  2266. ['arm'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.arm,
  2267. ['accuracy'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.hitchance,
  2268. ['range'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.shootrange,
  2269. }
  2270.  
  2271. local uid = self:getUniqueId()
  2272. local fullstats = {
  2273. ['charges'] = getItemAttribute(uid, ITEM_ATTRIBUTE_CHARGES),
  2274. ['time'] = self:getBaseDuration(),
  2275. ['atk'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACK),
  2276. ['def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_DEFENSE),
  2277. ['extra def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_EXTRADEFENSE),
  2278. ['arm'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ARMOR),
  2279. ['accuracy'] = getItemAttribute(uid, ITEM_ATTRIBUTE_HITCHANCE),
  2280. ['range'] = getItemAttribute(uid, ITEM_ATTRIBUTE_SHOOTRANGE)
  2281. }
  2282.  
  2283.  
  2284.  
  2285. if slot_t[i][2]:match("%%") then
  2286. local a, b = slot_t[i][2]:match('([+-])(%d+)%%')
  2287. --print (a .. b)
  2288. enchantGain = math.abs(math.floor((basestats2[spellname] * tonumber(a..b)/100)))
  2289. --mathstatgainItem = basestatsItem.attack + (lvlupGain * lvlItem) + enchantGain
  2290. self:setAttribute(attrkeys[spellname], basestats2[spellname] + (gainstats[spellname] * lvlItem))
  2291. --self:setAttribute(attrkeys[spellname], fullstats[spellname] - math.abs(math.floor((basestats2[spellname] * tonumber(a..b)/100))))
  2292. else
  2293. enchantGain = slot_t[i][2]
  2294. --mathatkItem = basestatsItem.attack + (gainstats[spellname] * lvlItem) + enchantGain
  2295. self:setAttribute(attrkeys[spellname], basestats2[spellname] + (gainstats[spellname] * lvlItem))
  2296. --self:setAttribute(attrkeys[spellname], fullstats[spellname] - tonumber(slot_t[i][2]))
  2297. end
  2298. end
  2299. --print("Item Upgrade; (removeslot) slot removed. slot: " .. slot_t[i][1] .. " " .. slot_t[i][2])
  2300. else -- its not the slot to remove
  2301. local spellname = slot_t[i][1]
  2302. if isInArray({'charges', 'time', 'atk', 'def', 'extra def', 'arm', 'accuracy', 'range'}, spellname) then
  2303. local enchantGain
  2304. local lvlItem
  2305. lvlItem = self:getLevel()
  2306. local basestats = self:getBaseStatsInfo()
  2307. local basestats2 = {
  2308. ['charges'] = basestats.charges,
  2309. ['time'] = basestats.duration,
  2310. ['atk'] = basestats.attack,
  2311. ['def'] = basestats.defense,
  2312. ['extra def'] = basestats.extraDefense,
  2313. ['arm'] = basestats.armor,
  2314. ['accuracy'] = basestats.hitChance,
  2315. ['range'] = basestats.shootRange
  2316. }
  2317.  
  2318. local gainstats = {
  2319. ['atk'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.atk,
  2320. ['def'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.def,
  2321. ['extra def'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.extradef,
  2322. ['arm'] =STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.arm,
  2323. ['accuracy'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.hitchance,
  2324. ['range'] = STATS_SYSTEM_CONFIG.UPGRADE_STATS_VALUES_PER_LVL.shootrange
  2325. }
  2326.  
  2327. local uid = self:getUniqueId()
  2328. local fullstats = {
  2329. ['charges'] = getItemAttribute(uid, ITEM_ATTRIBUTE_CHARGES),
  2330. ['time'] = self:getBaseDuration(),
  2331. ['atk'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACK),
  2332. ['def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_DEFENSE),
  2333. ['extra def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_EXTRADEFENSE),
  2334. ['arm'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ARMOR),
  2335. ['accuracy'] = getItemAttribute(uid, ITEM_ATTRIBUTE_HITCHANCE),
  2336. ['range'] = getItemAttribute(uid, ITEM_ATTRIBUTE_SHOOTRANGE)
  2337. }
  2338.  
  2339.  
  2340.  
  2341. if slot_t[i][2]:match("%%") then
  2342. local a, b = slot_t[i][2]:match('([+-])(%d+)%%')
  2343. --print (a .. b)
  2344. enchantGain = math.abs(math.floor((basestats2[spellname] * tonumber(a..b)/100)))
  2345. --mathstatgainItem = basestatsItem.attack + (lvlupGain * lvlItem) + enchantGain
  2346. self:setAttribute(attrkeys[spellname], basestats2[spellname] + (gainstats[spellname] * lvlItem) + enchantGain)
  2347. --self:setAttribute(attrkeys[spellname], fullstats[spellname] - math.abs(math.floor((basestats2[spellname] * tonumber(a..b)/100))))
  2348. else
  2349. enchantGain = slot_t[i][2]
  2350. --mathatkItem = basestatsItem.attack + (gainstats[spellname] * lvlItem) + enchantGain
  2351. self:setAttribute(attrkeys[spellname], basestats2[spellname] + (gainstats[spellname] * lvlItem) + enchantGain)
  2352. --self:setAttribute(attrkeys[spellname], fullstats[spellname] - tonumber(slot_t[i][2]))
  2353. end
  2354. end
  2355.  
  2356.  
  2357.  
  2358. --print("Item Upgrade; " "slot_t i: " .. slot_t[i][1])
  2359.  
  2360. if slot_t[i][2]:match("%%") then
  2361. local a, b = slot_t[i][2]:match('([+-])(%d+)%%')
  2362. self:addSlot(slot_t[i][1], tonumber(a..b), true)
  2363. else
  2364. self:addSlot(slot_t[i][1], tonumber(slot_t[i][2]), false)
  2365. end
  2366. --print("Item Upgrade; (removeslot) slot added. slot: " .. slot_t[i][1] .. " " .. slot_t[i][2])
  2367. end
  2368.  
  2369. end
  2370. return true
  2371. end
  2372.  
  2373. function Item:clearUpgrades()
  2374. local slots = self:getStatSlotCount()
  2375. local slotstodo = slots
  2376. if slots > 0 then
  2377. while slotstodo ~= 0 do
  2378. self:removeSlot(slotstodo)
  2379. slotstodo = slotstodo - 1
  2380. end
  2381.  
  2382. end
  2383.  
  2384. self:removeAttribute(ITEM_ATTRIBUTE_DESCRIPTION)
  2385. self:removeAttribute(ITEM_ATTRIBUTE_NAME)
  2386. self:removeAttribute(ITEM_ATTRIBUTE_ARTICLE)
  2387. self:removeAttribute(ITEM_ATTRIBUTE_PLURALNAME)
  2388. self:removeAttribute(ITEM_ATTRIBUTE_ATTACK)
  2389. self:removeAttribute(ITEM_ATTRIBUTE_DEFENSE)
  2390. self:removeAttribute(ITEM_ATTRIBUTE_EXTRADEFENSE)
  2391. self:removeAttribute(ITEM_ATTRIBUTE_ARMOR)
  2392. self:removeAttribute(ITEM_ATTRIBUTE_HITCHANCE)
  2393. self:removeAttribute(ITEM_ATTRIBUTE_SHOOTRANGE)
  2394. self:removeAttribute(ITEM_ATTRIBUTE_DURATION)
  2395. self:removeAttribute(ITEM_ATTRIBUTE_CHARGES)
  2396. return true
  2397. end
  2398.  
  2399. function Item:addLevel(change)
  2400. if not self then return false end
  2401. if not change then return false end
  2402.  
  2403. local it_id = self:getType()
  2404.  
  2405. if not it_id then return false end
  2406. if it_id:isStackable()then return false end
  2407.  
  2408. if it_id:getTransformEquipId() < 1 then
  2409. if it_id:getCharges() < 1 then
  2410. local item_sp_slot = it_id:getSlotPosition() - SLOTP_LEFT - SLOTP_RIGHT
  2411. if item_sp_slot ~= SLOTP_NECKLACE and item_sp_slot ~= SLOTP_RING then
  2412. local exu = self:getUniqueId()
  2413. local stat_lvl = self:getLevel()
  2414. if not stat_lvl then stat_lvl = 0 end
  2415.  
  2416. local it_name = self:getName()
  2417. if stat_lvl > 0 then
  2418. it_name = getItemAttribute(exu, ITEM_ATTRIBUTE_NAME):split("+")[1]
  2419. elseif stat_lvl < 0 then
  2420. it_name = getItemAttribute(exu, ITEM_ATTRIBUTE_NAME):split("-")[1]
  2421. end
  2422.  
  2423. it_name = it_name:gsub("^%s*(.-)%s*$", "%1")
  2424. for i = 1, #upgradable_stats do
  2425. local n_item_stat = upgradable_stats[i][2](it_id)
  2426. self:setAttribute(upgradable_stats[i][1], getItemAttribute(exu, upgradable_stats[i][1], true) + (upgradable_stats[i][3] * change))
  2427. end
  2428.  
  2429. self:setActionId(101)
  2430. self:setAttribute(ITEM_ATTRIBUTE_NAME, it_name .. (change + stat_lvl ~= 0 and (" " .. (change + stat_lvl > 0 and "+" or "") .. change + stat_lvl) or ""))
  2431. return true
  2432. end
  2433. end
  2434. end
  2435. return false
  2436. end
  2437.  
  2438. function Item:getLevel()
  2439. if not self then return nil end
  2440. local uid = self:getUniqueId()
  2441. return tonumber(getItemAttribute(uid, ITEM_ATTRIBUTE_NAME):match("%s%+%d+") or getItemAttribute(uid, ITEM_ATTRIBUTE_NAME):match("%s%-%d+")) or 0
  2442. end
  2443.  
  2444. function Item:setLevel(level)
  2445. self:addLevel(level - self:getLevel())
  2446. return true
  2447. end
  2448.  
  2449. STATSLOT_TYPE_NORMAL = 1
  2450. STATSLOT_TYPE_PERCENT = 2
  2451.  
  2452. function Item:generateTier(slots)
  2453. --[[
  2454. example slots: {
  2455. {'fire', '5', STATSLOT_TYPE_PERCENT},
  2456. {'ice', '20', STATSLOT_TYPE_NORMAL}
  2457. }
  2458. ]]
  2459. if not self then return false end
  2460. if not slots then return false end
  2461. local fslotc = 0
  2462.  
  2463. self:clearUpgrades()
  2464. local slotc = #slots
  2465. if slotc > 0 then
  2466. local upgrade = true
  2467. for i = 1, slotc do
  2468. local spellname = slots[i][1]
  2469. local spelltype = 0
  2470. local available_spell_types = {}
  2471. upgrade = true
  2472.  
  2473. for k = 1, #STATS_SYSTEM_CONFIG.STATS do
  2474. if STATS_SYSTEM_CONFIG.STATS[k].name == spellname then
  2475. if STATS_SYSTEM_CONFIG.STATS[k].enabledValues and slots[i][3] == STATSLOT_TYPE_NORMAL then
  2476. spelltype = SPELL_TYPE_VALUE
  2477. elseif STATS_SYSTEM_CONFIG.STATS[k].enabledPercent and slots[i][3] == STATSLOT_TYPE_PERCENT then
  2478. spelltype = SPELL_TYPE_PERCENT
  2479. end
  2480. wp_string = (STATS_SYSTEM_CONFIG.STATS[k].weaponLootName or "")
  2481. arm_string = (STATS_SYSTEM_CONFIG.STATS[k].armorLootName or "")
  2482. other_string = (STATS_SYSTEM_CONFIG.STATS[k].otherLootName or "")
  2483. end
  2484. end
  2485.  
  2486. if spelltype == 0 then
  2487. upgrade = false
  2488. end
  2489.  
  2490. local spellattr = nil
  2491. for l = 1, #STATS_SYSTEM_CONFIG.STATS do
  2492. if not spellattr then
  2493. if STATS_SYSTEM_CONFIG.STATS[l].name == spellname then
  2494. spellattr = STATS_SYSTEM_CONFIG.STATS[l]
  2495. end
  2496. end
  2497. end
  2498.  
  2499. if not spellattr then
  2500. upgrade = false
  2501. end
  2502.  
  2503. if upgrade then
  2504. local attrval = 0
  2505. local attrstr = ""
  2506.  
  2507. attrval = math.floor(slots[i][2])
  2508. if spelltype == SPELL_TYPE_PERCENT then
  2509. attrstr = "%"
  2510. end
  2511.  
  2512. if attrval == 0 then
  2513. upgrade = false
  2514. end
  2515.  
  2516. local slotcx = self:getStatSlotCount()
  2517. if slotcx == STATS_SYSTEM_CONFIG.maxSlotCount and upgrade then
  2518. upgrade = false
  2519. end
  2520.  
  2521. if upgrade then
  2522. local cur_slots = self:getStatSlots()
  2523. for m = 1, slotcx do
  2524. if spellname == cur_slots[m][1] then
  2525. upgrade = false
  2526. end
  2527. end
  2528. end
  2529.  
  2530. if upgrade then
  2531. if self:addStat(spellname, attrval, attrstr) then
  2532. fslotc = fslotc + 1
  2533. end
  2534. end
  2535. end
  2536. end
  2537. end
  2538.  
  2539. if fslotc == 0 then
  2540. return false
  2541. end
  2542.  
  2543. local uid = self:getUniqueId()
  2544. if fslotc > 1 then
  2545. self:setAttribute(ITEM_ATTRIBUTE_NAME, (STATS_SYSTEM_CONFIG.tiers[fslotc] .. " " or "") .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME))
  2546. elseif fslotc == 1 then
  2547. local it_id = self:getType()
  2548. local wp = it_id:getWeaponType()
  2549. if wp > 0 then
  2550. if wp == WEAPON_SHIELD then
  2551. self:setAttribute(ITEM_ATTRIBUTE_NAME, (arm_string[1] ~= "" and arm_string[1] .. " " or "") .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME) .. (arm_string[2] ~= "" and " " .. arm_string[2] or ""))
  2552. elseif isInArray({WEAPON_SWORD, WEAPON_CLUB, WEAPON_AXE, WEAPON_DISTANCE, WEAPON_WAND}, wp) then -- weapon
  2553. self:setAttribute(ITEM_ATTRIBUTE_NAME, ((wp_string[1] ~= "" and wp_string[1] .. " " or "") .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME) .. (wp_string[2] ~= "" and " " .. wp_string[2] or "")))
  2554. end
  2555. else
  2556. if it_id:getArmor() > 0 then -- armor
  2557. self:setAttribute(ITEM_ATTRIBUTE_NAME, ((arm_string[1] ~= "" and arm_string[1] .. " " or "") .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME) .. (arm_string[2] ~= "" and " " .. arm_string[2] or "")))
  2558. else
  2559. self:setAttribute(ITEM_ATTRIBUTE_NAME, ((other_string[1] ~= "" and other_string[1] .. " " or "") .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME) .. (other_string[2] ~= "" and " " .. other_string[2] or "")))
  2560. end
  2561. end
  2562. end
  2563.  
  2564. return true
  2565. end
  2566.  
  2567. function Item:generateLooted(it_lvl, slots)
  2568. if not self then return false end
  2569. if not tonumber(it_lvl) then it_lvl = 0 end
  2570.  
  2571. local it_id = self:getType()
  2572. if it_id:isStackable() then return false end
  2573.  
  2574. self:clearUpgrades()
  2575. local ntier = false
  2576. if slots then
  2577. ntier = self:generateTier(slots)
  2578. end
  2579.  
  2580. if it_id:getTransformEquipId() < 1 then
  2581. if it_id:getCharges() < 1 then
  2582. local item_sp_slot = it_id:getSlotPosition() - SLOTP_LEFT - SLOTP_RIGHT
  2583. if item_sp_slot ~= SLOTP_NECKLACE and item_sp_slot ~= SLOTP_RING then
  2584. if STATS_SYSTEM_CONFIG.weapon_levels[it_lvl] then
  2585. local uid = self:getUniqueId()
  2586. for o = 1, #upgradable_stats do
  2587. local n_item_stat = upgradable_stats[o][2](it_id)
  2588. if n_item_stat ~= 0 then
  2589. self:setAttribute(upgradable_stats[o][1], getItemAttribute(uid, upgradable_stats[o][1], true) + (upgradable_stats[o][3] * it_lvl))
  2590. end
  2591. end
  2592.  
  2593. if not ntier then
  2594. self:setAttribute(ITEM_ATTRIBUTE_NAME, STATS_SYSTEM_CONFIG.weapon_levels[it_lvl][1] .. " " .. getItemAttribute(uid, ITEM_ATTRIBUTE_NAME))
  2595. end
  2596. self:setAttribute(ITEM_ATTRIBUTE_NAME, getItemAttribute(uid, ITEM_ATTRIBUTE_NAME) .. " " .. (it_lvl > 0 and "+" or "") .. it_lvl)
  2597. end
  2598. end
  2599. end
  2600. end
  2601. return true
  2602. end
  2603.  
  2604. function Item:generateStats(slots, slotc, wp_lvl, min_sl, max_sl)
  2605. local t_s = {}
  2606. local level = 0
  2607.  
  2608. if slots and slotc then
  2609. local t = {}
  2610. for i = 1, #slots do
  2611. t[i] = slots[i]
  2612. end
  2613.  
  2614. if slotc > 0 then
  2615. local low5 = #t-5
  2616. while #t_s < slotc do
  2617. local sel = math.random(1, #t)
  2618. t_s[#t_s + 1] = t[sel]
  2619. table.remove(t, sel)
  2620. end
  2621. end
  2622.  
  2623. for i = 1, #t_s do
  2624. if min_sl then
  2625. if max_sl then
  2626. level = math.random(min_sl, max_sl)
  2627. else
  2628. level = min_sl
  2629. end
  2630. end
  2631. local tmp = 1
  2632. if math.random(1, 2) == 2 then tmp = 2 end
  2633. t_s[i] = {t_s[i][1], t_s[i][tmp + 1] * (level /STATS_SYSTEM_CONFIG.maxLevel), tmp}
  2634. end
  2635. end
  2636.  
  2637. self:generateLooted(wp_lvl, t_s)
  2638. return true
  2639. end
  2640.  
  2641. function stat_onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified)
  2642. --[[ -- generateStats example of looting specific item
  2643. if creature:isMonster() then
  2644. local c = Item(corpse)
  2645. local item = c:addItem("sword")
  2646. item:generateStats(item:getUpgradeType(), math.random(0, STATS_SYSTEM_CONFIG.maxSlotCount), math.random(0, 4), 1, STATS_SYSTEM_CONFIG.maxLevel)
  2647. local item2 = c:addItem("plate shield")
  2648. item2:generateStats({
  2649. {'lifedrain', 10, 15},
  2650. {'manadrain', 10, 15},
  2651. {'ice', 10, 15},
  2652. {'holy', 10, 15},
  2653. {'death', 10, 15},
  2654. }, 3, 6, 24)
  2655. end
  2656. ]]
  2657. return true
  2658. end
  2659.  
  2660. --[[ list of functions:
  2661. doItemSetAttribute(uid, key, value) -- 0.4 version of item:setAttribute(key, value)
  2662. doItemEraseAttribute(uid, key) -- 0.4 version of item:removeAttribute(key)
  2663. getItemAttribute(uid, key, force) -- known function from 0.4, force parameter works for items upgraded before
  2664.  
  2665. isWeapon(uid) -- is item a weapon
  2666. isShield(uid) -- is item a shield
  2667. isBow(uid) -- is item a bow
  2668.  
  2669. STATS_SYSTEM_CONFIG.skillFormula(level) -- shows exp for enchanting level
  2670. STATS_SYSTEM_CONFIG.levelUpgradeFormula(level, maxlevel) -- chance to upgrade item level on certain level
  2671.  
  2672. assign_loot_Stat(container) -- applies random stats on items inside this container
  2673. find_loot_Container(pos, extraPercent, monsterName, extraStackable, killer) -- applies random stats event functions on monster corpse
  2674. getEnchantingSkill(tries) -- returns enchanting skill based on amount of tries
  2675. improveChance(container, monsterName, extraPercent, killer) -- increases a chance to loot rare item from monster
  2676. improveStackables(container, value) -- stackables in container will be increased by random amount between 0 and value
  2677.  
  2678. creature:isSummon() -- is creature a summon
  2679.  
  2680. item:getBaseDuration() -- returns current duration or duration of brand-new item
  2681. item:getBaseStatsInfo() -- reads non-modified item stats
  2682. item:getStatSlotCount() -- returns amount of slots assigned to an item
  2683. item:getStatSlots() -- returns slots from item this way:
  2684. {
  2685. [1] = {'fire', '+25%'},
  2686. [2] = {'atk', '-2'},
  2687. }
  2688. item:getUpgradeType() -- returns spells available for item(STATS_SYSTEM_CONFIG.UPGRADE_SPELLS.type)
  2689.  
  2690. item:addLevel(levelchange) -- adds levels to item, works with negative values also
  2691. item:getLevel() -- get item level(+x or -x)
  2692. item:setLevel(level) -- set item level
  2693. item:addSlot(name, value, percent) -- adds slot and applying item attributes where name = spellname, value = spell value, percent = if true it will add % to number value
  2694. item:removeSlot(slotid) -- removes certain slot from item
  2695. item:clearUpgrades() -- removes all upgrades from item
  2696. item:generateTier(slots) -- generates item like it was looted from a monster, example slots:
  2697. {
  2698. {'fire', '5', STATSLOT_TYPE_PERCENT},
  2699. {'ice', '20', STATSLOT_TYPE_NORMAL}
  2700. }
  2701. item:generateLooted(it_lvl, slots) -- calls function above, plus allows you to set a level on item
  2702. item:generateStats(slots, slotc, wp_lvl, min_sl, max_sl) -- more random version of function above, go to stat_onDeath for example of use
  2703.  
  2704. -- functions used by the lib(not intended to be used by other scripts)
  2705. item:addStat(item, spellname, spellvalue, suffix, cid) -- upgrades attributes, doesn't add stat
  2706. item:addStatSlot(spell, value, suffix) -- adds slot one to description, doesn't upgrade attributes
  2707. check_slot(weapon, slot) -- returns value for skill conditions system
  2708. loadSet(cid) -- used by skill conditions system
  2709. chk(cid,slots) -- used by skill conditions system
  2710. stat_regen(cid, itemid, slot, checkid, sid) -- does regeneration, auto-used
  2711. stat_load(cid) -- executed to load player's stats and run other functions
  2712.  
  2713. SPELL_TYPE_VALUE
  2714. SPELL_TYPE_PERCENT
  2715.  
  2716. -- default events (advanced scripters may find calling it in unusual cases useful)
  2717. stat_onUse(player, item, fromPosition, itemEx, toPosition, attempt)
  2718. stat_onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
  2719. stat_onManaChange(creature, attacker, manaChange, origin)
  2720. stat_onLogin(player)
  2721. stat_onPrepareDeath(creature, lastHitKiller, mostDamageKiller)
  2722. stat_onTargetCombat(self, target)
  2723. stat_onKill(player, target, lastHit)
  2724. stat_onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified)
  2725. ]]
Add Comment
Please, Sign In to add comment