Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local config = {
- minutesToEnd = 3,
- minutesToStart = { 0, 5, 9, 10 },
- reward = {
- {itemId = 18422, count = 5},
- {itemId = 18422, count = 4},
- {itemId = 18422, count = 3},
- {itemId = 18422, count = 2},
- {itemId = 18422, count = 1},
- },
- waitingRoomPosition = Position(479, 847, 7),
- arena = {
- fromPosition = Position(503, 828, 4),
- toPosition = Position(539, 872, 7)
- },
- spawnPosition = {
- fromPosition = Position(503, 828, 7),
- toPosition = Position(539, 872, 7)
- },
- bullets = {
- effect = CONST_ANI_SNOWBALL,
- exhaustion = 500,
- speed = 150,
- },
- minBullets = 100,
- resetBulletsOnDeath = true,
- decreaseScoreOnDeath = true,
- pointsPerKill = 3,
- infiniteAmmo = false,
- ammoPerPoint = 2,
- minutesToNextExecution = 180,
- }
- local function getRandomSpawnPosition()
- local tries = 50
- local position
- for i = 1, tries do
- 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))
- if isWalkable(position) then
- break
- end
- end
- return position
- end
- local function blockProjectile(position)
- local tile = Tile(position)
- if not tile then
- return false
- end
- local items = tile:getItems()
- for _, item in ipairs(items) do
- local itemType = item:getType()
- if itemType:getType() ~= ITEM_TYPE_MAGICFIELD and not itemType:isMovable() and item:hasProperty(CONST_PROP_BLOCKPROJECTILE) then
- return true
- end
- end
- local ground = tile:getGround()
- if not ground or ground:hasProperty(CONST_PROP_BLOCKSOLID) or ground:hasProperty(CONST_PROP_IMMOVABLEBLOCKPATH) then
- return false
- end
- return false
- end
- if not PaintballEvent then
- PaintballEvent = {
- minPlayers = 10,
- joined = { },
- running = false,
- teleportIsActive = false,
- ammoStorage = 1234,
- scoreStorage = 1235,
- exhaustStorage = 1236,
- endEvent = nil,
- executed = 0,
- winnerStorage = 70002
- }
- end
- function PaintballEvent.addReward(self, playerId, scoreId)
- local reward = config.reward[scoreId]
- if not reward then
- return
- end
- local player = Player(playerId)
- if not player or not player:addItem(reward.itemId, reward.count) then
- return
- end
- if scoreId == 1 then
- player:setStorageValue(self.winnerStorage, math.max(0, player:getStorageValue(self.winnerStorage)) + 1)
- end
- 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)))
- end
- function PaintballEvent.broadcastMessage(self, type, msg)
- for i = 1, #self.joined do
- local tmpPlayer = Player(self.joined[i])
- if tmpPlayer then
- tmpPlayer:sendTextMessage(type, msg)
- end
- end
- end
- function PaintballEvent.commands(self, player, keyword)
- if keyword == 'info' then
- if not self:isInRange(player) or not self.running then
- player:sendCancelMessage("You need to be in the event.")
- return false
- end
- 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))
- local topScorers = self:getTopScorers()
- if #topScorers > 0 then
- local limit = #topScorers > 5 and 5 or #topScorers
- for i = 1, limit do
- local score = topScorers[i]
- text = string.format("%s%d. %s - %d points.\n", text, i, score.name, math.max(0, score.points))
- end
- end
- player:popupFYI(text)
- elseif keyword == 'ammo' then
- if not self:isInRange(player) or not self.running then
- player:sendCancelMessage("You need to be in the event.")
- return false
- end
- if config.infiniteAmmo then
- player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The ammunation is infinite, there's no need to buy more.")
- return false
- end
- local scoreStorage = math.max(0, player:getStorageValue(self.scoreStorage))
- if scoreStorage <= 0 then
- player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You do not have enough score points to buy ammo, you need " .. 1 - scoreStorage .. " more.")
- return false
- end
- player:setStorageValue(self.scoreStorage, scoreStorage - 1)
- player:setStorageValue(self.ammoStorage, player:getStorageValue(self.ammoStorage) + config.ammoPerPoint)
- player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have received " .. config.ammoPerPoint .. " bullets and you have lost 1 score point.")
- elseif keyword == 'bullet' then
- if not self:isInRange(player) or not self.running then
- player:sendCancelMessage("You need to be in the event.")
- return false
- end
- if player:getStorageValue(self.exhaustStorage) > 1 then
- player:sendCancelMessage("Gun is on cooldown")
- return false
- end
- local ammoStorage = player:getStorageValue(self.ammoStorage)
- if ammoStorage <= 0 then
- player:sendCancelMessage("You're out of ammo, exchange ammo for points with !shoot ammo or get killed for a recharge.")
- return false
- end
- if not config.infiniteAmmo then
- player:setStorageValue(self.ammoStorage, ammoStorage - 1)
- end
- player:setStorageValue(self.exhaustStorage, 2)
- local playerId = player:getId()
- addEvent(
- function(self, playerId)
- local player = Player(playerId)
- if player then
- player:setStorageValue(self.exhaustStorage, 1)
- end
- end, config.bullets.exhaustion, self, playerId
- )
- self:onPlayerShoot(playerId, player:getDirection(), player:getPosition(), 1)
- end
- end
- function PaintballEvent.deinit(self, message)
- if self.endEvent ~= nil then
- stopEvent(self.endEvent)
- self.endEvent = nil
- end
- if #self.joined > 0 then
- for i = 1, #self.joined do
- if message then
- self:releasePlayer(self.joined[i], message)
- end
- end
- end
- self.joined = { }
- self.running = false
- self.teleportIsActive = false
- end
- function PaintballEvent.getTopScorers(self)
- local scores = { }
- for i = 1, #self.joined do
- local tmpPlayer = Player(self.joined[i])
- if tmpPlayer then
- scores[#scores + 1] = {
- id = tmpPlayer:getId(),
- name = tmpPlayer:getName(),
- points = math.max(0, tmpPlayer:getStorageValue(self.scoreStorage))
- }
- end
- end
- table.sort(scores, function(a, b) return a.points > b.points end)
- return scores
- end
- function PaintballEvent.init(self)
- self.teleportIsActive = true
- self.executed = self.executed + 1
- local lastMinute = config.minutesToStart[#config.minutesToStart]
- for _, minutes in ipairs(config.minutesToStart) do
- if minutes == lastMinute then
- addEvent(function(self) self:start() end, minutes * 60000, self)
- else
- 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)
- end
- end
- end
- function PaintballEvent.isInRange(self, player)
- return isInRange(player:getPosition(), config.arena.fromPosition, config.arena.toPosition)
- end
- function PaintballEvent.onPlayerDeath(self, playerId, killerId)
- local player = Player(playerId)
- if not player then
- return
- end
- local killer = Player(killerId)
- if not killer then
- return
- end
- killer:setStorageValue(self.scoreStorage, math.max(0, killer:getStorageValue(self.scoreStorage)) + config.pointsPerKill)
- killer:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You killed " .. player:getName() .. ".")
- local position = getRandomSpawnPosition()
- player:teleportTo(position)
- position:sendMagicEffect(CONST_ME_HOLYAREA)
- player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You were killed by " .. killer:getName() .. ".")
- if config.decreaseScoreOnDeath then
- player:setStorageValue(self.scoreStorage, player:getStorageValue(self.scoreStorage) - 1)
- end
- if config.resetBulletsOnDeath then
- player:setStorageValue(self.ammoStorage, config.minBullets)
- end
- self:broadcastMessage(MESSAGE_EVENT_ADVANCE, string.format("[Paintball Event]: %s were killed by %s.", player:getName(), killer:getName()))
- end
- function PaintballEvent.onPlayerShoot(self, playerId, direction, fromPosition, distance)
- local targetPosition = fromPosition + Position.directionOffset[direction]
- if blockProjectile(targetPosition) then
- targetPosition:sendMagicEffect(CONST_ME_LOSEENERGY)
- return
- end
- fromPosition:sendDistanceEffect(targetPosition, CONST_ANI_SNOWBALL)
- local tile = Tile(targetPosition)
- if tile then
- local creature = tile:getTopCreature()
- if creature and creature:isPlayer() then
- local creatureId = creature:getId()
- if creatureId ~= playerId then
- self:onPlayerDeath(creatureId, playerId)
- targetPosition:sendMagicEffect(CONST_ME_DRAWBLOOD)
- return
- end
- end
- end
- distance = distance + 1
- if distance ~= 6 then
- addEvent(function(self, playerId, direction, fromPosition, distance) self:onPlayerShoot(playerId, direction, fromPosition, distance) end, 150, self, playerId, direction, targetPosition, distance)
- end
- end
- function PaintballEvent.releasePlayer(self, playerId, msg)
- local player = Player(playerId)
- if not player or not self:isInRange(player) then
- return
- end
- player:sendTextMessage(MESSAGE_INFO_DESCR, msg)
- player:teleportTo(player:getTown():getTemplePosition())
- player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
- player:setStorageValue(self.ammoStorage, -1)
- player:setStorageValue(self.scoreStorage, -1)
- player:setStorageValue(self.exhaustStorage, -1)
- end
- function PaintballEvent.removePlayer(self, playerId, msg)
- for i = 1, #self.joined do
- if self.joined[i] == playerId then
- self:releasePlayer(playerId, msg)
- table.remove(self.joined, i)
- break
- end
- end
- end
- function PaintballEvent.start(self)
- local spectators = Game.getSpectators(config.waitingRoomPosition, false, true, 4, 4, 4, 4)
- for i = 1, #spectators do
- self.joined[#self.joined + 1] = spectators[i]:getId()
- end
- if #self.joined < self.minPlayers then
- self:deinit('The Paintball Event did not start due to lack of players.\nYou were teleported back to your temple.')
- Game.broadcastMessage('The Paintball Event did not start due to lack of players.', MESSAGE_EVENT_ADVANCE)
- return
- end
- for i = 1, #self.joined do
- local tmpPlayer = Player(self.joined[i])
- if tmpPlayer then
- local position = getRandomSpawnPosition()
- tmpPlayer:teleportTo(position)
- position:sendMagicEffect(CONST_ME_HOLYAREA)
- tmpPlayer:setStorageValue(self.ammoStorage, config.minBullets)
- tmpPlayer:setStorageValue(self.scoreStorage, 0)
- 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.")
- end
- end
- self.running = true
- self.teleportIsActive = false
- self.nextExecution = (config.minutesToNextExecution * 60) + os.time()
- self.endEvent = addEvent(function(self) self:stop() end, config.minutesToEnd * 60 * 1000, self)
- Game.broadcastMessage('The Paintball Event has started. The event will automatically finish in ' .. config.minutesToEnd .. ' minutes.', MESSAGE_EVENT_ADVANCE)
- end
- function PaintballEvent.stop(self)
- local text = "The paintball event has ended."
- local topScorers = self:getTopScorers()
- if #topScorers > 0 then
- text = string.format("%s\nTop Scorers:\n", text)
- local limit = #topScorers > 5 and 5 or #topScorers
- for i = 1, limit do
- local score = topScorers[i]
- self:addReward(score.id, i)
- text = string.format("%s%d. %s - %d points.\n", text, i, score.name, score.points)
- end
- end
- Game.broadcastMessage(text, MESSAGE_STATUS_WARNING)
- self:deinit(text)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement