Advertisement
Guest User

Untitled

a guest
Jan 23rd, 2018
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.49 KB | None | 0 0
  1. local config = {
  2.     minutesToEnd = 3,
  3.     minutesToStart = { 0, 5, 9, 10 },
  4.     reward = {
  5.         {itemId = 18422, count = 5},
  6.         {itemId = 18422, count = 4},
  7.         {itemId = 18422, count = 3},
  8.         {itemId = 18422, count = 2},
  9.         {itemId = 18422, count = 1},
  10.     },
  11.     waitingRoomPosition = Position(479, 847, 7),
  12.     arena = {
  13.         fromPosition = Position(503, 828, 4),
  14.         toPosition = Position(539, 872, 7)
  15.     },
  16.     spawnPosition = {
  17.         fromPosition = Position(503, 828, 7),
  18.         toPosition = Position(539, 872, 7)
  19.     },
  20.     bullets = {
  21.         effect = CONST_ANI_SNOWBALL,
  22.         exhaustion = 500,
  23.         speed = 150,
  24.     },
  25.     minBullets = 100,
  26.     resetBulletsOnDeath = true,
  27.     decreaseScoreOnDeath = true,
  28.     pointsPerKill = 3,
  29.     infiniteAmmo = false,
  30.     ammoPerPoint = 2,
  31.     minutesToNextExecution = 180,
  32. }
  33.  
  34. local function getRandomSpawnPosition()
  35.     local tries = 50
  36.     local position
  37.     for i = 1, tries do
  38.         position = Position(math.random(config.spawnPosition.fromPosition.x, config.spawnPosition.toPosition.x), math.random(config.spawnPosition.fromPosition.y, config.spawnPosition.toPosition.y), math.random(config.spawnPosition.fromPosition.z, config.spawnPosition.toPosition.z))
  39.         if isWalkable(position) then
  40.             break
  41.         end
  42.     end
  43.  
  44.     return position
  45. end
  46.  
  47. local function blockProjectile(position)
  48.     local tile = Tile(position)
  49.     if not tile then
  50.         return false
  51.     end
  52.  
  53.     local items = tile:getItems()
  54.     for _, item in ipairs(items) do
  55.         local itemType = item:getType()
  56.         if itemType:getType() ~= ITEM_TYPE_MAGICFIELD and not itemType:isMovable() and item:hasProperty(CONST_PROP_BLOCKPROJECTILE) then
  57.             return true
  58.         end
  59.     end
  60.  
  61.     local ground = tile:getGround()
  62.     if not ground or ground:hasProperty(CONST_PROP_BLOCKSOLID) or ground:hasProperty(CONST_PROP_IMMOVABLEBLOCKPATH) then
  63.         return false
  64.     end
  65.  
  66.     return false
  67. end
  68.  
  69. if not PaintballEvent then
  70.     PaintballEvent = {
  71.         minPlayers = 10,
  72.         joined = { },
  73.         running = false,
  74.         teleportIsActive = false,
  75.         ammoStorage = 1234,
  76.         scoreStorage = 1235,
  77.         exhaustStorage = 1236,
  78.         endEvent = nil,
  79.         executed = 0,
  80.         winnerStorage = 70002
  81.     }
  82. end
  83.  
  84. function PaintballEvent.addReward(self, playerId, scoreId)
  85.     local reward = config.reward[scoreId]
  86.     if not reward then
  87.         return
  88.     end
  89.  
  90.     local player = Player(playerId)
  91.     if not player or not player:addItem(reward.itemId, reward.count) then
  92.         return
  93.     end
  94.  
  95.     if scoreId == 1 then
  96.         player:setStorageValue(self.winnerStorage, math.max(0, player:getStorageValue(self.winnerStorage)) + 1)
  97.     end
  98.  
  99.     player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format('You received %s for coming in %d%s place.', ItemType(reward.itemId):getNameDescription(reward.count), scoreId, getNumberPostfix(scoreId)))
  100. end
  101.  
  102. function PaintballEvent.broadcastMessage(self, type, msg)
  103.     for i = 1, #self.joined do
  104.         local tmpPlayer = Player(self.joined[i])
  105.         if tmpPlayer then
  106.             tmpPlayer:sendTextMessage(type, msg)
  107.         end
  108.     end
  109. end
  110.  
  111. function PaintballEvent.commands(self, player, keyword)
  112.     if keyword == 'info' then
  113.         if not self:isInRange(player) or not self.running then
  114.             player:sendCancelMessage("You need to be in the event.")
  115.             return false
  116.         end
  117.  
  118.         local text = string.format("You have %d points.\nYou have %d ammo left.\n------------------\nThe current high score in paintball is:\n", math.max(0, player:getStorageValue(self.scoreStorage)), player:getStorageValue(self.ammoStorage))
  119.         local topScorers = self:getTopScorers()
  120.         if #topScorers > 0 then
  121.             local limit = #topScorers > 5 and 5 or #topScorers
  122.             for i = 1, limit do
  123.                 local score = topScorers[i]
  124.                 text = string.format("%s%d. %s - %d points.\n", text, i, score.name, math.max(0, score.points))
  125.             end
  126.         end
  127.  
  128.         player:popupFYI(text)
  129.  
  130.     elseif keyword == 'ammo' then
  131.         if not self:isInRange(player) or not self.running then
  132.             player:sendCancelMessage("You need to be in the event.")
  133.             return false
  134.         end
  135.  
  136.         if config.infiniteAmmo then
  137.             player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The ammunation is infinite, there's no need to buy more.")
  138.             return false
  139.         end
  140.  
  141.         local scoreStorage = math.max(0, player:getStorageValue(self.scoreStorage))
  142.         if scoreStorage <= 0 then
  143.             player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You do not have enough score points to buy ammo, you need " .. 1 - scoreStorage .. " more.")
  144.             return false
  145.         end
  146.  
  147.         player:setStorageValue(self.scoreStorage, scoreStorage - 1)
  148.         player:setStorageValue(self.ammoStorage, player:getStorageValue(self.ammoStorage) + config.ammoPerPoint)
  149.         player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have received " .. config.ammoPerPoint .. " bullets and you have lost 1 score point.")
  150.  
  151.     elseif keyword == 'bullet' then
  152.         if not self:isInRange(player) or not self.running then
  153.             player:sendCancelMessage("You need to be in the event.")
  154.             return false
  155.         end
  156.  
  157.         if player:getStorageValue(self.exhaustStorage) > 1 then
  158.             player:sendCancelMessage("Gun is on cooldown")
  159.             return false
  160.         end
  161.  
  162.         local ammoStorage = player:getStorageValue(self.ammoStorage)
  163.         if ammoStorage <= 0 then
  164.             player:sendCancelMessage("You're out of ammo, exchange ammo for points with !shoot ammo or get killed for a recharge.")
  165.             return false
  166.         end
  167.  
  168.         if not config.infiniteAmmo then
  169.             player:setStorageValue(self.ammoStorage, ammoStorage - 1)
  170.         end
  171.  
  172.         player:setStorageValue(self.exhaustStorage, 2)
  173.  
  174.         local playerId = player:getId()
  175.         addEvent(
  176.             function(self, playerId)
  177.                 local player = Player(playerId)
  178.                 if player then
  179.                     player:setStorageValue(self.exhaustStorage, 1)
  180.                 end
  181.             end, config.bullets.exhaustion, self, playerId
  182.         )
  183.  
  184.         self:onPlayerShoot(playerId, player:getDirection(), player:getPosition(), 1)
  185.     end
  186. end
  187.  
  188. function PaintballEvent.deinit(self, message)
  189.     if self.endEvent ~= nil then
  190.         stopEvent(self.endEvent)
  191.         self.endEvent = nil
  192.     end
  193.  
  194.     if #self.joined > 0 then
  195.         for i = 1, #self.joined do
  196.             if message then
  197.                 self:releasePlayer(self.joined[i], message)
  198.             end
  199.         end
  200.     end
  201.  
  202.     self.joined = { }
  203.     self.running = false
  204.     self.teleportIsActive = false
  205. end
  206.  
  207. function PaintballEvent.getTopScorers(self)
  208.     local scores = { }
  209.     for i = 1, #self.joined do
  210.         local tmpPlayer = Player(self.joined[i])
  211.         if tmpPlayer then
  212.             scores[#scores + 1] = {
  213.                 id = tmpPlayer:getId(),
  214.                 name = tmpPlayer:getName(),
  215.                 points = math.max(0, tmpPlayer:getStorageValue(self.scoreStorage))
  216.             }
  217.         end
  218.     end
  219.  
  220.     table.sort(scores, function(a, b) return a.points > b.points end)
  221.  
  222.     return scores
  223. end
  224.  
  225. function PaintballEvent.init(self)
  226.     self.teleportIsActive = true
  227.     self.executed = self.executed + 1
  228.  
  229.     local lastMinute = config.minutesToStart[#config.minutesToStart]
  230.     for _, minutes in ipairs(config.minutesToStart) do
  231.         if minutes == lastMinute then
  232.             addEvent(function(self) self:start() end, minutes * 60000, self)
  233.         else
  234.             addEvent(Game.broadcastMessage, minutes * 60000, string.format('The Paintball Event will start in %d minute%s [%d players required to start]. You can join it by entering the teleporter in Enigma temple.', lastMinute - minutes, (lastMinute - minutes ~= 1 and "s " or ""), self.minPlayers), MESSAGE_EVENT_ADVANCE)
  235.         end
  236.     end
  237. end
  238.  
  239. function PaintballEvent.isInRange(self, player)
  240.     return isInRange(player:getPosition(), config.arena.fromPosition, config.arena.toPosition)
  241. end
  242.  
  243. function PaintballEvent.onPlayerDeath(self, playerId, killerId)
  244.     local player = Player(playerId)
  245.     if not player then
  246.         return
  247.     end
  248.  
  249.     local killer = Player(killerId)
  250.     if not killer then
  251.         return
  252.     end
  253.  
  254.     killer:setStorageValue(self.scoreStorage, math.max(0, killer:getStorageValue(self.scoreStorage)) + config.pointsPerKill)
  255.     killer:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You killed " .. player:getName() .. ".")
  256.  
  257.     local position = getRandomSpawnPosition()
  258.     player:teleportTo(position)
  259.     position:sendMagicEffect(CONST_ME_HOLYAREA)
  260.  
  261.     player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You were killed by " .. killer:getName() .. ".")
  262.  
  263.     if config.decreaseScoreOnDeath then
  264.         player:setStorageValue(self.scoreStorage, player:getStorageValue(self.scoreStorage) - 1)
  265.     end
  266.  
  267.     if config.resetBulletsOnDeath then
  268.         player:setStorageValue(self.ammoStorage, config.minBullets)
  269.     end
  270.  
  271.     self:broadcastMessage(MESSAGE_EVENT_ADVANCE, string.format("[Paintball Event]: %s were killed by %s.", player:getName(), killer:getName()))
  272. end
  273.  
  274. function PaintballEvent.onPlayerShoot(self, playerId, direction, fromPosition, distance)
  275.     local targetPosition = fromPosition + Position.directionOffset[direction]
  276.     if blockProjectile(targetPosition) then
  277.         targetPosition:sendMagicEffect(CONST_ME_LOSEENERGY)
  278.         return
  279.     end
  280.  
  281.     fromPosition:sendDistanceEffect(targetPosition, CONST_ANI_SNOWBALL)
  282.  
  283.     local tile = Tile(targetPosition)
  284.     if tile then
  285.         local creature = tile:getTopCreature()
  286.         if creature and creature:isPlayer() then
  287.             local creatureId = creature:getId()
  288.             if creatureId ~= playerId then
  289.                 self:onPlayerDeath(creatureId, playerId)
  290.                 targetPosition:sendMagicEffect(CONST_ME_DRAWBLOOD)
  291.                 return
  292.             end
  293.         end
  294.     end
  295.  
  296.     distance = distance + 1
  297.  
  298.     if distance ~= 6 then
  299.         addEvent(function(self, playerId, direction, fromPosition, distance) self:onPlayerShoot(playerId, direction, fromPosition, distance) end, 150, self, playerId, direction, targetPosition, distance)
  300.     end
  301. end
  302.  
  303. function PaintballEvent.releasePlayer(self, playerId, msg)
  304.     local player = Player(playerId)
  305.     if not player or not self:isInRange(player) then
  306.         return
  307.     end
  308.  
  309.     player:sendTextMessage(MESSAGE_INFO_DESCR, msg)
  310.     player:teleportTo(player:getTown():getTemplePosition())
  311.     player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
  312.     player:setStorageValue(self.ammoStorage, -1)
  313.     player:setStorageValue(self.scoreStorage, -1)
  314.     player:setStorageValue(self.exhaustStorage, -1)
  315. end
  316.  
  317. function PaintballEvent.removePlayer(self, playerId, msg)
  318.     for i = 1, #self.joined do
  319.         if self.joined[i] == playerId then
  320.             self:releasePlayer(playerId, msg)
  321.             table.remove(self.joined, i)
  322.             break
  323.         end
  324.     end
  325. end
  326.  
  327. function PaintballEvent.start(self)
  328.     local spectators = Game.getSpectators(config.waitingRoomPosition, false, true, 4, 4, 4, 4)
  329.     for i = 1, #spectators do
  330.         self.joined[#self.joined + 1] = spectators[i]:getId()
  331.     end
  332.  
  333.     if #self.joined < self.minPlayers then
  334.         self:deinit('The Paintball Event did not start due to lack of players.\nYou were teleported back to your temple.')
  335.         Game.broadcastMessage('The Paintball Event did not start due to lack of players.', MESSAGE_EVENT_ADVANCE)
  336.         return
  337.     end
  338.  
  339.     for i = 1, #self.joined do
  340.         local tmpPlayer = Player(self.joined[i])
  341.         if tmpPlayer then
  342.             local position = getRandomSpawnPosition()
  343.             tmpPlayer:teleportTo(position)
  344.             position:sendMagicEffect(CONST_ME_HOLYAREA)
  345.  
  346.             tmpPlayer:setStorageValue(self.ammoStorage, config.minBullets)
  347.             tmpPlayer:setStorageValue(self.scoreStorage, 0)
  348.             tmpPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Welcome to paintball, here are the commands:\n!shoot bullet --This will shot a bullet.\n!shoot ammo --This will give you " .. config.ammoPerPoint .. " bullets and take 1 point from your current score (you need at least 1 point to use this command).\n!shoot info --This will show you your current score and ammo, it'll also show the current high score of the event.\nIt is strongly recommended that you bind these commands to your hotkeys.")
  349.         end
  350.     end
  351.  
  352.     self.running = true
  353.     self.teleportIsActive = false
  354.     self.nextExecution = (config.minutesToNextExecution * 60) + os.time()
  355.     self.endEvent = addEvent(function(self) self:stop() end, config.minutesToEnd * 60 * 1000, self)
  356.     Game.broadcastMessage('The Paintball Event has started. The event will automatically finish in ' .. config.minutesToEnd .. ' minutes.', MESSAGE_EVENT_ADVANCE)
  357. end
  358.  
  359. function PaintballEvent.stop(self)
  360.     local text = "The paintball event has ended."
  361.     local topScorers = self:getTopScorers()
  362.     if #topScorers > 0 then
  363.         text = string.format("%s\nTop Scorers:\n", text)
  364.         local limit = #topScorers > 5 and 5 or #topScorers
  365.         for i = 1, limit do
  366.             local score = topScorers[i]
  367.             self:addReward(score.id, i)
  368.             text = string.format("%s%d. %s - %d points.\n", text, i, score.name, score.points)
  369.         end
  370.     end
  371.  
  372.     Game.broadcastMessage(text, MESSAGE_STATUS_WARNING)
  373.     self:deinit(text)
  374. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement