Advertisement
Guest User

Untitled

a guest
Sep 21st, 2017
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.27 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. lootFactor = lootFactor / participants ^ (1 / 3) -- tone down the loot a notch if there are many participants
  161. lootFactor = lootFactor * (1 + lootFactor) ^ (con.score / expectedScore) -- increase the loot multiplicatively by how many times the player surpassed the expected score
  162. playerLoot = monsterType:getBossReward(lootFactor, _ == 1)
  163.  
  164.  
  165. if con.player then
  166. for _, p in ipairs(playerLoot) do
  167. reward:addItem(p[1], p[2])
  168. print(playerLoot)
  169. end
  170. end
  171. end
  172.  
  173. if con.player then
  174. local lootMessage = {"The following items are available in your reward chest: "}
  175.  
  176. if --[[stamina > 840]]true then
  177. reward:getContentDescription(lootMessage)
  178. else
  179. table.insert(lootMessage, 'nothing (due to low stamina)')
  180. end
  181. table.insert(lootMessage, ".")
  182. con.player:sendTextMessage(MESSAGE_EVENT_ADVANCE, table.concat(lootMessage))
  183. else
  184. insertRewardItems(con.guid, timestamp, playerLoot)
  185. end
  186. end
  187.  
  188. globalBosses[bossId] = nil
  189. end
  190. return true
  191. end
  192.  
  193. function onThink(creature, interval)
  194. local bossId = creature:getId()
  195. local info = globalBosses[bossId]
  196. -- Reset all players' status
  197. for _, player in pairs(info) do
  198. player.active = false
  199. end
  200. -- Set all players in boss' target list as active in the fight
  201. local targets = creature:getTargetList()
  202. for _, target in ipairs(targets) do
  203. if target:isPlayer() then
  204. local stats = getPlayerStats(bossId, target:getGuid(), true)
  205. stats.playerId = target:getId() -- Update player id
  206. stats.active = true
  207. end
  208. end
  209. end
  210.  
  211. function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
  212. if not next(globalBosses) then
  213. return primaryDamage, primaryType, secondaryDamage, secondaryType
  214. end
  215.  
  216. if not creature or not attacker then
  217. return primaryDamage, primaryType, secondaryDamage, secondaryType
  218. end
  219.  
  220. local stats = creature:inBossFight()
  221. if not stats then
  222. return primaryDamage, primaryType, secondaryDamage, secondaryType
  223. end
  224.  
  225. local creatureId, attackerId = creature:getId(), attacker:getId()
  226. stats.playerId = creatureId -- Update player id
  227.  
  228. -- Account for healing of others active in the boss fight
  229. if primaryType == COMBAT_HEALING and attacker:isPlayer() and attackerId ~= creatureId then
  230. local healerStats = getPlayerStats(stats.bossId, attacker:getGuid(), true)
  231. healerStats.active = true
  232. healerStats.playerId = attackerId -- Update player id
  233. healerStats.healing = healerStats.healing + primaryDamage
  234. elseif stats.bossId == attackerId then
  235. -- Account for damage taken from the boss
  236. stats.damageIn = stats.damageIn + primaryDamage
  237. end
  238. return primaryDamage, primaryType, secondaryDamage, secondaryType
  239. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement