Guest User

Untitled

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