2021-02-06 22:42:10 +02:00
|
|
|
local Public = {}
|
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
local math_random = math.random
|
2021-02-06 22:42:10 +02:00
|
|
|
local table_size = table.size
|
|
|
|
local string_match = string.match
|
|
|
|
local string_lower = string.lower
|
2022-10-15 10:44:54 +02:00
|
|
|
local math_min = math.min
|
2021-02-06 22:42:10 +02:00
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
local Server = require 'utils.server'
|
2022-09-30 22:23:37 +02:00
|
|
|
local Map = require 'maps.scrap_towny_ffa.map'
|
|
|
|
local ScenarioTable = require 'maps.scrap_towny_ffa.table'
|
2022-10-08 17:17:10 +02:00
|
|
|
local PvPShield = require 'maps.scrap_towny_ffa.pvp_shield'
|
2022-10-15 12:27:16 +02:00
|
|
|
local CombatBalance = require 'maps.scrap_towny_ffa.combat_balance'
|
2021-02-06 22:42:10 +02:00
|
|
|
|
2021-03-24 17:46:00 +02:00
|
|
|
local outlander_color = {150, 150, 150}
|
|
|
|
local outlander_chat_color = {170, 170, 170}
|
|
|
|
local rogue_color = {150, 150, 150}
|
|
|
|
local rogue_chat_color = {170, 170, 170}
|
2021-02-06 22:42:10 +02:00
|
|
|
local item_drop_radius = 1.65
|
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
local destroy_wall_types = {
|
|
|
|
['gate'] = true,
|
|
|
|
['wall'] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
local destroy_military_types = {
|
|
|
|
['ammo-turret'] = true,
|
|
|
|
['artillery-turret'] = true,
|
|
|
|
['artillery-wagon'] = true,
|
|
|
|
['electric-turret'] = true,
|
|
|
|
['fluid-turret'] = true,
|
|
|
|
['lab'] = true,
|
|
|
|
['land-mine'] = true,
|
|
|
|
['logistic-robot'] = true,
|
|
|
|
['radar'] = true,
|
|
|
|
['reactor'] = true,
|
|
|
|
['roboport'] = true,
|
|
|
|
['rocket-silo'] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
local destroy_robot_types = {
|
|
|
|
['combat-robot'] = true,
|
|
|
|
['construction-robot'] = true,
|
2022-03-01 20:11:08 +02:00
|
|
|
['logistic-robot'] = true
|
2022-03-01 19:55:02 +02:00
|
|
|
}
|
|
|
|
|
2022-10-10 13:30:57 +02:00
|
|
|
local storage_types = {
|
|
|
|
['container'] = true,
|
|
|
|
['logistic-container'] = true,
|
|
|
|
['storage-tank'] = true
|
|
|
|
}
|
2022-10-11 22:16:51 +02:00
|
|
|
|
2022-10-06 08:41:10 +02:00
|
|
|
local player_force_disabled_recipes = {
|
|
|
|
'lab',
|
|
|
|
'automation-science-pack',
|
|
|
|
'stone-brick',
|
|
|
|
'radar'
|
|
|
|
}
|
|
|
|
local all_force_enabled_recipes = {
|
|
|
|
'submachine-gun',
|
|
|
|
'shotgun',
|
|
|
|
'shotgun-shell',
|
|
|
|
}
|
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
local function min_slots(slots)
|
|
|
|
local min = 0
|
|
|
|
for i = 1, 3, 1 do
|
2022-03-01 20:11:08 +02:00
|
|
|
if slots[i] > min then
|
|
|
|
min = slots[i]
|
|
|
|
end
|
2022-03-01 19:55:02 +02:00
|
|
|
end
|
|
|
|
return min
|
|
|
|
end
|
|
|
|
|
2022-10-12 20:22:48 +02:00
|
|
|
local function update_member_limit(force)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not force or not force.valid then
|
|
|
|
log('force nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local this = ScenarioTable.get_table()
|
|
|
|
local town_centers = this.town_centers
|
2021-02-06 22:42:10 +02:00
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
local slots = {0, 0, 0}
|
|
|
|
for _, town_center in pairs(town_centers) do
|
|
|
|
local players = table_size(town_center.market.force.players)
|
|
|
|
-- get min value for all slots
|
|
|
|
local min = min_slots(slots)
|
|
|
|
-- if our value greater than min of all three replace that slot
|
|
|
|
if players > min then
|
|
|
|
for i = 1, 3, 1 do
|
|
|
|
if slots[i] == min then
|
|
|
|
slots[i] = players
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
2022-10-15 10:44:54 +02:00
|
|
|
-- get the min of all slots -- TODO: without the hard limit, the soft limit increases too much so it never applies
|
|
|
|
this.member_limit = math_min(min_slots(slots) + 1, 3)
|
2022-10-12 20:22:48 +02:00
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
|
2022-10-12 20:22:48 +02:00
|
|
|
local function can_force_accept_member(force)
|
|
|
|
if not force or not force.valid then
|
|
|
|
log('force nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local this = ScenarioTable.get_table()
|
|
|
|
update_member_limit(force)
|
|
|
|
|
|
|
|
if #force.players >= this.member_limit then
|
|
|
|
game.print('>> Town ' .. force.name .. ' has too many settlers! Current limit (' .. this.member_limit .. ')', {255, 255, 0})
|
2022-03-01 19:55:02 +02:00
|
|
|
return false
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
return true
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
2022-09-30 22:23:37 +02:00
|
|
|
function Public.is_rogue(force)
|
|
|
|
return force.name == 'rogue'
|
|
|
|
end
|
|
|
|
|
|
|
|
function Public.is_outlander(force)
|
|
|
|
return force.name == 'player'
|
|
|
|
end
|
|
|
|
|
|
|
|
function Public.is_towny(force)
|
|
|
|
return force.name ~= 'rogue' and force.name ~= 'player'
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
2022-03-01 20:31:57 +02:00
|
|
|
function Public.has_key(index)
|
2022-09-30 22:23:37 +02:00
|
|
|
local this = ScenarioTable.get_table()
|
|
|
|
if this.key == nil then
|
|
|
|
this.key = {}
|
2022-03-01 20:11:08 +02:00
|
|
|
end
|
2022-09-30 22:23:37 +02:00
|
|
|
if this.key[index] ~= nil then
|
|
|
|
return this.key[index]
|
2022-03-01 19:55:02 +02:00
|
|
|
end
|
|
|
|
return false
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
2022-03-01 20:31:57 +02:00
|
|
|
function Public.give_key(index)
|
2022-09-30 22:23:37 +02:00
|
|
|
local this = ScenarioTable.get_table()
|
|
|
|
if this.key == nil then
|
|
|
|
this.key = {}
|
2022-03-01 20:11:08 +02:00
|
|
|
end
|
2022-09-30 22:23:37 +02:00
|
|
|
this.key[index] = true
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
2022-03-01 20:31:57 +02:00
|
|
|
function Public.remove_key(index)
|
2022-09-30 22:23:37 +02:00
|
|
|
local this = ScenarioTable.get_table()
|
|
|
|
if this.key == nil then
|
|
|
|
this.key = {}
|
2022-03-01 20:11:08 +02:00
|
|
|
end
|
2022-09-30 22:23:37 +02:00
|
|
|
this.key[index] = false
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function Public.set_player_color(player)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not player or not player.valid then
|
|
|
|
log('player nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local this = ScenarioTable.get_table()
|
|
|
|
local force_name = player.force.name
|
|
|
|
if force_name == 'player' then
|
2021-03-24 17:46:00 +02:00
|
|
|
player.color = outlander_color
|
|
|
|
player.chat_color = outlander_chat_color
|
|
|
|
return
|
|
|
|
end
|
2022-09-30 22:23:37 +02:00
|
|
|
if force_name == 'rogue' then
|
2021-03-24 17:46:00 +02:00
|
|
|
player.color = rogue_color
|
|
|
|
player.chat_color = rogue_chat_color
|
|
|
|
return
|
|
|
|
end
|
2022-09-30 22:23:37 +02:00
|
|
|
local town_center = this.town_centers[player.force.name]
|
2021-03-24 17:46:00 +02:00
|
|
|
if not town_center then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
player.color = town_center.color
|
|
|
|
player.chat_color = town_center.color
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function set_town_color(event)
|
2022-09-30 22:23:37 +02:00
|
|
|
local this = ScenarioTable.get_table()
|
2021-03-24 17:46:00 +02:00
|
|
|
if event.command ~= 'color' then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local player = game.players[event.player_index]
|
|
|
|
local force = player.force
|
2022-09-30 22:23:37 +02:00
|
|
|
local town_center = this.town_centers[force.name]
|
2021-03-24 17:46:00 +02:00
|
|
|
if not town_center then
|
|
|
|
Public.set_player_color(player)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
town_center.color = {player.color.r, player.color.g, player.color.b}
|
|
|
|
rendering.set_color(town_center.town_caption, town_center.color)
|
|
|
|
for _, p in pairs(force.players) do
|
|
|
|
Public.set_player_color(p)
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function Public.set_all_player_colors()
|
2021-03-24 17:46:00 +02:00
|
|
|
for _, p in pairs(game.connected_players) do
|
|
|
|
Public.set_player_color(p)
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
local function reset_player(player)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not player or not player.valid then
|
|
|
|
log('player nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
2022-03-01 19:55:02 +02:00
|
|
|
if player.character ~= nil then
|
|
|
|
local character = player.character
|
|
|
|
character.character_crafting_speed_modifier = 0.0
|
|
|
|
character.character_mining_speed_modifier = 0.0
|
|
|
|
character.character_inventory_slots_bonus = 0
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-06 22:42:10 +02:00
|
|
|
function Public.add_player_to_town(player, town_center)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not player or not player.valid then
|
|
|
|
log('player nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
|
|
|
if not town_center then
|
|
|
|
log('town_center nil!')
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local this = ScenarioTable.get_table()
|
2021-03-24 17:46:00 +02:00
|
|
|
local market = town_center.market
|
|
|
|
local force = market.force
|
|
|
|
local surface = market.surface
|
2022-03-01 19:55:02 +02:00
|
|
|
reset_player(player)
|
2021-03-24 17:46:00 +02:00
|
|
|
player.force = market.force
|
2022-03-01 19:55:02 +02:00
|
|
|
Public.remove_key(player.index)
|
2022-09-30 22:23:37 +02:00
|
|
|
this.spawn_point[player.index] = force.get_spawn_position(surface)
|
2021-03-24 17:46:00 +02:00
|
|
|
game.permissions.get_group(force.name).add_player(player)
|
|
|
|
player.tag = ''
|
2022-03-01 19:55:02 +02:00
|
|
|
Map.enable_world_map(player)
|
2021-03-24 17:46:00 +02:00
|
|
|
Public.set_player_color(player)
|
2022-10-12 20:22:48 +02:00
|
|
|
|
|
|
|
update_member_limit(force)
|
2022-10-15 10:44:54 +02:00
|
|
|
game.print('>> The new member limit for all towns is now ' .. this.member_limit, {255, 255, 0})
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
-- given to player upon respawn
|
|
|
|
function Public.give_player_items(player)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not player or not player.valid then
|
|
|
|
log('player nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
2022-03-01 19:55:02 +02:00
|
|
|
player.clear_items_inside()
|
2021-03-24 17:46:00 +02:00
|
|
|
player.insert({name = 'raw-fish', count = 3})
|
2022-10-05 22:03:01 +02:00
|
|
|
if player.force.name == 'rogue' or player.force.name == 'player' then
|
|
|
|
player.insert {name = 'stone-furnace', count = '1'}
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function Public.set_player_to_outlander(player)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not player or not player.valid then
|
|
|
|
log('player nil or not valid!')
|
2022-03-01 20:11:08 +02:00
|
|
|
return
|
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
player.force = game.forces.player
|
|
|
|
if game.permissions.get_group('outlander') == nil then
|
|
|
|
game.permissions.create_group('outlander')
|
|
|
|
end
|
|
|
|
game.permissions.get_group('outlander').add_player(player)
|
|
|
|
player.tag = '[Outlander]'
|
2022-03-01 19:55:02 +02:00
|
|
|
Map.disable_world_map(player)
|
2021-03-24 17:46:00 +02:00
|
|
|
Public.set_player_color(player)
|
2022-03-01 20:31:57 +02:00
|
|
|
Public.give_key(player.index)
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function set_player_to_rogue(player)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not player or not player.valid then
|
|
|
|
log('player nil or not valid!')
|
2022-03-01 20:11:08 +02:00
|
|
|
return
|
|
|
|
end
|
2022-10-04 17:51:22 +02:00
|
|
|
|
2022-10-05 10:09:28 +02:00
|
|
|
player.print("You have broken the peace with the biters. They will seek revenge!")
|
2022-03-01 19:55:02 +02:00
|
|
|
player.force = 'rogue'
|
2022-09-30 22:23:37 +02:00
|
|
|
local group = game.permissions.get_group('rogue')
|
|
|
|
if group == nil then
|
|
|
|
group = game.permissions.create_group('rogue')
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
2022-10-04 17:51:22 +02:00
|
|
|
|
|
|
|
if not player.object_name == 'LuaPlayer' then
|
|
|
|
log('Given object is not of LuaPlayer!')
|
|
|
|
return
|
|
|
|
end
|
2022-09-30 22:23:37 +02:00
|
|
|
group.add_player(player)
|
2021-03-24 17:46:00 +02:00
|
|
|
player.tag = '[Rogue]'
|
2022-03-01 19:55:02 +02:00
|
|
|
Map.disable_world_map(player)
|
2021-03-24 17:46:00 +02:00
|
|
|
Public.set_player_color(player)
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function ally_outlander(player, target)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not player or not player.valid then
|
|
|
|
log('player nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
|
|
|
if not target or not target.valid then
|
|
|
|
log('target nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local this = ScenarioTable.get_table()
|
2021-03-24 17:46:00 +02:00
|
|
|
local requesting_force = player.force
|
|
|
|
local target_force = target.force
|
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
-- don't handle if towns not yet enabled
|
2022-09-30 22:23:37 +02:00
|
|
|
if not this.towns_enabled then
|
2022-03-01 19:55:02 +02:00
|
|
|
player.print('You must wait for more players to join!', {255, 255, 0})
|
|
|
|
return false
|
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
-- don't handle request if target is not a town
|
2022-09-30 22:23:37 +02:00
|
|
|
if not Public.is_towny(requesting_force) and not Public.is_towny(target_force) then
|
2021-03-24 17:46:00 +02:00
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
-- don't handle request to another town if already in a town
|
2022-09-30 22:23:37 +02:00
|
|
|
if Public.is_towny(requesting_force) and Public.is_towny(target_force) then
|
2021-03-24 17:46:00 +02:00
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
-- handle the request
|
2022-09-30 22:23:37 +02:00
|
|
|
if not Public.is_towny(requesting_force) and Public.is_towny(target_force) then
|
|
|
|
this.requests[player.index] = target_force.name
|
2021-03-24 17:46:00 +02:00
|
|
|
|
2022-03-01 20:11:08 +02:00
|
|
|
local target_player
|
2021-03-24 17:46:00 +02:00
|
|
|
if target.type == 'character' then
|
|
|
|
target_player = target.player
|
|
|
|
else
|
|
|
|
target_player = game.players[target_force.name]
|
|
|
|
end
|
|
|
|
|
|
|
|
if target_player then
|
2022-09-30 22:23:37 +02:00
|
|
|
if this.requests[target_player.index] then
|
|
|
|
if this.requests[target_player.index] == player.name then
|
|
|
|
if this.town_centers[target_force.name] then
|
2021-03-24 17:46:00 +02:00
|
|
|
if not can_force_accept_member(target_force) then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
game.print('>> ' .. player.name .. ' has settled in ' .. target_force.name .. "'s Town!", {255, 255, 0})
|
2022-09-30 22:23:37 +02:00
|
|
|
Public.add_player_to_town(player, this.town_centers[target_force.name])
|
2021-03-24 17:46:00 +02:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
game.print('>> ' .. player.name .. ' wants to settle in ' .. target_force.name .. ' Town!', {255, 255, 0})
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
-- handle the approval
|
2022-09-30 22:23:37 +02:00
|
|
|
if Public.is_towny(requesting_force) and not Public.is_towny(target_force) then
|
2021-03-24 17:46:00 +02:00
|
|
|
if target.type ~= 'character' then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
local target_player = target.player
|
|
|
|
if not target_player then
|
|
|
|
return true
|
|
|
|
end
|
2022-09-30 22:23:37 +02:00
|
|
|
this.requests[player.index] = target_player.name
|
2021-03-24 17:46:00 +02:00
|
|
|
|
2022-09-30 22:23:37 +02:00
|
|
|
if this.requests[target_player.index] then
|
|
|
|
if this.requests[target_player.index] == player.force.name then
|
2021-03-24 17:46:00 +02:00
|
|
|
if not can_force_accept_member(player.force) then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
if player.force.name == player.name then
|
|
|
|
game.print('>> ' .. player.name .. ' has accepted ' .. target_player.name .. ' into their Town!', {255, 255, 0})
|
|
|
|
else
|
|
|
|
game.print('>> ' .. player.name .. ' has accepted ' .. target_player.name .. ' into' .. player.force.name .. "'s Town!", {255, 255, 0})
|
|
|
|
end
|
2022-09-30 22:23:37 +02:00
|
|
|
Public.add_player_to_town(target_player, this.town_centers[player.force.name])
|
2021-03-24 17:46:00 +02:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if player.force.name == player.name then
|
|
|
|
game.print('>> ' .. player.name .. ' is inviting ' .. target_player.name .. ' into their Town!', {255, 255, 0})
|
|
|
|
else
|
|
|
|
game.print('>> ' .. player.name .. ' is inviting ' .. target_player.name .. ' into ' .. player.force.name .. "'s Town!", {255, 255, 0})
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function ally_neighbour_towns(player, target)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not player or not player.valid then
|
|
|
|
log('player nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
|
|
|
if not target or not target.valid then
|
|
|
|
log('target nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
local requesting_force = player.force
|
|
|
|
local target_force = target.force
|
2021-02-06 22:42:10 +02:00
|
|
|
|
2021-03-24 17:46:00 +02:00
|
|
|
if target_force.get_friend(requesting_force) and requesting_force.get_friend(target_force) then
|
|
|
|
return
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
|
2021-03-24 17:46:00 +02:00
|
|
|
requesting_force.set_friend(target_force, true)
|
|
|
|
game.print('>> Town ' .. requesting_force.name .. ' has set ' .. target_force.name .. ' as their friend!', {255, 255, 0})
|
2021-02-06 22:42:10 +02:00
|
|
|
|
2021-03-24 17:46:00 +02:00
|
|
|
if target_force.get_friend(requesting_force) then
|
|
|
|
game.print('>> The towns ' .. requesting_force.name .. ' and ' .. target_force.name .. ' have formed an alliance!', {255, 255, 0})
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function ally_town(player, item)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not player or not player.valid then
|
|
|
|
log('player nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
local position = item.position
|
|
|
|
local surface = player.surface
|
|
|
|
local area = {{position.x - item_drop_radius, position.y - item_drop_radius}, {position.x + item_drop_radius, position.y + item_drop_radius}}
|
|
|
|
local requesting_force = player.force
|
|
|
|
local target = false
|
|
|
|
|
|
|
|
for _, e in pairs(surface.find_entities_filtered({type = {'character', 'market'}, area = area})) do
|
|
|
|
if e.force.name ~= requesting_force.name then
|
|
|
|
target = e
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if not target then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
if target.force == game.forces['enemy'] or target.force == game.forces['neutral'] then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if ally_outlander(player, target) then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
ally_neighbour_towns(player, target)
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function declare_war(player, item)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not player or not player.valid then
|
|
|
|
log('player nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local this = ScenarioTable.get_table()
|
2021-03-24 17:46:00 +02:00
|
|
|
local position = item.position
|
|
|
|
local surface = player.surface
|
|
|
|
local area = {{position.x - item_drop_radius, position.y - item_drop_radius}, {position.x + item_drop_radius, position.y + item_drop_radius}}
|
|
|
|
|
|
|
|
local requesting_force = player.force
|
|
|
|
local target = surface.find_entities_filtered({type = {'character', 'market'}, area = area})[1]
|
|
|
|
|
|
|
|
if not target then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local target_force = target.force
|
2022-09-30 22:23:37 +02:00
|
|
|
if not Public.is_towny(target_force) then
|
2021-03-24 17:46:00 +02:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if requesting_force.name == target_force.name then
|
|
|
|
if player.name ~= target.force.name then
|
|
|
|
Public.set_player_to_outlander(player)
|
|
|
|
game.print('>> ' .. player.name .. ' has abandoned ' .. target_force.name .. "'s Town!", {255, 255, 0})
|
2022-09-30 22:23:37 +02:00
|
|
|
this.requests[player.index] = nil
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
if player.name == target.force.name then
|
|
|
|
if target.type ~= 'character' then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local target_player = target.player
|
|
|
|
if not target_player then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
if target_player.index == player.index then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
Public.set_player_to_outlander(target_player)
|
|
|
|
game.print('>> ' .. player.name .. ' has banished ' .. target_player.name .. ' from their Town!', {255, 255, 0})
|
2022-09-30 22:23:37 +02:00
|
|
|
this.requests[player.index] = nil
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2022-09-30 22:23:37 +02:00
|
|
|
if not Public.is_towny(requesting_force) then
|
2021-03-24 17:46:00 +02:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
requesting_force.set_friend(target_force, false)
|
|
|
|
target_force.set_friend(requesting_force, false)
|
|
|
|
|
2022-09-22 20:19:19 +02:00
|
|
|
game.print('>> ' .. player.name .. ' has dropped the coal! Town ' .. target_force.name .. ' and ' .. requesting_force.name .. ' are now at war!', {255, 255, 0})
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function delete_chart_tag_for_all_forces(market)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not market or not market.valid then
|
|
|
|
log('market nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
local forces = game.forces
|
|
|
|
local position = market.position
|
|
|
|
local surface = market.surface
|
|
|
|
for _, force in pairs(forces) do
|
|
|
|
local tags = force.find_chart_tags(surface, {{position.x - 0.1, position.y - 0.1}, {position.x + 0.1, position.y + 0.1}})
|
|
|
|
local tag = tags[1]
|
|
|
|
if tag then
|
|
|
|
if tag.icon.name == 'stone-furnace' then
|
|
|
|
tag.destroy()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
function Public.add_chart_tag(town_center)
|
2022-09-30 22:23:37 +02:00
|
|
|
if not town_center then
|
|
|
|
log('town_center nil or not valid!')
|
|
|
|
return
|
|
|
|
end
|
2022-03-01 19:55:02 +02:00
|
|
|
local market = town_center.market
|
|
|
|
local force = market.force
|
2021-03-24 17:46:00 +02:00
|
|
|
local position = market.position
|
|
|
|
local tags = force.find_chart_tags(market.surface, {{position.x - 0.1, position.y - 0.1}, {position.x + 0.1, position.y + 0.1}})
|
|
|
|
if tags[1] then
|
|
|
|
return
|
|
|
|
end
|
2022-03-01 19:55:02 +02:00
|
|
|
force.add_chart_tag(market.surface, {icon = {type = 'item', name = 'stone-furnace'}, position = position, text = town_center.town_name})
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function Public.update_town_chart_tags()
|
2022-09-30 22:23:37 +02:00
|
|
|
local this = ScenarioTable.get_table()
|
|
|
|
local town_centers = this.town_centers
|
2021-03-24 17:46:00 +02:00
|
|
|
local forces = game.forces
|
|
|
|
for _, town_center in pairs(town_centers) do
|
|
|
|
local market = town_center.market
|
2022-03-01 19:55:02 +02:00
|
|
|
if market ~= nil and market.valid then
|
|
|
|
for _, force in pairs(forces) do
|
|
|
|
if force.is_chunk_visible(market.surface, town_center.chunk_position) then
|
|
|
|
Public.add_chart_tag(town_center)
|
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if game.forces['player'] ~= nil then
|
|
|
|
game.forces['player'].clear_chart(game.surfaces['nauvis'])
|
|
|
|
end
|
|
|
|
if game.forces['rogue'] ~= nil then
|
|
|
|
game.forces['rogue'].clear_chart(game.surfaces['nauvis'])
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function reset_permissions(permission_group)
|
2021-03-24 17:46:00 +02:00
|
|
|
for action_name, _ in pairs(defines.input_action) do
|
|
|
|
permission_group.set_allows_action(defines.input_action[action_name], true)
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
local function enable_blueprints(permission_group)
|
|
|
|
local defs = {
|
|
|
|
defines.input_action.alt_select_blueprint_entities,
|
|
|
|
defines.input_action.cancel_new_blueprint,
|
|
|
|
defines.input_action.change_blueprint_record_label,
|
|
|
|
defines.input_action.clear_selected_blueprint,
|
|
|
|
defines.input_action.create_blueprint_like,
|
|
|
|
defines.input_action.cycle_blueprint_backwards,
|
|
|
|
defines.input_action.cycle_blueprint_forwards,
|
|
|
|
defines.input_action.delete_blueprint_library,
|
|
|
|
defines.input_action.delete_blueprint_record,
|
|
|
|
defines.input_action.drop_blueprint_record,
|
|
|
|
defines.input_action.drop_to_blueprint_book,
|
|
|
|
defines.input_action.export_blueprint,
|
|
|
|
defines.input_action.grab_blueprint_record,
|
|
|
|
defines.input_action.import_blueprint,
|
|
|
|
defines.input_action.import_blueprint_string,
|
|
|
|
defines.input_action.open_blueprint_library_gui,
|
|
|
|
defines.input_action.open_blueprint_record,
|
|
|
|
defines.input_action.select_blueprint_entities,
|
|
|
|
defines.input_action.setup_blueprint,
|
|
|
|
defines.input_action.setup_single_blueprint_record,
|
2022-03-01 20:11:08 +02:00
|
|
|
defines.input_action.upgrade_open_blueprint
|
2022-03-01 19:55:02 +02:00
|
|
|
}
|
|
|
|
for _, d in pairs(defs) do
|
|
|
|
permission_group.set_allows_action(d, true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-06 22:42:10 +02:00
|
|
|
local function disable_blueprints(permission_group)
|
2021-03-24 17:46:00 +02:00
|
|
|
local defs = {
|
|
|
|
defines.input_action.alt_select_blueprint_entities,
|
|
|
|
defines.input_action.cancel_new_blueprint,
|
|
|
|
defines.input_action.change_blueprint_record_label,
|
|
|
|
defines.input_action.clear_selected_blueprint,
|
|
|
|
defines.input_action.create_blueprint_like,
|
|
|
|
defines.input_action.cycle_blueprint_backwards,
|
|
|
|
defines.input_action.cycle_blueprint_forwards,
|
|
|
|
defines.input_action.delete_blueprint_library,
|
|
|
|
defines.input_action.delete_blueprint_record,
|
|
|
|
defines.input_action.drop_blueprint_record,
|
|
|
|
defines.input_action.drop_to_blueprint_book,
|
|
|
|
defines.input_action.export_blueprint,
|
|
|
|
defines.input_action.grab_blueprint_record,
|
|
|
|
defines.input_action.import_blueprint,
|
|
|
|
defines.input_action.import_blueprint_string,
|
|
|
|
defines.input_action.open_blueprint_library_gui,
|
|
|
|
defines.input_action.open_blueprint_record,
|
|
|
|
defines.input_action.select_blueprint_entities,
|
|
|
|
defines.input_action.setup_blueprint,
|
|
|
|
defines.input_action.setup_single_blueprint_record,
|
2022-03-01 20:11:08 +02:00
|
|
|
defines.input_action.upgrade_open_blueprint
|
2022-03-01 19:55:02 +02:00
|
|
|
}
|
|
|
|
for _, d in pairs(defs) do
|
|
|
|
permission_group.set_allows_action(d, false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function enable_deconstruct(permission_group)
|
|
|
|
local defs = {
|
|
|
|
defines.input_action.deconstruct,
|
|
|
|
defines.input_action.clear_selected_deconstruction_item,
|
|
|
|
defines.input_action.cancel_deconstruct,
|
|
|
|
defines.input_action.toggle_deconstruction_item_entity_filter_mode,
|
|
|
|
defines.input_action.toggle_deconstruction_item_tile_filter_mode,
|
|
|
|
defines.input_action.set_deconstruction_item_tile_selection_mode,
|
|
|
|
defines.input_action.set_deconstruction_item_trees_and_rocks_only
|
|
|
|
}
|
|
|
|
for _, d in pairs(defs) do
|
|
|
|
permission_group.set_allows_action(d, true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function disable_deconstruct(permission_group)
|
|
|
|
local defs = {
|
2021-03-24 17:46:00 +02:00
|
|
|
defines.input_action.deconstruct,
|
|
|
|
defines.input_action.clear_selected_deconstruction_item,
|
|
|
|
defines.input_action.cancel_deconstruct,
|
|
|
|
defines.input_action.toggle_deconstruction_item_entity_filter_mode,
|
|
|
|
defines.input_action.toggle_deconstruction_item_tile_filter_mode,
|
|
|
|
defines.input_action.set_deconstruction_item_tile_selection_mode,
|
|
|
|
defines.input_action.set_deconstruction_item_trees_and_rocks_only
|
|
|
|
}
|
|
|
|
for _, d in pairs(defs) do
|
|
|
|
permission_group.set_allows_action(d, false)
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
2022-10-05 20:38:19 +02:00
|
|
|
--local function enable_artillery(force, permission_group)
|
|
|
|
-- permission_group.set_allows_action(defines.input_action.use_artillery_remote, true)
|
|
|
|
-- force.technologies['artillery'].enabled = true
|
|
|
|
-- force.technologies['artillery-shell-range-1'].enabled = true
|
|
|
|
-- force.technologies['artillery-shell-speed-1'].enabled = true
|
|
|
|
-- force.recipes['artillery-turret'].enabled = false
|
|
|
|
-- force.recipes['artillery-wagon'].enabled = false
|
|
|
|
-- force.recipes['artillery-targeting-remote'].enabled = false
|
|
|
|
-- force.recipes['artillery-shell'].enabled = false
|
|
|
|
--end
|
2022-09-30 22:23:37 +02:00
|
|
|
|
2021-02-06 22:42:10 +02:00
|
|
|
local function disable_artillery(force, permission_group)
|
2021-03-24 17:46:00 +02:00
|
|
|
permission_group.set_allows_action(defines.input_action.use_artillery_remote, false)
|
|
|
|
force.technologies['artillery'].enabled = false
|
|
|
|
force.technologies['artillery-shell-range-1'].enabled = false
|
|
|
|
force.technologies['artillery-shell-speed-1'].enabled = false
|
|
|
|
force.recipes['artillery-turret'].enabled = false
|
|
|
|
force.recipes['artillery-wagon'].enabled = false
|
|
|
|
force.recipes['artillery-targeting-remote'].enabled = false
|
|
|
|
force.recipes['artillery-shell'].enabled = false
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function disable_spidertron(force, permission_group)
|
2021-03-24 17:46:00 +02:00
|
|
|
permission_group.set_allows_action(defines.input_action.send_spidertron, false)
|
|
|
|
force.technologies['spidertron'].enabled = false
|
|
|
|
force.recipes['spidertron'].enabled = false
|
|
|
|
force.recipes['spidertron-remote'].enabled = false
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function disable_rockets(force)
|
2021-03-24 17:46:00 +02:00
|
|
|
force.technologies['rocketry'].enabled = false
|
|
|
|
force.technologies['explosive-rocketry'].enabled = false
|
|
|
|
force.recipes['rocket-launcher'].enabled = false
|
|
|
|
force.recipes['rocket'].enabled = false
|
|
|
|
force.recipes['explosive-rocket'].enabled = false
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function disable_nukes(force)
|
2021-03-24 17:46:00 +02:00
|
|
|
force.technologies['atomic-bomb'].enabled = false
|
|
|
|
force.recipes['atomic-bomb'].enabled = false
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function disable_cluster_grenades(force)
|
2021-03-24 17:46:00 +02:00
|
|
|
force.recipes['cluster-grenade'].enabled = false
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function enable_radar(force)
|
2021-03-24 17:46:00 +02:00
|
|
|
force.recipes['radar'].enabled = true
|
|
|
|
force.share_chart = true
|
|
|
|
force.clear_chart('nauvis')
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function disable_radar(force)
|
2021-03-24 17:46:00 +02:00
|
|
|
force.recipes['radar'].enabled = false
|
|
|
|
force.share_chart = false
|
|
|
|
force.clear_chart('nauvis')
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function disable_achievements(permission_group)
|
2021-03-24 17:46:00 +02:00
|
|
|
permission_group.set_allows_action(defines.input_action.open_achievements_gui, false)
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function disable_tips_and_tricks(permission_group)
|
2021-03-24 17:46:00 +02:00
|
|
|
permission_group.set_allows_action(defines.input_action.open_tips_and_tricks_gui, false)
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
-- setup a team force
|
|
|
|
function Public.add_new_force(force_name)
|
2022-09-30 22:23:37 +02:00
|
|
|
local this = ScenarioTable.get_table()
|
2021-03-24 17:46:00 +02:00
|
|
|
-- disable permissions
|
|
|
|
local force = game.create_force(force_name)
|
|
|
|
local permission_group = game.permissions.create_group(force_name)
|
|
|
|
reset_permissions(permission_group)
|
2022-03-01 19:55:02 +02:00
|
|
|
enable_blueprints(permission_group)
|
|
|
|
enable_deconstruct(permission_group)
|
2022-10-05 19:22:15 +02:00
|
|
|
disable_artillery(force, permission_group)
|
2021-03-24 17:46:00 +02:00
|
|
|
disable_spidertron(force, permission_group)
|
|
|
|
disable_rockets(force)
|
|
|
|
disable_nukes(force)
|
|
|
|
disable_cluster_grenades(force)
|
|
|
|
enable_radar(force)
|
|
|
|
disable_achievements(permission_group)
|
|
|
|
disable_tips_and_tricks(permission_group)
|
|
|
|
-- friendly fire
|
|
|
|
force.friendly_fire = true
|
|
|
|
-- disable technologies
|
2022-10-06 08:41:10 +02:00
|
|
|
for _, recipe_name in pairs(all_force_enabled_recipes) do
|
|
|
|
force.recipes[recipe_name].enabled = true
|
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
force.research_queue_enabled = true
|
|
|
|
-- balance initial combat
|
2022-10-15 12:27:16 +02:00
|
|
|
CombatBalance.init_player_weapon_damage(force)
|
2022-09-30 22:23:37 +02:00
|
|
|
if (this.testing_mode == true) then
|
2022-03-01 19:55:02 +02:00
|
|
|
local e_force = game.forces['enemy']
|
|
|
|
e_force.set_friend(force, true) -- team force should not be attacked by turrets
|
|
|
|
e_force.set_cease_fire(force, true) -- team force should not be attacked by units
|
|
|
|
force.enable_all_prototypes()
|
|
|
|
force.research_all_technologies()
|
|
|
|
end
|
|
|
|
return force
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
2022-09-30 22:23:37 +02:00
|
|
|
function Public.reset_all_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' and force.name ~= 'rogue' then
|
|
|
|
game.merge_forces(force.name, 'player')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
game.forces['enemy'].reset()
|
|
|
|
game.forces['neutral'].reset()
|
|
|
|
game.forces['player'].reset()
|
|
|
|
end
|
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
local function kill_force(force_name, cause)
|
2022-09-30 22:23:37 +02:00
|
|
|
local this = ScenarioTable.get_table()
|
2021-03-24 17:46:00 +02:00
|
|
|
local force = game.forces[force_name]
|
2022-09-30 22:23:37 +02:00
|
|
|
local town_center = this.town_centers[force_name]
|
2022-03-01 19:55:02 +02:00
|
|
|
local market = town_center.market
|
|
|
|
local position = market.position
|
2021-03-24 17:46:00 +02:00
|
|
|
local surface = market.surface
|
2022-03-01 19:55:02 +02:00
|
|
|
local balance = town_center.coin_balance
|
|
|
|
local town_name = town_center.town_name
|
|
|
|
surface.create_entity({name = 'big-artillery-explosion', position = position})
|
2022-10-10 14:53:57 +02:00
|
|
|
|
2022-10-11 23:17:30 +02:00
|
|
|
local is_suicide = cause and force_name == cause.force.name
|
2022-10-10 14:53:57 +02:00
|
|
|
|
2021-03-24 17:46:00 +02:00
|
|
|
for _, player in pairs(force.players) do
|
2022-09-30 22:23:37 +02:00
|
|
|
this.spawn_point[player.index] = nil
|
|
|
|
this.cooldowns_town_placement[player.index] = game.tick + 3600 * 5
|
|
|
|
this.buffs[player.index] = {}
|
2021-03-24 17:46:00 +02:00
|
|
|
if player.character then
|
|
|
|
player.character.die()
|
|
|
|
else
|
2022-09-30 22:23:37 +02:00
|
|
|
this.requests[player.index] = 'kill-character'
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
player.force = game.forces.player
|
2022-09-30 22:23:37 +02:00
|
|
|
Map.disable_world_map(player)
|
2021-03-24 17:46:00 +02:00
|
|
|
Public.set_player_color(player)
|
2022-03-01 19:55:02 +02:00
|
|
|
Public.give_key(player.index)
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
for _, e in pairs(surface.find_entities_filtered({force = force_name})) do
|
|
|
|
if e.valid then
|
2022-03-01 19:55:02 +02:00
|
|
|
if destroy_military_types[e.type] == true then
|
|
|
|
surface.create_entity({name = 'big-artillery-explosion', position = position})
|
2021-03-24 17:46:00 +02:00
|
|
|
e.die()
|
2022-10-10 13:30:57 +02:00
|
|
|
elseif destroy_robot_types[e.type] == true then
|
|
|
|
surface.create_entity({name = 'explosion', position = position})
|
|
|
|
e.die()
|
|
|
|
elseif destroy_wall_types[e.type] == true then
|
|
|
|
e.die()
|
2022-10-10 13:48:41 +02:00
|
|
|
elseif storage_types[e.type] ~= true then -- spare chests
|
2022-10-10 13:46:47 +02:00
|
|
|
local random = math_random()
|
|
|
|
if random > 0.5 or e.health == nil then
|
|
|
|
e.die()
|
|
|
|
elseif random < 0.25 then
|
|
|
|
e.health = e.health * math_random()
|
2022-03-01 19:55:02 +02:00
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2022-03-01 19:55:02 +02:00
|
|
|
local r = 27
|
2022-09-22 20:19:19 +02:00
|
|
|
for _, e in pairs(surface.find_entities_filtered({area = {{position.x - r, position.y - r}, {position.x + r, position.y + r}}, force = 'neutral', type = 'resource'})) do
|
2022-03-01 19:55:02 +02:00
|
|
|
if e.name ~= 'crude-oil' then
|
|
|
|
e.destroy()
|
|
|
|
end
|
|
|
|
end
|
2022-10-08 17:17:10 +02:00
|
|
|
if this.pvp_shields[force_name] then
|
2022-10-09 12:11:38 +02:00
|
|
|
PvPShield.remove_shield(this.pvp_shields[force_name])
|
2022-10-06 08:56:30 +02:00
|
|
|
end
|
2022-10-10 14:53:57 +02:00
|
|
|
|
2021-03-24 17:46:00 +02:00
|
|
|
game.merge_forces(force_name, 'neutral')
|
2022-09-30 22:23:37 +02:00
|
|
|
this.town_centers[force_name] = nil
|
2021-03-24 17:46:00 +02:00
|
|
|
delete_chart_tag_for_all_forces(market)
|
2022-10-08 20:09:23 +02:00
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
-- reward the killer
|
2022-10-08 20:09:23 +02:00
|
|
|
local message
|
2022-10-10 14:53:57 +02:00
|
|
|
if is_suicide then
|
|
|
|
message = town_name .. ' has given up'
|
|
|
|
elseif cause == nil or not cause.valid or cause.force == nil then
|
2022-10-12 10:03:35 +02:00
|
|
|
message = town_name .. ' has fallen to an unknown entity (DEBUG ID 0)!' -- TODO: remove after some testing
|
2022-10-08 20:09:23 +02:00
|
|
|
elseif cause.force.name == 'player' or cause.force.name == 'rogue' then
|
2022-03-01 19:55:02 +02:00
|
|
|
local items = {name = 'coin', count = balance}
|
|
|
|
town_center.coin_balance = 0
|
|
|
|
if balance > 0 then
|
|
|
|
if cause.can_insert(items) then
|
|
|
|
cause.insert(items)
|
|
|
|
else
|
|
|
|
local chest = surface.create_entity({name = 'steel-chest', position = position, force = 'neutral'})
|
|
|
|
chest.insert(items)
|
|
|
|
end
|
|
|
|
end
|
2022-10-15 13:23:11 +02:00
|
|
|
if cause.name == 'character' then
|
2022-10-10 14:53:57 +02:00
|
|
|
message = town_name .. ' has fallen to ' .. cause.player.name .. '!'
|
2022-10-08 20:09:23 +02:00
|
|
|
elseif cause.force.name == 'player' then
|
|
|
|
message = town_name .. ' has fallen to outlanders!'
|
2022-10-10 14:53:57 +02:00
|
|
|
elseif cause.force.name == 'rogue' then
|
2022-10-08 20:09:23 +02:00
|
|
|
message = town_name .. ' has fallen to rogues!'
|
2022-10-10 14:53:57 +02:00
|
|
|
else
|
2022-10-12 10:03:35 +02:00
|
|
|
message = town_name .. ' has fallen to an unknown entity (DEBUG ID 1)!' -- TODO: remove after some testing
|
2022-03-01 19:55:02 +02:00
|
|
|
end
|
2022-10-08 20:09:23 +02:00
|
|
|
elseif cause.force.name ~= 'enemy' then
|
|
|
|
if this.town_centers[cause.force.name] ~= nil then
|
|
|
|
local killer_town_center = this.town_centers[cause.force.name]
|
|
|
|
if balance > 0 then
|
|
|
|
killer_town_center.coin_balance = killer_town_center.coin_balance + balance
|
|
|
|
cause.force.print(balance .. " coins have been transferred to your town")
|
2022-03-01 19:55:02 +02:00
|
|
|
end
|
2022-10-15 13:23:11 +02:00
|
|
|
if cause.name == 'character' then
|
2022-10-10 14:53:57 +02:00
|
|
|
message = town_name .. ' has fallen to ' .. cause.player.name .. ' from ' .. killer_town_center.town_name .. '!'
|
|
|
|
else
|
|
|
|
message = town_name .. ' has fallen to ' .. killer_town_center.town_name .. '!'
|
|
|
|
end
|
|
|
|
else
|
2022-10-12 10:03:35 +02:00
|
|
|
message = town_name .. ' has fallen to an unknown entity (DEBUG ID 2)!' -- TODO: remove after some testing
|
|
|
|
log("cause.force.name=" .. cause.force.name)
|
2022-03-01 19:55:02 +02:00
|
|
|
end
|
2022-10-08 20:09:23 +02:00
|
|
|
else
|
|
|
|
message = town_name .. ' has fallen to the biters!'
|
2022-03-01 19:55:02 +02:00
|
|
|
end
|
2022-10-08 20:09:23 +02:00
|
|
|
|
|
|
|
Server.to_discord_embed(message)
|
|
|
|
game.print('>> ' .. message, {255, 255, 0})
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
|
2022-10-08 19:47:26 +02:00
|
|
|
local function on_forces_merged()
|
|
|
|
-- Remove any ghosts that have been moved into neutral after a town is destroyed. This caused desyncs before.
|
|
|
|
for _, e in pairs(game.surfaces.nauvis.find_entities_filtered({force = 'neutral', type = "entity-ghost"})) do
|
|
|
|
if e.valid then
|
|
|
|
e.destroy()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2022-09-30 22:23:37 +02:00
|
|
|
|
2022-03-01 19:55:02 +02:00
|
|
|
local function setup_neutral_force()
|
|
|
|
local force = game.forces['neutral']
|
|
|
|
force.technologies['military'].researched = true
|
|
|
|
force.technologies['automation'].researched = true
|
|
|
|
force.technologies['logistic-science-pack'].researched = true
|
|
|
|
force.technologies['steel-processing'].researched = true
|
|
|
|
force.technologies['engine'].researched = true
|
|
|
|
force.recipes['submachine-gun'].enabled = true
|
|
|
|
force.recipes['engine-unit'].enabled = true
|
|
|
|
force.recipes['stone-brick'].enabled = false
|
|
|
|
force.recipes['radar'].enabled = false
|
|
|
|
force.recipes['lab'].enabled = false
|
|
|
|
force.recipes['automation-science-pack'].enabled = false
|
|
|
|
force.recipes['logistic-science-pack'].enabled = false
|
|
|
|
end
|
|
|
|
|
2021-02-06 22:42:10 +02:00
|
|
|
-- setup the player force (this is the default for Outlanders)
|
|
|
|
local function setup_player_force()
|
2022-09-30 22:23:37 +02:00
|
|
|
local this = ScenarioTable.get_table()
|
2021-03-24 17:46:00 +02:00
|
|
|
local force = game.forces.player
|
|
|
|
local permission_group = game.permissions.create_group('outlander')
|
|
|
|
-- disable permissions
|
|
|
|
reset_permissions(permission_group)
|
|
|
|
disable_blueprints(permission_group)
|
2022-03-01 19:55:02 +02:00
|
|
|
disable_deconstruct(permission_group)
|
2021-03-24 17:46:00 +02:00
|
|
|
disable_artillery(force, permission_group)
|
|
|
|
disable_spidertron(force, permission_group)
|
|
|
|
disable_rockets(force)
|
|
|
|
disable_nukes(force)
|
|
|
|
disable_cluster_grenades(force)
|
|
|
|
disable_radar(force)
|
|
|
|
disable_achievements(permission_group)
|
|
|
|
disable_tips_and_tricks(permission_group)
|
|
|
|
-- disable research
|
|
|
|
force.disable_research()
|
|
|
|
force.research_queue_enabled = false
|
|
|
|
-- friendly fire
|
|
|
|
force.friendly_fire = true
|
|
|
|
-- disable recipes
|
|
|
|
local recipes = force.recipes
|
|
|
|
for _, recipe_name in pairs(player_force_disabled_recipes) do
|
|
|
|
recipes[recipe_name].enabled = false
|
|
|
|
end
|
2022-10-06 08:41:10 +02:00
|
|
|
for _, recipe_name in pairs(all_force_enabled_recipes) do
|
2021-03-24 17:46:00 +02:00
|
|
|
recipes[recipe_name].enabled = true
|
|
|
|
end
|
2022-10-15 12:27:16 +02:00
|
|
|
CombatBalance.init_player_weapon_damage(force)
|
2022-09-30 22:23:37 +02:00
|
|
|
if (this.testing_mode == true) then
|
2022-03-01 19:55:02 +02:00
|
|
|
force.enable_all_prototypes()
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function setup_rogue_force()
|
2022-09-30 22:23:37 +02:00
|
|
|
local this = ScenarioTable.get_table()
|
|
|
|
local force = game.forces['rogue']
|
|
|
|
if game.forces['rogue'] == nil then
|
|
|
|
force = game.create_force('rogue')
|
|
|
|
end
|
|
|
|
local permission_group = game.permissions.create_group('rogue')
|
2021-03-24 17:46:00 +02:00
|
|
|
-- disable permissions
|
|
|
|
reset_permissions(permission_group)
|
|
|
|
disable_blueprints(permission_group)
|
2022-03-01 19:55:02 +02:00
|
|
|
disable_deconstruct(permission_group)
|
2021-03-24 17:46:00 +02:00
|
|
|
disable_artillery(force, permission_group)
|
|
|
|
disable_spidertron(force, permission_group)
|
|
|
|
disable_rockets(force)
|
|
|
|
disable_nukes(force)
|
|
|
|
disable_cluster_grenades(force)
|
|
|
|
disable_radar(force)
|
|
|
|
disable_achievements(permission_group)
|
|
|
|
disable_tips_and_tricks(permission_group)
|
|
|
|
-- disable research
|
|
|
|
force.disable_research()
|
|
|
|
force.research_queue_enabled = false
|
|
|
|
-- friendly fire
|
|
|
|
force.friendly_fire = true
|
|
|
|
-- disable recipes
|
|
|
|
local recipes = force.recipes
|
|
|
|
for _, recipe_name in pairs(player_force_disabled_recipes) do
|
|
|
|
recipes[recipe_name].enabled = false
|
|
|
|
end
|
2022-10-06 08:41:10 +02:00
|
|
|
for _, recipe_name in pairs(all_force_enabled_recipes) do
|
2021-03-24 17:46:00 +02:00
|
|
|
recipes[recipe_name].enabled = true
|
|
|
|
end
|
2022-10-15 12:27:16 +02:00
|
|
|
CombatBalance.init_player_weapon_damage(force)
|
2022-09-30 22:23:37 +02:00
|
|
|
if (this.testing_mode == true) then
|
2022-03-01 19:55:02 +02:00
|
|
|
force.enable_all_prototypes()
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function setup_enemy_force()
|
2022-09-30 22:23:37 +02:00
|
|
|
local this = ScenarioTable.get_table()
|
2021-03-24 17:46:00 +02:00
|
|
|
local e_force = game.forces['enemy']
|
|
|
|
e_force.evolution_factor = 1 -- this should never change since we are changing biter types on spawn
|
|
|
|
e_force.set_friend(game.forces.player, true) -- outlander force (player) should not be attacked by turrets
|
|
|
|
e_force.set_cease_fire(game.forces.player, true) -- outlander force (player) should not be attacked by units
|
2022-09-30 22:23:37 +02:00
|
|
|
if (this.testing_mode == true) then
|
2022-03-01 19:55:02 +02:00
|
|
|
e_force.set_friend(game.forces['rogue'], true) -- rogue force (rogue) should not be attacked by turrets
|
|
|
|
e_force.set_cease_fire(game.forces['rogue'], true) -- rogue force (rogue) should not be attacked by units
|
|
|
|
else
|
2022-03-01 20:11:08 +02:00
|
|
|
-- note, these don't prevent an outlander or rogue from attacking a unit or spawner, we need to handle separately
|
2022-03-01 19:55:02 +02:00
|
|
|
e_force.set_friend(game.forces['rogue'], false) -- rogue force (rogue) should be attacked by turrets
|
|
|
|
e_force.set_cease_fire(game.forces['rogue'], false) -- rogue force (rogue) should be attacked by units
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
2022-09-30 22:23:37 +02:00
|
|
|
local function reset_forces()
|
|
|
|
local players = game.players
|
|
|
|
local forces = game.forces
|
|
|
|
for i = 1, #players do
|
|
|
|
local player = players[i]
|
|
|
|
local force = forces[player.name]
|
|
|
|
if force then
|
|
|
|
game.merge_forces(force, 'player')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-06 22:42:10 +02:00
|
|
|
local function on_player_dropped_item(event)
|
2021-03-24 17:46:00 +02:00
|
|
|
local player = game.players[event.player_index]
|
|
|
|
local entity = event.entity
|
2022-03-01 19:55:02 +02:00
|
|
|
if entity.stack.name == 'coin' then
|
2021-03-24 17:46:00 +02:00
|
|
|
ally_town(player, entity)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
if entity.stack.name == 'coal' then
|
|
|
|
declare_war(player, entity)
|
|
|
|
return
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function on_entity_damaged(event)
|
2021-03-24 17:46:00 +02:00
|
|
|
local entity = event.entity
|
2022-09-30 22:23:37 +02:00
|
|
|
if not entity or not entity.valid then
|
2021-03-24 17:46:00 +02:00
|
|
|
return
|
|
|
|
end
|
|
|
|
local cause = event.cause
|
|
|
|
local force = event.force
|
|
|
|
|
|
|
|
-- special case to handle enemies attacked by outlanders
|
|
|
|
if entity.force == game.forces['enemy'] then
|
|
|
|
if cause ~= nil then
|
2022-03-01 19:55:02 +02:00
|
|
|
if cause.type == 'character' and force.index == game.forces['player'].index then
|
2021-03-24 17:46:00 +02:00
|
|
|
local player = cause.player
|
2022-09-30 22:23:37 +02:00
|
|
|
if player and player.valid and force.index == game.forces['player'].index then
|
2021-03-24 17:46:00 +02:00
|
|
|
-- set the force of the player to rogue until they die or create a town
|
|
|
|
set_player_to_rogue(player)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-- cars and tanks
|
|
|
|
if cause.type == 'car' or cause.type == 'tank' then
|
|
|
|
local driver = cause.get_driver()
|
2022-09-30 22:23:37 +02:00
|
|
|
if driver and driver.valid then
|
|
|
|
-- driver may be LuaEntity or LuaPlayer
|
|
|
|
local player = driver
|
|
|
|
if driver.object_name == 'LuaEntity' then
|
|
|
|
player = driver.player
|
|
|
|
end
|
|
|
|
if player and player.valid and player.force.index == game.forces['player'].index then
|
|
|
|
-- set the force of the player to rogue until they die or create a town
|
|
|
|
set_player_to_rogue(player)
|
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
2022-09-30 22:23:37 +02:00
|
|
|
|
2021-03-24 17:46:00 +02:00
|
|
|
local passenger = cause.get_passenger()
|
2022-09-30 22:23:37 +02:00
|
|
|
if passenger and passenger.valid then
|
|
|
|
-- passenger may be LuaEntity or LuaPlayer
|
|
|
|
local player = passenger
|
|
|
|
if passenger.object_name == 'LuaEntity' then
|
|
|
|
player = passenger.player
|
|
|
|
end
|
|
|
|
if player and player.valid and player.force.index == game.forces['player'].index then
|
|
|
|
-- set the force of the player to rogue until they die or create a town
|
|
|
|
set_player_to_rogue(player)
|
2022-10-08 13:39:47 +02:00
|
|
|
-- set the vehicle to rogue
|
|
|
|
cause.force = game.forces['rogue']
|
2022-09-30 22:23:37 +02:00
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
-- trains
|
|
|
|
if cause.type == 'locomotive' or cause.type == 'cargo-wagon' or cause.type == 'fluid-wagon' or cause.type == 'artillery-wagon' then
|
|
|
|
local train = cause.train
|
|
|
|
for _, passenger in pairs(train.passengers) do
|
2022-09-30 22:23:37 +02:00
|
|
|
if passenger and passenger.valid then
|
|
|
|
-- passenger may be LuaEntity or LuaPlayer
|
|
|
|
local player = passenger
|
|
|
|
if passenger.object_name == 'LuaEntity' then
|
|
|
|
player = passenger.player
|
|
|
|
end
|
|
|
|
if player and player.valid and player.force.index == game.forces['player'].index then
|
|
|
|
set_player_to_rogue(player)
|
2022-10-08 13:39:47 +02:00
|
|
|
-- set the vehicle to rogue
|
|
|
|
cause.force = game.forces['rogue']
|
2022-09-30 22:23:37 +02:00
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-- combat robots
|
2022-03-01 19:55:02 +02:00
|
|
|
if cause.type == 'combat-robot' then
|
2022-09-30 22:23:37 +02:00
|
|
|
local owner = cause.combat_robot_owner
|
|
|
|
if owner and owner.valid and owner.force == game.forces['player'] then
|
2022-03-01 19:55:02 +02:00
|
|
|
-- set the force of the player to rogue until they die or create a town
|
|
|
|
set_player_to_rogue(owner)
|
2022-10-08 13:39:47 +02:00
|
|
|
-- set the robot to rogue
|
|
|
|
cause.force = game.forces['rogue']
|
2022-03-01 19:55:02 +02:00
|
|
|
end
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function on_entity_died(event)
|
2021-03-24 17:46:00 +02:00
|
|
|
local entity = event.entity
|
2022-03-01 19:55:02 +02:00
|
|
|
local cause = event.cause
|
2022-09-30 22:23:37 +02:00
|
|
|
if entity and entity.valid and entity.name == 'market' then
|
2022-03-01 19:55:02 +02:00
|
|
|
kill_force(entity.force.name, cause)
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function on_post_entity_died(event)
|
2021-03-24 17:46:00 +02:00
|
|
|
local prototype = event.prototype.type
|
|
|
|
if prototype ~= 'character' then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local entities = game.surfaces[event.surface_index].find_entities_filtered({position = event.position, radius = 1})
|
|
|
|
for _, e in pairs(entities) do
|
|
|
|
if e.type == 'character-corpse' then
|
2022-03-01 19:55:02 +02:00
|
|
|
Public.remove_key(e.character_corpse_player_index)
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function on_console_command(event)
|
2021-03-24 17:46:00 +02:00
|
|
|
set_town_color(event)
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function on_console_chat(event)
|
2021-03-24 17:46:00 +02:00
|
|
|
local player = game.players[event.player_index]
|
|
|
|
if string_match(string_lower(event.message), '%[armor%=') then
|
|
|
|
player.clear_console()
|
2022-10-10 23:23:22 +02:00
|
|
|
game.print('Viewing player armor is disabled')
|
2021-03-24 17:46:00 +02:00
|
|
|
end
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function Public.initialize()
|
2022-09-30 22:23:37 +02:00
|
|
|
reset_forces()
|
2022-03-01 19:55:02 +02:00
|
|
|
setup_neutral_force()
|
2021-03-24 17:46:00 +02:00
|
|
|
setup_player_force()
|
|
|
|
setup_rogue_force()
|
|
|
|
setup_enemy_force()
|
2021-02-06 22:42:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local Event = require 'utils.event'
|
|
|
|
Event.add(defines.events.on_player_dropped_item, on_player_dropped_item)
|
|
|
|
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
|
|
|
|
Event.add(defines.events.on_entity_died, on_entity_died)
|
|
|
|
Event.add(defines.events.on_post_entity_died, on_post_entity_died)
|
|
|
|
Event.add(defines.events.on_console_command, on_console_command)
|
|
|
|
Event.add(defines.events.on_console_chat, on_console_chat)
|
2022-10-08 19:47:26 +02:00
|
|
|
Event.add(defines.events.on_forces_merged, on_forces_merged)
|
2021-03-24 17:46:00 +02:00
|
|
|
return Public
|