mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-06 00:23:49 +02:00
513 lines
15 KiB
Lua
513 lines
15 KiB
Lua
|
|
local Public = {}
|
|
local Math = require 'maps.pirates.math'
|
|
local Memory = require 'maps.pirates.memory'
|
|
local Common = require 'maps.pirates.common'
|
|
local Utils = require 'maps.pirates.utils_local'
|
|
local inspect = require 'utils.inspect'.inspect
|
|
|
|
|
|
Public.base_extra_character_speed = 0.20
|
|
|
|
Public.technology_price_multiplier = 1
|
|
|
|
|
|
function Public.starting_boatEEIpower_production_MW()
|
|
-- return 3 * Math.sloped(Common.capacity_scale(), 1/2) / 2 --/2 as we have 2
|
|
return 3/2
|
|
end
|
|
function Public.starting_boatEEIelectric_buffer_size_MJ() --maybe needs to be at least the power_production
|
|
-- return 3 * Math.sloped(Common.capacity_scale(), 1/2) / 2 --/2 as we have 2
|
|
return 3/2
|
|
end
|
|
Public.EEI_stages = { --multipliers
|
|
1,2,5,8,12
|
|
}
|
|
|
|
|
|
function Public.scripted_biters_pollution_cost_multiplier()
|
|
return 1.33
|
|
end
|
|
|
|
function Public.cost_to_leave_multiplier()
|
|
return Common.difficulty()
|
|
end
|
|
|
|
Public.rocket_launch_coin_reward = 5000
|
|
|
|
function Public.onthefly_scaling_with_players_rule()
|
|
return (Common.activecrewcount()/10)^(1/2)
|
|
end
|
|
|
|
function Public.silo_base_est_time()
|
|
local T = Public.expected_time_on_island() * Public.onthefly_scaling_with_players_rule()^(1/3) --to undo some of the time scaling
|
|
local est_secs
|
|
if T > 0 then
|
|
est_secs = T/6
|
|
else
|
|
est_secs = 60 * 6
|
|
end
|
|
if Common.overworldx() == 0 then est_secs = 60 * 2 end
|
|
return est_secs
|
|
end
|
|
|
|
function Public.time_quest_seconds()
|
|
return 2.8 * Public.silo_base_est_time()
|
|
end
|
|
|
|
function Public.silo_energy_needed_MJ()
|
|
local est_secs = Public.silo_base_est_time()
|
|
|
|
local est_base_power = 2*Public.starting_boatEEIpower_production_MW() * (1 + 0.05 * (Common.overworldx()/40)^(5/3))
|
|
|
|
return est_secs * est_base_power
|
|
-- return est_secs * est_base_power * Math.sloped(Common.difficulty(), 1/3)
|
|
end
|
|
|
|
function Public.silo_count()
|
|
local E = Public.silo_energy_needed_MJ()
|
|
return Math.ceil(E/(16.8*120)) --no more than 2 minutes to charge it
|
|
end
|
|
|
|
function Public.silo_total_pollution()
|
|
return (
|
|
280 * (Common.difficulty()^(1.2)) * Public.onthefly_scaling_with_players_rule()^(4/5) * (1.25 + 0.75 * (Common.overworldx()/40)^(1.6))
|
|
)
|
|
end
|
|
|
|
|
|
function Public.max_time_on_island_formula() --always >0 --tuned
|
|
return 60 * (
|
|
(32 + 2 * (Common.overworldx()/40)^(1/3))
|
|
) / Public.onthefly_scaling_with_players_rule()^(2/3) / Math.sloped(Common.difficulty(), 1/4)
|
|
end
|
|
|
|
|
|
function Public.max_time_on_island()
|
|
if Common.overworldx() == 0 or ((Common.overworldx()/40) > 20 and (Common.overworldx()/40) < 25) then
|
|
return -1
|
|
else
|
|
return Math.ceil(Public.max_time_on_island_formula())
|
|
end
|
|
end
|
|
|
|
function Public.expected_time_on_island() --always >0
|
|
return 3/5 * Public.max_time_on_island_formula()
|
|
end
|
|
|
|
function Public.fuel_depletion_rate_static()
|
|
if (not Common.overworldx()) then return 0 end
|
|
|
|
local T = Public.expected_time_on_island()
|
|
|
|
return - 1300 * (Common.overworldx()/40)^(7/10) * Public.onthefly_scaling_with_players_rule()^(1/3) * Math.sloped(Common.difficulty(), 3/4) / T --the extra player dependency accounts for the fact that even in compressed time, more players get more resources...
|
|
end
|
|
|
|
function Public.fuel_depletion_rate_sailing()
|
|
if (not Common.overworldx()) then return 0 end
|
|
|
|
return - 10 * (1 + 0.5 * (Common.overworldx()/40)^(5/10))
|
|
end
|
|
|
|
function Public.boat_passive_pollution_per_minute(time)
|
|
local boost = 1
|
|
local T = Public.max_time_on_island_formula()
|
|
if time and time >= 90/100 * T then
|
|
boost = 15
|
|
elseif time and time >= 85/100 * T then
|
|
boost = 8
|
|
elseif time and time >= 75/100 * T then
|
|
boost = 5
|
|
elseif time and time >= 55/100 * T then
|
|
boost = 3
|
|
elseif time and time >= 40/100 * T then
|
|
boost = 2
|
|
end
|
|
|
|
return boost * (
|
|
6 * Common.difficulty() * (Common.overworldx()/40)^(16/10) * (Public.onthefly_scaling_with_players_rule())^(1/2)
|
|
)
|
|
end
|
|
|
|
|
|
function Public.base_evolution()
|
|
local evo = (0.0201 * (Common.overworldx()/40)) * Math.sloped(Common.difficulty(), 1/5)
|
|
if Common.overworldx()/40 == 0 then evo = 0 end
|
|
return evo
|
|
end
|
|
|
|
function Public.expected_time_evo()
|
|
return 0.14
|
|
end
|
|
|
|
function Public.evolution_per_second()
|
|
local destination = Common.current_destination()
|
|
|
|
local T = Public.expected_time_on_island() --always greater than 0
|
|
local rate = Public.expected_time_evo() / T
|
|
if Common.overworldx() == 0 then rate = 0 end
|
|
|
|
-- scale by biter nests remaining:
|
|
if destination and destination.dynamic_data then
|
|
local initial_spawner_count = destination.dynamic_data.initial_spawner_count
|
|
if initial_spawner_count and initial_spawner_count > 0 then
|
|
local surface = game.surfaces[destination.surface_name]
|
|
if surface and surface.valid then
|
|
rate = rate * Common.spawner_count(surface) / destination.dynamic_data.initial_spawner_count
|
|
end
|
|
end
|
|
end
|
|
|
|
return rate
|
|
end
|
|
|
|
function Public.evolution_per_biter_base_kill()
|
|
local destination = Common.current_destination()
|
|
if Common.overworldx() == 0 then return 0 end
|
|
|
|
if destination and destination.dynamic_data and destination.dynamic_data.timer and destination.dynamic_data.timer > 0 and destination.dynamic_data.initial_spawner_count and destination.dynamic_data.initial_spawner_count > 0 then
|
|
|
|
local initial_spawner_count = destination.dynamic_data.initial_spawner_count
|
|
local time = destination.dynamic_data.timer
|
|
local expected_time = Public.expected_time_on_island()
|
|
if time > expected_time then return 0
|
|
else
|
|
-- evo it 'would have' contributed:
|
|
return 1/initial_spawner_count * Public.expected_time_evo() * (expected_time - time)/expected_time
|
|
end
|
|
else
|
|
return 0
|
|
end
|
|
|
|
-- return 0.003 * Common.difficulty()
|
|
end
|
|
|
|
function Public.evolution_per_full_silo_charge()
|
|
return 0.08
|
|
end
|
|
|
|
function Public.bonus_damage_to_humans()
|
|
local ret = 0.125
|
|
local diff = Common.difficulty()
|
|
if diff <= 0.7 then ret = 0.1 end
|
|
if diff >= 1.3 then ret = 0.15 end
|
|
return ret
|
|
end
|
|
|
|
|
|
function Public.periodic_free_resources_per_x(x)
|
|
return {
|
|
}
|
|
-- return {
|
|
-- {name = 'iron-plate', count = Math.ceil(5 * (Common.overworldx()/40)^(2/3))},
|
|
-- {name = 'copper-plate', count = Math.ceil(1 * (Common.overworldx()/40)^(2/3))},
|
|
-- }
|
|
end
|
|
|
|
function Public.periodic_free_resources_per_destination_5_seconds(x)
|
|
return {
|
|
}
|
|
-- return {
|
|
-- {name = 'iron-ore', count = Math.ceil(7 * (Common.overworldx()/40)^(0.6))},
|
|
-- {name = 'copper-ore', count = Math.ceil(3 * (Common.overworldx()/40)^(0.6))},
|
|
-- }
|
|
end
|
|
|
|
function Public.class_resource_scale()
|
|
return 1 / Public.onthefly_scaling_with_players_rule()
|
|
end
|
|
|
|
function Public.biter_base_density_scale()
|
|
local p = Common.activecrewcount()
|
|
if p >= 10 then
|
|
return (Common.activecrewcount()/10)^(1/2)
|
|
else
|
|
return Math.max((Common.activecrewcount()/6)^(1/2), 0.6)
|
|
end
|
|
end
|
|
|
|
|
|
function Public.launch_fuel_reward()
|
|
return Math.ceil(1000 * (1 + 0.1 * (Common.overworldx()/40)^(8/10)) / Math.sloped(Common.difficulty(), 1/4))
|
|
end
|
|
|
|
function Public.quest_reward_multiplier()
|
|
return (0.4 + 0.08 * (Common.overworldx()/40)^(8/10)) * Math.sloped(Common.difficulty(), 1/3) * (Public.onthefly_scaling_with_players_rule())^(1/4)
|
|
end
|
|
|
|
function Public.island_richness_avg_multiplier()
|
|
return 0.7 + 0.1 * (Common.overworldx()/40)^(7/10)
|
|
end
|
|
|
|
function Public.resource_quest_multiplier()
|
|
return (1.0 + 0.075 * (Common.overworldx()/40)^(8/10)) * Math.sloped(Common.difficulty(), 1/3) * (Public.onthefly_scaling_with_players_rule())^(1/4)
|
|
end
|
|
|
|
|
|
function Public.apply_crew_buffs_per_x(force)
|
|
force.laboratory_productivity_bonus = force.laboratory_productivity_bonus + 10/100 * 1/40
|
|
end
|
|
|
|
function Public.class_cost()
|
|
return 9000
|
|
-- return Math.ceil(10000 / (Common.activecrewcount()/4)^(1/6))
|
|
end
|
|
|
|
|
|
Public.covered_first_appears_at = 40
|
|
|
|
Public.silo_max_hp = 10000
|
|
|
|
function Public.pistol_damage_multiplier() return 1.95 end
|
|
|
|
Public.kraken_spawns_base_extra_evo = 0.2
|
|
|
|
function Public.kraken_evo_increase_per_shot()
|
|
return 1/100 * 0.02
|
|
end
|
|
|
|
function Public.kraken_kill_reward()
|
|
return {{name = 'sulfuric-acid-barrel', count = 5}}
|
|
end
|
|
|
|
function Public.kraken_health()
|
|
return Math.ceil(2500 * Math.max(1, 1 + 0.1 * ((Common.overworldx()/40)^(13/10)-6)) * (Public.onthefly_scaling_with_players_rule()^(3/4)) * Math.sloped(Common.difficulty(), 1/2))
|
|
end
|
|
|
|
Public.kraken_regen_scale = 0.5
|
|
|
|
function Public.krakens_per_slot(overworldx)
|
|
local rng = Math.random()
|
|
if rng < 0.03 then
|
|
return 2
|
|
elseif rng < 0.25 then
|
|
return 1
|
|
else
|
|
return 0
|
|
end
|
|
end
|
|
|
|
function Public.krakens_per_free_slot(overworldx)
|
|
local rng = Math.random()
|
|
local multiplier = 1
|
|
if overworldx and overworldx > 600 then
|
|
multiplier = 1 + (overworldx-600)/600
|
|
end
|
|
if rng < 0.075 * multiplier then
|
|
return 2
|
|
elseif rng < 0.5 * multiplier then
|
|
return 1
|
|
else
|
|
return 0
|
|
end
|
|
end
|
|
|
|
|
|
function Public.main_shop_cost_multiplier()
|
|
return 1
|
|
end
|
|
|
|
function Public.covered_entry_price_scale()
|
|
return (1 + 0.025 * (Common.overworldx()/40 - 1))
|
|
end
|
|
|
|
function Public.barter_decay_parameter()
|
|
return 0.95
|
|
end
|
|
|
|
-- function Public.island_otherresources_prospect_decay_parameter()
|
|
-- return 0.95
|
|
-- end
|
|
|
|
Public.research_buffs = {
|
|
-- these already give .1 productivity so we're adding .1 to get to 20%
|
|
['mining-productivity-1'] = {['mining-drill-productivity-bonus'] = .1, ['character-inventory-slots-bonus'] = 5},
|
|
['mining-productivity-2'] = {['mining-drill-productivity-bonus'] = .1, ['character-inventory-slots-bonus'] = 5},
|
|
['mining-productivity-3'] = {['mining-drill-productivity-bonus'] = .1, ['character-inventory-slots-bonus'] = 5},
|
|
['mining-productivity-4'] = {['mining-drill-productivity-bonus'] = .1, ['character-inventory-slots-bonus'] = 5},
|
|
}
|
|
|
|
|
|
-- function Public.flamers_nerfs_size(jumps) return 0.02 * jumps * difficulty_sloped(1/2) end
|
|
|
|
|
|
|
|
|
|
function Public.player_ammo_damage_modifiers() -- modifiers are fractional. bullet affects gun turrets, but flamethrower does not affect flamer turrets
|
|
local data = {
|
|
['artillery-shell'] = 0,
|
|
['biological'] = 0,
|
|
['bullet'] = 0.1,
|
|
['cannon-shell'] = 0,
|
|
['capsule'] = 0,
|
|
['electric'] = 0,
|
|
['flamethrower'] = 0, --these nerfs are elsewhere for finer control
|
|
['grenade'] = 0,
|
|
['landmine'] = 0,
|
|
['melee'] = 0, -- doesn't do anything apparently
|
|
['rocket'] = 0,
|
|
['shotgun-shell'] = 0
|
|
}
|
|
return data
|
|
end
|
|
function Public.player_turret_attack_modifiers()
|
|
local data = {
|
|
['gun-turret'] = 0,
|
|
['artillery-turret'] = 0,
|
|
['laser-turret'] = 0,
|
|
}
|
|
return data
|
|
end
|
|
function Public.player_gun_speed_modifiers()
|
|
local data = {
|
|
['artillery-shell'] = 0,
|
|
['biological'] = 0,
|
|
['bullet'] = 0,
|
|
['cannon-shell'] = 0,
|
|
['capsule'] = 0,
|
|
['electric'] = 0,
|
|
['flamethrower'] = 0, --these nerfs are elsewhere for finer control
|
|
['grenade'] = -0.25,
|
|
['landmine'] = 0,
|
|
['melee'] = 0, -- doesn't do anything
|
|
['rocket'] = 0,
|
|
['shotgun-shell'] = 0.1
|
|
}
|
|
return data
|
|
end
|
|
|
|
|
|
Public.starting_items_player = {['pistol'] = 1, ['firearm-magazine'] = 12, ['raw-fish'] = 1, ['iron-plate'] = 12, ['medium-electric-pole'] = 4}
|
|
|
|
Public.starting_items_player_late = {['pistol'] = 1, ['firearm-magazine'] = 5}
|
|
|
|
function Public.starting_items_crew_upstairs()
|
|
return {
|
|
{['steel-plate'] = 38},
|
|
{['stone-brick'] = 60},
|
|
{['grenade'] = 3},
|
|
{['solar-panel'] = 4},
|
|
{['shotgun'] = 2, ['shotgun-shell'] = 36},
|
|
{['raw-fish'] = 5},
|
|
}
|
|
end
|
|
|
|
function Public.starting_items_crew_downstairs()
|
|
return {
|
|
{['transport-belt'] = Math.random(500,600)},
|
|
{['underground-belt'] = 80},
|
|
{['splitter'] = Math.random(40,48)},
|
|
{['inserter'] = Math.random(100,120)},
|
|
{['storage-tank'] = 4},
|
|
{['medium-electric-pole'] = Math.random(15,21)},
|
|
{['coin'] = 3000},
|
|
}
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
Public.covered1_entry_price_data_raw = { --watch out that the raw_materials chest can only hold e.g. 4.8 iron-plates
|
|
-- choose things that are easy to make at outposts
|
|
{1, 0, 1, false, {
|
|
price = {name = 'iron-stick', count = 1500},
|
|
raw_materials = {{name = 'iron-plate', count = 750}}}, {}},
|
|
{0.8, 0, 1, false, {
|
|
price = {name = 'copper-cable', count = 1500},
|
|
raw_materials = {{name = 'copper-plate', count = 750}}}, {}},
|
|
|
|
{1, 0, 0.3, true, {
|
|
price = {name = 'small-electric-pole', count = 800},
|
|
raw_materials = {{name = 'copper-plate', count = 400}}}, {}},
|
|
{1, 0.1, 1, false, {
|
|
price = {name = 'assembling-machine-1', count = 80},
|
|
raw_materials = {{name = 'iron-plate', count = 1760}, {name = 'copper-plate', count = 360}}}, {}},
|
|
{1, 0, 0.2, false, {
|
|
price = {name = 'burner-mining-drill', count = 200},
|
|
raw_materials = {{name = 'iron-plate', count = 1800}}}, {}},
|
|
{0.5, 0, 0.6, false, {
|
|
price = {name = 'burner-inserter', count = 300},
|
|
raw_materials = {{name = 'iron-plate', count = 900}}}, {}},
|
|
-- {1, 0, 1, false, {
|
|
-- price = {name = 'electronic-circuit', count = 800},
|
|
-- raw_materials = {{name = 'iron-plate', count = 800}, {name = 'copper-plate', count = 1200}}}, {}},
|
|
-- {1, 0, 1, false, {
|
|
-- price = {name = 'piercing-rounds-magazine', count = 100},
|
|
-- raw_materials = {{name = 'iron-plate', count = 400}, {name = 'copper-plate', count = 500}, {name = 'steel-plate', count = 100}}}, {}},
|
|
|
|
{1, 0.1, 1, false, {
|
|
price = {name = 'stone-furnace', count = 400},
|
|
raw_materials = {}}, {}},
|
|
{1, 0.5, 1, false, {
|
|
price = {name = 'advanced-circuit', count = 100},
|
|
raw_materials = {{name = 'iron-plate', count = 200}, {name = 'copper-plate', count = 500}, {name = 'plastic-bar', count = 200}}}, {}},
|
|
|
|
{1, -1, 1, true, {
|
|
price = {name = 'wooden-chest', count = 400},
|
|
raw_materials = {}}, {}},
|
|
{1, 0, 1, true, {
|
|
price = {name = 'iron-chest', count = 300},
|
|
raw_materials = {{name = 'iron-plate', count = 2400}}}, {}},
|
|
{1, 0, 2, true, {
|
|
price = {name = 'steel-chest', count = 200},
|
|
raw_materials = {{name = 'steel-plate', count = 1600}}}, {}},
|
|
}
|
|
function Public.covered1_entry_price_data()
|
|
local ret = {}
|
|
local data = Public.covered1_entry_price_data_raw
|
|
for i = 1, #data do
|
|
local data_item = data[i]
|
|
ret[#ret + 1] = {
|
|
weight = data_item[1],
|
|
game_completion_progress_min = data_item[2],
|
|
game_completion_progress_max = data_item[3],
|
|
scaling = data_item[4],
|
|
item = data_item[5],
|
|
map_subtypes = data_item[6],
|
|
}
|
|
end
|
|
return ret
|
|
end
|
|
|
|
|
|
function Public.covered1_entry_price()
|
|
local rng = Math.random()
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
local overworldx = memory.overworldx or 0
|
|
|
|
local game_completion_progress = Math.sloped(Common.difficulty(),1/2) * Common.game_completion_progress()
|
|
|
|
local data = Public.covered1_entry_price_data()
|
|
local types, weights = {}, {}
|
|
for i = 1, #data, 1 do
|
|
table.insert(types, data[i].item)
|
|
|
|
local destination = Common.current_destination()
|
|
if not (data[i].map_subtypes and #data[i].map_subtypes > 0 and destination and destination.subtype and data[i].map_subtypes and (not Utils.contains(data[i].map_subtypes, destination.subtype))) then
|
|
if data[i].scaling then -- scale down weights away from the midpoint 'peak' (without changing the mean)
|
|
local midpoint = (data[i].game_completion_progress_max + data[i].game_completion_progress_min) / 2
|
|
local difference = (data[i].game_completion_progress_max - data[i].game_completion_progress_min)
|
|
table.insert(weights, data[i].weight * Math.max(0, 1 - (Math.abs(game_completion_progress - midpoint) / (difference / 2))))
|
|
else -- no scaling
|
|
if data[i].game_completion_progress_min <= game_completion_progress and data[i].game_completion_progress_max >= game_completion_progress then
|
|
table.insert(weights, data[i].weight)
|
|
else
|
|
table.insert(weights, 0)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local res = Utils.deepcopy(Math.raffle(types, weights))
|
|
|
|
res.price.count = Math.ceil(res.price.count * Public.covered_entry_price_scale())
|
|
for i, _ in pairs(res.raw_materials) do
|
|
res.raw_materials[i].count = Math.ceil(res.raw_materials[i].count * Public.covered_entry_price_scale())
|
|
end
|
|
|
|
return res
|
|
end
|
|
|
|
return Public |