Advertisement
Guest User

Untitled

a guest
Sep 21st, 2017
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.33 KB | None | 0 0
  1.  
  2. --[[
  3.  
  4. <event type="death" name="BossDeath" script="rewardChest/boss.lua" />
  5. <event type="healthchange" name="BossParticipation" script="rewardChest/boss.lua" />
  6. <event type="think" name="BossThink" script="rewardChest/boss.lua" />
  7.  
  8. --]]
  9.  
  10.  
  11. local function pushSeparated(buffer, sep, ...)
  12. local argv = {...}
  13. local argc = #argv
  14. for k, v in ipairs(argv) do
  15. table.insert(buffer, v)
  16. if k < argc and sep then
  17. table.insert(buffer, sep)
  18. end
  19. end
  20. end
  21.  
  22. local function insertItems(buffer, info, parent, items)
  23. local start = info.running
  24. for _, item in ipairs(items) do
  25. if _ ~= 1 or parent > 100 then
  26. table.insert(buffer, ",")
  27. end
  28. info.running = info.running + 1
  29. table.insert(buffer, "(")
  30. pushSeparated(buffer, ",", info.playerGuid, parent, info.running, item:getId(), item:getSubType(), db.escapeBlob(item:serializeAttributes()))
  31. table.insert(buffer, ")")
  32.  
  33. if item:isContainer() then
  34. local size = item:getSize()
  35. if size > 0 then
  36. local subItems = {}
  37. for i = 1, size do
  38. table.insert(subItems, item:getItem(i - 1))
  39. end
  40.  
  41. insertItems(buffer, info, info.running, subItems)
  42. end
  43. end
  44. end
  45. return info.running - start
  46. end
  47.  
  48. local function insertRewardItems(playerGuid, timestamp, itemList)
  49. db.asyncStoreQuery('SELECT `pid`, `sid` FROM `player_rewards` WHERE player_id = ' .. playerGuid .. ' ORDER BY `sid` ASC;',
  50. function(query)
  51. local lastReward = 0
  52. local lastStoreId
  53. if(query) then
  54. repeat
  55. local sid = result.getDataInt(query, 'sid')
  56. local pid = result.getDataInt(query, 'pid')
  57.  
  58. if pid < 100 then
  59. lastReward = pid
  60. end
  61. lastStoreId = sid
  62. until not result.next(query)
  63. end
  64.  
  65. local buffer = {'INSERT INTO `player_rewards` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES'}
  66.  
  67. --reward bag
  68. local info = {
  69. playerGuid = playerGuid,
  70. running = lastStoreId or 100
  71. }
  72.  
  73. local bag = Game.createItem(ITEM_REWARD_CONTAINER)
  74. bag:setAttribute(ITEM_ATTRIBUTE_DATE, timestamp)
  75. if itemList then
  76. for _, p in ipairs(itemList) do
  77. bag:addItem(p[1], p[2])
  78. end
  79. end
  80.  
  81. local total = insertItems(buffer, info, lastReward + 1, {bag})
  82. table.insert(buffer, ";")
  83.  
  84. if total ~= 0 then
  85. db.query(table.concat(buffer))
  86. end
  87. end
  88. )
  89. end
  90.  
  91. local function getPlayerStats(bossId, playerGuid, autocreate)
  92. local ret = globalBosses[bossId][playerGuid]
  93. if not ret and autocreate then
  94. ret = {
  95. bossId = bossId,
  96. damageIn = 0, -- damage taken from the boss
  97. healing = 0, -- healing (other players) done
  98. }
  99. globalBosses[bossId][playerGuid] = ret
  100. return ret
  101. end
  102. return ret
  103. end
  104.  
  105. function onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
  106. local monsterType = creature:getType()
  107. if monsterType:isRewardBoss() then -- Make sure it is a boss
  108. local bossId = creature:getId()
  109. local timestamp = os.time()
  110.  
  111. local totalDamageOut, totalDamageIn, totalHealing = 0.1, 0.1, 0.1 -- avoid dividing by zero
  112.  
  113. local scores = {}
  114. local info = globalBosses[bossId]
  115. local damageMap = creature:getDamageMap()
  116.  
  117. for guid, stats in pairs(info) do
  118. local player = Player(stats.playerId)
  119. local part = damageMap[stats.playerId]
  120. local damageOut, damageIn, healing = (stats.damageOut or 0) + (part and part.total or 0), stats.damageIn or 0, stats.healing or 0
  121.  
  122. totalDamageOut = totalDamageOut + damageOut
  123. totalDamageIn = totalDamageIn + damageIn
  124. totalHealing = totalHealing + healing
  125.  
  126. table.insert(scores, {
  127. player = player,
  128. guid = guid,
  129. damageOut = damageOut,
  130. damageIn = damageIn,
  131. healing = healing,
  132. })
  133. end
  134.  
  135. local participants = 0
  136. for _, con in ipairs(scores) do
  137. local score = (con.damageOut / totalDamageOut) + (con.damageIn / totalDamageIn) + (con.healing / totalHealing)
  138. con.score = score / 3 -- normalize to 0-1
  139. if score ~= 0 then
  140. participants = participants + 1
  141. end
  142. end
  143. table.sort(scores, function(a, b) return a.score > b.score end)
  144.  
  145. local expectedScore = 1 / participants
  146.  
  147. for _, con in ipairs(scores) do
  148. local reward, stamina -- ignoring stamina for now because I heard you receive rewards even when it's depleted
  149. if con.player then
  150. reward = con.player:getReward(timestamp, true)
  151. stamina = con.player:getStamina()
  152.  
  153. else
  154. stamina = con.stamina or 0
  155. end
  156.  
  157. local playerLoot
  158. if --[[stamina > 840 and]] con.score ~= 0 then
  159. local lootFactor = 1
  160. if((_)==1)then
  161. lootFactor = 10
  162. end
  163.  
  164. lootFactor = lootFactor / participants ^ (1 / 3) -- tone down the loot a notch if there are many participants
  165. lootFactor = lootFactor * (1 + lootFactor) ^ (con.score / expectedScore) -- increase the loot multiplicatively by how many times the player surpassed the expected score
  166. playerLoot = monsterType:getBossReward(lootFactor, _ == 1)
  167.  
  168.  
  169. if con.player then
  170. for _, p in ipairs(playerLoot) do
  171. reward:addItem(p[1], p[2])
  172. print(_ .. " " .. p[1])
  173. end
  174. end
  175. end
  176.  
  177. if con.player then
  178. local lootMessage = {"The following items are available in your reward chest: "}
  179.  
  180. if --[[stamina > 840]]true then
  181. reward:getContentDescription(lootMessage)
  182. else
  183. table.insert(lootMessage, 'nothing (due to low stamina)')
  184. end
  185. table.insert(lootMessage, ".")
  186. con.player:sendTextMessage(MESSAGE_EVENT_ADVANCE, table.concat(lootMessage))
  187. else
  188. insertRewardItems(con.guid, timestamp, playerLoot)
  189. end
  190. end
  191.  
  192. globalBosses[bossId] = nil
  193. end
  194. return true
  195. end
  196.  
  197. function onThink(creature, interval)
  198. local bossId = creature:getId()
  199. local info = globalBosses[bossId]
  200. -- Reset all players' status
  201. for _, player in pairs(info) do
  202. player.active = false
  203. end
  204. -- Set all players in boss' target list as active in the fight
  205. local targets = creature:getTargetList()
  206. for _, target in ipairs(targets) do
  207. if target:isPlayer() then
  208. local stats = getPlayerStats(bossId, target:getGuid(), true)
  209. stats.playerId = target:getId() -- Update player id
  210. stats.active = true
  211. end
  212. end
  213. end
  214.  
  215. function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
  216. if not next(globalBosses) then
  217. return primaryDamage, primaryType, secondaryDamage, secondaryType
  218. end
  219.  
  220. if not creature or not attacker then
  221. return primaryDamage, primaryType, secondaryDamage, secondaryType
  222. end
  223.  
  224. local stats = creature:inBossFight()
  225. if not stats then
  226. return primaryDamage, primaryType, secondaryDamage, secondaryType
  227. end
  228.  
  229. local creatureId, attackerId = creature:getId(), attacker:getId()
  230. stats.playerId = creatureId -- Update player id
  231.  
  232. -- Account for healing of others active in the boss fight
  233. if primaryType == COMBAT_HEALING and attacker:isPlayer() and attackerId ~= creatureId then
  234. local healerStats = getPlayerStats(stats.bossId, attacker:getGuid(), true)
  235. healerStats.active = true
  236. healerStats.playerId = attackerId -- Update player id
  237. healerStats.healing = healerStats.healing + primaryDamage
  238. elseif stats.bossId == attackerId then
  239. -- Account for damage taken from the boss
  240. stats.damageIn = stats.damageIn + primaryDamage
  241. end
  242. return primaryDamage, primaryType, secondaryDamage, secondaryType
  243. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement