Guest User

Untitled

a guest
Mar 3rd, 2019
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 36.06 KB | None | 0 0
  1. -- Internal Use
  2. STONE_SKIN_AMULET = 2197
  3. GOLD_POUNCH = 26377
  4. ITEM_STORE_INBOX = 26052
  5. ITEM_PARCEL = 2595
  6.  
  7. -- No move items with actionID 8000
  8. NOT_MOVEABLE_ACTION = 8000
  9.  
  10. -- Players cannot throw items on teleports if set to true
  11. local blockTeleportTrashing = true
  12.  
  13. local titles = {
  14. {storageID = 14960, title = " Scout"},
  15. {storageID = 14961, title = " Sentinel"},
  16. {storageID = 14962, title = " Steward"},
  17. {storageID = 14963, title = " Warden"},
  18. {storageID = 14964, title = " Squire"},
  19. {storageID = 14965, title = " Warrior"},
  20. {storageID = 14966, title = " Keeper"},
  21. {storageID = 14967, title = " Guardian"},
  22. {storageID = 14968, title = " Sage"},
  23. {storageID = 14969, title = " Tutor"},
  24. {storageID = 14970, title = " Senior Tutor"},
  25. {storageID = 14971, title = " King"},
  26. }
  27.  
  28. local exercise_ids = {31821,31822,31823,31824,31825,31826}
  29.  
  30. local function getTitle(uid)
  31. local player = Player(uid)
  32. if not player then return false end
  33.  
  34. for i = #titles, 1, -1 do
  35. if player:getStorageValue(titles[i].storageID) == 1 then
  36. return titles[i].title
  37. end
  38. end
  39.  
  40. return false
  41. end
  42.  
  43. function Player:onBrowseField(position)
  44. return true
  45. end
  46.  
  47. local function getHours(seconds)
  48. return math.floor((seconds/60)/60)
  49. end
  50.  
  51. local function getMinutes(seconds)
  52. return math.floor(seconds/60)
  53. end
  54.  
  55. local function getSeconds(seconds)
  56. return seconds%60
  57. end
  58.  
  59. local function getTime(seconds)
  60. local hours, minutes = getHours(seconds), getMinutes(seconds)
  61. if (minutes > 59) then
  62. minutes = minutes-hours*60
  63. end
  64.  
  65. if (minutes < 10) then
  66. minutes = "0" ..minutes
  67. end
  68.  
  69. return hours..":"..minutes.. "h"
  70. end
  71.  
  72. local function getTimeinWords(secs)
  73. local hours, minutes, seconds = getHours(secs), getMinutes(secs), getSeconds(secs)
  74. if (minutes > 59) then
  75. minutes = minutes-hours*60
  76. end
  77.  
  78. local timeStr = ''
  79.  
  80. if hours > 0 then
  81. timeStr = timeStr .. ' hours '
  82. end
  83.  
  84. timeStr = timeStr .. minutes .. ' minutes and '.. seconds .. 'seconds.'
  85.  
  86. return timeStr
  87. end
  88.  
  89. function Player:onLook(thing, position, distance)
  90. local description = "You see " .. thing:getDescription(distance)
  91. description = stat_onLook(thing, description)
  92. if thing:isItem() then
  93. if thing.actionid == 5640 then
  94. description = description .. "a honeyflower patch."
  95. elseif thing.actionid == 5641 then
  96. description = description .. "a banana palm."
  97. elseif thing.itemid >= ITEM_HEALTH_CASK_START and thing.itemid <= ITEM_HEALTH_CASK_END
  98. or thing.itemid >= ITEM_MANA_CASK_START and thing.itemid <= ITEM_MANA_CASK_END
  99. or thing.itemid >= ITEM_SPIRIT_CASK_START and thing.itemid <= ITEM_SPIRIT_CASK_END
  100. or thing.itemid >= ITEM_KEG_START and thing.itemid <= ITEM_KEG_END then
  101. description = description .. thing:getDescription(distance)
  102. local charges = thing:getCharges()
  103. if charges then
  104. description = string.format("%s\nIt has %d refillings left.", description, charges)
  105. end
  106. else
  107. end
  108.  
  109. local itemType = thing:getType()
  110. if (itemType and itemType:getImbuingSlots() > 0) then
  111. local imbuingSlots = "Imbuements: ("
  112. for i = 1, itemType:getImbuingSlots() do
  113. local specialAttr = thing:getSpecialAttribute(i)
  114. local time = 0
  115. if (thing:getSpecialAttribute(i+3)) then
  116. time = getTime(thing:getSpecialAttribute(i+3))
  117. end
  118.  
  119. if (specialAttr and specialAttr ~= 0) then
  120. if (i ~= itemType:getImbuingSlots()) then
  121. imbuingSlots = imbuingSlots.. "" ..specialAttr.." " ..time..", "
  122. else
  123. imbuingSlots = imbuingSlots.. "" ..specialAttr.." " ..time..")."
  124. end
  125. else
  126. if (i ~= itemType:getImbuingSlots()) then
  127. imbuingSlots = imbuingSlots.. "Empty Slot, "
  128. else
  129. imbuingSlots = imbuingSlots.. "Empty Slot)."
  130. end
  131. end
  132. end
  133. description = string.gsub(description, "It weighs", imbuingSlots.. "\nIt weighs")
  134. end
  135. else
  136. description = description .. thing:getDescription(distance)
  137. if thing:isMonster() then
  138. local master = thing:getMaster()
  139. if master and table.contains({'thundergiant','grovebeast','emberwing','skullfrost'}, thing:getName():lower()) then
  140. description = description..' (Master: ' .. master:getName() .. '). It will disappear in ' .. getTimeinWords(master:getStorageValue(Storage.PetSummon) - os.time())
  141. end
  142. end
  143. end
  144.  
  145. if self:getGroup():getAccess() then
  146. if thing:isItem() then
  147. description = string.format("%s\nItem ID: %d", description, thing:getId())
  148.  
  149. local actionId = thing:getActionId()
  150. if actionId ~= 0 then
  151. description = string.format("%s, Action ID: %d", description, actionId)
  152. end
  153.  
  154. local uniqueId = thing:getAttribute(ITEM_ATTRIBUTE_UNIQUEID)
  155. if uniqueId > 0 and uniqueId < 65536 then
  156. description = string.format("%s, Unique ID: %d", description, uniqueId)
  157. end
  158.  
  159. local itemType = thing:getType()
  160.  
  161. local transformEquipId = itemType:getTransformEquipId()
  162. local transformDeEquipId = itemType:getTransformDeEquipId()
  163. if transformEquipId ~= 0 then
  164. description = string.format("%s\nTransforms to: %d (onEquip)", description, transformEquipId)
  165. elseif transformDeEquipId ~= 0 then
  166. description = string.format("%s\nTransforms to: %d (onDeEquip)", description, transformDeEquipId)
  167. end
  168.  
  169. local decayId = itemType:getDecayId()
  170. if decayId ~= -1 then
  171. description = string.format("%s\nDecays to: %d", description, decayId)
  172. end
  173. elseif thing:isCreature() then
  174. local str = "%s\nHealth: %d / %d"
  175. if thing:isPlayer() and thing:getMaxMana() > 0 then
  176. str = string.format("%s, Mana: %d / %d", str, thing:getMana(), thing:getMaxMana())
  177. end
  178. description = string.format(str, description, thing:getHealth(), thing:getMaxHealth()) .. "."
  179. end
  180.  
  181. local position = thing:getPosition()
  182. description = string.format(
  183. "%s\nPosition: %d, %d, %d",
  184. description, position.x, position.y, position.z
  185. )
  186.  
  187. if thing:isCreature() then
  188. if thing:isPlayer() then
  189. description = string.format("%s\nIP: %s.", description, Game.convertIpToString(thing:getIp()))
  190. end
  191. end
  192. end
  193. self:sendTextMessage(MESSAGE_INFO_DESCR, description)
  194. end
  195.  
  196. function Player:onLookInTrade(partner, item, distance)
  197. local description = item:getDescription(distance)
  198. description = stat_onLook(item, description)
  199. self:sendTextMessage(MESSAGE_INFO_DESCR, "You see " .. description)
  200. end
  201.  
  202. function Player:onLookInShop(itemType, count)
  203. return true
  204. end
  205.  
  206. local config = {
  207. maxItemsPerSeconds = 1,
  208. exhaustTime = 2000,
  209. }
  210.  
  211. if not pushDelay then
  212. pushDelay = { }
  213. end
  214.  
  215. local function antiPush(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
  216. if toPosition.x == CONTAINER_POSITION then
  217. return true
  218. end
  219.  
  220. local tile = Tile(toPosition)
  221. if not tile then
  222. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  223. return false
  224. end
  225.  
  226. local cid = self:getId()
  227. if not pushDelay[cid] then
  228. pushDelay[cid] = {items = 0, time = 0}
  229. end
  230.  
  231. pushDelay[cid].items = pushDelay[cid].items + 1
  232.  
  233. local currentTime = os.mtime()
  234. if pushDelay[cid].time == 0 then
  235. pushDelay[cid].time = currentTime
  236. elseif pushDelay[cid].time == currentTime then
  237. pushDelay[cid].items = pushDelay[cid].items + 1
  238. elseif currentTime > pushDelay[cid].time then
  239. pushDelay[cid].time = 0
  240. pushDelay[cid].items = 0
  241. end
  242.  
  243. if pushDelay[cid].items > config.maxItemsPerSeconds then
  244. pushDelay[cid].time = currentTime + config.exhaustTime
  245. end
  246.  
  247. if pushDelay[cid].time > currentTime then
  248. self:sendCancelMessage("You can't move that item so fast.")
  249. return false
  250. end
  251.  
  252. return true
  253. end
  254.  
  255. function Player:onMoveItem(item, count, fromPosition, toPosition, fromCylinder, toCylinder)
  256. -- No move if item count > 20 items
  257. local tile = Tile(toPosition)
  258. if tile and tile:getItemCount() > 20 then
  259. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  260. return false
  261. end
  262.  
  263. if isInArray(exercise_ids,item.itemid) then
  264. self:sendCancelMessage('You cannot move this item outside this container.')
  265. return false
  266. end
  267.  
  268. -- SSA exhaust
  269. local exhaust = { }
  270. if toPosition.x == CONTAINER_POSITION and toPosition.y == CONST_SLOT_NECKLACE and item:getId() == STONE_SKIN_AMULET then
  271. local pid = self:getId()
  272. if exhaust[pid] then
  273. self:sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED)
  274. return false
  275. else
  276. exhaust[pid] = true
  277. addEvent(function() exhaust[pid] = false end, 2000, pid)
  278. return true
  279. end
  280. end
  281.  
  282. -- Store Inbox
  283. local containerIdFrom = fromPosition.y - 64
  284. local containerFrom = self:getContainerById(containerIdFrom)
  285. if (containerFrom) then
  286. if (containerFrom:getId() == ITEM_STORE_INBOX and toPosition.y >= 1 and toPosition.y <= 11 and toPosition.y ~= 3) then
  287. self:sendCancelMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM)
  288. return false
  289. end
  290. end
  291.  
  292. local containerTo = self:getContainerById(toPosition.y-64)
  293. if (containerTo) then
  294. if (containerTo:getId() == ITEM_STORE_INBOX) then
  295. self:sendCancelMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM)
  296. return false
  297. end
  298. -- Gold Pounch
  299. if (containerTo:getId() == GOLD_POUNCH) then
  300. if (not (item:getId() == ITEM_CRYSTAL_COIN or item:getId() == ITEM_PLATINUM_COIN or item:getId() == ITEM_GOLD_COIN)) then
  301. self:sendCancelMessage("You can move only money to this container.")
  302. return false
  303. end
  304. end
  305. end
  306.  
  307. -- No move gold pounch
  308. if item:getId() == GOLD_POUNCH then
  309. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  310. return false
  311. end
  312.  
  313. -- No move items with actionID 8000
  314. if item:getActionId() == NOT_MOVEABLE_ACTION then
  315. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  316. return false
  317. end
  318.  
  319. -- Check two-handed weapons
  320. if toPosition.x ~= CONTAINER_POSITION then
  321. return true
  322. end
  323.  
  324. if item:getTopParent() == self and bit.band(toPosition.y, 0x40) == 0 then
  325. local itemType, moveItem = ItemType(item:getId())
  326. if bit.band(itemType:getSlotPosition(), SLOTP_TWO_HAND) ~= 0 and toPosition.y == CONST_SLOT_LEFT then
  327. moveItem = self:getSlotItem(CONST_SLOT_RIGHT)
  328. elseif itemType:getWeaponType() == WEAPON_SHIELD and toPosition.y == CONST_SLOT_RIGHT then
  329. moveItem = self:getSlotItem(CONST_SLOT_LEFT)
  330. if moveItem and bit.band(ItemType(moveItem:getId()):getSlotPosition(), SLOTP_TWO_HAND) == 0 then
  331. return true
  332. end
  333. end
  334.  
  335. if moveItem then
  336. local parent = item:getParent()
  337. if parent:getSize() == parent:getCapacity() then
  338. self:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM))
  339. return false
  340. else
  341. return moveItem:moveTo(parent)
  342. end
  343. end
  344. end
  345.  
  346. -- Reward System
  347. if toPosition.x == CONTAINER_POSITION then
  348. local containerId = toPosition.y - 64
  349. local container = self:getContainerById(containerId)
  350. if not container then
  351. return true
  352. end
  353.  
  354. -- Do not let the player insert items into either the Reward Container or the Reward Chest
  355. local itemId = container:getId()
  356. if itemId == ITEM_REWARD_CONTAINER or itemId == ITEM_REWARD_CHEST then
  357. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  358. return false
  359. end
  360.  
  361. -- The player also shouldn't be able to insert items into the boss corpse
  362. local tile = Tile(container:getPosition())
  363. for _, item in ipairs(tile:getItems() or { }) do
  364. if item:getAttribute(ITEM_ATTRIBUTE_CORPSEOWNER) == 2^31 - 1 and item:getName() == container:getName() then
  365. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  366. return false
  367. end
  368. end
  369. end
  370.  
  371. -- Do not let the player move the boss corpse.
  372. if item:getAttribute(ITEM_ATTRIBUTE_CORPSEOWNER) == 2^31 - 1 then
  373. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  374. return false
  375. end
  376.  
  377. -- Players cannot throw items on reward chest
  378. local tile = Tile(toPosition)
  379. if tile and tile:getItemById(ITEM_REWARD_CHEST) then
  380. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  381. self:getPosition():sendMagicEffect(CONST_ME_POFF)
  382. return false
  383. end
  384.  
  385. -- Players cannot throw items on teleports
  386. if blockTeleportTrashing and toPosition.x ~= CONTAINER_POSITION then
  387. local thing = Tile(toPosition):getItemByType(ITEM_TYPE_TELEPORT)
  388. if thing then
  389. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  390. self:getPosition():sendMagicEffect(CONST_ME_POFF)
  391. return false
  392. end
  393. end
  394.  
  395. -- No move parcel very heavy
  396. if item:getWeight() > 90000 and item:getId() == ITEM_PARCEL then
  397. self:sendCancelMessage('YOU CANNOT MOVE PARCELS TOO HEAVY.')
  398. return false
  399. end
  400.  
  401. if tile and tile:getItemById(370) then -- Trapdoor
  402. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  403. self:getPosition():sendMagicEffect(CONST_ME_POFF)
  404. return false
  405. end
  406.  
  407. --- LIONS ROCK START
  408. if self:getStorageValue(lionrock.storages.playerCanDoTasks) - os.time() < 0 then
  409. local p, i = lionrock.positions, lionrock.items
  410. local checkPr = false
  411. if item:getId() == lionrock.items.ruby and toPosition.x == p.ruby.x and toPosition.y == p.ruby.y and toPosition.z == p.ruby.z then
  412. -- Ruby
  413. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the ruby on the small socket. A red flame begins to burn.")
  414. checkPr = true
  415. if lionrock.taskactive.ruby ~= true then
  416. lionrock.taskactive.ruby = true
  417. end
  418.  
  419. local tile = Tile(p.ruby)
  420. if tile:getItemCountById(i.redflame) < 1 then
  421. Game.createItem(i.redflame, 1, p.ruby)
  422. end
  423. end
  424.  
  425. if item:getId() == lionrock.items.sapphire and toPosition.x == p.sapphire.x and toPosition.y == p.sapphire.y and toPosition.z == p.sapphire.z then
  426. -- Sapphire
  427. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the sapphire on the small socket. A blue flame begins to burn.")
  428. checkPr = true
  429. if lionrock.taskactive.sapphire ~= true then
  430. lionrock.taskactive.sapphire = true
  431. end
  432.  
  433. local tile = Tile(p.sapphire)
  434. if tile:getItemCountById(i.blueflame) < 1 then
  435. Game.createItem(i.blueflame, 1, p.sapphire)
  436. end
  437. end
  438.  
  439. if item:getId() == lionrock.items.amethyst and toPosition.x == p.amethyst.x and toPosition.y == p.amethyst.y and toPosition.z == p.amethyst.z then
  440. -- Amethyst
  441. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the topaz on the small socket. A yellow flame begins to burn.")
  442. checkPr = true
  443. if lionrock.taskactive.amethyst ~= true then
  444. lionrock.taskactive.amethyst = true
  445. end
  446.  
  447. local tile = Tile(p.amethyst)
  448. if tile:getItemCountById(i.yellowflame) < 1 then
  449. Game.createItem(i.yellowflame, 1, p.amethyst)
  450. end
  451. end
  452.  
  453. if item:getId() == lionrock.items.topaz and toPosition.x == p.topaz.x and toPosition.y == p.topaz.y and toPosition.z == p.topaz.z then
  454. -- Topaz
  455. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the amethyst on the small socket. A violet flame begins to burn.")
  456. checkPr = true
  457. if lionrock.taskactive.topaz ~= true then
  458. lionrock.taskactive.topaz = true
  459. end
  460.  
  461. local tile = Tile(p.topaz)
  462. if tile:getItemCountById(i.violetflame) < 1 then
  463. Game.createItem(i.violetflame, 1, p.topaz)
  464. end
  465. end
  466.  
  467. if checkPr == true then
  468. -- Adding the Fountain which gives present
  469. if lionrock.taskactive.ruby == true and lionrock.taskactive.sapphire == true and lionrock.taskactive.amethyst == true and lionrock.taskactive.topaz == true then
  470. local fountain = Game.createItem(i.rewardfountain, 1, { x=33073, y=32300, z=9})
  471. fountain:setActionId(41357)
  472. local stone = Tile({ x=33073, y=32300, z=9}):getItemById(3608)
  473. if stone ~= nil then
  474. stone:remove()
  475. end
  476. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Something happens at the centre of the room ...");
  477. end
  478.  
  479. -- Removing Item
  480. item:remove(1)
  481. end
  482. end
  483. ---- LIONS ROCK END
  484.  
  485. if not antiPush(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder) then
  486. return false
  487. end
  488.  
  489. return true
  490. end
  491.  
  492. function Player:onMoveCreature(creature, fromPosition, toPosition)
  493. return true
  494. end
  495.  
  496. local function hasPendingReport(name, targetName, reportType)
  497. local f = io.open(string.format("data/reports/players/%s-%s-%d.txt", name, targetName, reportType), "r")
  498. if f then
  499. io.close(f)
  500. return true
  501. else
  502. return false
  503. end
  504. end
  505.  
  506. function Player:onReportRuleViolation(targetName, reportType, reportReason, comment, translation)
  507. local name = self:getName()
  508. if hasPendingReport(name, targetName, reportType) then
  509. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your report is being processed.")
  510. return
  511. end
  512.  
  513. local file = io.open(string.format("data/reports/players/%s-%s-%d.txt", name, targetName, reportType), "a")
  514. if not file then
  515. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "There was an error when processing your report, please contact a gamemaster.")
  516. return
  517. end
  518.  
  519. io.output(file)
  520. io.write("------------------------------\n")
  521. io.write("Reported by: " .. name .. "\n")
  522. io.write("Target: " .. targetName .. "\n")
  523. io.write("Type: " .. reportType .. "\n")
  524. io.write("Reason: " .. reportReason .. "\n")
  525. io.write("Comment: " .. comment .. "\n")
  526. if reportType ~= REPORT_TYPE_BOT then
  527. io.write("Translation: " .. translation .. "\n")
  528. end
  529. io.write("------------------------------\n")
  530. io.close(file)
  531. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("Thank you for reporting %s. Your report will be processed by %s team as soon as possible.", targetName, configManager.getString(configKeys.SERVER_NAME)))
  532. return
  533. end
  534.  
  535. function Player:onReportBug(message, position, category)
  536. local name = self:getName()
  537. local file = io.open("data/reports/bugs/" .. name .. " report.txt", "a")
  538.  
  539. if not file then
  540. self:sendTextMessage(MESSAGE_EVENT_DEFAULT, "There was an error when processing your report, please contact a gamemaster.")
  541. return true
  542. end
  543.  
  544. io.output(file)
  545. io.write("------------------------------\n")
  546. io.write("Name: " .. name)
  547. if category == BUG_CATEGORY_MAP then
  548. io.write(" [Map position: " .. position.x .. ", " .. position.y .. ", " .. position.z .. "]")
  549. end
  550. local playerPosition = self:getPosition()
  551. io.write(" [Player Position: " .. playerPosition.x .. ", " .. playerPosition.y .. ", " .. playerPosition.z .. "]\n")
  552. io.write("Comment: " .. message .. "\n")
  553. io.close(file)
  554.  
  555. self:sendTextMessage(MESSAGE_EVENT_DEFAULT, "Your report has been sent to " .. configManager.getString(configKeys.SERVER_NAME) .. ".")
  556. return true
  557. end
  558.  
  559. function Player:onTurn(direction)
  560. if self:getGroup():getAccess() and self:getDirection() == direction then
  561. local nextPosition = self:getPosition()
  562. nextPosition:getNextPosition(direction)
  563.  
  564. self:teleportTo(nextPosition, true)
  565. end
  566.  
  567. return true
  568. end
  569.  
  570. function Player:onTradeRequest(target, item)
  571.  
  572. if isInArray(exercise_ids,item.itemid) then
  573. return false
  574. end
  575.  
  576. return true
  577. end
  578.  
  579. function Player:onTradeAccept(target, item, targetItem)
  580. return true
  581. end
  582.  
  583. local soulCondition = Condition(CONDITION_SOUL, CONDITIONID_DEFAULT)
  584. soulCondition:setTicks(4 * 60 * 1000)
  585. soulCondition:setParameter(CONDITION_PARAM_SOULGAIN, 1)
  586.  
  587. function useStaminaImbuing(playerId, itemuid)
  588. local player = Player(playerId)
  589. if not player then
  590. return false
  591. end
  592.  
  593. local item = Item(itemuid)
  594. if not item then
  595. return false
  596. end
  597.  
  598. for i = 1, item:getType():getImbuingSlots() do
  599. if (item:isActiveImbuement(i+3)) then
  600. local staminaMinutes = item:getSpecialAttribute(i+3)/60
  601. if (staminaMinutes > 0) then
  602. local currentTime = os.time()
  603. local timePassed = currentTime - item:getSpecialAttribute(i+6)
  604. if timePassed > 0 then
  605. if timePassed > 60 then
  606. if staminaMinutes > 2 then
  607. staminaMinutes = staminaMinutes - 2
  608. else
  609. staminaMinutes = 0
  610. end
  611.  
  612. item:setSpecialAttribute(i+6, currentTime + 120)
  613. else
  614. staminaMinutes = staminaMinutes - 1
  615. item:setSpecialAttribute(i+6, currentTime + 60)
  616. end
  617. end
  618.  
  619. item:setSpecialAttribute(i+3, staminaMinutes*60)
  620. if (staminaMinutes <= 0) then
  621. player:removeCondition(CONDITION_HASTE, item:getId() + i)
  622. player:removeCondition(CONDITION_ATTRIBUTES, item:getId() + i)
  623. item:setSpecialAttribute(i, 0, i+3, 0, i+6, 0)
  624. end
  625. end
  626. end
  627. end
  628. end
  629.  
  630. local function useStamina(player)
  631. local staminaMinutes = player:getStamina()
  632. if staminaMinutes == 0 then
  633. return
  634. end
  635.  
  636. local playerId = player:getId()
  637. local currentTime = os.time()
  638. local timePassed = currentTime - nextUseStaminaTime[playerId]
  639. if timePassed <= 0 then
  640. return
  641. end
  642.  
  643. if timePassed > 60 then
  644. if staminaMinutes > 2 then
  645. staminaMinutes = staminaMinutes - 2
  646. else
  647. staminaMinutes = 0
  648. end
  649. nextUseStaminaTime[playerId] = currentTime + 120
  650. else
  651. staminaMinutes = staminaMinutes - 1
  652. nextUseStaminaTime[playerId] = currentTime + 60
  653. end
  654. player:setStamina(staminaMinutes)
  655. end
  656.  
  657. local function useStaminaXp(player)
  658. local staminaMinutes = player:getExpBoostStamina() / 60
  659. if staminaMinutes == 0 then
  660. return
  661. end
  662.  
  663. local playerId = player:getId()
  664. local currentTime = os.time()
  665. local timePassed = currentTime - nextUseXpStamina[playerId]
  666. if timePassed <= 0 then
  667. return
  668. end
  669.  
  670. if timePassed > 60 then
  671. if staminaMinutes > 2 then
  672. staminaMinutes = staminaMinutes - 2
  673. else
  674. staminaMinutes = 0
  675. end
  676. nextUseXpStamina[playerId] = currentTime + 120
  677. else
  678. staminaMinutes = staminaMinutes - 1
  679. nextUseXpStamina[playerId] = currentTime + 60
  680. end
  681. player:setExpBoostStamina(staminaMinutes * 60)
  682. end
  683.  
  684. -- useStaminaPrey
  685. local function useStaminaPrey(player, name)
  686. for i = 1, 3 do
  687. if (player:isActiveByName(i-1, name)) then
  688. local staminaMinutes = player:getPreyStamina(i-1)/60
  689. if (staminaMinutes > 0) then
  690. local playerId = player:getId()+i
  691. local currentTime = os.time()
  692. local timePassed = currentTime - nextUseStaminaPrey[playerId].Time
  693. if timePassed > 0 then
  694. if timePassed > 60 then
  695. if staminaMinutes > 2 then
  696. staminaMinutes = staminaMinutes - 2
  697. else
  698. staminaMinutes = 0
  699. end
  700.  
  701. nextUseStaminaPrey[playerId].Time = currentTime + 120
  702. else
  703. staminaMinutes = staminaMinutes - 1
  704. nextUseStaminaPrey[playerId].Time = currentTime + 60
  705. end
  706. end
  707.  
  708. player:setPreyStamina(i-1, staminaMinutes*60)
  709. player:sendPreyTimeLeft(i-1, staminaMinutes*60)
  710. end
  711. end
  712. end
  713. end
  714.  
  715. function Player:onUseWeapon(normalDamage, elementType, elementDamage)
  716. -- Imbuement
  717. local weapon = self:getSlotItem(CONST_SLOT_LEFT)
  718. if not weapon or weapon:getType():getWeaponType() == WEAPON_SHIELD then
  719. weapon = self:getSlotItem(CONST_SLOT_RIGHT)
  720. if not weapon or weapon:getType():getWeaponType() == WEAPON_SHIELD then
  721. weapon = nil
  722. end
  723. end
  724.  
  725. for slot = 1, 10 do
  726. local nextEquip = self:getSlotItem(slot)
  727. if nextEquip and nextEquip:getType():getImbuingSlots() > 0 then
  728. for i = 1, nextEquip:getType():getImbuingSlots() do
  729. local slotEnchant = nextEquip:getSpecialAttribute(i)
  730. if (slotEnchant and type(slotEnchant) == 'string') then
  731. local percentDamage, enchantPercent = 0, nextEquip:getImbuementPercent(slotEnchant)
  732. local typeEnchant = nextEquip:getImbuementType(i) or ""
  733. if (typeEnchant ~= "" and typeEnchant ~= "skillShield" and not typeEnchant:find("absorb") and typeEnchant ~= "speed") then
  734. useStaminaImbuing(self:getId(), nextEquip:getUniqueId())
  735. end
  736.  
  737. if (typeEnchant ~= "hitpointsleech" and typeEnchant ~= "manapointsleech" and typeEnchant ~= "criticaldamage"
  738. and typeEnchant ~= "skillShield" and typeEnchant ~= "magiclevelpoints" and not typeEnchant:find("absorb") and typeEnchant ~= "speed") then
  739. local weaponType = nextEquip:getType():getWeaponType()
  740. if weaponType ~= WEAPON_NONE and weaponType ~= WEAPON_SHIELD and weaponType ~= WEAPON_AMMO then
  741. percentDamage = normalDamage*(enchantPercent/100)
  742. normalDamage = normalDamage - percentDamage
  743. elementDamage = nextEquip:getType():getAttack()*(enchantPercent/100)
  744. end
  745. end
  746.  
  747. if (typeEnchant == "hitpointsleech") then
  748. local healAmountHP = normalDamage*(enchantPercent/100)
  749. self:addHealth(math.abs(healAmountHP))
  750. elseif (typeEnchant == "manapointsleech") then
  751. local healAmountMP = normalDamage*(enchantPercent/100)
  752. self:addMana(math.abs(healAmountMP))
  753. end
  754.  
  755. if (typeEnchant == "firedamage") then
  756. elementType = COMBAT_FIREDAMAGE
  757. elseif (typeEnchant == "earthdamage") then
  758. elementType = COMBAT_EARTHDAMAGE
  759. elseif (typeEnchant == "icedamage") then
  760. elementType = COMBAT_ICEDAMAGE
  761. elseif (typeEnchant == "energydamage") then
  762. elementType = COMBAT_ENERGYDAMAGE
  763. elseif (typeEnchant == "deathdamage") then
  764. elementType = COMBAT_DEATHDAMAGE
  765. end
  766. end
  767. end
  768. end
  769. end
  770.  
  771. return normalDamage, elementType, elementDamage
  772. end
  773.  
  774. function Player:onCombatSpell(normalDamage, elementDamage, elementType, changeDamage)
  775. -- Imbuement
  776. local weapon = self:getSlotItem(CONST_SLOT_LEFT)
  777. if not weapon or weapon:getType():getWeaponType() == WEAPON_SHIELD then
  778. weapon = self:getSlotItem(CONST_SLOT_RIGHT)
  779. if not weapon or weapon:getType():getWeaponType() == WEAPON_SHIELD then
  780. weapon = nil
  781. end
  782. end
  783.  
  784. if normalDamage < 0 then
  785. for slot = 1, 10 do
  786. local nextEquip = self:getSlotItem(slot)
  787. if nextEquip and nextEquip:getType():getImbuingSlots() > 0 then
  788. for i = 1, nextEquip:getType():getImbuingSlots() do
  789. local slotEnchant = nextEquip:getSpecialAttribute(i)
  790. if (slotEnchant and type(slotEnchant) == 'string') then
  791. local percentDamage, enchantPercent = 0, nextEquip:getImbuementPercent(slotEnchant)
  792. local typeEnchant = nextEquip:getImbuementType(i) or ""
  793. if (typeEnchant ~= "" and typeEnchant ~= "skillShield" and not typeEnchant:find("absorb") and typeEnchant ~= "speed") then
  794. useStaminaImbuing(self:getId(), nextEquip:getUniqueId())
  795. end
  796.  
  797. if (typeEnchant == "firedamage" or typeEnchant == "earthdamage" or typeEnchant == "icedamage" or typeEnchant == "energydamage" or typeEnchant == "deathdamage") then
  798. local weaponType = nextEquip:getType():getWeaponType()
  799. if weaponType ~= WEAPON_NONE and weaponType ~= WEAPON_SHIELD and weaponType ~= WEAPON_AMMO then
  800. percentDamage = normalDamage*(enchantPercent/100)
  801. normalDamage = normalDamage - percentDamage
  802. elementDamage = nextEquip:getType():getAttack()*(enchantPercent/100)
  803. end
  804. end
  805.  
  806. if (typeEnchant == "firedamage") then
  807. elementType = COMBAT_FIREDAMAGE
  808. elseif (typeEnchant == "earthdamage") then
  809. elementType = COMBAT_EARTHDAMAGE
  810. elseif (typeEnchant == "icedamage") then
  811. elementType = COMBAT_ICEDAMAGE
  812. elseif (typeEnchant == "energydamage") then
  813. elementType = COMBAT_ENERGYDAMAGE
  814. elseif (typeEnchant == "deathdamage") then
  815. elementType = COMBAT_DEATHDAMAGE
  816. end
  817. end
  818. end
  819. end
  820. end
  821. end
  822.  
  823. return normalDamage, elementDamage, elementType, changeDamage
  824. end
  825.  
  826. function Player:onMove()
  827. local haveImbuingBoots = self:getSlotItem(CONST_SLOT_FEET) and self:getSlotItem(CONST_SLOT_FEET):getType():getImbuingSlots() or 0
  828. if haveImbuingBoots > 0 then
  829. local bootsItem = self:getSlotItem(CONST_SLOT_FEET)
  830. for slot = 1, haveImbuingBoots do
  831. local slotEnchant = bootsItem:getSpecialAttribute(slot)
  832. if (slotEnchant and type(slotEnchant) == 'string') then
  833. local typeEnchant = bootsItem:getImbuementType(slot) or ""
  834. if (typeEnchant == "speed") then
  835. useStaminaImbuing(self:getId(), bootsItem:getUniqueId())
  836. end
  837. end
  838. end
  839. end
  840. return true
  841. end
  842.  
  843. function Player:onEquipImbuement(item)
  844. local itemType = item:getType()
  845. for i = 1, itemType:getImbuingSlots() do
  846. local slotEnchant = item:getSpecialAttribute(i)
  847. if (slotEnchant and type(slotEnchant) == 'string') then
  848. conditionHaste = Condition(CONDITION_HASTE, item:getId() + i)
  849. conditionSkill = Condition(CONDITION_ATTRIBUTES, item:getId() + i)
  850. local skillValue = item:getImbuementPercent(slotEnchant)
  851. local typeEnchant = item:getImbuementType(i) or ""
  852. if (typeEnchant == "skillSword") then
  853. conditionSkill:setParameter(CONDITION_PARAM_TICKS, -1)
  854. conditionSkill:setParameter(CONDITION_PARAM_SKILL_SWORD, skillValue)
  855. self:addCondition(conditionSkill)
  856. elseif (typeEnchant == "skillAxe") then
  857. conditionSkill:setParameter(CONDITION_PARAM_TICKS, -1)
  858. conditionSkill:setParameter(CONDITION_PARAM_SKILL_AXE, skillValue)
  859. self:addCondition(conditionSkill)
  860. elseif (typeEnchant == "skillClub") then
  861. conditionSkill:setParameter(CONDITION_PARAM_TICKS, -1)
  862. conditionSkill:setParameter(CONDITION_PARAM_SKILL_CLUB, skillValue)
  863. self:addCondition(conditionSkill)
  864. elseif (typeEnchant == "skillDist") then
  865. conditionSkill:setParameter(CONDITION_PARAM_TICKS, -1)
  866. conditionSkill:setParameter(CONDITION_PARAM_SKILL_DISTANCE, skillValue)
  867. self:addCondition(conditionSkill)
  868. elseif (typeEnchant == "skillShield") then
  869. conditionSkill:setParameter(CONDITION_PARAM_TICKS, -1)
  870. conditionSkill:setParameter(CONDITION_PARAM_SKILL_SHIELD, skillValue)
  871. self:addCondition(conditionSkill)
  872. elseif (typeEnchant == "magiclevelpoints") then
  873. conditionSkill:setParameter(CONDITION_PARAM_TICKS, -1)
  874. conditionSkill:setParameter(CONDITION_PARAM_STAT_MAGICPOINTS, skillValue)
  875. self:addCondition(conditionSkill)
  876. elseif (typeEnchant == "speed") then
  877. conditionHaste:setParameter(CONDITION_PARAM_TICKS, -1)
  878. conditionHaste:setParameter(CONDITION_PARAM_SPEED, self:getSpeed() * (skillValue/100))
  879. self:addCondition(conditionHaste)
  880. elseif (typeEnchant == "criticaldamage") then
  881. conditionSkill:setParameter(CONDITION_PARAM_TICKS, -1)
  882. conditionSkill:setParameter(CONDITION_PARAM_SKILL_CRITICAL_HIT_CHANCE, 10)
  883. conditionSkill:setParameter(CONDITION_PARAM_SKILL_CRITICAL_HIT_DAMAGE, skillValue)
  884. self:addCondition(conditionSkill)
  885. elseif (typeEnchant == "hitpointsleech") then
  886. conditionSkill:setParameter(CONDITION_PARAM_TICKS, -1)
  887. conditionSkill:setParameter(CONDITION_PARAM_SKILL_LIFE_LEECH_CHANCE, 100)
  888. conditionSkill:setParameter(CONDITION_PARAM_SKILL_LIFE_LEECH_AMOUNT, skillValue)
  889. self:addCondition(conditionSkill)
  890. elseif (typeEnchant == "manapointsleech") then
  891. conditionSkill:setParameter(CONDITION_PARAM_TICKS, -1)
  892. conditionSkill:setParameter(CONDITION_PARAM_SKILL_MANA_LEECH_CHANCE, 100)
  893. conditionSkill:setParameter(CONDITION_PARAM_SKILL_MANA_LEECH_AMOUNT, skillValue)
  894. self:addCondition(conditionSkill)
  895. end
  896. end
  897. end
  898.  
  899. return true
  900. end
  901.  
  902. function Player:onDeEquipImbuement(item)
  903. for i = 1, item:getType():getImbuingSlots() do
  904. self:removeCondition(CONDITION_HASTE, item:getId() + i)
  905. self:removeCondition(CONDITION_ATTRIBUTES, item:getId() + i)
  906. end
  907.  
  908. return true
  909. end
  910.  
  911. function Player:onGainExperience(source, exp, rawExp)
  912. if not source or source:isPlayer() then
  913. return exp
  914. end
  915.  
  916. -- Soul regeneration
  917. local vocation = self:getVocation()
  918. if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then
  919. soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000)
  920. self:addCondition(soulCondition)
  921. end
  922.  
  923. -- Apply experience stage multiplier
  924. exp = exp * Game.getExperienceStage(self:getLevel())
  925. for i = 1, 3 do
  926. if (self:isActive(i-1)) then
  927. local bonusInfo = self:getBonusInfo(i-1)
  928. if (bonusInfo.Type == 2 and source:getName() == bonusInfo.Name) then
  929. exp = exp + math.floor(exp * (bonusInfo.Value/100))
  930. break
  931. end
  932. end
  933. end
  934.  
  935. if (self:getExpBoostStamina() <= 0 and self:getStoreXpBoost() > 0) then
  936. self:setStoreXpBoost(0) -- reset xp boost to 0
  937. end
  938.  
  939. -- More compact, after checking before (reset) it only of xp if you have
  940. if (self:getStoreXpBoost() > 0) then
  941. exp = exp + (exp * (self:getStoreXpBoost()/100)) -- Exp Boost
  942. end
  943.  
  944. local party = self:getParty()
  945. if (party) then
  946. if (party:isSharedExperienceActive() and
  947. party:isSharedExperienceEnabled()) then
  948. local tableVocs = {}
  949. local count = 0
  950. local totalCount = 0
  951. local leaderId = party:getLeader():getVocation():getId()
  952. if (leaderId) then
  953. tableVocs[leaderId] = 1
  954. count = count + 1
  955. totalCount = totalCount + 1
  956. end
  957. for i, v in pairs(party:getMembers()) do
  958. local vocId = v:getVocation():getId()
  959. if (tableVocs[vocId] == nil) then
  960. tableVocs[vocId] = 1
  961. count = count + 1
  962. end
  963. totalCount = totalCount + 1
  964. end
  965.  
  966. if (totalCount <= 10 and
  967. count >= 4) then
  968. exp = exp * 2
  969. end
  970. end
  971. end
  972.  
  973. -- Prey Stamina Modifier
  974. useStaminaPrey(self, source:getName())
  975.  
  976. -- Exp Boost Modifier
  977. useStaminaXp(self)
  978.  
  979. -- Exp stats
  980. local staminaMinutes = self:getStamina()
  981. local Boost = self:getExpBoostStamina()
  982. if staminaMinutes > 2400 and self:isPremium() and Boost > 0 then
  983. self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*2) -- 200 = 1.0x, 200 = 2.0x, ... premium account
  984. elseif staminaMinutes > 2400 and self:isPremium() and Boost <= 0 then
  985. self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*1.5) -- 150 = 1.0x, 150 = 1.5x, ... premium account
  986. elseif staminaMinutes <= 2400 and staminaMinutes > 840 and self:isPremium() and Boost > 0 then
  987. self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*1.5) -- 150 = 1.5x premium account
  988. elseif staminaMinutes > 840 and Boost > 0 then
  989. self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*1.5) -- 150 = 1.5x free account
  990. elseif staminaMinutes <= 840 and Boost > 0 then
  991. self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*1) -- 50 = 0.5x all players
  992. elseif staminaMinutes <= 840 then
  993. self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*0.5) -- 50 = 0.5x all players
  994. end
  995.  
  996. -- Stamina modifier
  997. if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
  998. useStamina(self)
  999.  
  1000. local staminaMinutes = self:getStamina()
  1001. if staminaMinutes > 2400 and self:isPremium() then
  1002. exp = exp * 1.5
  1003. elseif staminaMinutes <= 840 then
  1004. exp = exp * 0.5
  1005. end
  1006. end
  1007.  
  1008. return exp
  1009. end
  1010.  
  1011. function Player:onLoseExperience(exp)
  1012. return exp
  1013. end
  1014.  
  1015. function Player:onGainSkillTries(skill, tries)
  1016. if APPLY_SKILL_MULTIPLIER == false then
  1017. return tries
  1018. end
  1019.  
  1020. if skill == SKILL_MAGLEVEL then
  1021. return tries * configManager.getNumber(configKeys.RATE_MAGIC)
  1022. end
  1023. return tries * configManager.getNumber(configKeys.RATE_SKILL)
  1024. end
  1025.  
  1026. function Player:getCustomSkill(storage)
  1027. return self:getStorageValue(storage)
  1028. end
  1029. function Player:addCustomSkill(skillName, storage)
  1030. local skillStorage = math.max(10, self:getStorageValue(storage))
  1031. local skillTries = math.max(0, self:getStorageValue(storage + 1))
  1032. self:setStorageValue(storage, skillStorage + 1)
  1033. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You advanced to " .. string.lower(skillName) .. " level "..self:getCustomSkill(storage)..".")
  1034. self:setStorageValue(storage + 1, 0)
  1035. end
  1036. function Player:addCustomSkillTry(skillName, storage)
  1037. local skillStorage = math.max(10, self:getStorageValue(storage))
  1038. local skillTries = math.max(0, self:getStorageValue(storage + 1))
  1039. self:setStorageValue(storage + 1, skillTries + 1)
  1040. if skillTries > math.floor(20 * math.pow(1.1, (skillStorage - 11)) / 10) then
  1041. self:addCustomSkill(skillName, storage)
  1042. end
  1043. end
  1044. function Player:getCustomSkillPercent(storage)
  1045. local skillStorage = math.max(10, self:getStorageValue(storage))
  1046. local skillTries = math.max(0, self:getStorageValue(storage + 1))
  1047. local triesNeeded = math.floor(20 * math.pow(1.1, (skillStorage - 11)) / 10)
  1048. local percent = math.floor(100 * (1 - skillTries / triesNeeded))
  1049. if percent > 1 and percent <= 100 then
  1050. return percent
  1051. else
  1052. percent = 1
  1053. return percent
  1054. end
  1055. end
Add Comment
Please, Sign In to add comment