1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-06 00:23:49 +02:00
ComfyFactorio/maps/tank_battles.lua

856 lines
28 KiB
Lua
Raw Normal View History

2023-10-25 20:57:08 +02:00
--tank battles (royale)-- by mewmew
-- modified heavily by gerkiz
local Event = require 'utils.event'
local Global = require 'utils.global'
local simplex_noise = require 'utils.simplex_noise'.d2
local Core = require 'utils.core'
local Server = require 'utils.server'
local Map = require 'modules.map_info'
local this = {}
2018-12-18 06:36:23 +02:00
local arena_size = 160
2023-10-25 20:57:08 +02:00
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
2018-12-17 11:24:01 +02:00
local function shuffle(tbl)
2021-03-24 17:46:00 +02:00
local size = #tbl
for i = size, 1, -1 do
2023-10-25 20:57:08 +02:00
local rand = random(size)
2021-03-24 17:46:00 +02:00
tbl[i], tbl[rand] = tbl[rand], tbl[i]
end
return tbl
2018-12-17 11:24:01 +02:00
end
2023-10-25 20:57:08 +02:00
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
2021-03-24 17:46:00 +02:00
local function get_noise(name, pos)
2023-10-25 20:57:08 +02:00
local seed = this.noise_seed
2021-03-24 17:46:00 +02:00
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)
2023-10-25 20:57:08 +02:00
local noise_amp = noise[1] + noise[2] * 0.2
return noise_amp
2021-03-24 17:46:00 +02:00
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)
2023-10-25 20:57:08 +02:00
local noise_amp = noise[1] + noise[2] * 0.2
return noise_amp
2021-03-24 17:46:00 +02:00
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)
2023-10-25 20:57:08 +02:00
local noise_amp = noise[1] + noise[2] * 0.2
return noise_amp
2021-03-24 17:46:00 +02:00
end
2018-12-28 01:23:38 +02:00
end
2018-12-17 11:24:01 +02:00
local function create_tank_battle_score_gui()
2023-10-25 20:57:08 +02:00
if not check_winners() then
return
end
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
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
)
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
if scores and #scores == 0 then
return
end
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
Core.iter_connected_players(
function(player)
local frame = player.gui.left['tank_battle_score']
if frame and frame.valid then
frame.destroy()
2021-03-24 17:46:00 +02:00
end
2023-10-25 20:57:08 +02:00
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
2021-03-24 17:46:00 +02:00
end
end
2023-10-25 20:57:08 +02:00
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
2021-03-24 17:46:00 +02:00
end
end
2023-10-25 20:57:08 +02:00
)
2018-12-17 11:24:01 +02:00
end
2023-11-05 17:35:19 +02:00
local function get_valid_random_spawn_position(surface, chunks)
2021-03-24 17:46:00 +02:00
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}
2018-12-17 11:24:01 +02:00
end
local function put_players_into_arena()
2023-11-05 17:35:19 +02:00
local surface = game.get_surface('nauvis')
local chunks = {}
for chunk in surface.get_chunks() do
insert(chunks, {x = chunk.x, y = chunk.y})
end
2023-10-25 20:57:08 +02:00
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
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
player.create_character()
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
player.insert({name = 'combat-shotgun', count = 1})
player.insert({name = 'rocket-launcher', count = 1})
player.insert({name = 'flamethrower', count = 1})
2021-03-24 17:46:00 +02:00
2023-11-05 17:35:19 +02:00
local pos = get_valid_random_spawn_position(surface, chunks)
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
player.force.chart(surface, {{x = -1 * arena_size, y = -1 * arena_size}, {x = arena_size, y = arena_size}})
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
if pos then
player.teleport(pos, surface)
else
2023-11-05 17:35:19 +02:00
pos = get_valid_random_spawn_position(surface, chunks)
2023-10-25 20:57:08 +02:00
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
)
2018-12-17 11:24:01 +02:00
end
2018-12-28 15:49:37 +02:00
local function get_arena_layout_modifiers()
2023-10-25 20:57:08 +02:00
this.arena_layout_modifiers = {}
local proto = game.entity_prototypes
2021-03-24 17:46:00 +02:00
local tree_raffle = {}
2023-10-25 20:57:08 +02:00
for _, e in pairs(proto) do
2021-03-24 17:46:00 +02:00
if e.type == 'tree' then
2023-10-25 20:57:08 +02:00
insert(tree_raffle, e.name)
2021-03-24 17:46:00 +02:00
end
end
2023-10-25 20:57:08 +02:00
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
2021-03-24 17:46:00 +02:00
local entity_raffle = {}
local types = {'furnace', 'assembling-machine', 'power-switch', 'programmable-speaker', 'reactor'}
2023-10-25 20:57:08 +02:00
for _, e in pairs(proto) do
2021-03-24 17:46:00 +02:00
for _, t in pairs(types) do
if e.type == t then
2023-10-25 20:57:08 +02:00
insert(entity_raffle, e.name)
2021-03-24 17:46:00 +02:00
end
end
end
2023-10-25 20:57:08 +02:00
this.arena_layout_modifiers.secret_entity = entity_raffle[random(1, #entity_raffle)]
2021-03-24 17:46:00 +02:00
local tile_raffle = {}
2023-10-25 20:57:08 +02:00
2021-03-24 17:46:00 +02:00
for _, t in pairs(game.tile_prototypes) do
if not tile_blacklist[t.name] then
2023-10-25 20:57:08 +02:00
insert(tile_raffle, t.name)
2021-03-24 17:46:00 +02:00
end
end
2023-10-25 20:57:08 +02:00
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)]
2018-12-28 15:49:37 +02:00
end
local function regenerate_arena()
2023-10-25 20:57:08 +02:00
local surface = game.get_surface('nauvis')
2021-03-24 17:46:00 +02:00
for chunk in surface.get_chunks() do
2023-10-25 20:57:08 +02:00
surface.set_chunk_generated_status({x = chunk.x, y = chunk.y}, defines.chunk_generated_status.custom_tiles)
2021-03-24 17:46:00 +02:00
end
2023-10-25 20:57:08 +02:00
this.noise_seed = nil
---@diagnostic disable-next-line: param-type-mismatch
2021-03-24 17:46:00 +02:00
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
2023-10-25 20:57:08 +02:00
this.current_arena_size = arena_size
2021-03-24 17:46:00 +02:00
put_players_into_arena()
2023-10-25 20:57:08 +02:00
this.game_stage = 'ongoing_game'
2018-12-17 11:24:01 +02:00
end
2023-10-25 20:57:08 +02:00
local function shrink_arena()
local surface = game.get_surface('nauvis')
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
if this.current_arena_size < 0 then
2021-03-24 17:46:00 +02:00
return
end
local shrink_width = 8
2023-10-25 20:57:08 +02:00
local current_arena_size = this.current_arena_size
2021-03-24 17:46:00 +02:00
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}
2023-10-25 20:57:08 +02:00
local tile = surface.get_tile(pos.x, pos.y)
if tile.name ~= 'water' and tile.name ~= 'deepwater' then
2021-03-24 17:46:00 +02:00
if x > current_arena_size or y > current_arena_size or x < current_arena_size * -1 or y < current_arena_size * -1 then
2023-10-25 20:57:08 +02:00
if random(1, 3) ~= 1 then
insert(tiles, {name = 'water', position = pos})
2021-03-24 17:46:00 +02:00
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}
2023-10-25 20:57:08 +02:00
local tile = surface.get_tile(pos.x, pos.y)
if tile.name ~= 'water' and tile.name ~= 'deepwater' then
2021-03-24 17:46:00 +02:00
if x > current_arena_size or y > current_arena_size or x < current_arena_size * -1 or y < current_arena_size * -1 then
2023-10-25 20:57:08 +02:00
if random(1, 3) ~= 1 then
insert(tiles, {name = 'water', position = pos})
2021-03-24 17:46:00 +02:00
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}
2023-10-25 20:57:08 +02:00
local tile = surface.get_tile(pos.x, pos.y)
if tile.name ~= 'water' and tile.name ~= 'deepwater' then
2021-03-24 17:46:00 +02:00
if x > current_arena_size or y > current_arena_size or x < current_arena_size * -1 or y < current_arena_size * -1 then
2023-10-25 20:57:08 +02:00
if random(1, 3) ~= 1 then
insert(tiles, {name = 'water', position = pos})
2021-03-24 17:46:00 +02:00
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}
2023-10-25 20:57:08 +02:00
local tile = surface.get_tile(pos.x, pos.y)
if tile.name ~= 'water' and tile.name ~= 'deepwater' then
2021-03-24 17:46:00 +02:00
if x > current_arena_size or y > current_arena_size or x < current_arena_size * -1 or y < current_arena_size * -1 then
2023-10-25 20:57:08 +02:00
if random(1, 3) ~= 1 then
insert(tiles, {name = 'water', position = pos})
2021-03-24 17:46:00 +02:00
end
end
end
end
end
2023-10-25 20:57:08 +02:00
this.current_arena_size = this.current_arena_size - 1
2021-03-24 17:46:00 +02:00
surface.set_tiles(tiles, true)
2018-12-17 11:24:01 +02:00
end
2018-12-28 01:23:38 +02:00
local function get_arena_entity(surface, pos)
2021-03-24 17:46:00 +02:00
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 = 'rock-big', position = pos}
end
2023-10-25 20:57:08 +02:00
if random(1, 16) == 1 and noise2 > 0.78 then
2021-03-24 17:46:00 +02:00
if surface.can_place_entity({name = 'wooden-chest', position = pos, force = 'enemy'}) then
return {name = 'wooden-chest', position = pos, force = 'enemy'}
end
end
2023-10-25 20:57:08 +02:00
if random(1, 16) == 1 and noise2 < -0.78 then
2021-03-24 17:46:00 +02:00
if surface.can_place_entity({name = 'wooden-chest', position = pos, force = 'enemy'}) then
return {name = 'wooden-chest', position = pos, force = 'enemy'}
end
end
2023-10-25 20:57:08 +02:00
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}
2021-03-24 17:46:00 +02:00
end
2023-10-25 20:57:08 +02:00
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'}
2021-03-24 17:46:00 +02:00
end
end
2023-10-25 20:57:08 +02:00
if random(1, 64) == 1 then
2021-03-24 17:46:00 +02:00
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
2023-10-25 20:57:08 +02:00
if random(1, 32) == 1 then
2021-03-24 17:46:00 +02:00
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
2023-10-25 20:57:08 +02:00
if random(1, 512) == 1 then
2021-03-24 17:46:00 +02:00
if surface.can_place_entity({name = 'behemoth-biter', position = pos, force = 'enemy'}) then
return {name = 'behemoth-biter', position = pos, force = 'enemy'}
end
end
2023-10-25 20:57:08 +02:00
if random(1, 64) == 1 then
2021-03-24 17:46:00 +02:00
if surface.can_place_entity({name = 'big-biter', position = pos, force = 'enemy'}) then
return {name = 'big-biter', position = pos, force = 'enemy'}
end
end
end
2018-12-17 11:24:01 +02:00
end
2018-12-28 01:23:38 +02:00
local function render_arena_chunk(event)
2023-10-25 20:57:08 +02:00
if not this.noise_seed then
this.noise_seed = random(1, 2097152)
2021-03-24 17:46:00 +02:00
end
local surface = event.surface
local left_top = event.area.left_top
for _, entity in pairs(surface.find_entities_filtered({area = event.area})) do
2023-10-25 20:57:08 +02:00
if entity and entity.valid then
2021-03-24 17:46:00 +02:00
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
2023-10-25 20:57:08 +02:00
insert(tiles, {name = 'water', position = pos})
2021-03-24 17:46:00 +02:00
else
local noise = get_noise('terrain', pos)
if noise > 0 then
2023-10-25 20:57:08 +02:00
insert(tiles, {name = this.arena_layout_modifiers.arena_tile_1, position = pos})
2021-03-24 17:46:00 +02:00
else
2023-10-25 20:57:08 +02:00
insert(tiles, {name = this.arena_layout_modifiers.arena_tile_2, position = pos})
2021-03-24 17:46:00 +02:00
end
local entity = get_arena_entity(surface, pos)
if entity then
surface.create_entity(entity)
end
end
end
end
surface.set_tiles(tiles, true)
2018-12-17 11:24:01 +02:00
end
2018-12-23 14:01:34 +02:00
local function kill_idle_players()
2023-10-25 20:57:08 +02:00
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
2021-03-24 17:46:00 +02:00
player.character.die()
2023-10-25 20:57:08 +02:00
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
2021-03-24 17:46:00 +02:00
end
end
end
end
2023-10-25 20:57:08 +02:00
)
2018-12-23 14:01:34 +02:00
end
2018-12-17 11:24:01 +02:00
local function check_for_game_over()
2021-03-24 17:46:00 +02:00
kill_idle_players()
local alive_players = 0
2023-10-25 20:57:08 +02:00
create_tank_battle_score_gui()
Core.iter_connected_players(
function(player)
if player.character and player.driving then
alive_players = alive_players + 1
end
2021-03-24 17:46:00 +02:00
end
2023-10-25 20:57:08 +02:00
)
2021-03-24 17:46:00 +02:00
if alive_players > 1 then
return
2023-10-25 20:57:08 +02:00
end
2021-03-24 17:46:00 +02:00
local player
2023-10-25 20:57:08 +02:00
Core.iter_connected_players(
function(player_amp)
if player_amp.character and player_amp.driving then
player = player_amp
end
2021-03-24 17:46:00 +02:00
end
2023-10-25 20:57:08 +02:00
)
2021-03-24 17:46:00 +02:00
if alive_players == 1 then
2023-10-25 20:57:08 +02:00
if not this.tank_battles_score[player.index] then
this.tank_battles_score[player.index] = 1
2021-03-24 17:46:00 +02:00
else
2023-10-25 20:57:08 +02:00
this.tank_battles_score[player.index] = this.tank_battles_score[player.index] + 1
2021-03-24 17:46:00 +02:00
end
game.print(player.name .. ' has won the battle!', {r = 150, g = 150, b = 0})
2023-10-25 20:57:08 +02:00
Server.to_discord_embed(player.name .. ' has won the battle!')
2021-03-24 17:46:00 +02:00
create_tank_battle_score_gui()
end
if alive_players == 0 then
2023-10-25 20:57:08 +02:00
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!')
2021-03-24 17:46:00 +02:00
end
2023-10-25 20:57:08 +02:00
this.game_stage = 'lobby'
2018-12-17 11:24:01 +02:00
end
2018-12-28 01:23:38 +02:00
local function set_unique_player_force(player)
2023-10-25 20:57:08 +02:00
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
2018-12-28 01:23:38 +02:00
end
2021-03-24 17:46:00 +02:00
local function on_player_joined_game(event)
2023-10-25 20:57:08 +02:00
local player = game.get_player(event.player_index)
2021-03-24 17:46:00 +02:00
set_unique_player_force(player)
2023-10-25 20:57:08 +02:00
create_gui(player)
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
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
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
if player.character then
player.character.destroy()
end
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
if this.game_stage == 'ongoing_game' then
player.print("There is currently an ongoing match - please wait until it's over.")
2021-03-24 17:46:00 +02:00
end
2023-10-25 20:57:08 +02:00
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
2021-03-24 17:46:00 +02:00
end
2023-10-25 20:57:08 +02:00
if not player.driving then
entity.set_driver(player)
2021-03-24 17:46:00 +02:00
end
2018-12-28 01:23:38 +02:00
end
2023-10-25 20:57:08 +02:00
local function on_player_left_game(event)
local player = game.get_player(event.player_index)
remove_unique_player_force(player)
end
2018-12-28 01:23:38 +02:00
local function on_marked_for_deconstruction(event)
2023-10-25 20:57:08 +02:00
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
2018-12-28 01:23:38 +02:00
end
2018-12-17 11:24:01 +02:00
local function on_chunk_generated(event)
2021-03-24 17:46:00 +02:00
render_arena_chunk(event)
2018-12-17 11:24:01 +02:00
end
local function on_player_respawned(event)
2023-10-25 20:57:08 +02:00
local player = game.get_player(event.player_index)
2021-03-24 17:46:00 +02:00
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})
2018-12-17 11:24:01 +02:00
end
2021-03-24 17:46:00 +02:00
local function lobby()
2023-10-25 20:57:08 +02:00
local connected_players_count = #game.connected_players
2021-03-24 17:46:00 +02:00
if connected_players_count < 2 then
2023-10-25 20:57:08 +02:00
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
)
2021-03-24 17:46:00 +02:00
return
end
2023-10-25 20:57:08 +02:00
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
2021-03-24 17:46:00 +02:00
end
2023-10-25 20:57:08 +02:00
if this.lobby_timer % 600 == 0 then
if this.lobby_timer <= 0 then
2021-03-24 17:46:00 +02:00
game.print('Round has started!', {r = 0, g = 150, b = 150})
2023-10-25 20:57:08 +02:00
Server.to_discord_embed('Round has started!')
2021-03-24 17:46:00 +02:00
else
2023-10-25 20:57:08 +02:00
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.')
2021-03-24 17:46:00 +02:00
end
end
2023-10-25 20:57:08 +02:00
this.lobby_timer = this.lobby_timer - 300
if this.lobby_timer >= 0 then
2021-03-24 17:46:00 +02:00
return
end
2023-10-25 20:57:08 +02:00
this.lobby_timer = nil
this.game_stage = 'regenerate_arena'
2018-12-17 11:24:01 +02:00
end
2023-10-25 20:57:08 +02:00
local function on_tick()
local tick = game.tick
if tick % 300 == 0 then
if this.game_stage == 'lobby' then
2021-03-24 17:46:00 +02:00
lobby()
end
2023-10-25 20:57:08 +02:00
if this.game_stage == 'regenerate_arena' then
2021-03-24 17:46:00 +02:00
regenerate_arena()
end
2023-10-25 20:57:08 +02:00
if this.game_stage == 'ongoing_game' then
2021-03-24 17:46:00 +02:00
shrink_arena()
check_for_game_over()
end
end
2023-10-25 20:57:08 +02:00
if tick % 1000 == 0 then
check_obsolete_forces()
end
2018-12-17 11:24:01 +02:00
end
local function on_entity_died(event)
2023-10-25 20:57:08 +02:00
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)
2021-03-24 17:46:00 +02:00
end
2018-12-17 16:13:17 +02:00
end
local function on_player_died(event)
2023-10-25 20:57:08 +02:00
local player = game.get_player(event.player_index)
2021-03-24 17:46:00 +02:00
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
2023-10-25 20:57:08 +02:00
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
2021-03-24 17:46:00 +02:00
end
2023-10-25 20:57:08 +02:00
)
2018-12-17 16:13:17 +02:00
end
local function on_console_chat(event)
2021-03-24 17:46:00 +02:00
if not event.message then
return
end
if not event.player_index then
return
end
2023-10-25 20:57:08 +02:00
local player = game.get_player(event.player_index)
2021-03-24 17:46:00 +02:00
2023-10-25 20:57:08 +02:00
local color = player.color
2021-03-24 17:46:00 +02:00
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
2023-10-25 20:57:08 +02:00
Core.iter_connected_players(
function(target_player)
if target_player.name ~= player.name then
target_player.print(player.name .. ': ' .. event.message, color)
end
2021-03-24 17:46:00 +02:00
end
2023-10-25 20:57:08 +02:00
)
2018-12-17 11:24:01 +02:00
end
2023-10-25 20:57:08 +02:00
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)