1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-20 03:29:47 +02:00

Merge pull request #378 from Piratux/develop

Pirate ship update V1.4.3
This commit is contained in:
hanakocz 2023-01-13 17:36:20 +01:00 committed by GitHub
commit 6c75b4b4dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 402 additions and 223 deletions

View File

@ -16,7 +16,7 @@ softmod_info_tips_1=Features of the game that are hard to work out alone
softmod_info_tips_2=• The captain can steer the boat from the crow's nest by placing 100 rail signals in one of the blue boxes.\n• Resources granted to the ship appear in the captain's cabin.\n• Charging a silo drains power from everything else on its network.\n• The quantity of ore available on an island is independent of the order in which you break rocks.\n• Passive pollution ramps up over time on each island.\n• The strength of attacks is proportional to the number of remaining nests. (The time-based rate of evolution is proportional to nests too, but destroying a nest will immediately jump evolution by most of the amount it 'would have' made had it survived.)\n• Lab productivity increases with each league.\n• item-on-ground entities on the deck are moved to the cabin when the boat moves, for performance reasons.\n• Commands: /ccolor gives you a fun color. /classinfo {classname} gives the description of the named class. To manage your class, use /take {classname} or /giveup.
softmod_info_updates_1=Significant recent changes
softmod_info_updates_2=v1.4.2\n• Disabled 'disband crew' button.\n• Increased amount of fish caught by all fishing classes.\n• Enabled concrete tech.\n• Fixed Mysterious caves island always having the same layout.\n• Fixed issue where power could get disconnected between deck and hold.\n• Added /clear_north_tanks and /clear_south_tanks commands to clear fluid from ship's storage tanks.\n• Difficulty of Hard and Nightmare increased. Resistive roles slightly nerfed.\n\nv1.4.0\n• New private runs: Protect your run by a password.\n• New island: Mysterious caves.\n• New technologies now available: Car and nuclear energy.\n• New way to unlock extra holds and power upgrades.\n• Various island related balance changes.
softmod_info_updates_2=v1.4.3\n• Sandworm Caldera and Mysterious Caves islands now have auto-undock timer.\n• Gourmet doesn't grant ore at sea now.\n• Bugfixes and various tweaks.\n\nv1.4.2\n• Disabled 'disband crew' button.\n• Increased amount of fish caught by all fishing classes.\n• Enabled concrete tech.\n• Fixed Mysterious caves island always having the same layout.\n• Fixed issue where power could get disconnected between deck and hold.\n• Added /clear_north_tanks and /clear_south_tanks commands to clear fluid from ship's storage tanks.\n• Difficulty of Hard and Nightmare increased. Resistive roles slightly nerfed.
softmod_info_credits_1=Credits
softmod_info_credits_2=Pirate Ship designed and coded by thesixthroc. Updates from Piratux. Comfy codebase and help from Gerkiz, Hanakocz and Mew @ Comfy Industries (https://getcomfy.eu). Some island structure blueprints contributed by Mattisso.\n\nCome chat with us: https://getcomfy.eu/discord\n\n"Those white gloves. I'll never forget them 'till the day I die." - Dr. John
@ -74,7 +74,7 @@ parrot_maze_tip_1=Something seems wrong with our minimap.
parrot_cave_tip_1=That island looks suspiciously dark... I'm scared! Squawk!
parrot_captain_first_time_in_cabin_hint=Squawk! Captains and officers can buy rail signals to steer the ship!
parrot_cliff_explosive_tip=Cliff explosives? These look so powerful, they could blow away those annoying chests in the hold. Squawk!
parrot_burried_treasure_tip=Squawk! If X marks the spot - use an item to dig with!
parrot_buried_treasure_tip=Squawk! If X marks the spot - use an item to dig with!
@ -232,7 +232,7 @@ class_deckhand=Deckhand
class_deckhand_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) for the cabin whilst onboard above deck. No ore is generated while at sea.
class_fisherman=Fisherman
# class_fisherman_explanation=They fish at greater distance.
class_fisherman_explanation_advanced=They fish (as well as reach objects as side effect) at greater distance (__1__ extra tile range), and catch more (+__2__ fish).
class_fisherman_explanation_advanced=They fish at greater distance (__1__ extra tile range), and catch more (+__2__ fish).
class_scout=Scout
# class_scout_explanation=They are faster, but frail and deal less damage.
class_scout_explanation_advanced=They move __1__% times faster, but receive __2__% more damage and deal __3__% less damage.
@ -265,7 +265,7 @@ class_chief_excavator=Chief Excavator
class_chief_excavator_explanation_advanced=They find many more resources when handmining.
class_hatamoto=Hatamoto
# class_hatamoto_explanation=They are very tough, and *with no weapon equipped* fight well by melee, but poorly otherwise.
class_hatamoto_explanation_advanced=They receive __1__% less damage, and with no weapon equipped do extra __2__ damage in melee (scales with 'physical projectile damage' research bonuses), but deal __3__% less damage otherwise.\nIf the damage dealt in melee is an overkill, the remaining damage splashes onto nearby enemies.
class_hatamoto_explanation_advanced=They receive __1__% less damage, and with no weapon equipped do extra __2__ damage in melee (scales with 'physical projectile damage' research bonuses), but deal __3__% less damage otherwise.\n\nIf the damage dealt in melee is an overkill, the remaining damage splashes onto nearby enemies.
class_iron_leg=Iron Leg
# class_iron_leg_explanation=They are very resistant to damage when carrying 3000 iron ore.
class_iron_leg_explanation_advanced=They receive __1__% less damage when carrying at least __2__ iron ore.
@ -274,21 +274,21 @@ class_quartermaster=Quartermaster
class_quartermaster_explanation_advanced=Nearby crewmates (at __1__ tile radius) get +__2__% physical attack bonus and generate ore for the cabin (ore amount depends on nearby crewmate count).
class_dredger=Dredger
# class_dredger_explanation=They find surprising items when they fish.
class_dredger_explanation_advanced=They inherit the previous class bonuses and find surprising items when they fish.
class_dredger_explanation_advanced=They can grab fish from an insane distance (__1__ extra tile range), and catch more (+__2__ fish). In addition, they find surprising items when fishing.
class_smoldering=Smoldering
# class_smoldering_explanation=They periodically convert wood into coal, if they have less than 50 coal.
class_smoldering_explanation_advanced=They periodically convert wood into coal, if they have less than 50 coal.
class_gourmet=Gourmet
# class_gourmet_explanation=They generate ore for the cabin by eating fish in fancy locations.
class_gourmet_explanation_advanced=They generate ore for the cabin by eating fish in fancy locations.
class_gourmet_explanation_advanced=They generate ore for the cabin by eating fish in fancy locations. Does not generate ore while at sea.
class_chef=Chef
class_chef_explanation_advanced=They cook meat of defeated enemies and turn it into something tasty.
class_rock_eater=Rock Eater
class_rock_eater_explanation_advanced=When eating fish, if they have stone furnaces in their inventory, they will eat those instead.\nIn addition, they receive __1__% less damage.
class_rock_eater_explanation_advanced=When eating fish, if they have stone furnaces in their inventory, they will eat those instead.\n\nIn addition, they receive __1__% less damage.
class_soldier=Soldier
class_soldier_explanation_advanced=When eating fish, they have __1__% chance to summon defender to protect them.
class_veteran=Veteran
class_veteran_explanation_advanced=When eating fish, they have __1__% chance to summon destroyer to protect them.\nIn addition, they have __2__% chance to slow the enemy that hits them.
class_veteran_explanation_advanced=When eating fish, they have __1__% chance to summon destroyer to protect them.\n\nIn addition, they have __2__% chance to slow the enemy that hits them.
class_explanation=__1__: __2__
@ -306,6 +306,8 @@ class_upgrade=__1__ upgraded their class from __2__ to __3__ ([font=scenario-mes
# class_revoke=__1__ revoked __2__ from __3__.
class_purchase_error_prerequisite_class=Class purchase error: You need to be a __1__ to buy this.
cant_catch_fish=Looks like the fish has learned how to avoid being caught in these waters. Perhaps it would be a good idea to try somewhere else?
roles_confirm_captain=__1__ accepted the role of captain.
roles_confirm_captain_error_1=Command error: You're not the captain.
roles_confirm_captain_error_2=Command error: You're not temporary, so you don't need to accept.
@ -402,6 +404,7 @@ mode_tooltip=Mode.
auto_undock_tooltip=The maximum time to stay at this location.\n\nOnce this time is reached, the boat undocks automatically. The captain can choose to leave earlier by pressing this button (or typing /undock).
atsea_loading_tooltip=The next destination is loading.
defeat_krakens_tooltip=Defeat the krakens to proceed.
leave_anytime_tooltip=The captain chooses when to undock the ship.\n\nThey can undock by pressing this button.
atsea_waiting_tooltip=The ship pauses after each destination. When the captain is ready, they can click this button to proceed.
@ -546,10 +549,11 @@ gui_etaframe_board_warning=RETURN TO SHIP
gui_etaframe_board_warning_tooltip=Probably time to board...
gui_etaframe_autoundock=Auto-undock:
gui_etaframe_arriving_in=Arriving in
gui_etaframe_defeat_krakens=Defeat the krakens!
gui_etaframe_atsea_waiting=Captain — Click here to Sail
gui_etaframe_undock=Undock:
gui_etaframe_anytime=Anytime
gui_etaframe_nest_escape_cost=Next escape cost:
gui_etaframe_next_escape_cost=Next escape cost:
gui_etaframe_to_escape_store=To escape, store
gui_etaframe_or_store=Or store
gui_etaframe_rocket_requirement_tooltip=Launch a rocket

View File

@ -418,7 +418,7 @@ gui_etaframe_arriving_in=Прибываем через
gui_etaframe_atsea_waiting=Капитан - Нажмите здесь для отплытия
gui_etaframe_undock=Отчалить:
gui_etaframe_anytime=В любое время
gui_etaframe_nest_escape_cost=Цена следующего побега:
gui_etaframe_next_escape_cost=Цена следующего побега:
gui_etaframe_to_escape_store=Чтобы убежать, соберите
gui_etaframe_or_store=Или храните
gui_etaframe_rocket_requirement_tooltip=Запустите ракету

View File

@ -528,7 +528,7 @@ gui_etaframe_arriving_in=正在抵达
gui_etaframe_atsea_waiting=船长—点击这里继续冒险
gui_etaframe_undock=出坞:
gui_etaframe_anytime=随时
gui_etaframe_nest_escape_cost=下一个逃生成本:
gui_etaframe_next_escape_cost=下一个逃生成本:
gui_etaframe_to_escape_store=想要撤离,需要存储
gui_etaframe_or_store=或存储
gui_etaframe_rocket_requirement_tooltip=发射火箭

View File

@ -18,6 +18,7 @@ local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
-- local Sea = require 'maps.pirates.surfaces.sea.sea'
-- local Crew = require 'maps.pirates.crew'
-- local Quest = require 'maps.pirates.quest'
local SurfacesCommon = require 'maps.pirates.surfaces.common'
local Public = {}
@ -61,7 +62,7 @@ function Public.Tick_actions(tickinterval)
end
-- if destination.subtype and destination.subtype == IslandEnum.enum.RED_DESERT then return end -- This was a hack to stop biter boats causing attacks, but, it has the even worse effect of stopping all floating_pollution gathering.
-- if destination.subtype == IslandEnum.enum.RED_DESERT then return end -- This was a hack to stop biter boats causing attacks, but, it has the even worse effect of stopping all floating_pollution gathering.
local minute_cycle = {-- warning: use even seconds only
@ -114,7 +115,7 @@ function Public.eat_up_fraction_of_all_pollution(surface, fraction_of_global_pol
surface.pollute(p, - pollution_to_eat)
-- Radioactive world doesn't absorb map pollution:
if not (Common.current_destination().subtype and Common.current_destination().subtype == IslandEnum.enum.RADIOACTIVE) then
if not (Common.current_destination().subtype == IslandEnum.enum.RADIOACTIVE) then
pollution_available = pollution_available + pollution_to_eat
end
end
@ -128,6 +129,14 @@ end
function Public.wave_size_rng() -- random variance in attack sizes
local memory = Memory.get_crew_memory()
local destination = Common.current_destination()
-- prevent situation where when player reveals spawner, he immediately gets surrounded by massive amount of biters (especially late game)
if destination and destination.type == SurfacesCommon.enum.ISLAND then
if destination.dynamic_data and destination.dynamic_data.disabled_wave_timer and destination.dynamic_data.disabled_wave_timer > 0 then
return 0
end
end
local wave_percentage_chance = Math.clamp(0, 50, 11 + 8 * memory.floating_pollution/1500)
@ -439,11 +448,11 @@ function Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spaw
map_pollution_cost_multiplier = map_pollution_cost_multiplier * base_scripted_biters_pollution_cost_multiplier
if destination.subtype and destination.subtype == IslandEnum.enum.SWAMP then
if destination.subtype == IslandEnum.enum.SWAMP then
map_pollution_cost_multiplier = map_pollution_cost_multiplier * 0.95 --biters 5% more aggressive
end
-- if destination.subtype and destination.subtype == IslandEnum.enum.MAZE then
-- if destination.subtype == IslandEnum.enum.MAZE then
-- base_pollution_cost_multiplier = base_pollution_cost_multiplier * 1.2 --biters 20% less aggressive
-- end

View File

@ -59,10 +59,12 @@ function Public.silo_die()
if CoreData.rocket_silo_death_causes_loss then
-- Crew.lose_life()
Crew.try_lose({'pirates.loss_silo_destroyed'})
elseif (not destination.dynamic_data.rocketlaunched) and destination.static_params and destination.static_params.base_cost_to_undock and destination.static_params.base_cost_to_undock['launch_rocket'] and destination.static_params.base_cost_to_undock['launch_rocket'] == true and (not (destination.dynamic_data.time_remaining and destination.dynamic_data.time_remaining > 0)) then
Crew.try_lose({'pirates.loss_silo_destroyed_before_necessary_launch'})
elseif (not destination.dynamic_data.rocketlaunched) then
Common.notify_force(force, {'pirates.silo_destroyed'})
if destination.static_params and destination.static_params.base_cost_to_undock and destination.static_params.base_cost_to_undock['launch_rocket'] == true and Balance.need_resources_to_undock() then
Crew.try_lose({'pirates.loss_silo_destroyed_before_necessary_launch'})
else
Common.notify_force(force, {'pirates.silo_destroyed'})
end
end
end
@ -109,7 +111,7 @@ local function biters_chew_stuff_faster(event)
if (event.entity.force.index == 3 or event.entity.force.name == 'environment') then
event.entity.health = event.entity.health - event.final_damage_amount * 5
if destination and destination.type and destination.subtype and destination.type == Surfaces.enum.ISLAND and destination.subtype == IslandEnum.enum.MAZE then
if destination and destination.type == Surfaces.enum.ISLAND and destination.subtype == IslandEnum.enum.MAZE then
event.entity.health = event.entity.health - event.final_damage_amount * 10
end
elseif event.entity.name == 'pipe' then
@ -528,7 +530,7 @@ local function swamp_resist_poison(event)
if not (event.damage_type.name and event.damage_type.name == 'poison') then return end
local destination = Common.current_destination()
if not (destination and destination.subtype and destination.subtype == IslandEnum.enum.SWAMP) then return end
if not (destination and destination.subtype == IslandEnum.enum.SWAMP) then return end
if not (destination.surface_name == entity.surface.name) then return end
@ -546,7 +548,7 @@ local function maze_walls_resistance(event)
if not entity.valid then return end
local destination = Common.current_destination()
if not (destination and destination.subtype and destination.subtype == IslandEnum.enum.MAZE) then return end
if not (destination and destination.subtype == IslandEnum.enum.MAZE) then return end
if not (destination.surface_name == entity.surface.name) then return end
@ -819,34 +821,49 @@ local function event_on_player_mined_entity(event)
elseif entity.type == 'fish' then
if not event.buffer then return end
local fish_amount = Balance.base_caught_fish_amount
local to_give = {}
if class == Classes.enum.FISHERMAN then
fish_amount = fish_amount + Balance.fisherman_fish_bonus
to_give[#to_give + 1] = {name = 'raw-fish', count = fish_amount}
elseif class == Classes.enum.MASTER_ANGLER then
fish_amount = fish_amount + Balance.master_angler_fish_bonus
to_give[#to_give + 1] = {name = 'raw-fish', count = fish_amount}
to_give[#to_give + 1] = {name = 'coin', count = Balance.master_angler_coin_bonus}
elseif class == Classes.enum.DREDGER then
fish_amount = fish_amount + Balance.dredger_fish_bonus
to_give[#to_give + 1] = {name = 'raw-fish', count = fish_amount}
to_give[#to_give + 1] = Loot.dredger_loot()[1]
else
to_give[#to_give + 1] = {name = 'raw-fish', count = fish_amount}
-- Prevent dull strategy being staying in sea for long time catching as many fish as possible (as there is kind of infinite amount there)
local boat_is_at_sea = Boats.is_boat_at_sea()
local fish_caught_while_at_sea = -1
if boat_is_at_sea and memory.boat and memory.boat.fish_caught_while_at_sea then
fish_caught_while_at_sea = memory.boat.fish_caught_while_at_sea
end
Common.give(player, to_give, entity.position)
if destination and destination.dynamic_data and destination.dynamic_data.quest_type and (not destination.dynamic_data.quest_complete) then
if destination.dynamic_data.quest_type == Quest.enum.FISH then
destination.dynamic_data.quest_progress = destination.dynamic_data.quest_progress + fish_amount
Quest.try_resolve_quest()
if (not boat_is_at_sea) or (boat_is_at_sea and fish_caught_while_at_sea < Balance.maximum_fish_allowed_to_catch_at_sea) then
if fish_caught_while_at_sea ~= -1 then
memory.boat.fish_caught_while_at_sea = memory.boat.fish_caught_while_at_sea + 1
end
local fish_amount = Balance.base_caught_fish_amount
local to_give = {}
if class == Classes.enum.FISHERMAN then
fish_amount = fish_amount + Balance.fisherman_fish_bonus
to_give[#to_give + 1] = {name = 'raw-fish', count = fish_amount}
elseif class == Classes.enum.MASTER_ANGLER then
fish_amount = fish_amount + Balance.master_angler_fish_bonus
to_give[#to_give + 1] = {name = 'raw-fish', count = fish_amount}
to_give[#to_give + 1] = {name = 'coin', count = Balance.master_angler_coin_bonus}
elseif class == Classes.enum.DREDGER then
fish_amount = fish_amount + Balance.dredger_fish_bonus
to_give[#to_give + 1] = {name = 'raw-fish', count = fish_amount}
to_give[#to_give + 1] = Loot.dredger_loot()[1]
else
to_give[#to_give + 1] = {name = 'raw-fish', count = fish_amount}
end
Common.give(player, to_give, entity.position)
if destination and destination.dynamic_data and destination.dynamic_data.quest_type and (not destination.dynamic_data.quest_complete) then
if destination.dynamic_data.quest_type == Quest.enum.FISH then
destination.dynamic_data.quest_progress = destination.dynamic_data.quest_progress + fish_amount
Quest.try_resolve_quest()
end
end
else
Common.notify_player_error(player, {'pirates.cant_catch_fish'})
end
event.buffer.clear()
@ -1188,7 +1205,7 @@ local function event_on_entity_died(event)
end
if event.entity and event.entity.valid and event.entity.force and event.entity.force.name == memory.force_name then
if memory.boat and memory.boat.cannonscount and entity.name and entity.name == 'artillery-turret' then
if memory.boat and memory.boat.cannonscount and entity.name == 'artillery-turret' then
memory.boat.cannonscount = memory.boat.cannonscount - 1
-- if memory.boat.cannonscount <= 0 then
-- Crew.try_lose()

View File

@ -16,20 +16,20 @@ local Roles = require 'maps.pirates.roles.roles'
local Progression = require 'maps.pirates.progression'
local Crowsnest = require 'maps.pirates.surfaces.crowsnest'
local Hold = require 'maps.pirates.surfaces.hold'
local Cabin = require 'maps.pirates.surfaces.cabin'
-- local Cabin = require 'maps.pirates.surfaces.cabin'
local Balance = require 'maps.pirates.balance'
local Common = require 'maps.pirates.common'
local CoreData = require 'maps.pirates.coredata'
local Overworld = require 'maps.pirates.overworld'
local Utils = require 'maps.pirates.utils_local'
local Crew = require 'maps.pirates.crew'
local Parrot = require 'maps.pirates.parrot'
-- local Parrot = require 'maps.pirates.parrot'
local Math = require 'maps.pirates.math'
local _inspect = require 'utils.inspect'.inspect
local Kraken = require 'maps.pirates.surfaces.sea.kraken'
local Quest = require 'maps.pirates.quest'
local ShopDock = require 'maps.pirates.shop.dock'
-- local ShopDock = require 'maps.pirates.shop.dock'
local QuestStructures = require 'maps.pirates.structures.quest_structures.quest_structures'
local Public = {}
@ -134,7 +134,7 @@ function Public.check_all_spawners_dead(tickinterval)
local destination = Common.current_destination()
local boat = memory.boat
if destination.static_params and destination.static_params.base_cost_to_undock and (not (destination.subtype and destination.subtype == IslandEnum.enum.RED_DESERT)) then
if destination.static_params and destination.static_params.base_cost_to_undock and (not (destination.subtype == IslandEnum.enum.RED_DESERT or destination.subtype == IslandEnum.enum.CAVE)) then
if boat and boat.surface_name and boat.surface_name == destination.surface_name then
local surface = game.surfaces[destination.surface_name]
if not (surface and surface.valid) then return end
@ -310,7 +310,7 @@ function Public.periodic_free_resources(tickinterval)
Common.give_items_to_crew(Balance.periodic_free_resources_per_destination_5_seconds())
if game.tick % (300*30) == 0 and (destination and destination.subtype and destination.subtype == IslandEnum.enum.RADIOACTIVE) then -- every 150 seconds
if game.tick % (300*30) == 0 and (destination and destination.subtype == IslandEnum.enum.RADIOACTIVE) then -- every 150 seconds
local count = 2
Common.give_items_to_crew{{name = 'sulfuric-acid-barrel', count = count}}
local force = memory.force
@ -436,40 +436,6 @@ function Public.pick_up_tick(tickinterval)
end
end
local function cached_structure_delete_existing_entities_if_needed(surface, position, special)
if (not special.doNotDestroyExistingEntities) then
-- destroy existing entities
local area = {left_top = {position.x - special.width/2, position.y - special.height/2}, right_bottom = {position.x + special.width/2 + 0.5, position.y + special.height/2 + 0.5}}
surface.destroy_decoratives{area=area}
local existing = surface.find_entities_filtered{area = area}
if existing then
for _, e in pairs(existing) do
if not (((special.name == 'small_primitive_mining_base' or special.name == 'small_mining_base') and (e.name == 'iron-ore' or e.name == 'copper-ore' or e.name == 'stone')) or (special.name == 'uranium_miners' and e.name == 'uranium-ore')) then
if not (e.name and e.name == 'rocket-silo') then
e.destroy()
end
end
end
end
end
end
local function cached_structure_delete_existing_unwalkable_tiles_if_needed(surface, position, special)
local area = {left_top = {position.x - special.width/2, position.y - special.height/2}, right_bottom = {position.x + special.width/2 + 0.5, position.y + special.height/2 + 0.5}}
local existing = surface.find_tiles_filtered{area = area, collision_mask = "water-tile"}
if existing then
local tiles = {}
for _, t in pairs(existing) do
tiles[#tiles + 1] = {name = "landfill", position = t.position}
end
if #tiles > 0 then
surface.set_tiles(tiles, true)
end
end
end
function Public.interpret_shorthanded_force_name(shorthanded_name)
local memory = Memory.get_crew_memory()
@ -533,8 +499,10 @@ function Public.place_cached_structures(tickinterval)
Common.ensure_chunks_at(surface, position, Common.structure_ensure_chunk_radius)
cached_structure_delete_existing_entities_if_needed(surface, position, special)
cached_structure_delete_existing_unwalkable_tiles_if_needed(surface, position, special)
if not special.doNotDestroyExistingEntities then
Common.delete_entities(surface, position, special.width, special.height)
end
Common.replace_unwalkable_tiles(surface, position, special.width, special.height)
local saved_components = {}
for k = 1, #special.components do
@ -1037,14 +1005,10 @@ function Public.loading_update(tickinterval)
total = Common.map_loading_ticks_atsea_maze
end
local eta_ticks = total - (memory.loadingticks - (memory.extra_time_at_sea or 0))
-- local eta_ticks = total - (memory.loadingticks - (memory.extra_time_at_sea or 0))
if eta_ticks < 60*20 and
memory.active_sea_enemies and
memory.active_sea_enemies.kraken_count and
memory.active_sea_enemies.kraken_count > 0
then
memory.loadingticks = memory.loadingticks - tickinterval --reverse the change
if Kraken.get_active_kraken_count() > 0 then
memory.loadingticks = memory.loadingticks - tickinterval --reverse the change to avoid causing lag from map loading during fight
else
local fraction = memory.loadingticks / (total + (memory.extra_time_at_sea or 0))
@ -1192,7 +1156,7 @@ function Public.slower_boat_tick(tickinterval)
end
local p = memory.boat.position
if p and (not (destination.subtype and destination.subtype == IslandEnum.enum.RADIOACTIVE)) and destination.surface_name and game.surfaces[destination.surface_name] and game.surfaces[destination.surface_name].valid then --no locomotive pollute on radioactive islands
if p and destination.subtype ~= IslandEnum.enum.RADIOACTIVE and destination.surface_name and game.surfaces[destination.surface_name] and game.surfaces[destination.surface_name].valid then --no locomotive pollute on radioactive islands
local pollution = Balance.boat_passive_pollution_per_minute(destination.dynamic_data.timer) / 3600 * tickinterval
game.surfaces[destination.surface_name].pollute(p, pollution)
@ -1275,7 +1239,7 @@ function Public.Kraken_Destroyed_Backup_check(tickinterval) -- a server became s
local boat = memory.boat
if boat and boat.surface_name and boat.state and boat.state == Boats.enum_state.ATSEA_LOADING_MAP then
if (memory.active_sea_enemies and memory.active_sea_enemies.krakens and memory.active_sea_enemies.kraken_count and memory.active_sea_enemies.kraken_count > 0) then
if Kraken.get_active_kraken_count() > 0 then
local surface = game.surfaces[boat.surface_name]

View File

@ -14,7 +14,7 @@ local CoreData = require 'maps.pirates.coredata'
-- Kraken related parameters
Public.biter_swim_speed = 1
Public.biter_swim_speed = 1.5
Public.kraken_biter_spawn_radius = 6 -- only used during non automatic forced spawning during kraken's "special ability"
Public.kraken_spit_targeting_player_chance = 0
@ -78,6 +78,10 @@ Public.soldier_defender_summon_chance = 0.2
Public.veteran_destroyer_summon_chance = 0.2
Public.veteran_on_hit_slow_chance = 0.1
Public.maximum_fish_allowed_to_catch_at_sea = 30
Public.prevent_waves_from_spawning_in_cave_timer_length = 10 -- in seconds
function Public.starting_boatEEIpower_production_MW()
-- return 3 * Math.sloped(Common.capacity_scale(), 1/2) / 2 --/2 as we have 2
@ -164,10 +168,19 @@ end
Public.rockets_needed_x = 40*20
-- Returns true if resources are mandatory to escape from island. Returns false, when resources are needed to just undock early.
function Public.need_resources_to_undock()
local x = Common.overworldx()
if x >= Public.rockets_needed_x and x ~= 40*21 then
return true
else
return false
end
end
function Public.max_time_on_island()
local x = Common.overworldx()
if x == 0 or (x >= Public.rockets_needed_x and x ~= 40*21) then
if x == 0 or Public.need_resources_to_undock() then
-- if Common.overworldx() == 0 or ((Common.overworldx()/40) > 20 and (Common.overworldx()/40) < 25) then
return -1
else

View File

@ -1203,8 +1203,10 @@ if _DEBUG then
player.insert{name='uranium-rounds-magazine', count = 200}
player.insert{name='raw-fish', count = 100}
player.insert{name='coin', count = 50000}
player.insert{name='grenade', count = 100}
player.insert{name='cluster-grenade', count = 100}
player.insert{name='steel-chest', count = 50}
player.insert{name='express-loader', count = 50}
player.insert{name='burner-inserter', count = 50}
end
end)

View File

@ -1670,4 +1670,37 @@ function Public.force_connect_poles(pole1, pole2)
end
end
-- position here refers to middle position
function Public.delete_entities(surface, position, width, height)
local area = {left_top = {position.x - width/2, position.y - height/2}, right_bottom = {position.x + width/2 + 0.5, position.y + height/2 + 0.5}}
surface.destroy_decoratives{area = area}
local existing = surface.find_entities_filtered{area = area}
if not existing then return end
for _, e in pairs(existing) do
if not (e.name == 'iron-ore' or e.name == 'copper-ore' or e.name == 'stone' or e.name == 'uranium-ore' or e.name == 'crude-oil') then
if not (e.name == 'rocket-silo') then
e.destroy()
end
end
end
end
function Public.replace_unwalkable_tiles(surface, position, width, height)
local area = {left_top = {position.x - width/2, position.y - height/2}, right_bottom = {position.x + width/2 + 0.5, position.y + height/2 + 0.5}}
local existing = surface.find_tiles_filtered{area = area, collision_mask = "water-tile"}
if not existing then return end
local tiles = {}
for _, t in pairs(existing) do
tiles[#tiles + 1] = {name = "landfill", position = t.position}
end
if #tiles > 0 then
surface.set_tiles(tiles, true)
end
end
return Public

View File

@ -7,7 +7,7 @@ local _inspect = require 'utils.inspect'.inspect
local Public = {}
Public.scenario_id_name = 'pirates'
Public.version_string = '1.4.2' --major.minor.patch versioning, to match factorio mod portal
Public.version_string = '1.4.3' --major.minor.patch versioning, to match factorio mod portal
Public.blueprint_library_allowed = true
Public.blueprint_importing_allowed = true

View File

@ -284,8 +284,12 @@ function Public.join_spectators(player, crewid)
Common.notify_force(force, {'pirates.lobby_to_spectator', player.name})
Common.notify_lobby({'pirates.lobby_to_spectator_2', player.name, memory.name})
end
memory.spectatorplayerindices[#memory.spectatorplayerindices + 1] = player.index
memory.tempbanned_from_joining_data[player.index] = game.tick
if not _DEBUG then
memory.tempbanned_from_joining_data[player.index] = game.tick
end
-- if #Common.crew_get_crew_members() == 0 then
-- memory.crew_disband_tick = game.tick + 30
-- -- memory.crew_disband_tick = game.tick + 60*60*2 --give players time to log back in after a crash or save

View File

@ -27,6 +27,7 @@ local Roles = require 'maps.pirates.roles.roles'
local Event = require 'utils.event'
local CustomEvents = require 'maps.pirates.custom_events'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local Kraken = require 'maps.pirates.surfaces.sea.kraken'
local ComfyGui = require 'utils.gui'
ComfyGui.set_disabled_tab('Scoreboard', true)
@ -558,23 +559,32 @@ function Public.process_etaframe_update(player, flow1, bools)
flow2.etaframe_label_2.caption = Utils.standard_string_form_of_time_in_seconds(passive_eta)
elseif bools.atsea_loading_bool then
flow2.etaframe_label_1.visible = true
flow2.etaframe_label_2.visible = true
if Kraken.get_active_kraken_count() > 0 then
flow2.etaframe_label_1.visible = true
flow2.etaframe_label_2.visible = false
tooltip = {'pirates.atsea_loading_tooltip'}
tooltip = {'pirates.defeat_krakens_tooltip'}
local total = Common.map_loading_ticks_atsea
if destination.type == Surfaces.enum.DOCK then
total = Common.map_loading_ticks_atsea_dock
elseif destination.type == Surfaces.enum.ISLAND and destination.subtype == IslandEnum.enum.MAZE then
total = Common.map_loading_ticks_atsea_maze
flow2.etaframe_label_1.caption = {'pirates.gui_etaframe_defeat_krakens'}
else
flow2.etaframe_label_1.visible = true
flow2.etaframe_label_2.visible = true
tooltip = {'pirates.atsea_loading_tooltip'}
local total = Common.map_loading_ticks_atsea
if destination.type == Surfaces.enum.DOCK then
total = Common.map_loading_ticks_atsea_dock
elseif destination.type == Surfaces.enum.ISLAND and destination.subtype == IslandEnum.enum.MAZE then
total = Common.map_loading_ticks_atsea_maze
end
local eta_ticks = total + (memory.extra_time_at_sea or 0) - memory.loadingticks
flow2.etaframe_label_1.caption = {'pirates.gui_etaframe_arriving_in'}
flow2.etaframe_label_2.caption = Utils.standard_string_form_of_time_in_seconds(eta_ticks / 60)
end
local eta_ticks = total + (memory.extra_time_at_sea or 0) - memory.loadingticks
flow2.etaframe_label_1.caption = {'pirates.gui_etaframe_arriving_in'}
flow2.etaframe_label_2.caption = Utils.standard_string_form_of_time_in_seconds(eta_ticks / 60)
elseif bools.atsea_waiting_bool then
flow2.etaframe_label_1.visible = true
flow2.etaframe_label_2.visible = false
@ -593,7 +603,7 @@ function Public.process_etaframe_update(player, flow1, bools)
flow2.etaframe_label_2.caption = {'pirates.gui_etaframe_anytime'}
end
if bools.cost_bool then
if bools.cost_bool and Kraken.get_active_kraken_count() == 0 then
local costs = destination.static_params.base_cost_to_undock
local adjusted_costs = Common.time_adjusted_departure_cost(costs)
@ -608,16 +618,15 @@ function Public.process_etaframe_update(player, flow1, bools)
-- local caption
if bools.atsea_loading_bool then
-- @TODO: Fix magic numbers here
if memory.overworldx >= Balance.rockets_needed_x and (not (memory.overworldx == 21 * 40)) then --bools.eta_bool is not helpful yet
flow2.etaframe_label_3.caption = {'pirates.gui_etaframe_nest_escape_cost'}
if Balance.need_resources_to_undock() then
flow2.etaframe_label_3.caption = {'pirates.gui_etaframe_next_escape_cost'}
if bools.cost_includes_rocket_launch_bool then
tooltip = {'pirates.resources_needed_tooltip_0_rocketvariant'}
else
tooltip = {'pirates.resources_needed_tooltip_0'}
end
else
flow2.etaframe_label_3.caption = {'pirates.gui_etaframe_nest_escape_cost'}
flow2.etaframe_label_3.caption = {'pirates.gui_etaframe_next_escape_cost'}
if bools.cost_includes_rocket_launch_bool then
tooltip = {'pirates.resources_needed_tooltip_1_rocketvariant'}
else

View File

@ -350,7 +350,7 @@ function Public.chest_loot(number_of_items, game_completion_progress)
end
function Public.buried_treasure_loot()
local ret = Common.raffle_from_processed_loot_data(Common.processed_loot_data(Public.buried_treasure_loot_data_raw), 1, Math.sloped(Common.difficulty_scale(),1/2) * Common.game_completion_progress_capped())
local ret = Common.raffle_from_processed_loot_data(Common.processed_loot_data(Public.buried_treasure_loot_data_raw), 1, Math.clamp(0, 1, Math.sloped(Common.difficulty_scale(),1/2) * Common.game_completion_progress_capped()))
if ret and ret[1] then return ret[1] end
end

View File

@ -69,6 +69,8 @@ local Token = require 'utils.token'
local Task = require 'utils.task'
local Server = require 'utils.server'
local Math = require 'maps.pirates.math'
require 'utils.profiler'
local Public = {}
@ -225,6 +227,10 @@ local function crew_tick()
end
end
if destination.dynamic_data.disabled_wave_timer then
destination.dynamic_data.disabled_wave_timer = Math.max(0, destination.dynamic_data.disabled_wave_timer - 1)
end
if tick % 120 == 0 then
Ai.Tick_actions(120)

View File

@ -227,12 +227,19 @@ function Public.generate_destination_base_cost_to_undock(p, subtype)
base_cost_to_undock['launch_rocket'] = true
end
end
-- override:
if subtype == IslandEnum.enum.RADIOACTIVE then
base_cost_to_undock = {
['uranium-235'] = Math.ceil(Math.ceil(80 + (macro_p.x - 1))),
-- ['uranium-235'] = Math.ceil(Math.ceil(80 + (macro_p.x)/2)), --tried adding beacons instead of this
}
elseif subtype == IslandEnum.enum.CAVE then
base_cost_to_undock = nil -- make it a more chill island
elseif subtype == IslandEnum.enum.RED_DESERT then
if base_cost_to_undock and base_cost_to_undock['launch_rocket'] == true then
base_cost_to_undock['launch_rocket'] = false -- some extra variety
end
end
-- -- debug override:

View File

@ -613,6 +613,7 @@ function Public.go_from_currentdestination_to_sea()
memory.boat.speed = 0
memory.boat.position = new_boatposition
memory.boat.surface_name = seaname
memory.boat.fish_caught_while_at_sea = 0 -- how many times a fish was caught, rather than amount of fish caught in total
memory.enemy_force.reset_evolution()
@ -636,7 +637,7 @@ function Public.go_from_currentdestination_to_sea()
local maps = destination.dynamic_data.treasure_maps or {}
for _, map in pairs(maps) do
if map.state == 'picked_up' then
Common.parrot_speak(memory.force, {'pirates.parrot_burried_treasure_tip'})
Common.parrot_speak(memory.force, {'pirates.parrot_buried_treasure_tip'})
break
end
end

View File

@ -344,36 +344,37 @@ end
-- return ret
-- end
function Public.generate_flow_quest()
--@TODO: Ensure this function cannot return nil
--@TODO: This is related to a more general problem with raffles — how they handle game_completion being above 1. As of May '22, we cap game_completion at 1 before passing it to the raffle
-- @UNUSED
-- function Public.generate_flow_quest()
-- --@TODO: Ensure this function cannot return nil
-- --@TODO: This is related to a more general problem with raffles — how they handle game_completion being above 1. As of May '22, we cap game_completion at 1 before passing it to the raffle
local game_completion_progress = Common.game_completion_progress_capped()
-- local game_completion_progress = Common.game_completion_progress_capped()
local data = Public.flow_quest_data()
local v, w = {}, {}
-- local data = Public.flow_quest_data()
-- local v, w = {}, {}
for i = 1, #data, 1 do
table.insert(v, {item = data[i].item, base_rate = data[i].base_rate})
-- for i = 1, #data, 1 do
-- table.insert(v, {item = data[i].item, base_rate = data[i].base_rate})
local destination = Common.current_destination()
if not (destination and destination.subtype and data[i].map_subtype and data[i].map_subtype == 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(w, 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(w, data[i].weight)
else
table.insert(w, 0)
end
end
end
end
-- local destination = Common.current_destination()
-- if not (destination and destination.subtype and data[i].map_subtype and data[i].map_subtype == 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(w, 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(w, data[i].weight)
-- else
-- table.insert(w, 0)
-- end
-- end
-- end
-- end
return Raffle.raffle(v, w)
end
-- return Raffle.raffle(v, w)
-- end

View File

@ -4,7 +4,10 @@ local Math = require 'maps.pirates.math'
local Public = {}
-- @NOTE: Beware this function may return nil when there is at least 1 negative weight and guaranteed to return nil with all negative weights
-- Returns random value from values, with given probability weights. Both table parameters are expected to be arrays.
-- NOTE: This function:
-- - MAY return random equally distributed item from "values" when there is at least 1 weight <= 0 and
-- - WILL with all weights <= 0
function Public.raffle(values, weights) --arguments of the form {[a] = A, [b] = B, ...} and {[a] = a_weight, [b] = b_weight, ...} or just {a,b,c,...} and {1,2,3...}
local total_weight = 0
@ -15,7 +18,12 @@ function Public.raffle(values, weights) --arguments of the form {[a] = A, [b] =
end
-- negative weights treated as zero
end
if (not (total_weight > 0)) then return nil end
-- Fallback case
if (not (total_weight > 0)) then
local index = Math.random(1, table_size(values))
return values[index]
end
local cumulative_probability = 0
local rng = Math.random()
@ -26,28 +34,56 @@ function Public.raffle(values, weights) --arguments of the form {[a] = A, [b] =
return v
end
end
-- Fallback case
local index = Math.random(1, table_size(values))
return values[index]
end
-- @NOTE: Beware this function may return nil when there is at least 1 negative weight and guaranteed to return nil with all negative weights
-- Returns random key from table, with given probability values. Works with all types of keys.
-- NOTE: This function:
-- - MAY return random equally distributed item from "values" when there is at least 1 weight <= 0 and
-- - WILL with all weights <= 0
function Public.raffle2(table) --arguments of the form {v1 = w1, v2 = w2, ...}
local total_weight = 0
for k,w in pairs(table) do
for _, w in pairs(table) do
if w > 0 then
total_weight = total_weight + w
end
-- negative weights treated as zero
end
if (not (total_weight > 0)) then return nil end
-- Fallback case
if (not (total_weight > 0)) then
local index = Math.random(1, table_size(table))
for k, _ in pairs(table) do
if index == 1 then
return k
end
index = index - 1
end
end
local cumulative_probability = 0
local rng = Math.random()
for k,v in pairs(table) do
cumulative_probability = cumulative_probability + v/total_weight
for k, w in pairs(table) do
cumulative_probability = cumulative_probability + w/total_weight
if rng <= cumulative_probability then
return k
end
end
-- Fallback case
local index = Math.random(1, table_size(table))
for k, _ in pairs(table) do
if index == 1 then
return k
end
index = index - 1
end
end

View File

@ -9,6 +9,7 @@ local Common = require 'maps.pirates.common'
local Utils = require 'maps.pirates.utils_local'
local CoreData = require 'maps.pirates.coredata'
local SurfacesCommon = require 'maps.pirates.surfaces.common'
local Boats = require 'maps.pirates.structures.boats.boats'
-- local Server = require 'utils.server'
local Public = {}
@ -110,6 +111,10 @@ function Public.explanation(class, add_is_class_obtainable)
local extra_fish = Balance.master_angler_fish_bonus
local extra_coins = Balance.master_angler_coin_bonus
full_explanation = {'', {explanation, extra_range, extra_fish, extra_coins}}
elseif class == enum.DREDGER then
local extra_range = Balance.dredger_reach_bonus
local extra_fish = Balance.dredger_fish_bonus
full_explanation = {'', {explanation, extra_range, extra_fish}}
elseif class == enum.SCOUT then
local extra_speed = Public.percentage_points_difference_from_100_percent(Balance.scout_extra_speed)
local received_damage = Public.percentage_points_difference_from_100_percent(Balance.scout_damage_taken_multiplier)
@ -349,7 +354,7 @@ local function class_on_player_used_capsule(event)
local global_memory = Memory.get_global_memory()
global_memory.last_players_health[event.player_index] = player.character.health
if class == Public.enum.GOURMET then
if class == Public.enum.GOURMET and (not Boats.is_boat_at_sea()) then
local multiplier = 0
local surfacedata = SurfacesCommon.decode_surface_name(player.surface.name)
if surfacedata.type == SurfacesCommon.enum.CABIN then

View File

@ -351,6 +351,7 @@ function Public.assign_captain_based_on_priorities(excluded_player_index)
local captain_name = nil
-- Prefer officers for a captain (if there are any)
-- NOTE: this will try offering captain role to officer just once. It won't necessarily offer captain role to 2nd officer in the list if 1st officer rejects it.
for player_index, _ in pairs(memory.officers_table) do
local player = game.players[player_index]
local player_active = Utils.contains(Common.crew_get_nonafk_crew_members(), player)

View File

@ -1066,14 +1066,36 @@ local function teleport_handle_wake_tiles(boat, dummyboat, newsurface_name, olds
end
if friendlyboat_bool and boat.state == enum_state.RETREATING and vector.x < 0 then --in this case we need to place some landing tiles, as the cannon juts out
if (p.x >= boat.dockedposition.x + scope.Data.leftmost_gate_position) and (p.y <= scope.Data.upmost_gate_position or p.y >= scope.Data.downmost_gate_position) then t = CoreData.landing_tile end
if (p.x >= boat.dockedposition.x + scope.Data.leftmost_gate_position) and (p.y <= scope.Data.upmost_gate_position or p.y >= scope.Data.downmost_gate_position) then
t = CoreData.landing_tile
end
end
newtiles[#newtiles + 1] = {name = t, position = {x = p.x, y = p.y}}
end
end
end
oldsurface.set_tiles(newtiles, true, true, true)
-- prevent instant death when players stand in front of ship
oldsurface.set_tiles(newtiles, true, false, true)
-- but since players don't die instantly, they can get stuck in water, this prevents this (even though it let's you walk in front of ship while ship is departing)
-- NOTE: this will need to be changed, when ship doesn't necessarily arrive from the left
if vector.x < 0 then
for _, player in pairs(Common.crew_get_crew_members()) do
if player.character and player.character.valid then
local tile = oldsurface.get_tile(player.character.position.x, player.character.position.y)
if tile.valid then
if Utils.contains(CoreData.water_tile_names, tile.name) then
local new_pos = oldsurface.find_non_colliding_position('character', player.character.position, 20, 0.1, true)
if new_pos then
player.character.teleport(new_pos)
end
end
end
end
end
end
else

View File

@ -105,6 +105,7 @@ function Public.initialise_cached_quest_structure(position, quest_structure_type
rendering2 = rendering2,
rendering3 = rendering3,
rendering4 = rendering4,
completion_counter = 0,
}
elseif quest_structure_type == enum.FURNACE1 then
@ -242,20 +243,21 @@ function Public.tick_quest_structure_entry_price_check()
local entry_price = quest_structure_data.entry_price
local got = 0
for k, v in pairs(blue_contents) do
if quest_structure_data.state == 'covered' and k == entry_price.name then
got = v
quest_structure_data.completion_counter = quest_structure_data.completion_counter + v
else
-- @FIX: power armor loses components, items lose health!
-- @Piratux: ^ bro what?
red_inv.insert({name = k, count = v});
blue_inv.remove({name = k, count = v});
end
blue_inv.remove({name = k, count = v});
end
if quest_structure_data.state == 'covered' then
if got >= entry_price.count then
blue_inv.remove({name = entry_price.name, count = entry_price.count});
if quest_structure_data.completion_counter >= entry_price.count then
quest_structure_data.state = 'uncovered'
rendering.destroy(quest_structure_data.rendering1)
rendering.destroy(quest_structure_data.rendering2)
@ -268,7 +270,7 @@ function Public.tick_quest_structure_entry_price_check()
destination.dynamic_data.structures_waiting_to_be_placed[#destination.dynamic_data.structures_waiting_to_be_placed + 1] = {data = special, tick = game.tick}
else
if quest_structure_data.rendering1 then
rendering.set_text(quest_structure_data.rendering1, {'pirates.quest_structure_market_1', entry_price.count - got})
rendering.set_text(quest_structure_data.rendering1, {'pirates.quest_structure_market_1', entry_price.count - quest_structure_data.completion_counter})
end
end
end

View File

@ -9,6 +9,7 @@ local SurfacesCommon = require 'maps.pirates.surfaces.common'
local BoatData = require 'maps.pirates.structures.boats.sloop.data'
local Event = require 'utils.event'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local Balance = require 'maps.pirates.balance'
local Public = {}
Public.Data = require 'maps.pirates.surfaces.islands.cave.data'
@ -63,32 +64,44 @@ function Public.reveal(cave_miner, surface, source_surface, position, brushsize)
source_surface.set_tiles(copied_tiles, false, false, false, false)
for _, entity in pairs(source_surface.find_entities_filtered({area = {{position.x - brushsize, position.y - brushsize}, {position.x + brushsize, position.y + brushsize}}})) do
local entity_position = entity.position
if (position.x - entity_position.x) ^ 2 + (position.y - entity_position.y) ^ 2 < brushsize_square then
local e = entity.clone({position = entity_position, surface = surface})
if e.name == 'market' then
rendering.draw_light(
{
sprite = 'utility/light_medium',
scale = 7,
intensity = 0.8,
minimum_darkness = 0,
oriented = true,
color = {255, 255, 255},
target = e,
surface = surface,
visible = true,
only_in_alt_mode = false
}
)
end
if entity.valid then
local entity_position = entity.position
if (position.x - entity_position.x) ^ 2 + (position.y - entity_position.y) ^ 2 < brushsize_square then
local e = entity.clone({position = entity_position, surface = surface})
if e.name == 'market' then
rendering.draw_light(
{
sprite = 'utility/light_medium',
scale = 7,
intensity = 0.8,
minimum_darkness = 0,
oriented = true,
color = {255, 255, 255},
target = e,
surface = surface,
visible = true,
only_in_alt_mode = false
}
)
end
if entity.force.index == 2 then
e.active = true
table.insert(cave_miner.reveal_queue, {entity.type, entity.position.x, entity.position.y})
end
if entity.force.index == 2 then
e.active = true
table.insert(cave_miner.reveal_queue, {entity.type, entity.position.x, entity.position.y})
end
entity.destroy()
entity.destroy()
-- make revealing a spawner recursively reveal nearby ones too
if e.name == 'biter-spawner' or e.name == 'spitter-spawner' then
-- prevent spawners immediately spawning tons of biters for a while to give player a chance to clear them or run away
if destination.dynamic_data and destination.dynamic_data.disabled_wave_timer then
destination.dynamic_data.disabled_wave_timer = Balance.prevent_waves_from_spawning_in_cave_timer_length
end
Public.reveal(cave_miner, surface, source_surface, entity_position, 15)
end
end
end
end

View File

@ -14,6 +14,7 @@ local Classes = require 'maps.pirates.roles.classes'
local Public = {}
Public.Data = require 'maps.pirates.surfaces.islands.cave.data'
local math_random = Math.random
-- Code imported from cave_miner_v2 scenario for cave generation
@ -60,8 +61,8 @@ local function spawn_market(args, is_main)
end
local function place_rock(args)
local a = (-49 + Math.random(0, 98)) * 0.01
local b = (-49 + Math.random(0, 98)) * 0.01
local a = (-49 + math_random(0, 98)) * 0.01
local b = (-49 + math_random(0, 98)) * 0.01
args.entities[#args.entities + 1] = IslandsCommon.random_rock_1({x = args.p.x + a, y = args.p.y + b})
end
@ -70,7 +71,7 @@ local function place_spawner(args)
local memory = Memory.get_crew_memory()
local name
if Math.random(1, 2) == 1 then
if math_random(1, 2) == 1 then
name = 'biter-spawner'
else
name = 'spitter-spawner'
@ -98,11 +99,11 @@ function biomes.oasis(args, noise)
local noise_decoratives = GetNoise('decoratives', position, seed + 50000)
args.tiles[#args.tiles + 1] = {name = 'grass-1', position = args.p}
if Math.random(1, 16) == 1 and Math.abs(noise_decoratives) > 0.17 then
if math_random(1, 16) == 1 and Math.abs(noise_decoratives) > 0.17 then
args.entities[#args.entities + 1] = {name = 'tree-04', position = args.p}
end
if Math.random(1, 100) == 1 then
if math_random(1, 100) == 1 then
args.entities[#args.entities + 1] = {name = 'crude-oil', position = args.p, amount = Balance.pick_default_oil_amount() * 4}
end
@ -128,13 +129,13 @@ function biomes.pond_cave(args, noise)
args.tiles[#args.tiles + 1] = {name = 'dirt-7', position = args.p}
if Math.random(1, 512) == 1 then
if math_random(1, 512) == 1 then
args.specials[#args.specials + 1] = {name = 'chest', position = args.p}
return
end
if Math.abs(noise_2) > 0.25 then
if Math.random(1, 64) == 1 then
if math_random(1, 64) == 1 then
place_spawner(args)
else
place_rock(args)
@ -143,7 +144,7 @@ function biomes.pond_cave(args, noise)
return
end
if Math.random(1, 32) == 1 then
if math_random(1, 32) == 1 then
place_spawner(args)
return
end
@ -152,7 +153,7 @@ function biomes.pond_cave(args, noise)
place_rock(args)
return
else
if Math.random(1, 1024) == 1 then
if math_random(1, 1024) == 1 then
spawn_market(args)
return
end
@ -214,21 +215,21 @@ function biomes.worm_desert(args, noise)
return
end
if Math.random(1, 64) == 1 then
if math_random(1, 64) == 1 then
place_worm(args)
return
end
if Math.random(1, 32) == 1 then
if math_random(1, 32) == 1 then
local n = GetNoise('decoratives', position, seed + 10000)
if n > 0.2 then
local trees = {'dead-grey-trunk', 'dead-grey-trunk', 'dry-tree'}
args.entities[#args.entities + 1] = {name = trees[Math.random(1, 3)], position = args.p}
args.entities[#args.entities + 1] = {name = trees[math_random(1, 3)], position = args.p}
return
end
end
if Math.random(1, 512) == 1 then
if math_random(1, 512) == 1 then
args.specials[#args.specials + 1] = {name = 'chest', position = args.p}
end
end
@ -250,7 +251,7 @@ function biomes.cave(args, square_distance)
local no_rocks_2 = GetNoise('no_rocks_2', position, seed)
if no_rocks_2 > 0.7 then
if no_rocks_2 > 0.73 then
if Math.random(1, 256) == 1 then
if math_random(1, 256) == 1 then
spawn_market(args)
end
end
@ -280,8 +281,8 @@ function biomes.cave(args, square_distance)
-- add nest obstacles in these rings on "main" wide cave roads
if (square_distance > ring1_start and square_distance < ring1_end) or
(square_distance > ring2_start and square_distance < ring2_end) then
if Math.random(1, 32) == 1 then
if Math.random(1, 3) == 1 then
if math_random(1, 32) == 1 then
if math_random(1, 3) == 1 then
place_worm(args)
else
place_spawner(args)
@ -289,18 +290,18 @@ function biomes.cave(args, square_distance)
return
end
if Math.random(1, 512) == 1 then
if math_random(1, 512) == 1 then
args.specials[#args.specials + 1] = {name = 'chest', position = args.p}
return
end
if Math.random(1, 16) == 1 then
if math_random(1, 16) == 1 then
place_rock(args)
return
end
end
if Math.random(1, 1024) == 1 then
if math_random(1, 1024) == 1 then
args.specials[#args.specials + 1] = {name = 'chest', position = args.p}
return
end
@ -313,13 +314,13 @@ function biomes.cave(args, square_distance)
return
end
if Math.random(1, 8192) == 1 then
if math_random(1, 8192) == 1 then
spawn_market(args)
return
end
if Math.random(1, 16) == 1 then
if Math.random(1, 3) == 1 then
if math_random(1, 16) == 1 then
if math_random(1, 3) == 1 then
place_worm(args)
return
else

View File

@ -161,7 +161,7 @@ function Public.spawn_ores_on_arrival(destination, points_to_avoid)
local surface = game.surfaces[destination.surface_name]
if not surface and surface.valid then return end
if (destination.subtype and (destination.subtype == enum.STANDARD or destination.subtype == enum.STANDARD_VARIANT or destination.subtype == enum.MAZE)) then
if destination.subtype == enum.STANDARD or destination.subtype == enum.STANDARD_VARIANT or destination.subtype == enum.MAZE then
local ores = {'iron-ore', 'copper-ore', 'stone', 'coal', 'crude-oil'}
local args = {
@ -288,8 +288,13 @@ function Public.spawn_silo_setup(points_to_avoid)
if silo_count >= 2 then game.print('debug - silo count: ' .. silo_count) end
end
for i=1,silo_count do
local silo = surface.create_entity({name = 'rocket-silo', position = {p_silo.x + 9*(i-1), p_silo.y}, force = force, create_build_effect_smoke = false})
for i = 1, silo_count do
local pos = {x = p_silo.x + 9*(i-1), y = p_silo.y}
Common.delete_entities(surface, pos, 11, 11)
Common.replace_unwalkable_tiles(surface, pos, 11, 11)
local silo = surface.create_entity({name = 'rocket-silo', position = pos, force = force, create_build_effect_smoke = false})
if silo and silo.valid then
if not destination.dynamic_data.rocketsilos then destination.dynamic_data.rocketsilos = {} end
destination.dynamic_data.rocketsilos[#destination.dynamic_data.rocketsilos + 1]= silo

View File

@ -247,7 +247,7 @@ function Public.chunk_structures(args)
placeable = noises.farness(p) > 0.66,
spawners_indestructible = noises.farness(p) > 0.7,
-- spawners_indestructible = true,
density_perchunk = 150 * Math.slopefromto(noises.farness(p), 0.3, 1)^2 * args.biter_base_density_scale,
density_perchunk = 150 * Math.slopefromto(noises.farness(p), 0.3, 0.9)^2 * args.biter_base_density_scale,
}
end
@ -261,7 +261,7 @@ end
function Public.generate_silo_setup_position(points_to_avoid)
return Hunt.silo_setup_position(points_to_avoid, 0.5)
return Hunt.silo_setup_position(points_to_avoid)
end

View File

@ -50,17 +50,29 @@ local swimming_biters_tick_token =
end
)
function Public.get_active_kraken_count()
local memory = Memory.get_crew_memory()
if memory.active_sea_enemies and memory.active_sea_enemies.kraken_count then
return memory.active_sea_enemies.kraken_count
else
return 0
end
end
-- should only be used during kraken encounter
function Public.swimming_biters_tick(crew_id, kraken_id)
Memory.set_working_id(crew_id)
local memory = Memory.get_crew_memory()
if not Common.is_id_valid(memory.id) then return end --check if crew disbanded
if memory.game_lost then return end
local kraken_data = memory.active_sea_enemies.krakens[kraken_id]
if not kraken_data then return end --check if kraken died
local surface = game.surfaces[memory.sea_name]
if not Boats.is_boat_at_sea() then return end
local surface = game.surfaces[memory.sea_name]
local spawners_biters = surface.find_entities_filtered{force = memory.enemy_force_name}
if Public.get_active_kraken_count() == 0 and #spawners_biters == 0 then return end
for _, biter in pairs(spawners_biters) do
if biter and biter.valid then
if biter.name ~= 'biter-spawner' then -- might need to be changed if kraken battle one day will involve worms too
@ -266,7 +278,7 @@ end
function Public.overall_kraken_tick()
local memory = Memory.get_crew_memory()
if memory.active_sea_enemies and memory.active_sea_enemies.kraken_count and memory.active_sea_enemies.kraken_count > 0 then
if Public.get_active_kraken_count() > 0 then
local evo_increase = Balance.kraken_evo_increase_per_second()
if evo_increase > 0 then
if not memory.dynamic_kraken_evo then memory.dynamic_kraken_evo = 0 end
@ -306,7 +318,11 @@ function Public.try_spawn_kraken()
memory.active_sea_enemies.kraken_count = memory.active_sea_enemies.kraken_count + 1
Task.set_timeout_in_ticks(10, kraken_tick_token, {crew_id = memory.id, kraken_id = kraken_id, step = 1, substep = 1})
Task.set_timeout_in_ticks(10, swimming_biters_tick_token, {crew_id = memory.id, kraken_id = kraken_id})
-- creating multiple swim tick tokens, causes biters to swim faster
if Public.get_active_kraken_count() == 1 then
Task.set_timeout_in_ticks(10, swimming_biters_tick_token, {crew_id = memory.id, kraken_id = kraken_id})
end
end
end

View File

@ -277,6 +277,10 @@ function Public.destination_on_arrival(destination)
destination.dynamic_data.time_remaining = -1
elseif destination.subtype == IslandEnum.enum.MAZE then --more time
destination.dynamic_data.time_remaining = Math.ceil(1.05 * Balance.max_time_on_island())
elseif destination.subtype == IslandEnum.enum.CAVE then -- supposed to be chill island
destination.dynamic_data.time_remaining = Math.ceil(0.8 * Balance.max_time_on_island_formula())
elseif destination.subtype == IslandEnum.enum.RED_DESERT then --this island has big amount of resources so rather high risk (need time to mine resources) and high reward (lots of iron/copper/stone), also try prevent infinite stay (on late game this island becomes too easy)
destination.dynamic_data.time_remaining = Math.ceil(0.8 * Balance.max_time_on_island_formula())
else
destination.dynamic_data.time_remaining = Math.ceil(Balance.max_time_on_island())
end
@ -382,9 +386,13 @@ function Public.destination_on_arrival(destination)
-- game.print('spawning silo')
if destination.subtype ~= IslandEnum.enum.RADIOACTIVE then
local silo_position = Islands.spawn_silo_setup(points_to_avoid)
if silo_position then
points_to_avoid[#points_to_avoid + 1] = {x = silo_position.x, y = silo_position.y, r = 22}
local first_silo_pos = Islands.spawn_silo_setup(points_to_avoid)
if first_silo_pos then
local silo_count = Balance.silo_count()
for i = 1, silo_count do
local avoid_pos = {x = first_silo_pos.x + 9 * (i-1), y = first_silo_pos.y}
points_to_avoid[#points_to_avoid + 1] = {x = avoid_pos.x, y = avoid_pos.y, r = 22}
end
end
end
@ -417,7 +425,7 @@ function Public.destination_on_departure(destination)
Common.parrot_speak(memory.force, {'pirates.parrot_kraken_warning'})
end
if destination.subtype and destination.subtype == IslandEnum.enum.MAZE then
if destination.subtype == IslandEnum.enum.MAZE then
local force = memory.force
force.manual_mining_speed_modifier = 3 --put back to normal
end