mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-14 02:34:09 +02:00
358160c247
Revert "Fix 'player' shadowing in flying_texts.lua" This reverts commit 40805e68e3c0bf588b40f510d5c32b66ecca4717. Fix 'player' shadowing in flying_texts.lua all_central_positions_within_area utils/math/raffle
329 lines
10 KiB
Lua
329 lines
10 KiB
Lua
-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/ComfyFactory/ComfyFactorio and https://github.com/danielmartin0/ComfyFactorio-Pirates.
|
|
|
|
local Balance = require('maps.pirates.balance')
|
|
-- local Memory = require 'maps.pirates.memory'
|
|
local Math = require('maps.pirates.math')
|
|
local Raffle = require 'utils.math.raffle'
|
|
local CoreData = require('maps.pirates.coredata')
|
|
local _inspect = require('utils.inspect').inspect
|
|
local Common = require('maps.pirates.common')
|
|
local Utils = require('maps.pirates.utils_local')
|
|
local simplex_noise = require('utils.math.simplex_noise').d2
|
|
--
|
|
|
|
local Public = {}
|
|
|
|
-- Gives less and less ore with every call, until given amount slowly converges to 2
|
|
-- For now used just for Cave island to give players ore when mining rocks
|
|
-- NOTE: Also gives some coins
|
|
function Public.try_give_ore(player, realp, source_name)
|
|
local destination = Common.current_destination()
|
|
local choices = destination.dynamic_data.hidden_ore_remaining_abstract
|
|
|
|
if choices and Utils.length(choices) > 0 then
|
|
local choices_possible = {}
|
|
local choices_to_prioitise = {}
|
|
local total_ore_left = 0
|
|
|
|
for k, v in pairs(choices) do
|
|
if v > 0 then
|
|
choices_possible[k] = v
|
|
end
|
|
|
|
total_ore_left = total_ore_left + v
|
|
|
|
if not destination.dynamic_data.ore_types_spawned[k] then
|
|
choices_to_prioitise[#choices_to_prioitise + 1] = k
|
|
end
|
|
end
|
|
|
|
if Utils.length(choices_possible) > 0 then
|
|
local choice
|
|
if Utils.length(choices_to_prioitise) > 0 then
|
|
choice = choices_to_prioitise[Math.random(Utils.length(choices_to_prioitise))]
|
|
else
|
|
choice = Raffle.raffle(choices_possible)
|
|
end
|
|
|
|
if not choice then
|
|
return
|
|
end
|
|
|
|
local coin_amount = Math.ceil(0.15 * Balance.coin_amount_from_rock())
|
|
local real_amount = Common.ore_abstract_to_real(choices[choice])
|
|
|
|
local given_amount = Math.ceil(real_amount * Math.random_float_in_range(0.004, 0.006))
|
|
|
|
if source_name == 'huge-rock' then
|
|
given_amount = given_amount * 2
|
|
coin_amount = coin_amount * 2
|
|
end
|
|
|
|
given_amount = Math.max(8 * Balance.game_resources_scale(), given_amount)
|
|
|
|
local to_give = {}
|
|
to_give[#to_give + 1] = { name = choice, count = Math.ceil(given_amount) }
|
|
to_give[#to_give + 1] = { name = 'coin', count = Math.ceil(coin_amount) }
|
|
Common.give(player, to_give, realp)
|
|
|
|
-- 1 here indicates that ore type should still be given
|
|
choices[choice] = Math.max(1, choices[choice] - Common.ore_real_to_abstract(given_amount))
|
|
end
|
|
end
|
|
end
|
|
|
|
function Public.try_ore_spawn(surface, realp, source_name, density_bonus, from_tree)
|
|
density_bonus = density_bonus or 0
|
|
from_tree = from_tree or false
|
|
-- local memory = Memory.get_crew_memory()
|
|
local destination = Common.current_destination()
|
|
local choices = destination.dynamic_data.hidden_ore_remaining_abstract
|
|
|
|
if from_tree then
|
|
choices = destination.static_params.abstract_ore_amounts
|
|
end
|
|
|
|
local ret = false
|
|
|
|
if choices and Utils.length(choices) > 0 then
|
|
local choices_possible = {}
|
|
local choices_to_prioitise = {}
|
|
|
|
for k, v in pairs(choices) do
|
|
if v > 0 then
|
|
choices_possible[k] = v
|
|
end
|
|
|
|
if not destination.dynamic_data.ore_types_spawned[k] then
|
|
choices_to_prioitise[#choices_to_prioitise + 1] = k
|
|
end
|
|
end
|
|
|
|
if Utils.length(choices_possible) > 0 then
|
|
local choice
|
|
if Utils.length(choices_to_prioitise) > 0 then
|
|
choice = choices_to_prioitise[Math.random(Utils.length(choices_to_prioitise))]
|
|
else
|
|
choice = Raffle.raffle(choices_possible)
|
|
end
|
|
|
|
local placed
|
|
if choice == 'crude-oil' then
|
|
placed = Common.oil_abstract_to_real(
|
|
6 + 0.7 * choices[choice] / (Math.max(1, Math.ceil((choices[choice] / 4) ^ (1 / 2))))
|
|
) * (0.8 + 0.4 * Math.random()) --thesixthroc's magic function, just plot this to see that it makes sense
|
|
|
|
placed = Math.min(placed, Common.oil_abstract_to_real(choices[choice]))
|
|
|
|
local tile = surface.get_tile(realp)
|
|
if
|
|
not (
|
|
tile
|
|
and tile.name
|
|
and Utils.contains(CoreData.tiles_that_conflict_with_resource_layer_extended, tile.name)
|
|
)
|
|
then
|
|
surface.create_entity({ name = 'crude-oil', amount = placed, position = realp })
|
|
else
|
|
placed = 0
|
|
end
|
|
|
|
if placed then
|
|
choices[choice] = Math.max(0, choices[choice] - Common.oil_real_to_abstract(placed))
|
|
if placed > 0 and not destination.dynamic_data.ore_types_spawned[choice] then
|
|
destination.dynamic_data.ore_types_spawned[choice] = true
|
|
end
|
|
ret = true
|
|
end
|
|
else
|
|
if not choice then
|
|
return false
|
|
end
|
|
|
|
local real_amount = Common.ore_abstract_to_real(choices[choice])
|
|
if from_tree then
|
|
real_amount = Math.ceil(real_amount * 0.1)
|
|
end
|
|
real_amount = Math.max(Common.minimum_ore_placed_per_tile, real_amount)
|
|
|
|
local density = (density_bonus + 17 + 4 * Math.random()) -- not too big, and not too much variation; it makes players have to stay longer
|
|
|
|
local radius_squared = (
|
|
destination.static_params and destination.static_params.radius_squared_modifier or 1
|
|
)
|
|
* (12 + 45 * Math.slopefromto(Common.ore_abstract_to_real(choices[choice]), 800, 20000))
|
|
* (0.6 + Math.random()) --tuned
|
|
|
|
if source_name == 'huge-rock' then
|
|
radius_squared = radius_squared * 1.5
|
|
end
|
|
|
|
placed = Public.draw_noisy_ore_patch(surface, realp, choice, real_amount, radius_squared, density)
|
|
|
|
if placed then
|
|
choices[choice] = Math.max(0, choices[choice] - Common.ore_real_to_abstract(placed))
|
|
if placed > 0 and not destination.dynamic_data.ore_types_spawned[choice] then
|
|
destination.dynamic_data.ore_types_spawned[choice] = true
|
|
end
|
|
ret = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return ret
|
|
end
|
|
|
|
function Public.draw_noisy_ore_patch(surface, position, name, budget, radius_squared, density, forced, flat)
|
|
flat = flat or false
|
|
budget = budget or 999999999
|
|
forced = forced or false
|
|
local amountplaced = 0
|
|
local radius = Math.sqrt(radius_squared)
|
|
|
|
position = { x = Math.ceil(position.x) - 0.5, y = Math.ceil(position.y) - 0.5 }
|
|
|
|
if not position then
|
|
return 0
|
|
end
|
|
if not name then
|
|
return 0
|
|
end
|
|
if not surface then
|
|
return 0
|
|
end
|
|
if not radius then
|
|
return 0
|
|
end
|
|
if not density then
|
|
return 0
|
|
end
|
|
local mixed_ore_raffle = {
|
|
'iron-ore',
|
|
'iron-ore',
|
|
'iron-ore',
|
|
'copper-ore',
|
|
'copper-ore',
|
|
'coal',
|
|
'stone',
|
|
}
|
|
local seed = surface.map_gen_settings.seed
|
|
|
|
local function try_draw_at_relative_position(x, y, strength)
|
|
local absx = x + position.x
|
|
local absy = y + position.y
|
|
local absp = { x = absx, y = absy }
|
|
|
|
local amount_to_place_here = Math.min(density * strength, budget - amountplaced)
|
|
|
|
if amount_to_place_here >= Common.minimum_ore_placed_per_tile then
|
|
if name == 'mixed' then
|
|
local noise = simplex_noise(x * 0.005, y * 0.005, seed)
|
|
+ simplex_noise(x * 0.01, y * 0.01, seed) * 0.3
|
|
+ simplex_noise(x * 0.05, y * 0.05, seed) * 0.2
|
|
local i = (Math.floor(noise * 100) % #mixed_ore_raffle) + 1
|
|
name = mixed_ore_raffle[i]
|
|
end
|
|
local entity = { name = name, position = absp, amount = amount_to_place_here }
|
|
-- local area = {{absx - 0.05, absy - 0.05}, {absx + 0.05, absy + 0.05}}
|
|
local area2 = { { absx - 0.1, absy - 0.1 }, { absx + 0.1, absy + 0.1 } }
|
|
local area3 = { { absx - 2, absy - 2 }, { absx + 2, absy + 2 } }
|
|
local preexisting_ores = surface.find_entities_filtered({ area = area2, type = 'resource' })
|
|
|
|
local added
|
|
if #preexisting_ores >= 1 then
|
|
local addedbool = false
|
|
for _, ore in pairs(preexisting_ores) do
|
|
if ore.name == name then
|
|
ore.amount = ore.amount + amount_to_place_here
|
|
amountplaced = amountplaced + amount_to_place_here
|
|
addedbool = true
|
|
break
|
|
end
|
|
end
|
|
if not addedbool then
|
|
added = surface.create_entity(entity)
|
|
end
|
|
else
|
|
local tile = surface.get_tile(absp)
|
|
local silos = surface.find_entities_filtered({ area = area3, name = 'rocket-silo' })
|
|
if
|
|
#silos == 0
|
|
and not (
|
|
tile
|
|
and tile.name
|
|
and Utils.contains(CoreData.tiles_that_conflict_with_resource_layer_extended, tile.name)
|
|
)
|
|
then
|
|
if forced then
|
|
surface.destroy_decoratives({ area = area2 })
|
|
for _, tree in pairs(surface.find_entities_filtered({ area = area2, type = 'tree' })) do
|
|
tree.destroy()
|
|
end
|
|
added = surface.create_entity(entity)
|
|
else
|
|
local pos2 = surface.find_non_colliding_position(name, absp, 10, 1, true)
|
|
pos2 = pos2 or absp
|
|
entity = { name = name, position = pos2, amount = amount_to_place_here }
|
|
surface.destroy_decoratives({ area = area2 })
|
|
if pos2 and surface.can_place_entity(entity) then
|
|
added = surface.create_entity(entity)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if added and added.valid then
|
|
amountplaced = amountplaced + amount_to_place_here
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, p in ipairs(Math.points_in_m20t20_squared_sorted_by_distance_to_origin) do
|
|
local x, y = p[1], p[2]
|
|
local distance_to_center = Math.sqrt(x ^ 2 + y ^ 2)
|
|
local noise
|
|
if flat then
|
|
noise = 0.99
|
|
* simplex_noise((position.x + x) * 1 / 3, (position.y + y) * 1 / 3, seed)
|
|
* simplex_noise((position.x + x) * 1 / 9, (position.y + y) * 1 / 9, seed + 100)
|
|
else --put noise on the unit circle
|
|
if distance_to_center > 0 then
|
|
noise = 0.99
|
|
* simplex_noise(
|
|
(position.x + x / distance_to_center) * 1 / 3,
|
|
(position.y + y / distance_to_center) * 1 / 3,
|
|
seed
|
|
)
|
|
* simplex_noise(
|
|
(position.x + x / distance_to_center) * 1 / 9,
|
|
(position.y + y / distance_to_center) * 1 / 9,
|
|
seed + 100
|
|
)
|
|
else
|
|
noise = 0.99
|
|
* simplex_noise(position.x * 1 / 3, position.y * 1 / 3, seed)
|
|
* simplex_noise(position.x * 1 / 9, position.y * 1 / 9, seed + 100)
|
|
end
|
|
end
|
|
local radius_noisy = radius * (1 + noise)
|
|
if distance_to_center < radius_noisy then
|
|
local strength
|
|
if flat then
|
|
-- if noise > -0.5 then strength = 1 else strength = 0 end
|
|
-- its hard to make it both noncircular and flat in per-tile count
|
|
strength = 1
|
|
else
|
|
strength = (3 / 2) * (1 - (distance_to_center / radius_noisy) ^ 2)
|
|
end
|
|
try_draw_at_relative_position(x, y, strength)
|
|
end
|
|
if amountplaced >= budget then
|
|
break
|
|
end
|
|
end
|
|
|
|
return amountplaced
|
|
end
|
|
|
|
return Public
|