diff --git a/control.lua b/control.lua index db3cb2c0..18b312d8 100644 --- a/control.lua +++ b/control.lua @@ -111,7 +111,7 @@ require 'utils.freeplay' --require 'maps.chronosphere.main' --![[Adventure as a crew of pirates]]-- ---require 'maps.pirates.main' +require 'maps.pirates.main' --![[Launch rockets in increasingly harder getting worlds.]]-- --require 'maps.journey.main' diff --git a/maps/pirates/ai.lua b/maps/pirates/ai.lua index 03e310dc..96997891 100644 --- a/maps/pirates/ai.lua +++ b/maps/pirates/ai.lua @@ -123,89 +123,96 @@ function Public.eat_up_fraction_of_all_pollution(surface, fraction_of_global_pol memory.floating_pollution = pollution_available end -function Public.try_main_attack() +function Public.wave_size_rng() -- random variance in attack sizes local wave_size_multiplier = 1 local memory = Memory.get_crew_memory() if memory.overworldx > 0 then - if Math.random(10) >= 5 then - log('attack aborted by chance') - return nil - end --variance in attack sizes - if Math.random(10) == 1 then wave_size_multiplier = 1.7 end --variance in attack sizes - if Math.random(70) == 1 then wave_size_multiplier = 3.2 end --variance in attack sizes - if Math.random(500) == 1 then wave_size_multiplier = 5 end --variance in attack sizes + local rng = Math.random(1000) + if rng <= 600 then + wave_size_multiplier = 0 + elseif rng <= 960 then + wave_size_multiplier = 1 + elseif rng <= 990 then + wave_size_multiplier = 1.5 + elseif rng <= 994 then + wave_size_multiplier = 2 + elseif rng <= 998 then + wave_size_multiplier = 2.5 + else + wave_size_multiplier = 3 + end end - local group = Public.spawn_group_of_scripted_biters(2/3, 6, 180, wave_size_multiplier) - local target = Public.generate_main_attack_target() - if not group or not group.valid or not target or not target.valid then return end + return wave_size_multiplier +end - -- group.set_command(Public.attack_target(target)) +function Public.try_main_attack() + local wave_size_multiplier = Public.wave_size_rng() - Public.group_set_commands(group, Public.attack_target(target)) + if wave_size_multiplier == 0 then + -- log('attack aborted by chance') + return nil + else + local group = Public.spawn_group_of_scripted_biters(2/3, 6, 180, wave_size_multiplier) + local target = Public.generate_main_attack_target() + if not group or not group.valid or not target or not target.valid then return end - -- if _DEBUG then game.print(game.tick .. string.format(": sending main attack of %s units from {%f,%f} to %s", #group.members, group.position.x, group.position.y, target.name)) end + -- group.set_command(Public.attack_target(target)) + + Public.group_set_commands(group, Public.attack_target(target)) + + -- if _DEBUG then game.print(game.tick .. string.format(": sending main attack of %s units from {%f,%f} to %s", #group.members, group.position.x, group.position.y, target.name)) end + end end function Public.try_secondary_attack() - local wave_size_multiplier = 1 - local memory = Memory.get_crew_memory() - if memory.overworldx > 0 then - if Math.random(10) >= 5 then - log('attack aborted by chance') - return nil - end --variance in attack sizes - if Math.random(10) == 1 then wave_size_multiplier = 1.7 end --variance in attack sizes - if Math.random(70) == 1 then wave_size_multiplier = 3.2 end --variance in attack sizes - if Math.random(500) == 1 then wave_size_multiplier = 5 end --variance in attack sizes - end + local wave_size_multiplier = Public.wave_size_rng() - local surface = game.surfaces[Common.current_destination().surface_name] - - - local group = Public.spawn_group_of_scripted_biters(2/3, 12, 180, wave_size_multiplier) - if not (group and group.valid) then return end - - local target - if Math.random(2) == 1 then - target = Public.generate_main_attack_target() + if wave_size_multiplier == 0 then + -- log('attack aborted by chance') + return nil else - target = Public.generate_side_attack_target(surface, group.position) + local surface = game.surfaces[Common.current_destination().surface_name] + + local group = Public.spawn_group_of_scripted_biters(2/3, 12, 180, wave_size_multiplier) + if not (group and group.valid) then return end + + local target + if Math.random(2) == 1 then + target = Public.generate_main_attack_target() + else + target = Public.generate_side_attack_target(surface, group.position) + end + if not group or not group.valid or not target or not target.valid then log('target invalid') return end + + -- group.set_command(Public.attack_target(target)) + + Public.group_set_commands(group, Public.attack_target(target)) + + -- if _DEBUG then game.print(game.tick .. string.format(": sending main attack of %s units from {%f,%f} to %s", #group.members, group.position.x, group.position.y, target.name)) end end - if not group or not group.valid or not target or not target.valid then log('target invalid') return end - - -- group.set_command(Public.attack_target(target)) - - Public.group_set_commands(group, Public.attack_target(target)) - - -- if _DEBUG then game.print(game.tick .. string.format(": sending main attack of %s units from {%f,%f} to %s", #group.members, group.position.x, group.position.y, target.name)) end end function Public.try_rogue_attack() - local wave_size_multiplier = 1 - local memory = Memory.get_crew_memory() - if memory.overworldx > 0 then - if Math.random(10) >= 5 then - log('attack aborted by chance') - return nil - end --variance in attack sizes - if Math.random(10) == 1 then wave_size_multiplier = 1.7 end --variance in attack sizes - if Math.random(70) == 1 then wave_size_multiplier = 3.2 end --variance in attack sizes - if Math.random(500) == 1 then wave_size_multiplier = 5 end --variance in attack sizes + local wave_size_multiplier = Public.wave_size_rng() + + if wave_size_multiplier == 0 then + -- log('attack aborted by chance') + return nil + else + local surface = game.surfaces[Common.current_destination().surface_name] + + local group = Public.spawn_group_of_scripted_biters(1/2, 6, 180, wave_size_multiplier) + if not (group and group.valid) then return end + local target = Public.generate_side_attack_target(surface, group.position) + if not (target and target.valid) then return end + + -- group.set_command(Public.attack_target(target)) + + Public.group_set_commands(group, Public.attack_target(target)) + + -- if _DEBUG then game.print(game.tick .. string.format(": sending rogue attack of %s units from {%f,%f} to %s", #group.members, group.position.x, group.position.y, target.name)) end end - - local surface = game.surfaces[Common.current_destination().surface_name] - - local group = Public.spawn_group_of_scripted_biters(1/2, 6, 180, wave_size_multiplier) - if not (group and group.valid) then return end - local target = Public.generate_side_attack_target(surface, group.position) - if not (target and target.valid) then return end - - -- group.set_command(Public.attack_target(target)) - - Public.group_set_commands(group, Public.attack_target(target)) - - -- if _DEBUG then game.print(game.tick .. string.format(": sending rogue attack of %s units from {%f,%f} to %s", #group.members, group.position.x, group.position.y, target.name)) end end @@ -342,7 +349,7 @@ function Public.spawn_group_of_scripted_biters(fraction_of_floating_pollution, m nearby_units_to_bring = {} end - local new_units = Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spawner.position, fraction_of_floating_pollution, minimum_avg_units, maximum_units, 1/wave_size_multiplier) + local new_units = Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spawner.position, fraction_of_floating_pollution, minimum_avg_units, maximum_units, wave_size_multiplier) if (new_units and nearby_units_to_bring and (#new_units + #nearby_units_to_bring) == 0) then return end @@ -360,7 +367,7 @@ function Public.spawn_group_of_scripted_biters(fraction_of_floating_pollution, m end -function Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spawnposition, fraction_of_floating_pollution, minimum_avg_units, maximum_units, unit_pollutioncost_multiplier, enforce_type) +function Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spawnposition, fraction_of_floating_pollution, minimum_avg_units, maximum_units, wave_size_multiplier, enforce_type) maximum_units = maximum_units or 256 -- log('ai spawning attempt params: ' .. (fraction_of_floating_pollution or '') .. ' ' .. (minimum_avg_units or '') .. ' ' .. (maximum_units or '') .. ' ' .. (unit_pollutioncost_multiplier or '') .. ' ' .. (enforce_type or '')) @@ -382,7 +389,7 @@ function Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spaw local initialpollution = memory.floating_pollution -- local initialbudget = budget - local base_pollution_cost_multiplier = 1 + local map_pollution_cost_multiplier = 1 local destination = Common.current_destination() if destination.dynamic_data and destination.dynamic_data.initial_spawner_count then @@ -399,40 +406,40 @@ function Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spaw -- end -- base_pollution_cost_multiplier = (initial_spawner_count/spawnerscount)^(1/2) -- Now directly proportional: - base_pollution_cost_multiplier = initial_spawner_count/spawnerscount + map_pollution_cost_multiplier = initial_spawner_count/spawnerscount if memory.overworldx == 0 then - base_pollution_cost_multiplier = Math.max(1, base_pollution_cost_multiplier) + map_pollution_cost_multiplier = Math.max(1, map_pollution_cost_multiplier) end -- The first map not being fully loaded when you get there commonly means it records too few initial spawners, which this helps fix else - base_pollution_cost_multiplier = 1000000 + map_pollution_cost_multiplier = 1000000 end end end - if memory.overworldx == 0 then - -- less biters: - base_pollution_cost_multiplier = base_pollution_cost_multiplier * 2.30 --tuned to teach players to defend, but then to feel relaxing once they do - end + -- if memory.overworldx == 0 then + -- -- less biters: + -- base_pollution_cost_multiplier = base_pollution_cost_multiplier * 2.30 --tuned to teach players to defend, but then to feel relaxing once they do + -- end -- moved to scripted_biters_pollution_cost_multiplier - base_pollution_cost_multiplier = base_pollution_cost_multiplier * unit_pollutioncost_multiplier + local base_scripted_biters_pollution_cost_multiplier = Balance.scripted_biters_pollution_cost_multiplier() - base_pollution_cost_multiplier = base_pollution_cost_multiplier * Balance.scripted_biters_pollution_cost_multiplier() + map_pollution_cost_multiplier = map_pollution_cost_multiplier * base_scripted_biters_pollution_cost_multiplier if destination.subtype and destination.subtype == IslandsCommon.enum.SWAMP then - base_pollution_cost_multiplier = base_pollution_cost_multiplier * 0.9 --biters 10% more aggressive + map_pollution_cost_multiplier = map_pollution_cost_multiplier * 0.95 --biters 5% more aggressive end -- if destination.subtype and destination.subtype == IslandsCommon.enum.MAZE then -- base_pollution_cost_multiplier = base_pollution_cost_multiplier * 1.2 --biters 20% less aggressive -- end - if budget >= minimum_avg_units * Common.averageUnitPollutionCost(evolution) * base_pollution_cost_multiplier then + if budget >= minimum_avg_units * Common.averageUnitPollutionCost(evolution) * map_pollution_cost_multiplier then local function spawn(name2) units_created_count = units_created_count + 1 - local unittype_pollutioncost = CoreData.biterPollutionValues[name2] * base_pollution_cost_multiplier + local unit_pollutioncost = CoreData.biterPollutionValues[name2] * map_pollution_cost_multiplier / wave_size_multiplier local p = surface.find_non_colliding_position(name2, spawnposition, 60, 1) if not p then @@ -445,10 +452,10 @@ function Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spaw units_created[#units_created + 1] = biter memory.scripted_biters[biter.unit_number] = {entity = biter, created_at = game.tick} - temp_floating_pollution = temp_floating_pollution - unittype_pollutioncost - budget = budget - unittype_pollutioncost + temp_floating_pollution = temp_floating_pollution - unit_pollutioncost + budget = budget - unit_pollutioncost -- flow statistics should reflect the number of biters generated. Therefore it should mismatch the actual pollution spent, because it should miss all the factors that can vary: - game.pollution_statistics.on_flow(name2, - CoreData.biterPollutionValues[name2] * Balance.scripted_biters_pollution_cost_multiplier()) + game.pollution_statistics.on_flow(name2, - CoreData.biterPollutionValues[name2]) return biter.unit_number end @@ -459,7 +466,7 @@ function Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spaw local whilesafety = 1000 local next_name = enforce_type or Common.get_random_unit_type(evolution) - while units_created_count < maximum_units and budget >= CoreData.biterPollutionValues[next_name] * base_pollution_cost_multiplier and #memory.scripted_biters < CoreData.total_max_biters and whilesafety > 0 do + while units_created_count < maximum_units and budget >= CoreData.biterPollutionValues[next_name] * map_pollution_cost_multiplier and #memory.scripted_biters < CoreData.total_max_biters and whilesafety > 0 do whilesafety = whilesafety - 1 spawn(next_name) next_name = enforce_type or Common.get_random_unit_type(evolution) @@ -468,17 +475,19 @@ function Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spaw local name = enforce_type or Common.get_random_unit_type(evolution) local whilesafety = 1000 - while units_created_count < maximum_units and budget >= CoreData.biterPollutionValues[name] * base_pollution_cost_multiplier and #memory.scripted_biters < CoreData.total_max_biters and whilesafety > 0 do + while units_created_count < maximum_units and budget >= CoreData.biterPollutionValues[name] * map_pollution_cost_multiplier and #memory.scripted_biters < CoreData.total_max_biters and whilesafety > 0 do whilesafety = whilesafety - 1 spawn(name) end end memory.floating_pollution = temp_floating_pollution - end + -- else + -- log('insufficient pollution for wave') + end if units_created_count > 0 then - log('Spent ' .. Math.floor(100 * (initialpollution - temp_floating_pollution) / initialpollution) .. '% of ' .. Math.ceil(initialpollution) .. ' pollution budget on biters, at ' .. Math.ceil(base_pollution_cost_multiplier*100)/100 .. 'x price.') + log('Spent ' .. Math.floor(100 * (initialpollution - temp_floating_pollution) / initialpollution) .. '% of ' .. Math.ceil(initialpollution) .. ' pollution budget on biters, at ' .. Math.ceil(map_pollution_cost_multiplier/wave_size_multiplier*100)/100 .. 'x price.') end return units_created diff --git a/maps/pirates/balance.lua b/maps/pirates/balance.lua index 08a9260f..a9447a26 100644 --- a/maps/pirates/balance.lua +++ b/maps/pirates/balance.lua @@ -28,7 +28,12 @@ Public.EEI_stages = { --multipliers function Public.scripted_biters_pollution_cost_multiplier() - return 1.3 --tuned + -- return 1.3 --tuned + -- return 1.33 + -- return 1.45 --We started getting too strong biter attacks once we staggered the waves more + -- caught a bug with the wave multiplier! going back to 1.3 + + return 1.3 * (1 + 1.3 / ((1 + (Common.overworldx()/40))^(1.5+Common.difficulty()))) -- the factor in brackets makes the early-game easier; in particular the first island, but on easier difficulties the next few islands as well end function Public.cost_to_leave_multiplier() @@ -116,7 +121,7 @@ function Public.fuel_depletion_rate_static() local rate if Common.overworldx() > 0 then - rate = 550 * (0 + (Common.overworldx()/40)^(9/10)) * Public.crew_scale()^(1/7) * Math.sloped(Common.difficulty(), 65/100) / T --most of the crewsize dependence is through T, i.e. the coal cost per island stays the same... but the extra player dependency accounts for the fact that even in compressed time, more players seem to get more resources per island + rate = 575 * (0 + (Common.overworldx()/40)^(9/10)) * Public.crew_scale()^(1/7) * Math.sloped(Common.difficulty(), 65/100) / T --most of the crewsize dependence is through T, i.e. the coal cost per island stays the same... but the extra player dependency accounts for the fact that even in compressed time, more players seem to get more resources per island else rate = 0 end @@ -127,7 +132,7 @@ end function Public.fuel_depletion_rate_sailing() if (not Common.overworldx()) then return 0 end - return - 7.55 * (1 + 0.135 * (Common.overworldx()/40)^(100/100)) * Math.sloped(Common.difficulty(), 1/20) --shouldn't depend on difficulty much if at all, as available resources don't depend much on difficulty + return - 7.65 * (1 + 0.135 * (Common.overworldx()/40)^(100/100)) * Math.sloped(Common.difficulty(), 1/20) --shouldn't depend on difficulty much if at all, as available resources don't depend much on difficulty end function Public.silo_total_pollution() @@ -287,7 +292,7 @@ end function Public.launch_fuel_reward() - return Math.ceil(1100 * (1 + 0.13 * (Common.overworldx()/40)^(9/10))) + return Math.ceil(1250 * (1 + 0.13 * (Common.overworldx()/40)^(9/10))) -- return Math.ceil(1000 * (1 + 0.1 * (Common.overworldx()/40)^(8/10)) / Math.sloped(Common.difficulty(), 1/4)) end @@ -315,7 +320,7 @@ function Public.apply_crew_buffs_per_x(force) end function Public.class_cost() - return 10000 + return 9000 -- return Math.ceil(10000 / (Public.crew_scale()*10/4)^(1/6)) end @@ -519,7 +524,7 @@ Public.covered1_entry_price_data_raw = { --watch out that the raw_materials ches {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.15, false, { + {0.25, 0, 0.15, false, { price = {name = 'burner-mining-drill', count = 150}, raw_materials = {{name = 'iron-plate', count = 1350}}}, {}}, {0.75, 0, 0.6, false, { @@ -531,7 +536,7 @@ Public.covered1_entry_price_data_raw = { --watch out that the raw_materials ches {1, 0, 1, false, { price = {name = 'firearm-magazine', count = 700}, raw_materials = {{name = 'iron-plate', count = 2800}}}, {}}, - {1, 0, 1, false, { + {0.6, 0, 1, false, { price = {name = 'constant-combinator', count = 276}, raw_materials = {{name = 'iron-plate', count = 552}, {name = 'copper-plate', count = 1518}}}, {}}, diff --git a/maps/pirates/coredata.lua b/maps/pirates/coredata.lua index 0cd9bf20..fc5d653d 100644 --- a/maps/pirates/coredata.lua +++ b/maps/pirates/coredata.lua @@ -5,8 +5,8 @@ local _inspect = require 'utils.inspect'.inspect local Public = {} Public.scenario_id_name = 'pirates' -Public.version_string = '1.1.2.0.0' -Public.version_float = 1.1200 +Public.version_string = '1.1.2.0.3' +Public.version_float = 1.1203 Public.blueprint_library_allowed = true Public.blueprint_importing_allowed = true diff --git a/maps/pirates/interface.lua b/maps/pirates/interface.lua index 0bfb0286..662d4e58 100644 --- a/maps/pirates/interface.lua +++ b/maps/pirates/interface.lua @@ -865,7 +865,7 @@ local function base_kill_rewards(event) if revenge_target then Common.give(revenge_target.player, stack, revenge_target.player.position, entity.surface, entity.position) else - if event.cause.position then + if event.cause and event.cause.valid and event.cause.position then Common.give(nil, stack, event.cause.position, entity.surface, entity.position) else Common.give(nil, stack, entity.position, entity.surface) diff --git a/maps/pirates/shop/dock.lua b/maps/pirates/shop/dock.lua index bb9cee19..0475fd73 100644 --- a/maps/pirates/shop/dock.lua +++ b/maps/pirates/shop/dock.lua @@ -38,7 +38,7 @@ Public.market_barters = { } Public.market_permanent_offers = { - {price = {{'pistol', 1}}, offer = {type = 'give-item', item = 'coin', count = 450}}, + {price = {{'pistol', 1}}, offer = {type = 'give-item', item = 'coin', count = 400}}, {price = {{'coin', 3000}}, offer = {type = 'give-item', item = 'iron-ore', count = 800}}, {price = {{'coin', 3000}}, offer = {type = 'give-item', item = 'copper-ore', count = 800}}, {price = {{'coin', 3500}}, offer = {type = 'give-item', item = 'crude-oil-barrel', count = 100}}, diff --git a/maps/pirates/surfaces/cabin.lua b/maps/pirates/surfaces/cabin.lua index 2cc1bab0..d9c26382 100644 --- a/maps/pirates/surfaces/cabin.lua +++ b/maps/pirates/surfaces/cabin.lua @@ -97,7 +97,7 @@ Public.Data.surfacename_rendering_pos = {x = -0.5, y = -15} Public.cabin_shop_data = { { - price = {{'electronic-circuit', 25}, {'coin', 1200}}, + price = {{'electronic-circuit', 30}, {'coin', 800}}, offer = {type='give-item', item = 'rail-signal', count = 100}, }, { @@ -105,7 +105,7 @@ Public.cabin_shop_data = { offer = {type='give-item', item = 'artillery-shell', count = 8}, }, { - price = {{'stone-brick', 100}, {'coin', 1000}}, + price = {{'stone-brick', 30}, {'coin', 800}}, offer = {type='give-item', item = 'uranium-238', count = 10}, }, { diff --git a/maps/pirates/surfaces/islands/horseshoe/horseshoe.lua b/maps/pirates/surfaces/islands/horseshoe/horseshoe.lua index 6cd6140e..b8dea526 100644 --- a/maps/pirates/surfaces/islands/horseshoe/horseshoe.lua +++ b/maps/pirates/surfaces/islands/horseshoe/horseshoe.lua @@ -114,10 +114,10 @@ function Public.chunk_structures(args) local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed} return { - placeable = noises.farness(p) > 0.35, + placeable = noises.farness(p) > 0.36, spawners_indestructible = false, -- spawners_indestructible = noises.farness(p) > 0.7, - density_perchunk = 10 * Math.slopefromto(noises.mood(p), 0.12, -0.18) * Math.slopefromto(noises.farness(p), 0.35, 1) * args.biter_base_density_scale, + density_perchunk = 9 * Math.slopefromto(noises.mood(p), 0.12, -0.18) * Math.slopefromto(noises.farness(p), 0.36, 1) * args.biter_base_density_scale, } end diff --git a/maps/pirates/surfaces/islands/hunt.lua b/maps/pirates/surfaces/islands/hunt.lua index a4952ee7..67598167 100644 --- a/maps/pirates/surfaces/islands/hunt.lua +++ b/maps/pirates/surfaces/islands/hunt.lua @@ -232,7 +232,7 @@ function Public.position_away_from_players_1(_, radius) local tile = surface.get_tile(p2) if tile and tile.valid and tile.name then - if not Utils.contains(CoreData.tiles_that_conflict_with_resource_layer, tile.name) then + if not Utils.contains(CoreData.tiles_that_conflict_with_resource_layer_extended, tile.name) then local nearby_characters = surface.find_entities_filtered{position = p2, radius = radius, name = 'character'} if (not nearby_characters) or (#nearby_characters == 0) then p_ret = p2 diff --git a/maps/pirates/surfaces/surfaces.lua b/maps/pirates/surfaces/surfaces.lua index a92b7536..99cfd4a1 100644 --- a/maps/pirates/surfaces/surfaces.lua +++ b/maps/pirates/surfaces/surfaces.lua @@ -200,7 +200,7 @@ function Public.destination_on_collide(destination) -- scheduled_raft_raids[#scheduled_raft_raids + 1] = {timeinseconds = t, max_bonus_evolution = 0.52} end end - elseif memory.overworldx == 200 or _DEBUG then + elseif memory.overworldx == 200 then local times if playercount <= 2 then times = {1, 5, 10, 15, 20} diff --git a/maps/pirates/tick_functions.lua b/maps/pirates/tick_functions.lua index 55f0d63b..c3e0d347 100644 --- a/maps/pirates/tick_functions.lua +++ b/maps/pirates/tick_functions.lua @@ -622,7 +622,7 @@ function Public.place_cached_structures(tickinterval) covered_data.market.rotatable = false covered_data.market.destructible = false - covered_data.market.add_market_item{price={{'pistol', 1}}, offer={type = 'give-item', item = 'coin', count = 450}} + covered_data.market.add_market_item{price={{'pistol', 1}}, offer={type = 'give-item', item = 'coin', count = 400}} covered_data.market.add_market_item{price={{'burner-mining-drill', 1}}, offer={type = 'give-item', item = 'iron-plate', count = 9}} local how_many_coin_offers = 4