mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-24 03:47:58 +02:00
29b3a89b33
Fixed issue with determining if market is placeable Allow entities to be placed within the initial town square Fixed info to remove reference to small plane Fixed issue with no messages when can't place item due to building restrictions Fixed issue with inability to place new towns near enemy spawners or turrets Fixed issue with market listings breaking when special features disabled due to deprecation of computer item Fixed issue with mining sound missing for big-crash-site-# entities (in mod) Default to showing entity info for players (alt-info on chests)
523 lines
17 KiB
Lua
523 lines
17 KiB
Lua
local Public = {}
|
|
|
|
local math_random = math.random
|
|
local table_insert = table.insert
|
|
local math_floor = math.floor
|
|
local table_shuffle = table.shuffle_table
|
|
|
|
local Table = require 'modules.scrap_towny_ffa.table'
|
|
local Team = require "modules.scrap_towny_ffa.team"
|
|
local Building = require "modules.scrap_towny_ffa.building"
|
|
|
|
local town_radius = 27
|
|
local radius_between_towns = 160
|
|
local ore_amount = 250
|
|
|
|
local colors = {}
|
|
local c1 = 250
|
|
local c2 = 210
|
|
local c3 = -40
|
|
for v = c1, c2, c3 do
|
|
table_insert(colors, { 0, 0, v })
|
|
end
|
|
for v = c1, c2, c3 do
|
|
table_insert(colors, { 0, v, 0 })
|
|
end
|
|
for v = c1, c2, c3 do
|
|
table_insert(colors, { v, 0, 0 })
|
|
end
|
|
for v = c1, c2, c3 do
|
|
table_insert(colors, { 0, v, v })
|
|
end
|
|
for v = c1, c2, c3 do
|
|
table_insert(colors, { v, v, 0 })
|
|
end
|
|
for v = c1, c2, c3 do
|
|
table_insert(colors, { v, 0, v })
|
|
end
|
|
|
|
local town_wall_vectors = {}
|
|
for x = 2, town_radius, 1 do
|
|
table_insert(town_wall_vectors, { x, town_radius })
|
|
table_insert(town_wall_vectors, { x * -1, town_radius })
|
|
table_insert(town_wall_vectors, { x, town_radius * -1 })
|
|
table_insert(town_wall_vectors, { x * -1, town_radius * -1 })
|
|
end
|
|
for y = 2, town_radius - 1, 1 do
|
|
table_insert(town_wall_vectors, { town_radius, y })
|
|
table_insert(town_wall_vectors, { town_radius, y * -1 })
|
|
table_insert(town_wall_vectors, { town_radius * -1, y })
|
|
table_insert(town_wall_vectors, { town_radius * -1, y * -1 })
|
|
end
|
|
|
|
local gate_vectors_horizontal = {}
|
|
for x = -1, 1, 1 do
|
|
table_insert(gate_vectors_horizontal, { x, town_radius })
|
|
table_insert(gate_vectors_horizontal, { x, town_radius * -1 })
|
|
end
|
|
local gate_vectors_vertical = {}
|
|
for y = -1, 1, 1 do
|
|
table_insert(gate_vectors_vertical, { town_radius, y })
|
|
table_insert(gate_vectors_vertical, { town_radius * -1, y })
|
|
end
|
|
|
|
local resource_vectors = {}
|
|
resource_vectors[1] = {}
|
|
for x = 7, 24, 1 do
|
|
for y = 7, 24, 1 do
|
|
table_insert(resource_vectors[1], { x, y })
|
|
end
|
|
end
|
|
resource_vectors[2] = {}
|
|
for _, vector in pairs(resource_vectors[1]) do table_insert(resource_vectors[2], { vector[1] * -1, vector[2] }) end
|
|
resource_vectors[3] = {}
|
|
for _, vector in pairs(resource_vectors[1]) do table_insert(resource_vectors[3], { vector[1] * -1, vector[2] * -1 }) end
|
|
resource_vectors[4] = {}
|
|
for _, vector in pairs(resource_vectors[1]) do table_insert(resource_vectors[4], { vector[1], vector[2] * -1 }) end
|
|
|
|
local additional_resource_vectors = {}
|
|
additional_resource_vectors[1] = {}
|
|
for x = 10, 22, 1 do
|
|
for y = -4, 4, 1 do
|
|
table_insert(additional_resource_vectors[1], { x, y })
|
|
end
|
|
end
|
|
additional_resource_vectors[2] = {}
|
|
for _, vector in pairs(additional_resource_vectors[1]) do table_insert(additional_resource_vectors[2], { vector[1] * -1, vector[2] }) end
|
|
additional_resource_vectors[3] = {}
|
|
for y = 10, 22, 1 do
|
|
for x = -4, 4, 1 do
|
|
table_insert(additional_resource_vectors[3], { x, y })
|
|
end
|
|
end
|
|
additional_resource_vectors[4] = {}
|
|
for _, vector in pairs(additional_resource_vectors[3]) do table_insert(additional_resource_vectors[4], { vector[1], vector[2] * -1 }) end
|
|
|
|
local clear_whitelist_types = {
|
|
["simple-entity"] = true,
|
|
["resource"] = true,
|
|
["cliff"] = true,
|
|
["tree"] = true,
|
|
}
|
|
|
|
local starter_supplies = {
|
|
{ name = "raw-fish", count = 3 },
|
|
{ name = "grenade", count = 3 },
|
|
{ name = "stone", count = 32 },
|
|
{ name = "land-mine", count = 4 },
|
|
{ name = "iron-gear-wheel", count = 16 },
|
|
{ name = "iron-plate", count = 32 },
|
|
{ name = "copper-plate", count = 16 },
|
|
{ name = "shotgun", count = 1 },
|
|
{ name = "shotgun-shell", count = 8 },
|
|
{ name = "firearm-magazine", count = 16 },
|
|
{ name = "firearm-magazine", count = 16 },
|
|
{ name = "gun-turret", count = 2 },
|
|
}
|
|
|
|
local function count_nearby_ore(surface, position, ore_name)
|
|
local count = 0
|
|
local r = town_radius + 8
|
|
for _, e in pairs(surface.find_entities_filtered({ area = { { position.x - r, position.y - r }, { position.x + r, position.y + r } }, force = "neutral", name = ore_name })) do
|
|
count = count + e.amount
|
|
end
|
|
return count
|
|
end
|
|
|
|
local function draw_town_spawn(player_name)
|
|
local ffatable = Table.get_table()
|
|
local market = ffatable.town_centers[player_name].market
|
|
local position = market.position
|
|
local surface = market.surface
|
|
|
|
local area = { { position.x - (town_radius + 1), position.y - (town_radius + 1) }, { position.x + (town_radius + 1), position.y + (town_radius + 1) } }
|
|
|
|
-- remove other than cliffs, rocks and ores and trees
|
|
for _, e in pairs(surface.find_entities_filtered({ area = area, force = "neutral" })) do
|
|
if not clear_whitelist_types[e.type] then
|
|
e.destroy()
|
|
end
|
|
end
|
|
|
|
-- create walls
|
|
for _, vector in pairs(gate_vectors_horizontal) do
|
|
local p = { position.x + vector[1], position.y + vector[2] }
|
|
--p = surface.find_non_colliding_position("gate", p, 64, 1)
|
|
if p then
|
|
surface.create_entity({ name = "gate", position = p, force = player_name, direction = 2 })
|
|
end
|
|
end
|
|
for _, vector in pairs(gate_vectors_vertical) do
|
|
local p = { position.x + vector[1], position.y + vector[2] }
|
|
--p = surface.find_non_colliding_position("gate", p, 64, 1)
|
|
if p then
|
|
surface.create_entity({ name = "gate", position = p, force = player_name, direction = 0 })
|
|
end
|
|
end
|
|
|
|
for _, vector in pairs(town_wall_vectors) do
|
|
local p = { position.x + vector[1], position.y + vector[2] }
|
|
--p = surface.find_non_colliding_position("stone-wall", p, 64, 1)
|
|
if p then
|
|
surface.create_entity({ name = "stone-wall", position = p, force = player_name })
|
|
end
|
|
end
|
|
|
|
-- ore patches
|
|
local ores = { "iron-ore", "copper-ore", "stone", "coal" }
|
|
table_shuffle(ores)
|
|
|
|
for i = 1, 4, 1 do
|
|
if count_nearby_ore(surface, position, ores[i]) < 200000 then
|
|
for _, vector in pairs(resource_vectors[i]) do
|
|
local p = { position.x + vector[1], position.y + vector[2] }
|
|
p = surface.find_non_colliding_position(ores[i], p, 64, 1)
|
|
if p then
|
|
surface.create_entity({ name = ores[i], position = p, amount = ore_amount })
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- starter chests
|
|
for _, item_stack in pairs(starter_supplies) do
|
|
local m1 = -8 + math_random(0, 16)
|
|
local m2 = -8 + math_random(0, 16)
|
|
local p = { position.x + m1, position.y + m2 }
|
|
p = surface.find_non_colliding_position("wooden-chest", p, 64, 1)
|
|
if p then
|
|
local e = surface.create_entity({ name = "wooden-chest", position = p, force = player_name })
|
|
local inventory = e.get_inventory(defines.inventory.chest)
|
|
inventory.insert(item_stack)
|
|
end
|
|
end
|
|
|
|
local vector_indexes = { 1, 2, 3, 4 }
|
|
table_shuffle(vector_indexes)
|
|
|
|
-- trees
|
|
--local tree = "tree-0" .. math_random(1, 9)
|
|
--for _, vector in pairs(additional_resource_vectors[vector_indexes[1]]) do
|
|
-- if math_random(1, 6) == 1 then
|
|
-- local p = {position.x + vector[1], position.y + vector[2]}
|
|
-- p = surface.find_non_colliding_position(tree, p, 64, 1)
|
|
-- if p then
|
|
-- surface.create_entity({name = tree, position = p})
|
|
-- end
|
|
-- end
|
|
--end
|
|
|
|
--local area = {{position.x - town_radius * 1.5, position.y - town_radius * 1.5}, {position.x + town_radius * 1.5, position.y + town_radius * 1.5}}
|
|
|
|
-- pond
|
|
for _, vector in pairs(additional_resource_vectors[vector_indexes[2]]) do
|
|
local x = position.x + vector[1]
|
|
local y = position.y + vector[2]
|
|
local p = { x = x, y = y }
|
|
if surface.get_tile(p).name ~= "out-of-map" then
|
|
surface.set_tiles({ { name = "water-green", position = p } })
|
|
end
|
|
end
|
|
|
|
-- fish
|
|
for _, vector in pairs(additional_resource_vectors[vector_indexes[2]]) do
|
|
local x = position.x + vector[1] + 0.5
|
|
local y = position.y + vector[2] + 0.5
|
|
local p = { x = x, y = y }
|
|
if math_random(1, 5) == 1 then
|
|
if surface.can_place_entity({ name = "fish", position = p }) then
|
|
surface.create_entity({ name = "water-splash", position = p })
|
|
surface.create_entity({ name = "fish", position = p })
|
|
end
|
|
end
|
|
end
|
|
|
|
-- uranium ore
|
|
--if count_nearby_ore(surface, position, "uranium-ore") < 100000 then
|
|
-- for _, vector in pairs(additional_resource_vectors[vector_indexes[3]]) do
|
|
-- local p = {position.x + vector[1], position.y + vector[2]}
|
|
-- p = surface.find_non_colliding_position("uranium-ore", p, 64, 1)
|
|
-- if p then
|
|
-- surface.create_entity({name = "uranium-ore", position = p, amount = ore_amount * 2})
|
|
-- end
|
|
-- end
|
|
--end
|
|
|
|
-- oil patches
|
|
--local vectors = additional_resource_vectors[vector_indexes[4]]
|
|
--for _ = 1, 3, 1 do
|
|
-- local vector = vectors[math_random(1, #vectors)]
|
|
-- local p = {position.x + vector[1], position.y + vector[2]}
|
|
-- p = surface.find_non_colliding_position("crude-oil", p, 64, 1)
|
|
-- if p then
|
|
-- surface.create_entity({name = "crude-oil", position = p, amount = 500000})
|
|
-- end
|
|
--end
|
|
end
|
|
|
|
local function is_valid_location(surface, position)
|
|
local ffatable = Table.get_table()
|
|
|
|
if not surface.can_place_entity({ name = "market", position = position }) then
|
|
surface.create_entity({
|
|
name = "flying-text",
|
|
position = position,
|
|
text = "Position is obstructed - no room for market!",
|
|
color = { r = 0.77, g = 0.0, b = 0.0 }
|
|
})
|
|
return false
|
|
end
|
|
|
|
for _, vector in pairs(town_wall_vectors) do
|
|
local p = { x = math_floor(position.x + vector[1]), y = math_floor(position.y + vector[2]) }
|
|
local tile = surface.get_tile(p.x, p.y)
|
|
if tile.name == "out-of-map" then
|
|
surface.create_entity({
|
|
name = "flying-text",
|
|
position = position,
|
|
text = "Town would be off-map!",
|
|
color = { r = 0.77, g = 0.0, b = 0.0 }
|
|
})
|
|
return false
|
|
end
|
|
end
|
|
|
|
if ffatable.size_of_town_centers > 48 then
|
|
surface.create_entity({
|
|
name = "flying-text",
|
|
position = position,
|
|
text = "Too many town centers on the map!",
|
|
color = { r = 0.77, g = 0.0, b = 0.0 }
|
|
})
|
|
return false
|
|
end
|
|
|
|
if Building.near_town(position, surface, radius_between_towns) then
|
|
surface.create_entity({
|
|
name = "flying-text",
|
|
position = position,
|
|
text = "Town location is too close to another town center!",
|
|
color = { r = 0.77, g = 0.0, b = 0.0 }
|
|
})
|
|
return false
|
|
end
|
|
|
|
local area = { { position.x - town_radius, position.y - town_radius }, { position.x + town_radius, position.y + town_radius } }
|
|
local count = 0
|
|
for _, e in pairs(surface.find_entities_filtered({ area = area })) do
|
|
if e.force.name == "enemy" then
|
|
count = count + 1
|
|
end
|
|
end
|
|
|
|
if count > 1 then
|
|
surface.create_entity({
|
|
name = "flying-text",
|
|
position = position,
|
|
text = "I got a bad feeling about this! There are enemies nearby.",
|
|
color = { r = 0.77, g = 0.0, b = 0.0 }
|
|
})
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function Public.set_market_health(entity, final_damage_amount)
|
|
local ffatable = Table.get_table()
|
|
local town_center = ffatable.town_centers[entity.force.name]
|
|
town_center.health = math_floor(town_center.health - final_damage_amount)
|
|
if town_center.health > town_center.max_health then town_center.health = town_center.max_health end
|
|
local m = town_center.health / town_center.max_health
|
|
entity.health = 150 * m
|
|
rendering.set_text(town_center.health_text, "HP: " .. town_center.health .. " / " .. town_center.max_health)
|
|
end
|
|
|
|
function Public.update_coin_balance(force)
|
|
local ffatable = Table.get_table()
|
|
local town_center = ffatable.town_centers[force.name]
|
|
rendering.set_text(town_center.coins_text, "Coins: " .. town_center.coin_balance)
|
|
end
|
|
|
|
local function is_color_used(color, town_centers)
|
|
for _, center in pairs(town_centers) do
|
|
if center.color then
|
|
if center.color.r == color.r and center.color.g == color.g and center.color.b == color.b then return true end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function get_color()
|
|
local ffatable = Table.get_table()
|
|
local town_centers = ffatable.town_centers
|
|
local c
|
|
|
|
local shuffle_index = {}
|
|
for i = 1, #colors, 1 do shuffle_index[i] = i end
|
|
table_shuffle(shuffle_index)
|
|
|
|
for i = 1, #colors, 1 do
|
|
c = { r = colors[shuffle_index[i]][1], g = colors[shuffle_index[i]][2], b = colors[shuffle_index[i]][3], }
|
|
if not is_color_used(c, town_centers) then return c end
|
|
end
|
|
|
|
return c
|
|
end
|
|
|
|
local function found_town(event)
|
|
local entity = event.created_entity
|
|
if entity == nil or not entity.valid then return true end -- cancel, not a valid entity placed
|
|
if entity.name ~= "stone-furnace" then return false end -- cancel, player did not place a stone-furnace
|
|
local player = game.players[event.player_index]
|
|
if player.force ~= game.forces.player and player.force ~= game.forces["rogue"] then return false end -- cancel, player is in a team already
|
|
local force_name = tostring(player.name)
|
|
if game.forces[force_name] then return end -- cancel, player is mayor of town
|
|
if Team.has_key(player) == false then return false end -- cancel, player has already placed a town
|
|
|
|
local surface = entity.surface
|
|
local ffatable = Table.get_table()
|
|
|
|
if ffatable.cooldowns_town_placement[player.index] then
|
|
if game.tick < ffatable.cooldowns_town_placement[player.index] then
|
|
surface.create_entity({
|
|
name = "flying-text",
|
|
position = entity.position,
|
|
text = "Town founding is on cooldown for " .. math.ceil((ffatable.cooldowns_town_placement[player.index] - game.tick) / 3600) .. " minutes.",
|
|
color = { r = 0.77, g = 0.0, b = 0.0 }
|
|
})
|
|
player.insert({ name = "stone-furnace", count = 1 })
|
|
entity.destroy()
|
|
return true
|
|
end
|
|
end
|
|
|
|
local position = entity.position
|
|
entity.destroy()
|
|
|
|
if not is_valid_location(surface, position) then
|
|
player.insert({ name = "stone-furnace", count = 1 })
|
|
return true
|
|
end
|
|
|
|
Team.add_new_force(force_name)
|
|
|
|
ffatable.town_centers[force_name] = {}
|
|
local town_center = ffatable.town_centers[force_name]
|
|
town_center.market = surface.create_entity({ name = "market", position = position, force = force_name })
|
|
town_center.chunk_position = { math.floor(town_center.market.position.x / 32), math.floor(town_center.market.position.y / 32) }
|
|
town_center.max_health = 1000
|
|
town_center.coin_balance = 0
|
|
town_center.input_buffer = {}
|
|
town_center.output_buffer = {}
|
|
town_center.health = town_center.max_health
|
|
town_center.color = get_color()
|
|
town_center.research_counter = 1
|
|
town_center.upgrades = {}
|
|
town_center.upgrades.mining_prod = 0
|
|
town_center.upgrades.laser_turret = {}
|
|
town_center.upgrades.laser_turret.slots = 0
|
|
town_center.upgrades.laser_turret.locations = {}
|
|
town_center.evolution = {}
|
|
town_center.evolution.biters = 0
|
|
town_center.evolution.spitters = 0
|
|
town_center.evolution.worms = 0
|
|
|
|
town_center.coins_text = rendering.draw_text {
|
|
text = "Coins: " .. town_center.coin_balance,
|
|
surface = surface,
|
|
target = town_center.market,
|
|
target_offset = { 0, -2.75 },
|
|
color = { 200, 200, 200 },
|
|
scale = 1.00,
|
|
font = "default-game",
|
|
alignment = "center",
|
|
scale_with_zoom = false
|
|
}
|
|
|
|
town_center.health_text = rendering.draw_text {
|
|
text = "HP: " .. town_center.health .. " / " .. town_center.max_health,
|
|
surface = surface,
|
|
target = town_center.market,
|
|
target_offset = { 0, -3.25 },
|
|
color = { 200, 200, 200 },
|
|
scale = 1.00,
|
|
font = "default-game",
|
|
alignment = "center",
|
|
scale_with_zoom = false
|
|
}
|
|
|
|
town_center.town_caption = rendering.draw_text {
|
|
text = player.name .. "'s Town",
|
|
surface = surface,
|
|
target = town_center.market,
|
|
target_offset = { 0, -4.25 },
|
|
color = town_center.color,
|
|
scale = 1.30,
|
|
font = "default-game",
|
|
alignment = "center",
|
|
scale_with_zoom = false
|
|
}
|
|
|
|
ffatable.size_of_town_centers = ffatable.size_of_town_centers + 1
|
|
|
|
draw_town_spawn(force_name)
|
|
|
|
Team.add_player_to_town(player, town_center)
|
|
Team.add_chart_tag(game.forces.player, town_center.market)
|
|
|
|
local force = player.force
|
|
|
|
-- set the spawn point
|
|
local pos = { x = town_center.market.position.x, y = town_center.market.position.y + 4 }
|
|
--log("setting spawn point = {" .. spawn_point.x .. "," .. spawn_point.y .. "}")
|
|
force.set_spawn_position(pos, surface)
|
|
ffatable.spawn_point[player.name] = pos
|
|
|
|
ffatable.cooldowns_town_placement[player.index] = game.tick + 3600 * 15
|
|
|
|
Team.remove_key(player)
|
|
|
|
game.print(">> " .. player.name .. " has founded a new town!", { 255, 255, 0 })
|
|
return true
|
|
end
|
|
|
|
local function on_built_entity(event)
|
|
found_town(event)
|
|
end
|
|
|
|
local function on_player_repaired_entity(event)
|
|
local entity = event.entity
|
|
if entity.name == "market" then
|
|
Public.set_market_health(entity, -4)
|
|
end
|
|
end
|
|
|
|
--local function on_robot_repaired_entity(event)
|
|
-- local entity = event.entity
|
|
-- if entity.name == "market" then
|
|
-- Public.set_market_health(entity, -4)
|
|
-- end
|
|
--end
|
|
|
|
local function on_entity_damaged(event)
|
|
local entity = event.entity
|
|
if not entity.valid then return end
|
|
if entity.name == "market" then
|
|
Public.set_market_health(entity, event.final_damage_amount)
|
|
end
|
|
end
|
|
|
|
local on_init = function ()
|
|
local ffatable = Table.get_table()
|
|
ffatable.town_centers = {}
|
|
ffatable.size_of_town_centers = 0
|
|
ffatable.cooldowns_town_placement = {}
|
|
end
|
|
|
|
local Event = require 'utils.event'
|
|
Event.on_init(on_init)
|
|
Event.add(defines.events.on_built_entity, on_built_entity)
|
|
Event.add(defines.events.on_player_repaired_entity, on_player_repaired_entity)
|
|
--Event.add(defines.events.on_robot_repaired_entity, on_robot_repaired_entity)
|
|
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
|
|
|
|
return Public |