mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2024-12-24 22:14:44 +02:00
358160c247
Revert "Fix 'player' shadowing in flying_texts.lua" This reverts commit 40805e68e3c0bf588b40f510d5c32b66ecca4717. Fix 'player' shadowing in flying_texts.lua all_central_positions_within_area utils/math/raffle
856 lines
29 KiB
Lua
856 lines
29 KiB
Lua
--tank battles (royale)-- by mewmew
|
|
-- modified heavily by gerkiz
|
|
|
|
local Event = require 'utils.event'
|
|
local Global = require 'utils.global'
|
|
local simplex_noise = require 'utils.math.simplex_noise'.d2
|
|
local Core = require 'utils.core'
|
|
local Server = require 'utils.server'
|
|
local Map = require 'modules.map_info'
|
|
|
|
local this = {}
|
|
local arena_size = 160
|
|
local insert = table.insert
|
|
local random = math.random
|
|
|
|
Global.register(
|
|
this,
|
|
function (tbl)
|
|
this = tbl
|
|
end
|
|
)
|
|
|
|
local tile_blacklist = {
|
|
['water'] = true,
|
|
['deepwater'] = true,
|
|
['water-green'] = true,
|
|
['deepwater-green'] = true,
|
|
['out-of-map'] = true,
|
|
['hazard-concrete-left'] = true,
|
|
['hazard-concrete-right'] = true,
|
|
['lab-dark-1'] = true,
|
|
['lab-dark-2'] = true,
|
|
['lab-white'] = true,
|
|
['refined-hazard-concrete-left'] = true,
|
|
['refined-hazard-concrete-right'] = true,
|
|
['water-wube'] = true,
|
|
['tile-unknown'] = true,
|
|
['tutorial-grid'] = true
|
|
}
|
|
|
|
local loot = {
|
|
{ { name = 'flamethrower-ammo', count = 16 }, weight = 2 },
|
|
{ { name = 'piercing-shotgun-shell', count = 16 }, weight = 2 },
|
|
{ { name = 'explosive-rocket', count = 8 }, weight = 2 },
|
|
{ { name = 'rocket', count = 8 }, weight = 2 },
|
|
{ { name = 'grenade', count = 16 }, weight = 2 },
|
|
{ { name = 'cluster-grenade', count = 8 }, weight = 2 },
|
|
{ { name = 'defender-capsule', count = 6 }, weight = 1 },
|
|
{ { name = 'distractor-capsule', count = 3 }, weight = 1 },
|
|
{ { name = 'cannon-shell', count = 8 }, weight = 16 },
|
|
{ { name = 'explosive-cannon-shell', count = 8 }, weight = 16 },
|
|
{ { name = 'uranium-cannon-shell', count = 8 }, weight = 6 },
|
|
{ { name = 'explosive-uranium-cannon-shell', count = 8 }, weight = 6 },
|
|
{ { name = 'energy-shield-equipment', count = 1 }, weight = 2 },
|
|
{ { name = 'fusion-reactor-equipment', count = 1 }, weight = 2 },
|
|
{ { name = 'repair-pack', count = 1 }, weight = 6 },
|
|
{ { name = 'coal', count = 16 }, weight = 3 },
|
|
{ { name = 'nuclear-fuel', count = 1 }, weight = 1 },
|
|
{ { name = 'gate', count = 16 }, weight = 2 },
|
|
{ { name = 'stone-wall', count = 16 }, weight = 2 }
|
|
}
|
|
local loot_raffle = {}
|
|
for _, item in pairs(loot) do
|
|
for _ = 1, item.weight, 1 do
|
|
insert(loot_raffle, item[1])
|
|
end
|
|
end
|
|
|
|
local function shuffle(tbl)
|
|
local size = #tbl
|
|
for i = size, 1, -1 do
|
|
local rand = random(size)
|
|
tbl[i], tbl[rand] = tbl[rand], tbl[i]
|
|
end
|
|
return tbl
|
|
end
|
|
|
|
local function create_gui(player)
|
|
local frame = player.gui.left['status_players']
|
|
if frame and frame.valid then
|
|
return
|
|
end
|
|
|
|
frame = player.gui.left.add({ type = 'frame', name = 'status_players', direction = 'vertical' })
|
|
|
|
local lbl = frame.add({ type = 'label', caption = 'Waiting for more players before round starts.' })
|
|
lbl.style.font_color = { r = 0.98, g = 0.66, b = 0.22 }
|
|
lbl.style.font = 'default-listbox'
|
|
|
|
frame.visible = false
|
|
end
|
|
|
|
local function check_winners()
|
|
local scores = this.tank_battles_score
|
|
if not scores or not next(scores) then
|
|
return
|
|
end
|
|
|
|
for _, score in pairs(scores) do
|
|
if score > 0 then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function get_noise(name, pos)
|
|
local seed = this.noise_seed
|
|
local noise = {}
|
|
local noise_seed_add = 25000
|
|
if name == 'rocks' then
|
|
noise[1] = simplex_noise(pos.x * 0.02, pos.y * 0.02, seed)
|
|
seed = seed + noise_seed_add
|
|
noise[2] = simplex_noise(pos.x * 0.1, pos.y * 0.1, seed)
|
|
local noise_amp = noise[1] + noise[2] * 0.2
|
|
return noise_amp
|
|
end
|
|
seed = seed + noise_seed_add
|
|
seed = seed + noise_seed_add
|
|
if name == 'rocks_2' then
|
|
noise[1] = simplex_noise(pos.x * 0.02, pos.y * 0.02, seed)
|
|
seed = seed + noise_seed_add
|
|
noise[2] = simplex_noise(pos.x * 0.1, pos.y * 0.1, seed)
|
|
local noise_amp = noise[1] + noise[2] * 0.2
|
|
return noise_amp
|
|
end
|
|
seed = seed + noise_seed_add
|
|
seed = seed + noise_seed_add
|
|
if name == 'terrain' then
|
|
noise[1] = simplex_noise(pos.x * 0.02, pos.y * 0.02, seed)
|
|
seed = seed + noise_seed_add
|
|
noise[2] = simplex_noise(pos.x * 0.1, pos.y * 0.1, seed)
|
|
local noise_amp = noise[1] + noise[2] * 0.2
|
|
return noise_amp
|
|
end
|
|
end
|
|
|
|
local function create_tank_battle_score_gui()
|
|
if not check_winners() then
|
|
return
|
|
end
|
|
|
|
local scores = {}
|
|
Core.iter_connected_players(
|
|
function (player_amp)
|
|
if this.tank_battles_score[player_amp.index] then
|
|
insert(scores, { name = player_amp.name, score = this.tank_battles_score[player_amp.index], color = player_amp.color })
|
|
end
|
|
end
|
|
)
|
|
|
|
if scores and #scores == 0 then
|
|
return
|
|
end
|
|
|
|
Core.iter_connected_players(
|
|
function (player)
|
|
local frame = player.gui.left['tank_battle_score']
|
|
if frame and frame.valid then
|
|
frame.destroy()
|
|
end
|
|
|
|
frame = player.gui.left.add({ type = 'frame', name = 'tank_battle_score', direction = 'vertical' })
|
|
|
|
local lbl = frame.add({ type = 'label', caption = 'Won rounds' })
|
|
lbl.style.font_color = { r = 0.98, g = 0.66, b = 0.22 }
|
|
lbl.style.font = 'default-listbox'
|
|
|
|
local t = frame.add({ type = 'table', column_count = 2 })
|
|
|
|
for _ = 1, #scores, 1 do
|
|
for y = 1, #scores, 1 do
|
|
if not scores[y + 1] then
|
|
break
|
|
end
|
|
if scores[y]['score'] < scores[y + 1]['score'] then
|
|
local key = scores[y]
|
|
scores[y] = scores[y + 1]
|
|
scores[y + 1] = key
|
|
end
|
|
end
|
|
end
|
|
|
|
for i = 1, 8, 1 do
|
|
if scores[i] then
|
|
local player_name = scores[i].name
|
|
local player_color = scores[i].color
|
|
local player_score = scores[i].score
|
|
local l = t.add({ type = 'label', caption = player_name })
|
|
player_color = { r = player_color.r * 0.6 + 0.4, g = player_color.g * 0.6 + 0.4, b = player_color.b * 0.6 + 0.4, a = 1 }
|
|
l.style.font_color = player_color
|
|
l.style.font = 'default-bold'
|
|
t.add({ type = 'label', caption = player_score })
|
|
end
|
|
end
|
|
end
|
|
)
|
|
end
|
|
|
|
local function get_valid_random_spawn_position(surface, chunks)
|
|
chunks = shuffle(chunks)
|
|
|
|
for _, chunk in pairs(chunks) do
|
|
if chunk.x * 32 < arena_size and chunk.y * 32 < arena_size and chunk.x * 32 >= arena_size * -1 and chunk.y * 32 >= arena_size * -1 then
|
|
local area = { { chunk.x * 32 - 64, chunk.y * 32 - 64 }, { chunk.x * 32 + 64, chunk.y * 32 + 64 } }
|
|
if surface.count_entities_filtered({ name = 'tank', area = area }) == 0 then
|
|
local pos = surface.find_non_colliding_position('tank', { chunk.x * 32 + 16, chunk.y * 32 + 16 }, 16, 8)
|
|
return pos
|
|
end
|
|
end
|
|
end
|
|
|
|
local pos = surface.find_non_colliding_position('tank', { 0, 0 }, 32, 4)
|
|
if pos then
|
|
return pos
|
|
end
|
|
|
|
return { 0, 0 }
|
|
end
|
|
|
|
local function put_players_into_arena()
|
|
local surface = game.get_surface('nauvis')
|
|
|
|
local chunks = {}
|
|
for chunk in surface.get_chunks() do
|
|
insert(chunks, { x = chunk.x, y = chunk.y })
|
|
end
|
|
|
|
Core.iter_connected_players(
|
|
function (player)
|
|
local permissions_group = game.permissions.get_group('Default')
|
|
permissions_group.add_player(player.name)
|
|
|
|
if player.character then
|
|
player.character.destroy()
|
|
player.character = nil
|
|
end
|
|
|
|
player.create_character()
|
|
|
|
player.insert({ name = 'combat-shotgun', count = 1 })
|
|
player.insert({ name = 'rocket-launcher', count = 1 })
|
|
player.insert({ name = 'flamethrower', count = 1 })
|
|
|
|
local pos = get_valid_random_spawn_position(surface, chunks)
|
|
|
|
player.force.chart(surface, { { x = -1 * arena_size, y = -1 * arena_size }, { x = arena_size, y = arena_size } })
|
|
|
|
if pos then
|
|
player.teleport(pos, surface)
|
|
else
|
|
pos = get_valid_random_spawn_position(surface, chunks)
|
|
end
|
|
local tank = surface.create_entity({ name = 'tank', force = game.forces[player.name], position = pos })
|
|
tank.insert({ name = 'coal', count = 24 })
|
|
tank.insert({ name = 'cannon-shell', count = 16 })
|
|
tank.set_driver(player)
|
|
end
|
|
)
|
|
end
|
|
|
|
local function get_arena_layout_modifiers()
|
|
this.arena_layout_modifiers = {}
|
|
local proto = prototypes.entity
|
|
|
|
local tree_raffle = {}
|
|
for _, e in pairs(proto) do
|
|
if e.type == 'tree' then
|
|
insert(tree_raffle, e.name)
|
|
end
|
|
end
|
|
this.arena_layout_modifiers.arena_tree = tree_raffle[random(1, #tree_raffle)]
|
|
this.arena_layout_modifiers.arena_tree_chance = random(4, 20)
|
|
this.arena_layout_modifiers.arena_tree_noise = random(0, 75) * 0.01
|
|
|
|
local entity_raffle = {}
|
|
local types = { 'furnace', 'assembling-machine', 'power-switch', 'programmable-speaker', 'reactor' }
|
|
for _, e in pairs(proto) do
|
|
for _, t in pairs(types) do
|
|
if e.type == t then
|
|
insert(entity_raffle, e.name)
|
|
end
|
|
end
|
|
end
|
|
this.arena_layout_modifiers.secret_entity = entity_raffle[random(1, #entity_raffle)]
|
|
|
|
local tile_raffle = {}
|
|
|
|
for _, t in pairs(prototypes.tile) do
|
|
if not tile_blacklist[t.name] then
|
|
insert(tile_raffle, t.name)
|
|
end
|
|
end
|
|
this.arena_layout_modifiers.arena_tile_1 = tile_raffle[random(1, #tile_raffle)]
|
|
this.arena_layout_modifiers.arena_tile_2 = tile_raffle[random(1, #tile_raffle)]
|
|
end
|
|
|
|
local function regenerate_arena()
|
|
local surface = game.get_surface('nauvis')
|
|
for chunk in surface.get_chunks() do
|
|
surface.set_chunk_generated_status({ x = chunk.x, y = chunk.y }, defines.chunk_generated_status.custom_tiles)
|
|
end
|
|
|
|
this.noise_seed = nil
|
|
---@diagnostic disable-next-line: param-type-mismatch
|
|
surface.request_to_generate_chunks({ 0, 0 }, math.ceil(arena_size / 32) + 3)
|
|
|
|
get_arena_layout_modifiers()
|
|
|
|
surface.force_generate_chunk_requests()
|
|
surface.daytime = 1
|
|
surface.freeze_daytime = 1
|
|
|
|
this.current_arena_size = arena_size
|
|
|
|
put_players_into_arena()
|
|
|
|
this.game_stage = 'ongoing_game'
|
|
end
|
|
|
|
local function shrink_arena()
|
|
local surface = game.get_surface('nauvis')
|
|
|
|
if this.current_arena_size < 0 then
|
|
return
|
|
end
|
|
|
|
local shrink_width = 8
|
|
local current_arena_size = this.current_arena_size
|
|
local tiles = {}
|
|
|
|
for x = arena_size * -1, arena_size, 1 do
|
|
for y = current_arena_size * -1 - shrink_width, current_arena_size * -1, 1 do
|
|
local pos = { x = x, y = y }
|
|
local tile = surface.get_tile(pos.x, pos.y)
|
|
if tile.name ~= 'water' and tile.name ~= 'deepwater' then
|
|
if x > current_arena_size or y > current_arena_size or x < current_arena_size * -1 or y < current_arena_size * -1 then
|
|
if random(1, 3) ~= 1 then
|
|
insert(tiles, { name = 'water', position = pos })
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for x = arena_size * -1, arena_size, 1 do
|
|
for y = current_arena_size, current_arena_size + shrink_width, 1 do
|
|
local pos = { x = x, y = y }
|
|
local tile = surface.get_tile(pos.x, pos.y)
|
|
if tile.name ~= 'water' and tile.name ~= 'deepwater' then
|
|
if x > current_arena_size or y > current_arena_size or x < current_arena_size * -1 or y < current_arena_size * -1 then
|
|
if random(1, 3) ~= 1 then
|
|
insert(tiles, { name = 'water', position = pos })
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for x = current_arena_size * -1 - shrink_width, current_arena_size * -1, 1 do
|
|
for y = arena_size * -1, arena_size, 1 do
|
|
local pos = { x = x, y = y }
|
|
local tile = surface.get_tile(pos.x, pos.y)
|
|
if tile.name ~= 'water' and tile.name ~= 'deepwater' then
|
|
if x > current_arena_size or y > current_arena_size or x < current_arena_size * -1 or y < current_arena_size * -1 then
|
|
if random(1, 3) ~= 1 then
|
|
insert(tiles, { name = 'water', position = pos })
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for x = current_arena_size, current_arena_size + shrink_width, 1 do
|
|
for y = arena_size * -1, arena_size, 1 do
|
|
local pos = { x = x, y = y }
|
|
local tile = surface.get_tile(pos.x, pos.y)
|
|
if tile.name ~= 'water' and tile.name ~= 'deepwater' then
|
|
if x > current_arena_size or y > current_arena_size or x < current_arena_size * -1 or y < current_arena_size * -1 then
|
|
if random(1, 3) ~= 1 then
|
|
insert(tiles, { name = 'water', position = pos })
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
this.current_arena_size = this.current_arena_size - 1
|
|
|
|
surface.set_tiles(tiles, true)
|
|
end
|
|
|
|
local function get_arena_entity(surface, pos)
|
|
local noise = get_noise('rocks', pos)
|
|
local noise2 = get_noise('rocks_2', pos)
|
|
|
|
if noise > -0.1 and noise < 0.1 and noise2 > -0.3 and noise2 < 0.3 then
|
|
return { name = 'big-rock', position = pos }
|
|
end
|
|
|
|
if random(1, 16) == 1 and noise2 > 0.78 then
|
|
if surface.can_place_entity({ name = 'wooden-chest', position = pos, force = 'enemy' }) then
|
|
return { name = 'wooden-chest', position = pos, force = 'enemy' }
|
|
end
|
|
end
|
|
|
|
if random(1, 16) == 1 and noise2 < -0.78 then
|
|
if surface.can_place_entity({ name = 'wooden-chest', position = pos, force = 'enemy' }) then
|
|
return { name = 'wooden-chest', position = pos, force = 'enemy' }
|
|
end
|
|
end
|
|
|
|
if random(1, this.arena_layout_modifiers.arena_tree_chance) == 1 and noise > this.arena_layout_modifiers.arena_tree_noise then
|
|
return { name = this.arena_layout_modifiers.arena_tree, position = pos }
|
|
end
|
|
|
|
if random(1, 1024) == 1 then
|
|
if random(1, 16) == 1 then
|
|
if surface.can_place_entity({ name = this.arena_layout_modifiers.secret_entity, position = pos, force = 'enemy' }) then
|
|
return { name = this.arena_layout_modifiers.secret_entity, position = pos, force = 'enemy' }
|
|
end
|
|
end
|
|
if random(1, 64) == 1 then
|
|
if surface.can_place_entity({ name = 'big-worm-turret', position = pos, force = 'enemy' }) then
|
|
return { name = 'big-worm-turret', position = pos, force = 'enemy' }
|
|
end
|
|
end
|
|
if random(1, 32) == 1 then
|
|
if surface.can_place_entity({ name = 'medium-worm-turret', position = pos, force = 'enemy' }) then
|
|
return { name = 'medium-worm-turret', position = pos, force = 'enemy' }
|
|
end
|
|
end
|
|
if random(1, 512) == 1 then
|
|
if surface.can_place_entity({ name = 'behemoth-biter', position = pos, force = 'enemy' }) then
|
|
return { name = 'behemoth-biter', position = pos, force = 'enemy' }
|
|
end
|
|
end
|
|
if random(1, 64) == 1 then
|
|
if surface.can_place_entity({ name = 'big-biter', position = pos, force = 'enemy' }) then
|
|
return { name = 'big-biter', position = pos, force = 'enemy' }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function render_arena_chunk(event)
|
|
if not this.noise_seed then
|
|
this.noise_seed = random(1, 2097152)
|
|
end
|
|
local surface = event.surface
|
|
local left_top = event.area.left_top
|
|
|
|
for _, entity in pairs(surface.find_entities_filtered({ area = event.area })) do
|
|
if entity and entity.valid then
|
|
if entity.name ~= 'character' then
|
|
entity.destroy()
|
|
end
|
|
end
|
|
end
|
|
|
|
local tiles = {}
|
|
for x = 0, 31, 1 do
|
|
for y = 0, 31, 1 do
|
|
local pos = { x = left_top.x + x, y = left_top.y + y }
|
|
if pos.x > arena_size or pos.y > arena_size or pos.x < arena_size * -1 or pos.y < arena_size * -1 then
|
|
insert(tiles, { name = 'water', position = pos })
|
|
else
|
|
local noise = get_noise('terrain', pos)
|
|
if noise > 0 then
|
|
insert(tiles, { name = this.arena_layout_modifiers.arena_tile_1, position = pos })
|
|
else
|
|
insert(tiles, { name = this.arena_layout_modifiers.arena_tile_2, position = pos })
|
|
end
|
|
local entity = get_arena_entity(surface, pos)
|
|
if entity then
|
|
surface.create_entity(entity)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
surface.set_tiles(tiles, true)
|
|
end
|
|
|
|
local function kill_idle_players()
|
|
Core.iter_connected_players(
|
|
function (player)
|
|
if player.character then
|
|
if player.afk_time > 600 then
|
|
local area = { { player.position.x - 1, player.position.y - 1 }, { player.position.x + 1, player.position.y + 1 } }
|
|
local water_tile_count = player.surface.count_tiles_filtered({ name = { 'water', 'deepwater' }, area = area })
|
|
if water_tile_count and water_tile_count > 3 then
|
|
player.character.die()
|
|
game.print(player.name .. ' drowned.', { r = 150, g = 150, b = 0 })
|
|
else
|
|
if player.afk_time > 9000 then
|
|
player.character.die()
|
|
game.print(player.name .. ' was idle for too long.', { r = 150, g = 150, b = 0 })
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
)
|
|
end
|
|
|
|
local function check_for_game_over()
|
|
kill_idle_players()
|
|
|
|
local alive_players = 0
|
|
|
|
create_tank_battle_score_gui()
|
|
|
|
Core.iter_connected_players(
|
|
function (player)
|
|
if player.character and player.driving then
|
|
alive_players = alive_players + 1
|
|
end
|
|
end
|
|
)
|
|
|
|
if alive_players > 1 then
|
|
return
|
|
end
|
|
|
|
local player
|
|
Core.iter_connected_players(
|
|
function (player_amp)
|
|
if player_amp.character and player_amp.driving then
|
|
player = player_amp
|
|
end
|
|
end
|
|
)
|
|
|
|
if alive_players == 1 then
|
|
if not this.tank_battles_score[player.index] then
|
|
this.tank_battles_score[player.index] = 1
|
|
else
|
|
this.tank_battles_score[player.index] = this.tank_battles_score[player.index] + 1
|
|
end
|
|
game.print(player.name .. ' has won the battle!', { r = 150, g = 150, b = 0 })
|
|
Server.to_discord_embed(player.name .. ' has won the battle!')
|
|
create_tank_battle_score_gui()
|
|
end
|
|
|
|
if alive_players == 0 then
|
|
game.print('No players alive! Round ends in a draw!', { r = 150, g = 150, b = 0 })
|
|
Server.to_discord_embed('No players alive! Round ends in a draw!')
|
|
end
|
|
|
|
this.game_stage = 'lobby'
|
|
end
|
|
|
|
local function set_unique_player_force(player)
|
|
local player_force = game.forces[player.name]
|
|
if not player_force then
|
|
player_force = game.create_force(player.name)
|
|
player_force.share_chart = false
|
|
player_force.clear_chart(player.surface.name)
|
|
player_force.technologies['follower-robot-count-1'].researched = true
|
|
player_force.technologies['follower-robot-count-2'].researched = true
|
|
player_force.technologies['follower-robot-count-3'].researched = true
|
|
player_force.technologies['follower-robot-count-4'].researched = true
|
|
player_force.technologies['follower-robot-count-5'].researched = true
|
|
end
|
|
player.force = player_force
|
|
end
|
|
|
|
local function remove_unique_player_force(player)
|
|
if not player or not player.valid then
|
|
return
|
|
end
|
|
|
|
local player_force = game.forces[player.name]
|
|
local enemy_force = game.forces.enemy
|
|
if player_force then
|
|
print('remove_unique_player_force - removing force with name: ' .. player.name)
|
|
game.merge_forces(player_force, enemy_force)
|
|
end
|
|
end
|
|
|
|
local function on_chunk_charted(event)
|
|
local force = event.force
|
|
local surface = game.get_surface('nauvis')
|
|
|
|
if not surface or not surface.valid then
|
|
return
|
|
end
|
|
if force.valid then
|
|
force.clear_chart(surface)
|
|
end
|
|
end
|
|
|
|
local function check_obsolete_forces()
|
|
for _, force in pairs(game.forces) do
|
|
if force and force.valid then
|
|
if force.name ~= 'enemy' and force.name ~= 'player' and force.name ~= 'neutral' then
|
|
if #force.connected_players == 0 then
|
|
remove_unique_player_force(force)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function on_player_joined_game(event)
|
|
local player = game.get_player(event.player_index)
|
|
|
|
set_unique_player_force(player)
|
|
|
|
create_gui(player)
|
|
|
|
create_tank_battle_score_gui()
|
|
|
|
player.map_view_settings = {
|
|
['show-player-names'] = false
|
|
}
|
|
player.show_on_map = false
|
|
local game_view_settings = {
|
|
show_minimap = false
|
|
}
|
|
player.game_view_settings = game_view_settings
|
|
|
|
if player.character then
|
|
player.character.destroy()
|
|
end
|
|
|
|
if this.game_stage == 'ongoing_game' then
|
|
player.print("There is currently an ongoing match - please wait until it's over.")
|
|
end
|
|
|
|
local permissions_group = game.permissions.get_group('Spectator')
|
|
permissions_group.add_player(player.name)
|
|
player.teleport({ 0, 0 }, 'nauvis')
|
|
end
|
|
|
|
local function on_player_driving_changed_state(event)
|
|
local player = game.get_player(event.player_index)
|
|
local entity = event.entity
|
|
|
|
if not entity or not entity.valid then
|
|
return
|
|
end
|
|
|
|
if not player.driving then
|
|
entity.set_driver(player)
|
|
end
|
|
end
|
|
|
|
local function on_player_left_game(event)
|
|
local player = game.get_player(event.player_index)
|
|
|
|
remove_unique_player_force(player)
|
|
end
|
|
|
|
local function on_marked_for_deconstruction(event)
|
|
local entity = event.entity
|
|
if entity and entity.valid then
|
|
local player = game.get_player(event.player_index)
|
|
entity.cancel_deconstruction(player.force.name)
|
|
end
|
|
end
|
|
|
|
local function on_chunk_generated(event)
|
|
render_arena_chunk(event)
|
|
end
|
|
|
|
local function on_player_respawned(event)
|
|
local player = game.get_player(event.player_index)
|
|
|
|
local permissions_group = game.permissions.get_group('Spectator')
|
|
permissions_group.add_player(player.name)
|
|
player.character.destroy()
|
|
player.character = nil
|
|
|
|
player.print('You are now spectating.', { r = 0, g = 150, b = 150 })
|
|
end
|
|
|
|
local function lobby()
|
|
local connected_players_count = #game.connected_players
|
|
|
|
if connected_players_count < 2 then
|
|
Core.iter_connected_players(
|
|
function (player)
|
|
create_gui(player)
|
|
local gui = player.gui.left.status_players
|
|
if gui and gui.valid then
|
|
gui.visible = true
|
|
end
|
|
end
|
|
)
|
|
return
|
|
end
|
|
|
|
Core.iter_connected_players(
|
|
function (player)
|
|
local gui = player.gui.left.status_players
|
|
if gui and gui.valid then
|
|
gui.visible = false
|
|
end
|
|
end
|
|
)
|
|
|
|
if not this.lobby_timer then
|
|
this.lobby_timer = 1200
|
|
end
|
|
if this.lobby_timer % 600 == 0 then
|
|
if this.lobby_timer <= 0 then
|
|
game.print('Round has started!', { r = 0, g = 150, b = 150 })
|
|
Server.to_discord_embed('Round has started!')
|
|
else
|
|
game.print('Round will begin in ' .. this.lobby_timer / 60 .. ' seconds.', { r = 0, g = 150, b = 150 })
|
|
Server.to_discord_embed('Round will begin in ' .. this.lobby_timer / 60 .. ' seconds.')
|
|
end
|
|
end
|
|
this.lobby_timer = this.lobby_timer - 300
|
|
if this.lobby_timer >= 0 then
|
|
return
|
|
end
|
|
this.lobby_timer = nil
|
|
this.game_stage = 'regenerate_arena'
|
|
end
|
|
|
|
local function on_tick()
|
|
local tick = game.tick
|
|
if tick % 300 == 0 then
|
|
if this.game_stage == 'lobby' then
|
|
lobby()
|
|
end
|
|
if this.game_stage == 'regenerate_arena' then
|
|
regenerate_arena()
|
|
end
|
|
if this.game_stage == 'ongoing_game' then
|
|
shrink_arena()
|
|
check_for_game_over()
|
|
end
|
|
end
|
|
if tick % 1000 == 0 then
|
|
check_obsolete_forces()
|
|
end
|
|
end
|
|
|
|
local function on_entity_died(event)
|
|
local entity = event.entity
|
|
if not entity or not entity.valid then
|
|
return
|
|
end
|
|
|
|
if entity.name == 'wooden-chest' then
|
|
local loot_amp = loot_raffle[random(1, #loot_raffle)]
|
|
entity.surface.spill_item_stack(entity.position, loot_amp, true)
|
|
end
|
|
end
|
|
|
|
local function on_player_died(event)
|
|
local player = game.get_player(event.player_index)
|
|
local str = ' '
|
|
if event.cause then
|
|
if event.cause.name ~= nil then
|
|
str = ' by ' .. event.cause.name
|
|
end
|
|
if event.cause.name == 'character' then
|
|
str = ' by ' .. event.cause.player.name
|
|
end
|
|
if event.cause.name == 'tank' then
|
|
local driver = event.cause.get_driver()
|
|
if driver.player then
|
|
str = ' by ' .. driver.player.name
|
|
end
|
|
end
|
|
end
|
|
Core.iter_connected_players(
|
|
function (target_player)
|
|
if target_player.name ~= player.name then
|
|
player.print(player.name .. ' was killed' .. str, { r = 0.99, g = 0.0, b = 0.0 })
|
|
end
|
|
end
|
|
)
|
|
end
|
|
|
|
local function on_console_chat(event)
|
|
if not event.message then
|
|
return
|
|
end
|
|
if not event.player_index then
|
|
return
|
|
end
|
|
local player = game.get_player(event.player_index)
|
|
|
|
local color = player.color
|
|
color.r = color.r * 0.6 + 0.35
|
|
color.g = color.g * 0.6 + 0.35
|
|
color.b = color.b * 0.6 + 0.35
|
|
color.a = 1
|
|
|
|
Core.iter_connected_players(
|
|
function (target_player)
|
|
if target_player.name ~= player.name then
|
|
target_player.print(player.name .. ': ' .. event.message, color)
|
|
end
|
|
end
|
|
)
|
|
end
|
|
|
|
Event.on_init(
|
|
function ()
|
|
local surface = game.get_surface('nauvis')
|
|
local mgs = surface.map_gen_settings
|
|
mgs.width = 400
|
|
mgs.height = 400
|
|
surface.map_gen_settings = mgs
|
|
surface.clear()
|
|
|
|
local spectator_permission_group = game.permissions.create_group('Spectator')
|
|
for action_name, _ in pairs(defines.input_action) do
|
|
spectator_permission_group.set_allows_action(defines.input_action[action_name], false)
|
|
end
|
|
spectator_permission_group.set_allows_action(defines.input_action.write_to_console, true)
|
|
spectator_permission_group.set_allows_action(defines.input_action.gui_click, true)
|
|
spectator_permission_group.set_allows_action(defines.input_action.gui_selection_state_changed, true)
|
|
spectator_permission_group.set_allows_action(defines.input_action.start_walking, true)
|
|
spectator_permission_group.set_allows_action(defines.input_action.open_character_gui, true)
|
|
spectator_permission_group.set_allows_action(defines.input_action.edit_permission_group, true)
|
|
spectator_permission_group.set_allows_action(defines.input_action.toggle_show_entity_info, true)
|
|
|
|
get_arena_layout_modifiers()
|
|
|
|
this.tank_battles_score = {}
|
|
this.game_stage = 'lobby'
|
|
|
|
local T = Map.Pop_info()
|
|
T.main_caption = 'The eternal battle of tanks'
|
|
T.sub_caption = 'a playground made for tanks'
|
|
T.text =
|
|
table.concat(
|
|
{
|
|
'The opponent wants your tank destroyed! Destroy their tank to win the round!\n',
|
|
'\n',
|
|
"The tank doors has oddly malfunctioned and you're locked inside.\n",
|
|
'\n',
|
|
'Destroying wooden chests seems to grant loot.\n'
|
|
}
|
|
)
|
|
end
|
|
)
|
|
Event.add(defines.events.on_tick, on_tick)
|
|
Event.add(defines.events.on_console_chat, on_console_chat)
|
|
Event.add(defines.events.on_entity_died, on_entity_died)
|
|
Event.add(defines.events.on_player_died, on_player_died)
|
|
Event.add(defines.events.on_marked_for_deconstruction, on_marked_for_deconstruction)
|
|
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
|
Event.add(defines.events.on_player_left_game, on_player_left_game)
|
|
Event.add(defines.events.on_player_respawned, on_player_respawned)
|
|
Event.add(defines.events.on_chunk_generated, on_chunk_generated)
|
|
Event.add(defines.events.on_player_driving_changed_state, on_player_driving_changed_state)
|
|
Event.add(defines.events.on_chunk_charted, on_chunk_charted)
|