From a9e9be612c15c3a4b7d4597a2f72bd6c8be9b457 Mon Sep 17 00:00:00 2001 From: Chalwk77 Date: Thu, 13 Jul 2023 13:50:50 +1200 Subject: [PATCH] . --- INDEV/Battle Royale/about.md | 3 +- INDEV/Battle Royale/countdown/pre_game.lua | 24 +++++--- INDEV/Battle Royale/events/on_death.lua | 26 +++++++++ INDEV/Battle Royale/events/on_pre_spawn.lua | 3 +- INDEV/Battle Royale/events/on_spawn.lua | 56 +++++++++++++++++++ INDEV/Battle Royale/safe zone/hurt_player.lua | 4 +- INDEV/Battle Royale/sky spawning/teleport.lua | 8 ++- INDEV/Battle Royale/spectator/spectate.lua | 3 + INDEV/Battle Royale/weight/weapons.lua | 2 +- 9 files changed, 113 insertions(+), 16 deletions(-) diff --git a/INDEV/Battle Royale/about.md b/INDEV/Battle Royale/about.md index c3ea83ba..e45d5635 100644 --- a/INDEV/Battle Royale/about.md +++ b/INDEV/Battle Royale/about.md @@ -69,10 +69,11 @@ Loot crates will spawn randomly around the map, containing weapons, ammo, and ot # Known bugs: - ~~Energy weapons from loot crates don't have battery power.~~ - ~~Receiving a weapon from a loot crate that you already have caused the server to crash.~~ -- Game doesn't end with the last man standing +- ~Game doesn't end with the last man standing~ - ~~Time remaining HUD keeps resetting when the zone shrinks.~~ - ~~Nuke is crashing the server.~~ - ~~Players are given too many golden bullets. Needs to be limited to 3 max?~~ +- ~Players can spawn outside the safe zone.~ - When receiving an overshield from a loot crate, you won't see the shield bar change until you take damage.
Unfortunately, this is a limitation of Halo's net code. diff --git a/INDEV/Battle Royale/countdown/pre_game.lua b/INDEV/Battle Royale/countdown/pre_game.lua index 8628ae40..30675983 100644 --- a/INDEV/Battle Royale/countdown/pre_game.lua +++ b/INDEV/Battle Royale/countdown/pre_game.lua @@ -63,22 +63,22 @@ function timer:phaseCheck(quit, player) local required_players = self.required_players local game_started = (self.pre_game_timer and self.pre_game_timer.started) + -- Enough players have joined the game, start the pre-game timer: if (count >= required_players and not self.pre_game_timer) then self.pre_game_timer = self:new() self.pre_game_timer:start() - -- Player has joined mid-game: - elseif (not quit and player and count >= required_players and game_started) then - if (self.new_player_spectate) then - player.spectator = true - player:setSpectatorBits() - player:newMessage('You have joined mid-game, you will be able to play next round', 5) - end + -- Player has joined mid-game. Put into spectator mode if enabled: + elseif (not quit and player and count >= required_players and game_started and self.new_player_spectate) then + player.spectator = true + player:setSpectatorBits() + player:newMessage('You have joined mid-game, you will be able to play next round', 5) - -- A player has quit the game before the pre-game timer has elapsed. Reset the timer: + -- A player has quit the game before the pre-game timer has elapsed. + -- Reset the timer: elseif (quit and self.pre_game_timer and not self.pre_game_timer.started) then self.pre_game_timer = nil @@ -86,7 +86,13 @@ function timer:phaseCheck(quit, player) -- The game has started but there is only one player left, end the game: elseif (quit and count == 1 and game_started) then execute_command('sv_map_next') - print('[VICTORY] Game ended - last player wins!') + print('[BATTLE ROYALE] Game ended - last player wins!') + + + -- No players left: + elseif (quit and count == 0) then + execute_command('sv_map_next') + print('[BATTLE ROYALE] Game ended - no players left!') end end diff --git a/INDEV/Battle Royale/events/on_death.lua b/INDEV/Battle Royale/events/on_death.lua index d761c771..bb34092b 100644 --- a/INDEV/Battle Royale/events/on_death.lua +++ b/INDEV/Battle Royale/events/on_death.lua @@ -1,5 +1,24 @@ local event = {} +local function endGame(self) + + local lives = {} + for i,v in pairs(self.players) do + if (v.lives > 0) then + lives[#lives + 1] = v + end + end + + if (#lives == 1) then + execute_command('sv_end_game') + local winner = lives[1] + self:say(string.format('[VICTORY] %s has won the game!', winner.name), true) + return true + end + + return false +end + function event:onDeath(victim) if (not self.pre_game_timer or not self.pre_game_timer.started) then @@ -20,9 +39,16 @@ function event:onDeath(victim) if (player.lives <= 0) then player.spectator = true player:setSpectatorBits() + + local game_over = endGame(self) + if (game_over) then + return + end + for _, v in pairs(self.players) do v:newMessage(player.name .. ' has been eliminated', 5) end + return end diff --git a/INDEV/Battle Royale/events/on_pre_spawn.lua b/INDEV/Battle Royale/events/on_pre_spawn.lua index e005a340..ff51898a 100644 --- a/INDEV/Battle Royale/events/on_pre_spawn.lua +++ b/INDEV/Battle Royale/events/on_pre_spawn.lua @@ -9,7 +9,8 @@ function event:onPreSpawn(id) return end - self.players[id]:teleport() -- sky spawning system / only works if the pre-game timer has elapsed. + -- @args: god, height + self.players[id]:teleport(true, true) end register_callback(cb['EVENT_PRESPAWN'], 'OnPreSpawn') diff --git a/INDEV/Battle Royale/events/on_spawn.lua b/INDEV/Battle Royale/events/on_spawn.lua index 66c17e7d..b82a92fa 100644 --- a/INDEV/Battle Royale/events/on_spawn.lua +++ b/INDEV/Battle Royale/events/on_spawn.lua @@ -12,6 +12,62 @@ function event:onSpawn(id) execute_command('hp ' .. id .. ' ' .. self.health) execute_command('wdel ' .. id) execute_command('s ' .. id .. ' ' .. self.default_running_speed) + + -- + -- Prevents players from spawning outside the safe zone: + -- Only in effect during game play. + -- + + if (player.god) then + return + end + + -- Gets all sky-spawn points: + local spawns = self:getSpawns() + + -- Safe zone X, Y, Z and radius: + local radius = self.safe_zone_size + local bX, bY, bZ = self.safe_zone.x, self.safe_zone.y, self.safe_zone.z + + -- Saves all points inside the circle: + local candidates = {} + for i = 1, #spawns do + local point = spawns[i] + + local x = point[1] + local y = point[2] + local z = point[3] + + local distance = self:getDistance(x, y, z, bX, bY, bZ) + if (distance <= radius) then + candidates[#candidates + 1] = point + end + end + + -- If there are no points inside the circle, then we'll pick the closest one to the centre of the circle: + if (#candidates == 0) then + + local closest + local closest_distance + for i = 1, #spawns do + + local point = spawns[i] + local x = point[1] + local y = point[2] + local z = point[3] + + local distance = self:getDistance(x, y, z, bX, bY, bZ) + if (not closest or distance < closest_distance) then + closest = point + closest_distance = distance + end + end + player.spawn = closest + else + player.spawn = candidates[rand(1, #candidates + 1)] + end + + player:teleport(false, false) end register_callback(cb['EVENT_SPAWN'], 'OnSpawn') diff --git a/INDEV/Battle Royale/safe zone/hurt_player.lua b/INDEV/Battle Royale/safe zone/hurt_player.lua index 71eae7fb..ef10948b 100644 --- a/INDEV/Battle Royale/safe zone/hurt_player.lua +++ b/INDEV/Battle Royale/safe zone/hurt_player.lua @@ -2,7 +2,9 @@ local safe_zone = {} function safe_zone:hurt(player) - if (not player.kill_timer) then + if (self.spectator) then + return + elseif (not player.kill_timer) then player.kill_timer = self:new() player.kill_timer:start() end diff --git a/INDEV/Battle Royale/sky spawning/teleport.lua b/INDEV/Battle Royale/sky spawning/teleport.lua index 8a2d6205..1a6d1f1b 100644 --- a/INDEV/Battle Royale/sky spawning/teleport.lua +++ b/INDEV/Battle Royale/sky spawning/teleport.lua @@ -1,6 +1,6 @@ local player = {} -function player:teleport() +function player:teleport(god, height) local dyn = get_dynamic_player(self.id) if (dyn == 0) then @@ -10,13 +10,15 @@ function player:teleport() local x, y, z = self.spawn[1], self.spawn[2], self.spawn[3] local rotation = self.spawn[4] - local height = self.spawn[5] + height = (height and self.spawn[5]) or 0 write_vector3d(dyn + 0x5C, x, y, z + height) write_vector3d(dyn + 0x74, math.cos(rotation), math.sin(rotation), 0) --print('Spawned: ' .. x .. ', ' .. y .. ', ' .. z, rotation) - self.god = self:new() -- god mode timer + if (god) then + self.god = self:new() -- god mode timer + end end return player \ No newline at end of file diff --git a/INDEV/Battle Royale/spectator/spectate.lua b/INDEV/Battle Royale/spectator/spectate.lua index d75b26aa..311bd09f 100644 --- a/INDEV/Battle Royale/spectator/spectate.lua +++ b/INDEV/Battle Royale/spectator/spectate.lua @@ -28,6 +28,9 @@ function spectator:spectate() -- Force the player into camoflauge mode: execute_command('camo ' .. self.id .. ' 1') + + -- Force the player into god mode: + execute_command('god ' .. self.id) end function spectator:setSpectatorBits() diff --git a/INDEV/Battle Royale/weight/weapons.lua b/INDEV/Battle Royale/weight/weapons.lua index de8bd7c3..8b5d08bd 100644 --- a/INDEV/Battle Royale/weight/weapons.lua +++ b/INDEV/Battle Royale/weight/weapons.lua @@ -20,7 +20,7 @@ function weight:getSpeed() local speed = self.default_running_speed local dyn = get_dynamic_player(self.id) - if (dyn == 0 or not player_alive(self.id)) then + if (dyn == 0 or not player_alive(self.id) or self.spectator) then return speed end