Guest User

Untitled

a guest
Feb 16th, 2021
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.56 KB | None | 0 0
  1. -- Internal Use
  2. STONE_SKIN_AMULET = 2197
  3. GOLD_POUCH = 26377
  4. ITEM_STORE_INBOX = 26052
  5.  
  6. DISABLE_CONTAINER_WEIGHT = 0 -- 0 = ENABLE CONTAINER WEIGHT CHECK | 1 = DISABLE CONTAINER WEIGHT CHECK
  7. CONTAINER_WEIGHT = 1000000 -- 1000000 = 10k = 10000.00 oz | this function is only for containers, item below the weight determined here can be moved inside the container, for others items look game.cpp at the src
  8.  
  9. -- Items sold on the store that should not be moved off the store container
  10. local storeItemID = {32124,32125,32126,32127,32128,32129,32109,33299,26378,29020,32109,35172,35173,35174,35175,35176,35177,35178,35179,35180}
  11.  
  12. -- No move/trade items with actionID 8000
  13. BLOCK_ITEM_WITH_ACTION = 8000
  14.  
  15. -- Capacity imbuement store
  16. local STORAGE_CAPACITY_IMBUEMENT = 42154
  17.  
  18. -- Players cannot throw items on teleports if set to true
  19. local blockTeleportTrashing = true
  20.  
  21. local titles = {
  22. {storageID = 14960, title = " Scout"},
  23. {storageID = 14961, title = " Sentinel"},
  24. {storageID = 14962, title = " Steward"},
  25. {storageID = 14963, title = " Warden"},
  26. {storageID = 14964, title = " Squire"},
  27. {storageID = 14965, title = " Warrior"},
  28. {storageID = 14966, title = " Keeper"},
  29. {storageID = 14967, title = " Guardian"},
  30. {storageID = 14968, title = " Sage"},
  31. {storageID = 14969, title = " Tutor"},
  32. {storageID = 14970, title = " Senior Tutor"},
  33. {storageID = 14971, title = " King"},
  34. }
  35.  
  36. local function getTitle(uid)
  37. local player = Player(uid)
  38. if not player then return false end
  39.  
  40. for i = #titles, 1, -1 do
  41. if player:getStorageValue(titles[i].storageID) == 1 then
  42. return titles[i].title
  43. end
  44. end
  45.  
  46. return false
  47. end
  48.  
  49. function Player:onBrowseField(position)
  50. return true
  51. end
  52.  
  53. local function getHours(seconds)
  54. return math.floor((seconds/60)/60)
  55. end
  56.  
  57. local function getMinutes(seconds)
  58. return math.floor(seconds/60)
  59. end
  60.  
  61. local function getSeconds(seconds)
  62. return seconds%60
  63. end
  64.  
  65. local function getTime(seconds)
  66. local hours, minutes = getHours(seconds), getMinutes(seconds)
  67. if (minutes > 59) then
  68. minutes = minutes-hours*60
  69. end
  70.  
  71. if (minutes < 10) then
  72. minutes = "0" ..minutes
  73. end
  74.  
  75. return hours..":"..minutes.. "h"
  76. end
  77.  
  78. local function getTimeinWords(secs)
  79. local hours, minutes, seconds = getHours(secs), getMinutes(secs), getSeconds(secs)
  80. if (minutes > 59) then
  81. minutes = minutes-hours*60
  82. end
  83.  
  84. local timeStr = ''
  85.  
  86. if hours > 0 then
  87. timeStr = timeStr .. ' hours '
  88. end
  89.  
  90. timeStr = timeStr .. minutes .. ' minutes and '.. seconds .. 'seconds.'
  91.  
  92. return timeStr
  93. end
  94.  
  95. function Player:onLook(thing, position, distance)
  96. local description = "You see "
  97. if thing:isItem() then
  98. if thing.actionid == 5640 then
  99. description = description .. "a honeyflower patch."
  100. elseif thing.actionid == 5641 then
  101. description = description .. "a banana palm."
  102. elseif thing.itemid >= ITEM_HEALTH_CASK_START and thing.itemid <= ITEM_HEALTH_CASK_END
  103. or thing.itemid >= ITEM_MANA_CASK_START and thing.itemid <= ITEM_MANA_CASK_END
  104. or thing.itemid >= ITEM_SPIRIT_CASK_START and thing.itemid <= ITEM_SPIRIT_CASK_END
  105. or thing.itemid >= ITEM_KEG_START and thing.itemid <= ITEM_KEG_END then
  106. description = description .. thing:getDescription(distance)
  107. local charges = thing:getCharges()
  108. if charges then
  109. description = string.format("%s\nIt has %d refillings left.", description, charges)
  110. end
  111. else
  112. description = description .. thing:getDescription(distance)
  113. end
  114.  
  115. local itemType = thing:getType()
  116. if (itemType and itemType:getImbuingSlots() > 0) then
  117. local imbuingSlots = "Imbuements: ("
  118. for slot = 0, itemType:getImbuingSlots() - 1 do
  119. if slot > 0 then
  120. imbuingSlots = string.format("%s, ", imbuingSlots)
  121. end
  122. local duration = thing:getImbuementDuration(slot)
  123. if duration > 0 then
  124. local imbue = thing:getImbuement(slot)
  125. imbuingSlots = string.format("%s%s %s %s", imbuingSlots, imbue:getBase().name, imbue:getName(), getTime(duration))
  126. else
  127. imbuingSlots = string.format("%sEmpty Slot", imbuingSlots)
  128. end
  129. end
  130. imbuingSlots = string.format("%s).", imbuingSlots)
  131. description = string.gsub(description, "It weighs", imbuingSlots.. "\nIt weighs")
  132. end
  133. else
  134. description = description .. thing:getDescription(distance)
  135. if thing:isMonster() then
  136. local master = thing:getMaster()
  137. if master and table.contains({'thundergiant','grovebeast','emberwing','skullfrost'}, thing:getName():lower()) then
  138. description = description..' (Master: ' .. master:getName() .. '). It will disappear in ' .. getTimeinWords(master:getStorageValue(Storage.PetSummon) - os.time())
  139. end
  140. end
  141. end
  142.  
  143. if self:getGroup():getAccess() then
  144. if thing:isItem() then
  145. description = string.format("%s\nItem ID: %d", description, thing:getId())
  146.  
  147. local actionId = thing:getActionId()
  148. if actionId ~= 0 then
  149. description = string.format("%s, Action ID: %d", description, actionId)
  150. end
  151.  
  152. local uniqueId = thing:getAttribute(ITEM_ATTRIBUTE_UNIQUEID)
  153. if uniqueId > 0 and uniqueId < 65536 then
  154. description = string.format("%s, Unique ID: %d", description, uniqueId)
  155. end
  156.  
  157. if thing:isContainer() then
  158. local quickLootCategories = {}
  159. local container = Container(thing.uid)
  160. for categoryId = LOOT_START, LOOT_END do
  161. if container:hasQuickLootCategory(categoryId) then
  162. table.insert(quickLootCategories, categoryId)
  163. end
  164. end
  165.  
  166. description = string.format("%s, QuickLootCategory: (%s)", description, table.concat(quickLootCategories, ", "))
  167. end
  168.  
  169. local itemType = thing:getType()
  170.  
  171. local transformEquipId = itemType:getTransformEquipId()
  172. local transformDeEquipId = itemType:getTransformDeEquipId()
  173. if transformEquipId ~= 0 then
  174. description = string.format("%s\nTransforms to: %d (onEquip)", description, transformEquipId)
  175. elseif transformDeEquipId ~= 0 then
  176. description = string.format("%s\nTransforms to: %d (onDeEquip)", description, transformDeEquipId)
  177. end
  178.  
  179. local decayId = itemType:getDecayId()
  180. if decayId ~= -1 then
  181. description = string.format("%s\nDecays to: %d", description, decayId)
  182. end
  183. elseif thing:isCreature() then
  184. local str = "%s\nHealth: %d / %d"
  185. if thing:isPlayer() and thing:getMaxMana() > 0 then
  186. str = string.format("%s, Mana: %d / %d", str, thing:getMana(), thing:getMaxMana())
  187. end
  188. description = string.format(str, description, thing:getHealth(), thing:getMaxHealth()) .. "."
  189. end
  190.  
  191. local position = thing:getPosition()
  192. description = string.format(
  193. "%s\nPosition: %d, %d, %d",
  194. description, position.x, position.y, position.z
  195. )
  196.  
  197. if thing:isCreature() then
  198. if thing:isPlayer() then
  199. description = string.format("%s\nIP: %s.", description, Game.convertIpToString(thing:getIp()))
  200. end
  201. end
  202. end
  203. self:sendTextMessage(MESSAGE_INFO_DESCR, description)
  204. end
  205.  
  206. function Player:onLookInBattleList(creature, distance)
  207. local description = "You see " .. creature:getDescription(distance)
  208. if creature:isMonster() then
  209. local master = creature:getMaster()
  210. if master and table.contains({'thundergiant','grovebeast','emberwing','skullfrost'}, creature:getName():lower()) then
  211. description = description..' (Master: ' .. master:getName() .. '). It will disappear in ' .. getTimeinWords(master:getStorageValue(Storage.PetSummon) - os.time())
  212. end
  213. end
  214. if self:getGroup():getAccess() then
  215. local str = "%s\nHealth: %d / %d"
  216. if creature:isPlayer() and creature:getMaxMana() > 0 then
  217. str = string.format("%s, Mana: %d / %d", str, creature:getMana(), creature:getMaxMana())
  218. end
  219. description = string.format(str, description, creature:getHealth(), creature:getMaxHealth()) .. "."
  220.  
  221. local position = creature:getPosition()
  222. description = string.format(
  223. "%s\nPosition: %d, %d, %d",
  224. description, position.x, position.y, position.z
  225. )
  226.  
  227. if creature:isPlayer() then
  228. description = string.format("%s\nIP: %s", description, Game.convertIpToString(creature:getIp()))
  229. end
  230. end
  231. self:sendTextMessage(MESSAGE_INFO_DESCR, description)
  232. end
  233.  
  234. function Player:onLookInTrade(partner, item, distance)
  235. self:sendTextMessage(MESSAGE_INFO_DESCR, "You see " .. item:getDescription(distance))
  236. end
  237.  
  238. function Player:onLookInShop(itemType, count)
  239. return true
  240. end
  241.  
  242. local config = {
  243. maxItemsPerSeconds = 1,
  244. exhaustTime = 2000,
  245. }
  246.  
  247. if not pushDelay then
  248. pushDelay = { }
  249. end
  250.  
  251. local function antiPush(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
  252. if toPosition.x == CONTAINER_POSITION then
  253. return true
  254. end
  255.  
  256. local tile = Tile(toPosition)
  257. if not tile then
  258. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  259. return false
  260. end
  261.  
  262. local cid = self:getId()
  263. if not pushDelay[cid] then
  264. pushDelay[cid] = {items = 0, time = 0}
  265. end
  266.  
  267. pushDelay[cid].items = pushDelay[cid].items + 1
  268.  
  269. local currentTime = os.mtime()
  270. if pushDelay[cid].time == 0 then
  271. pushDelay[cid].time = currentTime
  272. elseif pushDelay[cid].time == currentTime then
  273. pushDelay[cid].items = pushDelay[cid].items + 1
  274. elseif currentTime > pushDelay[cid].time then
  275. pushDelay[cid].time = 0
  276. pushDelay[cid].items = 0
  277. end
  278.  
  279. if pushDelay[cid].items > config.maxItemsPerSeconds then
  280. pushDelay[cid].time = currentTime + config.exhaustTime
  281. end
  282.  
  283. if pushDelay[cid].time > currentTime then
  284. self:sendCancelMessage("You can't move that item so fast.")
  285. return false
  286. end
  287.  
  288. return true
  289. end
  290.  
  291. function Player:onMoveItem(item, count, fromPosition, toPosition, fromCylinder, toCylinder)
  292. -- No move items with actionID = 8000
  293. if item:getActionId() == BLOCK_ITEM_WITH_ACTION then
  294. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  295. return false
  296. end
  297. -- Store Items
  298. if isInArray(storeItemID,item.itemid) then
  299. self:sendCancelMessage('You cannot move this item outside this container.')
  300. return false
  301. end
  302. -- No move if item count > 20 items
  303. local tile = Tile(toPosition)
  304. if tile and tile:getItemCount() > 20 then
  305. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  306. return false
  307. end
  308.  
  309. -- No move parcel very heavy
  310. if DISABLE_CONTAINER_WEIGHT == 0 and ItemType(item:getId()):isContainer() and item:getWeight() > CONTAINER_WEIGHT then
  311. self:sendCancelMessage("Your cannot move this item too heavy.")
  312. return false
  313. end
  314.  
  315. -- Loot Analyser apenas 11.x+
  316. if self:getClient().os == CLIENTOS_NEW_WINDOWS then
  317. local t = Tile(fromCylinder:getPosition())
  318. local corpse = t:getTopDownItem()
  319. if corpse then
  320. local itemType = corpse:getType()
  321. if itemType:isCorpse() and toPosition.x == CONTAINER_POSITION then
  322. self:sendLootStats(item)
  323. end
  324. end
  325. end
  326.  
  327. -- Cults of Tibia begin
  328. local frompos = Position(33023, 31904, 14) -- Checagem
  329. local topos = Position(33052, 31932, 15) -- Checagem
  330. if self:getPosition():isInRange(frompos, topos) and item:getId() == 26397 then
  331. local tileBoss = Tile(toPosition)
  332. if tileBoss and tileBoss:getTopCreature() and tileBoss:getTopCreature():isMonster() then
  333. if tileBoss:getTopCreature():getName():lower() == 'the remorseless corruptor' then
  334. tileBoss:getTopCreature():addHealth(-17000)
  335. item:remove(1)
  336. if tileBoss:getTopCreature():getHealth() <= 300 then
  337. tileBoss:getTopCreature():remove()
  338. local monster = Game.createMonster('the corruptor of souls', toPosition)
  339. monster:registerEvent('checkPiso')
  340. if Game.getStorageValue('healthSoul') > 0 then
  341. monster:addHealth(-(monster:getHealth() - Game.getStorageValue('healthSoul')))
  342. end
  343. Game.setStorageValue('checkPiso', os.time()+30)
  344. end
  345. elseif tileBoss:getTopCreature():getName():lower() == 'the corruptor of souls' then
  346. Game.setStorageValue('checkPiso', os.time()+30)
  347. item:remove(1)
  348. end
  349. end
  350. end
  351. -- Cults of Tibia end
  352.  
  353. --- LIONS ROCK START
  354. if self:getStorageValue(lionrock.storages.playerCanDoTasks) - os.time() < 0 then
  355. local p, i = lionrock.positions, lionrock.items
  356. local checkPr = false
  357. if item:getId() == 2147 and toPosition.x == 33069 and toPosition.y == 32298 and toPosition.z == 9 then
  358. -- Ruby
  359. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the ruby on the small socket. A red flame begins to burn.")
  360. checkPr = true
  361. if lionrock.taskactive.ruby ~= true then
  362. lionrock.taskactive.ruby = true
  363. end
  364.  
  365. local item = Tile(Position(33069, 32298, 9))
  366. if (item:getItemCountById(1488) > 0) then
  367. local flameruby = Game.createItem(1488, 1, Position(33069, 32298, 9))
  368. end
  369. end
  370.  
  371. if item:getId() == 2146 and toPosition.x == 33069 and toPosition.y == 32302 and toPosition.z == 9 then
  372. -- Sapphire
  373. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the sapphire on the small socket. A blue flame begins to burn.")
  374. checkPr = true
  375. if lionrock.taskactive.sapphire ~= true then
  376. lionrock.taskactive.sapphire = true
  377. end
  378.  
  379. local item = Tile(Position(33069, 32302, 9))
  380. if (item:getItemCountById(8058) > 0) then
  381. local flamesapphire = Game.createItem(8058, 1, Position(33069, 32302, 9))
  382. end
  383. end
  384.  
  385. if item:getId() == 2150 and toPosition.x == 33077 and toPosition.y == 32302 and toPosition.z == 9 then
  386. -- Amethyst
  387. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the amethyst on the small socket. A violet flame begins to burn.")
  388. checkPr = true
  389. if lionrock.taskactive.amethyst ~= true then
  390. lionrock.taskactive.amethyst = true
  391. end
  392.  
  393. local item = Tile(Position(33077, 32302, 9))
  394. if (item:getItemCountById(1500) > 0) then
  395. local flameamethyst = Game.createItem(1500, 1, Position(33077, 32302, 9))
  396. end
  397. end
  398.  
  399. if item:getId() == 9970 and toPosition.x == 33077 and toPosition.y == 32298 and toPosition.z == 9 then
  400. -- Topaz
  401. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the topaz on the small socket. A yellow flame begins to burn.")
  402. checkPr = true
  403. if lionrock.taskactive.topaz ~= true then
  404. lionrock.taskactive.topaz = true
  405. end
  406.  
  407. local item = Tile(Position(33077, 32298, 9))
  408. if (item:getItemCountById(7473) > 0) then
  409. local flametopaz = Game.createItem(7473, 1, Position(33077, 32298, 9))
  410. end
  411. end
  412.  
  413. if checkPr == true then
  414. -- Adding the Fountain which gives present
  415. if lionrock.taskactive.ruby == true and lionrock.taskactive.sapphire == true and lionrock.taskactive.amethyst == true and lionrock.taskactive.topaz == true then
  416. local fountain = Game.createItem(6390, 1, Position(33073, 32300, 9))
  417. fountain:setActionId(41357)
  418. local stone = Tile(Position(33073, 32300, 9)):getItemById(3608)
  419. if stone ~= nil then
  420. stone:remove()
  421. end
  422. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Something happens at the centre of the room ...");
  423. end
  424.  
  425. -- Removing Item
  426. item:remove(1)
  427. end
  428. end
  429. ---- LIONS ROCK END
  430.  
  431. -- SSA exhaust
  432. local exhaust = { }
  433. if toPosition.x == CONTAINER_POSITION and toPosition.y == CONST_SLOT_NECKLACE and item:getId() == STONE_SKIN_AMULET then
  434. local pid = self:getId()
  435. if exhaust[pid] then
  436. self:sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED)
  437. return false
  438. else
  439. exhaust[pid] = true
  440. addEvent(function() exhaust[pid] = false end, 2000, pid)
  441. return true
  442. end
  443. end
  444.  
  445. -- Store Inbox
  446. local containerIdFrom = fromPosition.y - 64
  447. local containerFrom = self:getContainerById(containerIdFrom)
  448. if (containerFrom) then
  449. if (containerFrom:getId() == ITEM_STORE_INBOX and toPosition.y >= 1 and toPosition.y <= 11 and toPosition.y ~= 3) then
  450. self:sendCancelMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM)
  451. return false
  452. end
  453. end
  454.  
  455. local containerTo = self:getContainerById(toPosition.y-64)
  456. if (containerTo) then
  457. if (containerTo:getId() == ITEM_STORE_INBOX) then
  458. self:sendCancelMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM)
  459. return false
  460. end
  461. if ItemType(containerTo:getId()):isCorpse() and ItemType(item.itemid):isCorpse() then
  462. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  463. print(''..self:getName()..' moveu corpo dentro de corpo')
  464. return false
  465. end
  466. -- Gold Pouch
  467. if (containerTo:getId() == GOLD_POUCH) then
  468. if (not (item:getId() == ITEM_CRYSTAL_COIN or item:getId() == ITEM_PLATINUM_COIN or item:getId() == ITEM_GOLD_COIN)) then
  469. self:sendCancelMessage("You can move only money to this container.")
  470. return false
  471. end
  472. end
  473. end
  474.  
  475. -- No move gold pouch
  476. if item:getId() == GOLD_POUCH then
  477. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  478. return false
  479. end
  480.  
  481. -- Check two-handed weapons
  482. if toPosition.x ~= CONTAINER_POSITION then
  483. if item:isContainer() then
  484. local container = Container(item.uid)
  485. for categoryId = LOOT_START, LOOT_END do
  486. if container:hasQuickLootCategory(categoryId) then
  487. container:removeQuickLootCategory(categoryId)
  488. self:setQuickLootBackpack(categoryId, nil)
  489. end
  490. end
  491. end
  492. return true
  493. end
  494.  
  495. if item:getTopParent() == self and bit.band(toPosition.y, 0x40) == 0 then
  496. local itemType, moveItem = ItemType(item:getId())
  497. if bit.band(itemType:getSlotPosition(), SLOTP_TWO_HAND) ~= 0 and toPosition.y == CONST_SLOT_LEFT then
  498. moveItem = self:getSlotItem(CONST_SLOT_RIGHT)
  499. elseif itemType:getWeaponType() == WEAPON_SHIELD and toPosition.y == CONST_SLOT_RIGHT then
  500. moveItem = self:getSlotItem(CONST_SLOT_LEFT)
  501. if moveItem and bit.band(ItemType(moveItem:getId()):getSlotPosition(), SLOTP_TWO_HAND) == 0 then
  502. return true
  503. end
  504. end
  505.  
  506. if moveItem then
  507. local parent = item:getParent()
  508. if parent:getSize() == parent:getCapacity() then
  509. self:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM))
  510. return false
  511. else
  512. return moveItem:moveTo(parent)
  513. end
  514. end
  515. end
  516.  
  517. -- Reward System
  518. if toPosition.x == CONTAINER_POSITION then
  519. local containerId = toPosition.y - 64
  520. local container = self:getContainerById(containerId)
  521. if not container then
  522. return true
  523. end
  524.  
  525. -- Do not let the player insert items into either the Reward Container or the Reward Chest
  526. local itemId = container:getId()
  527. if itemId == ITEM_REWARD_CONTAINER or itemId == ITEM_REWARD_CHEST then
  528. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  529. return false
  530. end
  531.  
  532. -- The player also shouldn't be able to insert items into the boss corpse
  533. local tile = Tile(container:getPosition())
  534. for _, item in ipairs(tile:getItems() or { }) do
  535. if item:getAttribute(ITEM_ATTRIBUTE_CORPSEOWNER) == 2^31 - 1 and item:getName() == container:getName() then
  536. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  537. return false
  538. end
  539. end
  540. end
  541.  
  542. -- Do not let the player move the boss corpse.
  543. if item:getAttribute(ITEM_ATTRIBUTE_CORPSEOWNER) == 2^31 - 1 then
  544. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  545. return false
  546. end
  547.  
  548. -- Players cannot throw items on reward chest
  549. local tile = Tile(toPosition)
  550. if tile and tile:getItemById(ITEM_REWARD_CHEST) then
  551. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  552. self:getPosition():sendMagicEffect(CONST_ME_POFF)
  553. return false
  554. end
  555.  
  556. -- Players cannot throw items on teleports
  557. if blockTeleportTrashing and toPosition.x ~= CONTAINER_POSITION then
  558. local thing = Tile(toPosition):getItemByType(ITEM_TYPE_TELEPORT)
  559. if thing then
  560. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  561. self:getPosition():sendMagicEffect(CONST_ME_POFF)
  562. return false
  563. end
  564. end
  565.  
  566. if tile and tile:getItemById(370) then -- Trapdoor
  567. self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
  568. self:getPosition():sendMagicEffect(CONST_ME_POFF)
  569. return false
  570. end
  571.  
  572. if not antiPush(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder) then
  573. return false
  574. end
  575.  
  576. return true
  577. end
  578.  
  579. function Player:onItemMoved(item, count, fromPosition, toPosition, fromCylinder, toCylinder)
  580. end
  581.  
  582. function Player:onMoveCreature(creature, fromPosition, toPosition)
  583. return true
  584. end
  585.  
  586. local function hasPendingReport(name, targetName, reportType)
  587. local f = io.open(string.format("data/reports/players/%s-%s-%d.txt", name, targetName, reportType), "r")
  588. if f then
  589. io.close(f)
  590. return true
  591. else
  592. return false
  593. end
  594. end
  595.  
  596. function Player:onReportRuleViolation(targetName, reportType, reportReason, comment, translation)
  597. local name = self:getName()
  598. if hasPendingReport(name, targetName, reportType) then
  599. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your report is being processed.")
  600. return
  601. end
  602.  
  603. local file = io.open(string.format("data/reports/players/%s-%s-%d.txt", name, targetName, reportType), "a")
  604. if not file then
  605. self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "There was an error when processing your report, please contact a gamemaster.")
  606. return
  607. end
  608.  
  609. io.output(file)
  610. io.write("------------------------------\n")
  611. io.write("Reported by: " .. name .. "\n")
  612. io.write("Target: " .. targetName .. "\n")
  613. io.write("Type: " .. reportType .. "\n")
  614. io.write("Reason: " .. reportReason .. "\n")
  615. io.write("Comment: " .. comment .. "\n")
  616. if reportType ~= REPORT_TYPE_BOT then
  617. io.write("Translation: " .. translation .. "\n")
  618. end
  619. io.write("------------------------------\n")
  620. io.close(file)
  621. 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)))
  622. return
  623. end
  624.  
  625. function Player:onReportBug(message, position, category)
  626. local name = self:getName()
  627. local file = io.open("data/reports/bugs/" .. name .. " report.txt", "a")
  628.  
  629. if not file then
  630. self:sendTextMessage(MESSAGE_EVENT_DEFAULT, "There was an error when processing your report, please contact a gamemaster.")
  631. return true
  632. end
  633.  
  634. io.output(file)
  635. io.write("------------------------------\n")
  636. io.write("Name: " .. name)
  637. if category == BUG_CATEGORY_MAP then
  638. io.write(" [Map position: " .. position.x .. ", " .. position.y .. ", " .. position.z .. "]")
  639. end
  640. local playerPosition = self:getPosition()
  641. io.write(" [Player Position: " .. playerPosition.x .. ", " .. playerPosition.y .. ", " .. playerPosition.z .. "]\n")
  642. io.write("Comment: " .. message .. "\n")
  643. io.close(file)
  644.  
  645. self:sendTextMessage(MESSAGE_EVENT_DEFAULT, "Your report has been sent to " .. configManager.getString(configKeys.SERVER_NAME) .. ".")
  646. return true
  647. end
  648.  
  649. function Player:onTurn(direction)
  650. if self:getGroup():getAccess() and self:getDirection() == direction then
  651. local nextPosition = self:getPosition()
  652. nextPosition:getNextPosition(direction)
  653.  
  654. self:teleportTo(nextPosition, true)
  655. end
  656.  
  657. return true
  658. end
  659.  
  660. function Player:onTradeRequest(target, item)
  661. -- No trade items with actionID = 8000
  662. if item:getActionId() == BLOCK_ITEM_WITH_ACTION then
  663. return false
  664. end
  665.  
  666. if isInArray(storeItemID,item.itemid) then
  667. return false
  668. end
  669. return true
  670. end
  671.  
  672. function Player:onTradeAccept(target, item, targetItem)
  673. target:closeImbuementWindow(self)
  674. return true
  675. end
  676.  
  677. local soulCondition = Condition(CONDITION_SOUL, CONDITIONID_DEFAULT)
  678. soulCondition:setTicks(4 * 60 * 1000)
  679. soulCondition:setParameter(CONDITION_PARAM_SOULGAIN, 1)
  680.  
  681. local function useStamina(player)
  682. local staminaMinutes = player:getStamina()
  683. if staminaMinutes == 0 then
  684. return
  685. end
  686.  
  687. local playerId = player:getId()
  688. local currentTime = os.time()
  689. local timePassed = currentTime - nextUseStaminaTime[playerId]
  690. if timePassed <= 0 then
  691. return
  692. end
  693.  
  694. if timePassed > 60 then
  695. if staminaMinutes > 2 then
  696. staminaMinutes = staminaMinutes - 2
  697. else
  698. staminaMinutes = 0
  699. end
  700. nextUseStaminaTime[playerId] = currentTime + 120
  701. else
  702. staminaMinutes = staminaMinutes - 1
  703. nextUseStaminaTime[playerId] = currentTime + 60
  704. end
  705. player:setStamina(staminaMinutes)
  706. end
  707.  
  708. local function useStaminaXp(player)
  709. local staminaMinutes = player:getExpBoostStamina() / 60
  710. if staminaMinutes == 0 then
  711. return
  712. end
  713.  
  714. local playerId = player:getId()
  715. local currentTime = os.time()
  716. local timePassed = currentTime - nextUseXpStamina[playerId]
  717. if timePassed <= 0 then
  718. return
  719. end
  720.  
  721. if timePassed > 60 then
  722. if staminaMinutes > 2 then
  723. staminaMinutes = staminaMinutes - 2
  724. else
  725. staminaMinutes = 0
  726. end
  727. nextUseXpStamina[playerId] = currentTime + 120
  728. else
  729. staminaMinutes = staminaMinutes - 1
  730. nextUseXpStamina[playerId] = currentTime + 60
  731. end
  732. player:setExpBoostStamina(staminaMinutes * 60)
  733. end
  734.  
  735. function Player:onGainExperience(source, exp, rawExp)
  736. if not source or source:isPlayer() then
  737. return exp
  738. end
  739.  
  740. -- Soul Regeneration
  741. local vocation = self:getVocation()
  742. if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then
  743. soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000)
  744. self:addCondition(soulCondition)
  745. end
  746.  
  747. -- Experience Stage Multiplier
  748. local expStage = Game.getExperienceStage(self:getLevel())
  749. exp = exp * expStage
  750. baseExp = rawExp * expStage
  751. if Game.getStorageValue(GlobalStorage.XpDisplayMode) > 0 then
  752. displayRate = expStage
  753. else
  754. displayRate = 1
  755. end
  756.  
  757. -- VIP Bonus
  758. local vipBonus = 2 -- This is where you add your multip
  759. if self:isVip() then
  760. exp = exp * vipBonus
  761. end
  762.  
  763. -- Store Bonus
  764. useStaminaXp(self) -- Use store boost stamina
  765. local Boost = self:getExpBoostStamina()
  766. local stillHasBoost = Boost > 0
  767. local storeXpBoostAmount = stillHasBoost and self:getStoreXpBoost() or 0
  768. self:setStoreXpBoost(storeXpBoostAmount)
  769.  
  770. if (storeXpBoostAmount > 0) then
  771. exp = exp + (baseExp * (storeXpBoostAmount/100)) -- Exp Boost
  772. end
  773.  
  774. -- Stamina Bonus
  775. if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
  776. useStamina(self)
  777. local staminaMinutes = self:getStamina()
  778. if staminaMinutes > 2400 and self:isPremium() then
  779. exp = exp * 1.5
  780. self:setStaminaXpBoost(150)
  781. elseif staminaMinutes <= 840 then
  782. exp = exp * 0.5 --TODO destroy loot of people with 840- stamina
  783. self:setStaminaXpBoost(50)
  784. else
  785. self:setStaminaXpBoost(100)
  786. end
  787. end
  788.  
  789. -- Boosted creature
  790. if source:getName():lower() == BoostedCreature.name:lower() then
  791. exp = exp * 2
  792. end
  793.  
  794. self:setBaseXpGain(displayRate * 100)
  795. return exp
  796. end
  797.  
  798. function Player:onLoseExperience(exp)
  799. return exp
  800. end
  801.  
  802. function Player:onGainSkillTries(skill, tries)
  803. if APPLY_SKILL_MULTIPLIER == false then
  804. return tries
  805. end
  806.  
  807. if skill == SKILL_MAGLEVEL then
  808. return tries * configManager.getNumber(configKeys.RATE_MAGIC)
  809. end
  810. return tries * configManager.getNumber(configKeys.RATE_SKILL)
  811. end
  812.  
  813. function Player:onRemoveCount(item)
  814. -- Apenas cliente 11.x
  815. if self:getClient().os == CLIENTOS_NEW_WINDOWS then
  816. self:sendWaste(item:getId())
  817. end
  818. end
  819.  
  820. function Player:onRequestQuestLog()
  821. self:sendQuestLog()
  822. end
  823.  
  824. function Player:onRequestQuestLine(questId)
  825. self:sendQuestLine(questId)
  826. end
  827.  
  828. function Player:onStorageUpdate(key, value, oldValue, currentFrameTime)
  829. self:updateStorage(key, value, oldValue, currentFrameTime)
  830. end
  831.  
  832. function Player:canBeAppliedImbuement(imbuement, item)
  833. local categories = {}
  834. local slots = ItemType(item:getId()):getImbuingSlots()
  835. if slots > 0 then
  836. for slot = 0, slots - 1 do
  837. local duration = item:getImbuementDuration(slot)
  838. if duration > 0 then
  839. local imbue = item:getImbuement(slot)
  840. local catid = imbue:getCategory().id
  841. table.insert(categories, catid)
  842. end
  843. end
  844. end
  845.  
  846. if isInArray(categories, imbuement:getCategory().id) then
  847. return false
  848. end
  849.  
  850. if imbuement:isPremium() and self:getPremiumDays() < 1 then
  851. return false
  852. end
  853.  
  854. if self:getStorageValue(Storage.ForgottenKnowledge.Tomes) > 0 then
  855. imbuable = true
  856. else
  857. return false
  858. end
  859.  
  860. if not self:canImbueItem(imbuement, item) then
  861. return false
  862. end
  863.  
  864. return true
  865. end
  866.  
  867. function Player:onApplyImbuement(imbuement, item, slot, protectionCharm)
  868. for _, pid in pairs(imbuement:getItems()) do
  869. if self:getItemCount(pid.itemid) < pid.count then
  870. self:sendImbuementResult(MESSAGEDIALOG_IMBUEMENT_ROLL_FAILED, "You don't have all necessary items.")
  871. return false
  872. end
  873. end
  874.  
  875. if item:getImbuementDuration(slot) > 0 then
  876. self:sendImbuementResult(MESSAGEDIALOG_IMBUEMENT_ERROR, "An error ocurred, please reopen imbuement window.")
  877. return false
  878. end
  879. local base = imbuement:getBase()
  880. local price = base.price + (protectionCharm and base.protection or 0)
  881.  
  882. local chance = protectionCharm and 100 or base.percent
  883. if math.random(100) > chance then -- failed attempt
  884. self:sendImbuementResult(MESSAGEDIALOG_IMBUEMENT_ROLL_FAILED, "Oh no!\n\nThe imbuement has failed. You have lost the astral sources and gold you needed for the imbuement.\n\nNext time use a protection charm to better your chances.")
  885. -- Removing items
  886. for _, pid in pairs(imbuement:getItems()) do
  887. self:removeItem(pid.itemid, pid.count)
  888. end
  889. -- Removing money
  890. self:removeMoneyNpc(price)
  891. -- Refreshing shrine window
  892. local nitem = Item(item.uid)
  893. self:sendImbuementPanel(nitem)
  894. return false
  895. end
  896.  
  897. -- Removing items
  898. for _, pid in pairs(imbuement:getItems()) do
  899. if not self:removeItem(pid.itemid, pid.count) then
  900. self:sendImbuementResult(MESSAGEDIALOG_IMBUEMENT_ROLL_FAILED, "You don't have all necessary items.")
  901. return false
  902. end
  903. end
  904.  
  905. if not self:removeMoneyNpc(price) then
  906. self:sendImbuementResult(MESSAGEDIALOG_IMBUEMENT_ROLL_FAILED, "You don't have enough money " ..price.. " gps.")
  907. return false
  908. end
  909.  
  910. if not item:addImbuement(slot, imbuement:getId()) then
  911. self:sendImbuementResult(MESSAGEDIALOG_IMBUEMENT_ROLL_FAILED, "Item failed to apply imbuement.")
  912. return false
  913. end
  914.  
  915. -- Update item
  916. local nitem = Item(item.uid)
  917. self:sendImbuementPanel(nitem)
  918. return true
  919. end
  920.  
  921. function Player:clearImbuement(item, slot)
  922. local slots = ItemType(item:getId()):getImbuingSlots()
  923. if slots < slot then
  924. self:sendImbuementResult(MESSAGEDIALOG_CLEARING_CHARM_ERROR, "Sorry, not possible.")
  925. return false
  926. end
  927.  
  928. if item:getTopParent() ~= self or item:getParent() == self then
  929. self:sendImbuementResult(MESSAGEDIALOG_CLEARING_CHARM_ERROR, "An error occurred while applying the clearing charm to the item.")
  930. return false
  931. end
  932.  
  933. -- slot is not used
  934. local info = item:getImbuementDuration(slot)
  935. if info == 0 then
  936. self:sendImbuementResult(MESSAGEDIALOG_CLEARING_CHARM_ERROR, "An error occurred while applying the clearing charm to the item.")
  937. return false
  938. end
  939.  
  940. local imbuement = item:getImbuement(slot)
  941. if not self:removeMoneyNpc(imbuement:getBase().removecust) then
  942. self:sendImbuementResult(MESSAGEDIALOG_CLEARING_CHARM_ERROR, "You don't have enough money " ..imbuement:getBase().removecust.. " gps.")
  943. return false
  944. end
  945.  
  946. if not item:cleanImbuement(slot) then
  947. self:sendImbuementResult(MESSAGEDIALOG_CLEARING_CHARM_ERROR, "An error occurred while applying the clearing charm to the item.")
  948. return false
  949. end
  950.  
  951. -- Update item
  952. local nitem = Item(item.uid)
  953. self:sendImbuementResult(MESSAGEDIALOG_CLEARING_CHARM_SUCCESS, "Congratulations! You have successfully applied the clearing charm to your item.");
  954. self:sendImbuementPanel(nitem)
  955.  
  956. return true
  957. end
  958.  
  959. function Player:onCombat(target, item, primaryDamage, primaryType, secondaryDamage, secondaryType)
  960. if not item or not target then
  961. return primaryDamage, primaryType, secondaryDamage, secondaryType
  962. end
  963.  
  964. local slots = ItemType(item:getId()):getImbuingSlots()
  965. if slots > 0 then
  966. for i = 0, slots - 1 do
  967. local imbuement = item:getImbuement(i)
  968. if imbuement then
  969. local percent = imbuement:getElementDamage()
  970. local totalDmg = primaryDamage --store it for damage adjustment
  971. if percent and percent > 0 then
  972. if primaryDamage ~= 0 then
  973. local factor = percent / 100
  974. secondaryType = imbuement:getCombatType()
  975. primaryDamage = totalDmg * (1 - factor)
  976. secondaryDamage = totalDmg * (factor)
  977. end
  978. end
  979. end
  980. end
  981. end
  982.  
  983. return primaryDamage, primaryType, secondaryDamage, secondaryType
  984. end
Add Comment
Please, Sign In to add comment